From dd1e96fa8655b75092525061a4a7c0d26b4b3849 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 17 Jan 2025 16:42:18 +0100 Subject: [PATCH 001/521] Bump JDK baseline to 17 Co-authored-by: Christian Stein --- .github/actions/setup-test-jdk/action.yml | 4 +- documentation/documentation.gradle.kts | 4 +- gradle.properties | 2 +- .../src/main/kotlin/JavaLibraryExtension.kt | 2 +- ...tbuild.java-library-conventions.gradle.kts | 7 +- ...uild.java-multi-release-sources.gradle.kts | 45 --- .../junit-platform-commons.gradle.kts | 28 -- .../platform/commons/util/ModuleUtils.java | 245 ++++++++++++-- .../commons/util/PackageNameUtils.java | 10 +- .../commons/util/ServiceLoaderUtils.java | 15 +- .../platform/commons/util/ModuleUtils.java | 311 ------------------ .../commons/util/PackageNameUtils.java | 30 -- .../commons/util/ServiceLoaderUtils.java | 56 ---- ...nit-platform-console-standalone.gradle.kts | 8 - .../junit-platform-console.gradle.kts | 21 -- .../console/ConsoleLauncherToolProvider.java | 0 .../console/options/ConsoleUtils.java | 4 +- .../console/options/ConsoleUtils.java | 42 --- .../junit-platform-jfr.gradle.kts | 10 - .../platform-tooling-support-tests.gradle.kts | 4 +- .../gradle-kotlin-extensions/build.gradle.kts | 6 +- .../gradle.properties | 2 +- .../gradle-missing-engine/build.gradle.kts | 2 +- .../gradle-missing-engine/gradle.properties | 2 +- .../projects/java-versions/pom.xml | 63 ---- .../test/java/JUnitPlatformCommonsTests.java | 37 --- .../jupiter-starter/gradle.properties | 2 +- .../projects/jupiter-starter/pom.xml | 3 +- .../maven-surefire-compatibility/pom.xml | 3 +- .../reflection-tests/build.gradle.kts | 2 +- .../reflection-tests/gradle.properties | 2 +- .../projects/vintage/build.gradle.kts | 2 +- .../projects/vintage/gradle.properties | 2 +- .../projects/vintage/pom.xml | 3 +- .../platform/tooling/support/HelperTests.java | 2 +- .../tests/GradleKotlinExtensionsTests.java | 2 +- .../tests/GradleMissingEngineTests.java | 2 +- .../support/tests/GradleModuleFileTests.java | 4 +- .../support/tests/GradleStarterTests.java | 26 +- .../support/tests/JavaVersionsTests.java | 72 ---- .../tooling/support/tests/ManifestTests.java | 6 +- .../support/tests/MavenStarterTests.java | 4 +- .../MavenSurefireCompatibilityTests.java | 2 +- .../tests/ReflectionCompatibilityTests.java | 4 +- .../support/tests/StandaloneTests.java | 20 +- .../tests/UnalignedClasspathTests.java | 2 +- .../tests/VintageGradleIntegrationTests.java | 2 +- .../tests/VintageMavenIntegrationTests.java | 2 +- 48 files changed, 287 insertions(+), 842 deletions(-) delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts delete mode 100644 junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ModuleUtils.java delete mode 100644 junit-platform-commons/src/main/java9/org/junit/platform/commons/util/PackageNameUtils.java delete mode 100644 junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ServiceLoaderUtils.java rename junit-platform-console/src/main/{java9 => java}/org/junit/platform/console/ConsoleLauncherToolProvider.java (100%) delete mode 100644 junit-platform-console/src/main/java17/org/junit/platform/console/options/ConsoleUtils.java delete mode 100644 platform-tooling-support-tests/projects/java-versions/pom.xml delete mode 100644 platform-tooling-support-tests/projects/java-versions/src/test/java/JUnitPlatformCommonsTests.java delete mode 100644 platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java diff --git a/.github/actions/setup-test-jdk/action.yml b/.github/actions/setup-test-jdk/action.yml index b2d6b1dbc46b..f417044940cd 100644 --- a/.github/actions/setup-test-jdk/action.yml +++ b/.github/actions/setup-test-jdk/action.yml @@ -11,7 +11,7 @@ runs: - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: ${{ inputs.distribution }} - java-version: 8 + java-version: 17 check-latest: true - shell: bash - run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV + run: echo "JDK17=$JAVA_HOME" >> $GITHUB_ENV diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 799c16ae3833..9fccf43eea7f 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -25,8 +25,8 @@ val modularProjects: List by rootProject modularProjects.forEach { evaluationDependsOn(it.path) } javaLibrary { - mainJavaVersion = JavaVersion.VERSION_1_8 - testJavaVersion = JavaVersion.VERSION_1_8 + mainJavaVersion = JavaVersion.VERSION_17 + testJavaVersion = JavaVersion.VERSION_17 } val apiReport = configurations.dependencyScope("apiReport") diff --git a/gradle.properties b/gradle.properties index 1f57336a6a6a..6e27e89740d2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -14,7 +14,7 @@ org.gradle.jvmargs=-Xmx1g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryEr org.gradle.caching=true org.gradle.parallel=true org.gradle.configuration-cache.parallel=true -org.gradle.java.installations.fromEnv=GRAALVM_HOME,JDK8,JDK18,JDK19,JDK20,JDK21,JDK22,JDK23,JDK24 +org.gradle.java.installations.fromEnv=GRAALVM_HOME,JDK17,JDK21,JDK24,JDK25 org.gradle.kotlin.dsl.allWarningsAsErrors=true # Test Distribution diff --git a/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt b/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt index 64a61da7fb7b..9cc28076bbc4 100644 --- a/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt +++ b/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt @@ -1,7 +1,7 @@ import org.gradle.api.JavaVersion open class JavaLibraryExtension { - var mainJavaVersion: JavaVersion = JavaVersion.VERSION_1_8 + var mainJavaVersion: JavaVersion = JavaVersion.VERSION_17 var testJavaVersion: JavaVersion = JavaVersion.VERSION_21 var configureRelease: Boolean = true } 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 b14973e05474..96b3b1b06bbc 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 @@ -184,10 +184,8 @@ val compileModule by tasks.registering(JavaCompile::class) { enabled = project in modularProjects source = fileTree(combinedModuleSourceDir).builtBy(prepareModuleSourceDir) destinationDirectory = moduleOutputDir - sourceCompatibility = "9" - targetCompatibility = "9" classpath = files() - options.release = 9 + options.release = 17 options.compilerArgs.addAll(listOf( // Suppress warnings for automatic modules: org.apiguardian.api, org.opentest4j "-Xlint:all,-requires-automatic,-requires-transitive-automatic", @@ -262,17 +260,14 @@ tasks.withType().configureEach { } tasks.compileJava { - // See: https://docs.oracle.com/en/java/javase/12/tools/javac.html options.compilerArgs.addAll(listOf( "-Xlint:all", // Enables all recommended warnings. "-Werror", // Terminates compilation when warnings occur. - // Required for compatibility with Java 8's reflection APIs (see https://github.com/junit-team/junit5/issues/3797). "-parameters", // Generates metadata for reflection on method parameters. )) } tasks.compileTestJava { - // See: https://docs.oracle.com/en/java/javase/12/tools/javac.html options.compilerArgs.addAll(listOf( "-Xlint", // Enables all recommended warnings. "-Xlint:-overrides", // Disables "method overrides" warnings. diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts deleted file mode 100644 index 83b2a8e8e273..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-sources.gradle.kts +++ /dev/null @@ -1,45 +0,0 @@ -import junitbuild.extensions.capitalized - -plugins { - id("junitbuild.java-library-conventions") -} - -val mavenizedProjects: List by rootProject.extra - -listOf(9, 17).forEach { javaVersion -> - val sourceSet = sourceSets.register("mainRelease${javaVersion}") { - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - java { - setSrcDirs(setOf("src/main/java${javaVersion}")) - } - } - - configurations.named(sourceSet.get().compileClasspathConfigurationName).configure { - extendsFrom(configurations.compileClasspath.get()) - } - - tasks { - - named("allMainClasses").configure { - dependsOn(sourceSet.get().classesTaskName) - } - - named(sourceSet.get().compileJavaTaskName).configure { - options.release = javaVersion - } - - named("checkstyle${sourceSet.name.capitalized()}").configure { - config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) - } - - if (project in mavenizedProjects) { - javadoc { - source(sourceSet.get().allJava) - } - named("sourcesJar").configure { - from(sourceSet.get().allSource) - } - } - } -} diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 3465b0078020..89a6f0ecb227 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -1,8 +1,5 @@ -import junitbuild.java.UpdateJarAction - plugins { id("junitbuild.java-library-conventions") - id("junitbuild.java-multi-release-sources") `java-test-fixtures` } @@ -13,28 +10,3 @@ dependencies { compileOnlyApi(libs.apiguardian) } - -tasks.jar { - val release9ClassesDir = sourceSets.mainRelease9.get().output.classesDirs.singleFile - inputs.dir(release9ClassesDir).withPathSensitivity(PathSensitivity.RELATIVE) - doLast(objects.newInstance(UpdateJarAction::class).apply { - javaLauncher = javaToolchains.launcherFor(java.toolchain) - args.addAll( - "--file", archiveFile.get().asFile.absolutePath, - "--release", "9", - "-C", release9ClassesDir.absolutePath, "." - ) - }) -} - -tasks.codeCoverageClassesJar { - exclude("org/junit/platform/commons/util/ModuleUtils.class") - exclude("org/junit/platform/commons/util/PackageNameUtils.class") - exclude("org/junit/platform/commons/util/ServiceLoaderUtils.class") -} - -eclipse { - classpath { - sourceSets -= project.sourceSets.mainRelease9.get() - } -} diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index 980c06394ea2..9f20d964f471 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -10,18 +10,34 @@ package org.junit.platform.commons.util; -import static java.util.Collections.emptyList; -import static java.util.Collections.emptySet; +import static java.util.function.Predicate.isEqual; +import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; +import java.io.IOException; +import java.lang.module.Configuration; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReader; +import java.lang.module.ModuleReference; +import java.lang.module.ResolvedModule; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apiguardian.api.API; +import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; +import org.junit.platform.commons.support.DefaultResource; import org.junit.platform.commons.support.Resource; import org.junit.platform.commons.support.scanning.ClassFilter; @@ -49,42 +65,40 @@ public class ModuleUtils { * potentially empty */ public static Set findAllNonSystemBootModuleNames() { - logger.config(() -> "Basic version of findAllNonSystemBootModuleNames() always returns an empty set!"); - return emptySet(); + // @formatter:off + Set systemModules = ModuleFinder.ofSystem().findAll().stream() + .map(reference -> reference.descriptor().name()) + .collect(toSet()); + return streamResolvedModules(name -> !systemModules.contains(name)) + .map(ResolvedModule::name) + .collect(toCollection(LinkedHashSet::new)); + // @formatter:on } /** - * Determine if the current Java runtime supports the Java Platform Module System. + * Java 9+ runtime supports the Java Platform Module System. * - * @return {@code true} if the Java Platform Module System is available, - * otherwise {@code false} + * @return {@code true} */ public static boolean isJavaPlatformModuleSystemAvailable() { - return false; + return true; } - /** - * Return the name of the module that the class or interface is a member of. - * - * @param type class or interface to analyze - * @return the module name; never {@code null} but potentially empty - */ public static Optional getModuleName(Class type) { - return Optional.empty(); + Preconditions.notNull(type, "Class type must not be null"); + + return Optional.ofNullable(type.getModule().getName()); } - /** - * Return the raw version of the module that the class or interface is a member of. - * - * @param type class or interface to analyze - * @return the raw module version; never {@code null} but potentially empty - */ public static Optional getModuleVersion(Class type) { - return Optional.empty(); + Preconditions.notNull(type, "Class type must not be null"); + + Module module = type.getModule(); + return module.isNamed() ? module.getDescriptor().rawVersion() : Optional.empty(); } /** - * Find all classes for the given module name. + * Find all {@linkplain Class classes} for the given module name. * * @param moduleName the name of the module to scan; never {@code null} or * empty @@ -96,12 +110,17 @@ public static List> findAllClassesInModule(String moduleName, ClassFilt Preconditions.notBlank(moduleName, "Module name must not be null or empty"); Preconditions.notNull(filter, "Class filter must not be null"); - logger.config(() -> "Basic version of findAllClassesInModule() always returns an empty list!"); - return emptyList(); + logger.debug(() -> "Looking for classes in module: " + moduleName); + // @formatter:off + Set moduleReferences = streamResolvedModules(isEqual(moduleName)) + .map(ResolvedModule::reference) + .collect(toSet()); + // @formatter:on + return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader()); } /** - * Find all resources for the given module name. + * Find all {@linkplain Resource resources} for the given module name. * * @param moduleName the name of the module to scan; never {@code null} or * empty @@ -115,8 +134,178 @@ public static List findAllResourcesInModule(String moduleName, Predica Preconditions.notBlank(moduleName, "Module name must not be null or empty"); Preconditions.notNull(filter, "Resource filter must not be null"); - logger.config(() -> "Basic version of findAllResourcesInModule() always returns an empty list!"); - return emptyList(); + logger.debug(() -> "Looking for classes in module: " + moduleName); + // @formatter:off + Set moduleReferences = streamResolvedModules(isEqual(moduleName)) + .map(ResolvedModule::reference) + .collect(toSet()); + // @formatter:on + return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader()); + } + + /** + * Stream resolved modules from current (or boot) module layer. + */ + private static Stream streamResolvedModules(Predicate moduleNamePredicate) { + Module module = ModuleUtils.class.getModule(); + ModuleLayer layer = module.getLayer(); + if (layer == null) { + logger.config(() -> ModuleUtils.class + " is a member of " + module + + " - using boot layer returned by ModuleLayer.boot() as fall-back."); + layer = ModuleLayer.boot(); + } + return streamResolvedModules(moduleNamePredicate, layer); + } + + /** + * Stream resolved modules from the supplied layer. + */ + private static Stream streamResolvedModules(Predicate moduleNamePredicate, + ModuleLayer layer) { + logger.debug(() -> "Streaming modules for layer @" + System.identityHashCode(layer) + ": " + layer); + Configuration configuration = layer.configuration(); + logger.debug(() -> "Module layer configuration: " + configuration); + Stream stream = configuration.modules().stream(); + return stream.filter(module -> moduleNamePredicate.test(module.name())); + } + + /** + * Scan for classes using the supplied set of module references, class + * filter, and loader. + */ + private static List> scan(Set references, ClassFilter filter, ClassLoader loader) { + logger.debug(() -> "Scanning " + references.size() + " module references: " + references); + ModuleReferenceClassScanner scanner = new ModuleReferenceClassScanner(filter, loader); + List> classes = new ArrayList<>(); + for (ModuleReference reference : references) { + classes.addAll(scanner.scan(reference)); + } + logger.debug(() -> "Found " + classes.size() + " classes: " + classes); + return Collections.unmodifiableList(classes); + } + + /** + * Scan for classes using the supplied set of module references, class + * filter, and loader. + */ + private static List scan(Set references, Predicate filter, + ClassLoader loader) { + logger.debug(() -> "Scanning " + references.size() + " module references: " + references); + ModuleReferenceResourceScanner scanner = new ModuleReferenceResourceScanner(filter, loader); + List classes = new ArrayList<>(); + for (ModuleReference reference : references) { + classes.addAll(scanner.scan(reference)); + } + logger.debug(() -> "Found " + classes.size() + " classes: " + classes); + return Collections.unmodifiableList(classes); + } + + /** + * {@link ModuleReference} class scanner. + * + * @since 1.1 + */ + static class ModuleReferenceClassScanner { + + private final ClassFilter classFilter; + private final ClassLoader classLoader; + + ModuleReferenceClassScanner(ClassFilter classFilter, ClassLoader classLoader) { + this.classFilter = classFilter; + this.classLoader = classLoader; + } + + /** + * Scan module reference for classes that potentially contain testable methods. + */ + List> scan(ModuleReference reference) { + try (ModuleReader reader = reference.open()) { + try (Stream names = reader.list()) { + // @formatter:off + return names.filter(name -> name.endsWith(".class")) + .map(this::className) + .filter(name -> !name.equals("module-info")) + .filter(classFilter::match) + .map(this::loadClassUnchecked) + .filter(classFilter::match) + .collect(Collectors.toList()); + // @formatter:on + } + } + catch (IOException e) { + throw new JUnitException("Failed to read contents of " + reference + ".", e); + } + } + + /** + * Convert resource name to binary class name. + */ + private String className(String resourceName) { + resourceName = resourceName.substring(0, resourceName.length() - 6); // 6 = ".class".length() + resourceName = resourceName.replace('/', '.'); + return resourceName; + } + + /** + * Load class by its binary name. + * + * @see ClassLoader#loadClass(String) + */ + private Class loadClassUnchecked(String binaryName) { + try { + return classLoader.loadClass(binaryName); + } + catch (ClassNotFoundException e) { + throw new JUnitException("Failed to load class with name '" + binaryName + "'.", e); + } + } + + } + + /** + * {@link ModuleReference} resource class scanner. + * + * @since 1.11 + */ + static class ModuleReferenceResourceScanner { + + private final Predicate resourceFilter; + private final ClassLoader classLoader; + + ModuleReferenceResourceScanner(Predicate resourceFilter, ClassLoader classLoader) { + this.resourceFilter = resourceFilter; + this.classLoader = classLoader; + } + + /** + * Scan module reference for resources that potentially contain testable resources. + */ + List scan(ModuleReference reference) { + try (ModuleReader reader = reference.open()) { + try (Stream names = reader.list()) { + // @formatter:off + return names.filter(name -> !name.endsWith(".class")) + .map(this::loadResourceUnchecked) + .filter(resourceFilter) + .collect(Collectors.toList()); + // @formatter:on + } + } + catch (IOException e) { + throw new JUnitException("Failed to read contents of " + reference + ".", e); + } + } + + private Resource loadResourceUnchecked(String binaryName) { + try { + URI uri = classLoader.getResource(binaryName).toURI(); + return new DefaultResource(binaryName, uri); + } + catch (URISyntaxException e) { + throw new JUnitException("Failed to load resource with name '" + binaryName + "'.", e); + } + } + } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java index 2a0094dda4c4..0cb6aec9e8d8 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java @@ -10,8 +10,6 @@ package org.junit.platform.commons.util; -import static org.junit.platform.commons.util.PackageUtils.DEFAULT_PACKAGE_NAME; - /** * Collection of utilities for working with package names. * @@ -26,13 +24,7 @@ class PackageNameUtils { static String getPackageName(Class clazz) { - Package p = clazz.getPackage(); - if (p != null) { - return p.getName(); - } - String className = clazz.getName(); - int index = className.lastIndexOf('.'); - return index == -1 ? DEFAULT_PACKAGE_NAME : className.substring(0, index); + return clazz.getPackageName(); } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java index 0a060bee0999..db209116b615 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java @@ -13,9 +13,9 @@ import java.util.ServiceLoader; import java.util.function.Predicate; import java.util.stream.Stream; -import java.util.stream.StreamSupport; import org.apiguardian.api.API; +import org.apiguardian.api.API.Status; /** * Collection of utilities for working with {@link ServiceLoader}. @@ -28,7 +28,7 @@ * * @since 1.11 */ -@API(status = API.Status.INTERNAL, since = "1.11") +@API(status = Status.INTERNAL, since = "1.11") public class ServiceLoaderUtils { private ServiceLoaderUtils() { @@ -45,11 +45,12 @@ private ServiceLoaderUtils() { */ public static Stream filter(ServiceLoader serviceLoader, Predicate> providerPredicate) { - return StreamSupport.stream(serviceLoader.spliterator(), false).filter(it -> { - @SuppressWarnings("unchecked") - Class type = (Class) it.getClass(); - return providerPredicate.test(type); - }); + // @formatter:off + return serviceLoader + .stream() + .filter(provider -> providerPredicate.test(provider.type())) + .map(ServiceLoader.Provider::get); + // @formatter:on } } diff --git a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ModuleUtils.java deleted file mode 100644 index 9f20d964f471..000000000000 --- a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ModuleUtils.java +++ /dev/null @@ -1,311 +0,0 @@ -/* - * 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 java.util.function.Predicate.isEqual; -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toSet; -import static org.apiguardian.api.API.Status.INTERNAL; - -import java.io.IOException; -import java.lang.module.Configuration; -import java.lang.module.ModuleFinder; -import java.lang.module.ModuleReader; -import java.lang.module.ModuleReference; -import java.lang.module.ResolvedModule; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apiguardian.api.API; -import org.junit.platform.commons.JUnitException; -import org.junit.platform.commons.logging.Logger; -import org.junit.platform.commons.logging.LoggerFactory; -import org.junit.platform.commons.support.DefaultResource; -import org.junit.platform.commons.support.Resource; -import org.junit.platform.commons.support.scanning.ClassFilter; - -/** - * Collection of utilities for working with {@code java.lang.Module} - * and friends. - * - *

DISCLAIMER

- * - *

These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.1 - */ -@API(status = INTERNAL, since = "1.1") -public class ModuleUtils { - - private static final Logger logger = LoggerFactory.getLogger(ModuleUtils.class); - - /** - * Find all non-system boot modules names. - * - * @return a set of all such module names; never {@code null} but - * potentially empty - */ - public static Set findAllNonSystemBootModuleNames() { - // @formatter:off - Set systemModules = ModuleFinder.ofSystem().findAll().stream() - .map(reference -> reference.descriptor().name()) - .collect(toSet()); - return streamResolvedModules(name -> !systemModules.contains(name)) - .map(ResolvedModule::name) - .collect(toCollection(LinkedHashSet::new)); - // @formatter:on - } - - /** - * Java 9+ runtime supports the Java Platform Module System. - * - * @return {@code true} - */ - public static boolean isJavaPlatformModuleSystemAvailable() { - return true; - } - - public static Optional getModuleName(Class type) { - Preconditions.notNull(type, "Class type must not be null"); - - return Optional.ofNullable(type.getModule().getName()); - } - - public static Optional getModuleVersion(Class type) { - Preconditions.notNull(type, "Class type must not be null"); - - Module module = type.getModule(); - return module.isNamed() ? module.getDescriptor().rawVersion() : Optional.empty(); - } - - /** - * Find all {@linkplain Class classes} for the given module name. - * - * @param moduleName the name of the module to scan; never {@code null} or - * empty - * @param filter the class filter to apply; never {@code null} - * @return an immutable list of all such classes found; never {@code null} - * but potentially empty - */ - public static List> findAllClassesInModule(String moduleName, ClassFilter filter) { - Preconditions.notBlank(moduleName, "Module name must not be null or empty"); - Preconditions.notNull(filter, "Class filter must not be null"); - - logger.debug(() -> "Looking for classes in module: " + moduleName); - // @formatter:off - Set moduleReferences = streamResolvedModules(isEqual(moduleName)) - .map(ResolvedModule::reference) - .collect(toSet()); - // @formatter:on - return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader()); - } - - /** - * Find all {@linkplain Resource resources} for the given module name. - * - * @param moduleName the name of the module to scan; never {@code null} or - * empty - * @param filter the class filter to apply; never {@code null} - * @return an immutable list of all such resources found; never {@code null} - * but potentially empty - * @since 1.11 - */ - @API(status = INTERNAL, since = "1.11") - public static List findAllResourcesInModule(String moduleName, Predicate filter) { - Preconditions.notBlank(moduleName, "Module name must not be null or empty"); - Preconditions.notNull(filter, "Resource filter must not be null"); - - logger.debug(() -> "Looking for classes in module: " + moduleName); - // @formatter:off - Set moduleReferences = streamResolvedModules(isEqual(moduleName)) - .map(ResolvedModule::reference) - .collect(toSet()); - // @formatter:on - return scan(moduleReferences, filter, ModuleUtils.class.getClassLoader()); - } - - /** - * Stream resolved modules from current (or boot) module layer. - */ - private static Stream streamResolvedModules(Predicate moduleNamePredicate) { - Module module = ModuleUtils.class.getModule(); - ModuleLayer layer = module.getLayer(); - if (layer == null) { - logger.config(() -> ModuleUtils.class + " is a member of " + module - + " - using boot layer returned by ModuleLayer.boot() as fall-back."); - layer = ModuleLayer.boot(); - } - return streamResolvedModules(moduleNamePredicate, layer); - } - - /** - * Stream resolved modules from the supplied layer. - */ - private static Stream streamResolvedModules(Predicate moduleNamePredicate, - ModuleLayer layer) { - logger.debug(() -> "Streaming modules for layer @" + System.identityHashCode(layer) + ": " + layer); - Configuration configuration = layer.configuration(); - logger.debug(() -> "Module layer configuration: " + configuration); - Stream stream = configuration.modules().stream(); - return stream.filter(module -> moduleNamePredicate.test(module.name())); - } - - /** - * Scan for classes using the supplied set of module references, class - * filter, and loader. - */ - private static List> scan(Set references, ClassFilter filter, ClassLoader loader) { - logger.debug(() -> "Scanning " + references.size() + " module references: " + references); - ModuleReferenceClassScanner scanner = new ModuleReferenceClassScanner(filter, loader); - List> classes = new ArrayList<>(); - for (ModuleReference reference : references) { - classes.addAll(scanner.scan(reference)); - } - logger.debug(() -> "Found " + classes.size() + " classes: " + classes); - return Collections.unmodifiableList(classes); - } - - /** - * Scan for classes using the supplied set of module references, class - * filter, and loader. - */ - private static List scan(Set references, Predicate filter, - ClassLoader loader) { - logger.debug(() -> "Scanning " + references.size() + " module references: " + references); - ModuleReferenceResourceScanner scanner = new ModuleReferenceResourceScanner(filter, loader); - List classes = new ArrayList<>(); - for (ModuleReference reference : references) { - classes.addAll(scanner.scan(reference)); - } - logger.debug(() -> "Found " + classes.size() + " classes: " + classes); - return Collections.unmodifiableList(classes); - } - - /** - * {@link ModuleReference} class scanner. - * - * @since 1.1 - */ - static class ModuleReferenceClassScanner { - - private final ClassFilter classFilter; - private final ClassLoader classLoader; - - ModuleReferenceClassScanner(ClassFilter classFilter, ClassLoader classLoader) { - this.classFilter = classFilter; - this.classLoader = classLoader; - } - - /** - * Scan module reference for classes that potentially contain testable methods. - */ - List> scan(ModuleReference reference) { - try (ModuleReader reader = reference.open()) { - try (Stream names = reader.list()) { - // @formatter:off - return names.filter(name -> name.endsWith(".class")) - .map(this::className) - .filter(name -> !name.equals("module-info")) - .filter(classFilter::match) - .map(this::loadClassUnchecked) - .filter(classFilter::match) - .collect(Collectors.toList()); - // @formatter:on - } - } - catch (IOException e) { - throw new JUnitException("Failed to read contents of " + reference + ".", e); - } - } - - /** - * Convert resource name to binary class name. - */ - private String className(String resourceName) { - resourceName = resourceName.substring(0, resourceName.length() - 6); // 6 = ".class".length() - resourceName = resourceName.replace('/', '.'); - return resourceName; - } - - /** - * Load class by its binary name. - * - * @see ClassLoader#loadClass(String) - */ - private Class loadClassUnchecked(String binaryName) { - try { - return classLoader.loadClass(binaryName); - } - catch (ClassNotFoundException e) { - throw new JUnitException("Failed to load class with name '" + binaryName + "'.", e); - } - } - - } - - /** - * {@link ModuleReference} resource class scanner. - * - * @since 1.11 - */ - static class ModuleReferenceResourceScanner { - - private final Predicate resourceFilter; - private final ClassLoader classLoader; - - ModuleReferenceResourceScanner(Predicate resourceFilter, ClassLoader classLoader) { - this.resourceFilter = resourceFilter; - this.classLoader = classLoader; - } - - /** - * Scan module reference for resources that potentially contain testable resources. - */ - List scan(ModuleReference reference) { - try (ModuleReader reader = reference.open()) { - try (Stream names = reader.list()) { - // @formatter:off - return names.filter(name -> !name.endsWith(".class")) - .map(this::loadResourceUnchecked) - .filter(resourceFilter) - .collect(Collectors.toList()); - // @formatter:on - } - } - catch (IOException e) { - throw new JUnitException("Failed to read contents of " + reference + ".", e); - } - } - - private Resource loadResourceUnchecked(String binaryName) { - try { - URI uri = classLoader.getResource(binaryName).toURI(); - return new DefaultResource(binaryName, uri); - } - catch (URISyntaxException e) { - throw new JUnitException("Failed to load resource with name '" + binaryName + "'.", e); - } - } - - } - -} diff --git a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/PackageNameUtils.java b/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/PackageNameUtils.java deleted file mode 100644 index 0cb6aec9e8d8..000000000000 --- a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/PackageNameUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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; - -/** - * Collection of utilities for working with package names. - * - *

DISCLAIMER

- * - *

These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.11.3 - */ -class PackageNameUtils { - - static String getPackageName(Class clazz) { - return clazz.getPackageName(); - } - -} diff --git a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ServiceLoaderUtils.java b/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ServiceLoaderUtils.java deleted file mode 100644 index db209116b615..000000000000 --- a/junit-platform-commons/src/main/java9/org/junit/platform/commons/util/ServiceLoaderUtils.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 java.util.ServiceLoader; -import java.util.function.Predicate; -import java.util.stream.Stream; - -import org.apiguardian.api.API; -import org.apiguardian.api.API.Status; - -/** - * Collection of utilities for working with {@link ServiceLoader}. - * - *

DISCLAIMER

- * - *

These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.11 - */ -@API(status = Status.INTERNAL, since = "1.11") -public class ServiceLoaderUtils { - - private ServiceLoaderUtils() { - /* no-op */ - } - - /** - * Filters the supplied service loader using the supplied predicate. - * - * @param the type of the service - * @param serviceLoader the service loader to be filtered - * @param providerPredicate the predicate to filter the loaded services - * @return a stream of loaded services that match the predicate - */ - public static Stream filter(ServiceLoader serviceLoader, - Predicate> providerPredicate) { - // @formatter:off - return serviceLoader - .stream() - .filter(provider -> providerPredicate.test(provider.type())) - .map(ServiceLoader.Provider::get); - // @formatter:on - } - -} diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index 99ed213d9837..2e30aaf527a9 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -86,12 +86,4 @@ tasks { )) } } - - // This jar contains some Java 9 code - // (org.junit.platform.console.ConsoleLauncherToolProvider which implements - // java.util.spi.ToolProvider which is @since 9). - // So in order to resolve this, it can only run on Java 9 - osgiProperties { - property("-runee", "JavaSE-9") - } } diff --git a/junit-platform-console/junit-platform-console.gradle.kts b/junit-platform-console/junit-platform-console.gradle.kts index cd256959b629..586b30004004 100644 --- a/junit-platform-console/junit-platform-console.gradle.kts +++ b/junit-platform-console/junit-platform-console.gradle.kts @@ -3,7 +3,6 @@ import junitbuild.java.UpdateJarAction plugins { id("junitbuild.java-library-conventions") id("junitbuild.shadow-conventions") - id("junitbuild.java-multi-release-sources") } description = "JUnit Platform Console" @@ -33,22 +32,17 @@ tasks { )) } shadowJar { - val release17ClassesDir = sourceSets.mainRelease17.get().output.classesDirs.singleFile - inputs.dir(release17ClassesDir).withPathSensitivity(PathSensitivity.RELATIVE) exclude("META-INF/versions/9/module-info.class") relocate("picocli", "org.junit.platform.console.shadow.picocli") from(projectDir) { include("LICENSE-picocli.md") into("META-INF") } - from(sourceSets.mainRelease9.get().output.classesDirs) doLast(objects.newInstance(UpdateJarAction::class).apply { javaLauncher = project.javaToolchains.launcherFor(java.toolchain) args.addAll( "--file", archiveFile.get().asFile.absolutePath, "--main-class", "org.junit.platform.console.ConsoleLauncher", - "--release", "17", - "-C", release17ClassesDir.absolutePath, "." ) }) } @@ -60,19 +54,4 @@ tasks { attributes("Main-Class" to "org.junit.platform.console.ConsoleLauncher") } } - - // This jar contains some Java 9 code - // (org.junit.platform.console.ConsoleLauncherToolProvider which implements - // java.util.spi.ToolProvider which is @since 9). - // So in order to resolve this, it can only run on Java 9 - osgiProperties { - property("-runee", "JavaSE-9") - } -} - -eclipse { - classpath { - sourceSets -= project.sourceSets.mainRelease9.get() - sourceSets -= project.sourceSets.mainRelease17.get() - } } diff --git a/junit-platform-console/src/main/java9/org/junit/platform/console/ConsoleLauncherToolProvider.java b/junit-platform-console/src/main/java/org/junit/platform/console/ConsoleLauncherToolProvider.java similarity index 100% rename from junit-platform-console/src/main/java9/org/junit/platform/console/ConsoleLauncherToolProvider.java rename to junit-platform-console/src/main/java/org/junit/platform/console/ConsoleLauncherToolProvider.java diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ConsoleUtils.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ConsoleUtils.java index 680e3381df6a..bd39bff687da 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ConsoleUtils.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ConsoleUtils.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.INTERNAL; +import java.io.Console; import java.nio.charset.Charset; import org.apiguardian.api.API; @@ -35,7 +36,8 @@ public class ConsoleUtils { * {@return the charset of the console} */ public static Charset charset() { - return Charset.defaultCharset(); + Console console = System.console(); + return console != null ? console.charset() : Charset.defaultCharset(); } } diff --git a/junit-platform-console/src/main/java17/org/junit/platform/console/options/ConsoleUtils.java b/junit-platform-console/src/main/java17/org/junit/platform/console/options/ConsoleUtils.java deleted file mode 100644 index 145ebed63fd4..000000000000 --- a/junit-platform-console/src/main/java17/org/junit/platform/console/options/ConsoleUtils.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * 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.console.options; - -import static org.apiguardian.api.API.Status.INTERNAL; - -import java.io.Console; -import java.nio.charset.Charset; - -import org.apiguardian.api.API; - -/** - * Collection of utilities for working with {@code java.io.Console} - * and friends. - * - *

DISCLAIMER

- * - *

These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.9 - */ -@API(status = INTERNAL, since = "1.9") -public class ConsoleUtils { - - /** - * {@return the charset of the console} - */ - public static Charset charset() { - Console console = System.console(); - return console != null ? console.charset() : Charset.defaultCharset(); - } -} diff --git a/junit-platform-jfr/junit-platform-jfr.gradle.kts b/junit-platform-jfr/junit-platform-jfr.gradle.kts index 0f03e2b99f86..8d82379addad 100644 --- a/junit-platform-jfr/junit-platform-jfr.gradle.kts +++ b/junit-platform-jfr/junit-platform-jfr.gradle.kts @@ -20,17 +20,7 @@ dependencies { osgiVerification(projects.junitPlatformLauncher) } -javaLibrary { - // --release 8 does not support jdk.jfr even though it was backported - configureRelease = false -} - tasks { - compileJava { - javaCompiler = project.javaToolchains.compilerFor { - languageVersion = JavaLanguageVersion.of(8) - } - } compileModule { options.release = 11 } diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 94bc99c60916..3052d2b52622 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -211,12 +211,12 @@ val test by testing.suites.getting(JvmTestSuite::class) { develocity { testDistribution { - requirements.add("jdk=8") + requirements.add("jdk=17") this as TestDistributionConfigurationInternal preferredMaxDuration = Duration.ofMillis(500) } } - jvmArgumentProviders += JavaHomeDir(project, 8, develocity.testDistribution.enabled) + jvmArgumentProviders += JavaHomeDir(project, 17, develocity.testDistribution.enabled) jvmArgumentProviders += JavaHomeDir(project, 17, develocity.testDistribution.enabled) val gradleJavaVersion = JavaVersion.current().majorVersion.toInt() diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 0fef24865e1f..f58173e5d285 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -13,20 +13,20 @@ val jupiterVersion: String by project val platformVersion: String by project dependencies { - testImplementation(kotlin("stdlib-jdk8")) + testImplementation(kotlin("stdlib")) testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") testRuntimeOnly("org.junit.platform:junit-platform-launcher:$platformVersion") } java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(17) } } tasks.withType().configureEach { kotlinOptions { - jvmTarget = "1.8" + jvmTarget = "17" apiVersion = "1.6" languageVersion = "1.6" } diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle.properties b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle.properties index 79b428ebc70c..bed2250e4577 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle.properties +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JDK8 +org.gradle.java.installations.fromEnv=JDK17 diff --git a/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts index 50b4e7b2924b..0e7c2e9ac3b3 100644 --- a/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(17) } } diff --git a/platform-tooling-support-tests/projects/gradle-missing-engine/gradle.properties b/platform-tooling-support-tests/projects/gradle-missing-engine/gradle.properties index 79b428ebc70c..bed2250e4577 100644 --- a/platform-tooling-support-tests/projects/gradle-missing-engine/gradle.properties +++ b/platform-tooling-support-tests/projects/gradle-missing-engine/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JDK8 +org.gradle.java.installations.fromEnv=JDK17 diff --git a/platform-tooling-support-tests/projects/java-versions/pom.xml b/platform-tooling-support-tests/projects/java-versions/pom.xml deleted file mode 100644 index 664c9092e437..000000000000 --- a/platform-tooling-support-tests/projects/java-versions/pom.xml +++ /dev/null @@ -1,63 +0,0 @@ - - - 4.0.0 - - platform.tooling.support.tests - java-versions - 1.0-SNAPSHOT - - - UTF-8 - - - - - org.junit.jupiter - junit-jupiter-engine - ${junit.jupiter.version} - test - - - org.junit.platform - junit-platform-commons - ${junit.platform.version} - test - - - - - - - - maven-compiler-plugin - 3.14.0 - - 1.8 - 1.8 - - - - maven-surefire-plugin - 3.5.3 - - - - - - - - local-temp - file://${maven.repo} - - true - ignore - - - true - ignore - - - - - diff --git a/platform-tooling-support-tests/projects/java-versions/src/test/java/JUnitPlatformCommonsTests.java b/platform-tooling-support-tests/projects/java-versions/src/test/java/JUnitPlatformCommonsTests.java deleted file mode 100644 index 7e7a888bdd6b..000000000000 --- a/platform-tooling-support-tests/projects/java-versions/src/test/java/JUnitPlatformCommonsTests.java +++ /dev/null @@ -1,37 +0,0 @@ - -/* - * 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 - */ -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.DisabledOnJre; -import org.junit.jupiter.api.condition.EnabledOnJre; -import org.junit.jupiter.api.condition.JRE; -import org.junit.platform.commons.util.ModuleUtils; - -class JUnitPlatformCommonsTests { - - @Test - @EnabledOnJre(JRE.JAVA_8) - void onJava8() { - assertFalse(ModuleUtils.isJavaPlatformModuleSystemAvailable()); - assertFalse(ModuleUtils.getModuleName(Object.class).isPresent()); - } - - @Test - @DisabledOnJre(JRE.JAVA_8) - void onJava9OrHigher() { - assertTrue(ModuleUtils.isJavaPlatformModuleSystemAvailable()); - assertEquals("java.base", ModuleUtils.getModuleName(Object.class).orElseThrow(Error::new)); - } - -} diff --git a/platform-tooling-support-tests/projects/jupiter-starter/gradle.properties b/platform-tooling-support-tests/projects/jupiter-starter/gradle.properties index 35b90dc7fdf0..bed2250e4577 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/gradle.properties +++ b/platform-tooling-support-tests/projects/jupiter-starter/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JDK8,JDK17 +org.gradle.java.installations.fromEnv=JDK17 diff --git a/platform-tooling-support-tests/projects/jupiter-starter/pom.xml b/platform-tooling-support-tests/projects/jupiter-starter/pom.xml index 5fa4fdabaebb..95b03c224a57 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/pom.xml +++ b/platform-tooling-support-tests/projects/jupiter-starter/pom.xml @@ -9,8 +9,7 @@ UTF-8 - 1.8 - ${maven.compiler.source} + 17 ${junit.platform.version} diff --git a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml index 47aba716ed6a..0bf039f4fdad 100644 --- a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml +++ b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml @@ -9,8 +9,7 @@ UTF-8 - 1.8 - ${maven.compiler.source} + 17 diff --git a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts index 0dea5aab80a1..88cc4dff4bb4 100644 --- a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts +++ b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts @@ -18,7 +18,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(17) } } diff --git a/platform-tooling-support-tests/projects/reflection-tests/gradle.properties b/platform-tooling-support-tests/projects/reflection-tests/gradle.properties index 79b428ebc70c..bed2250e4577 100644 --- a/platform-tooling-support-tests/projects/reflection-tests/gradle.properties +++ b/platform-tooling-support-tests/projects/reflection-tests/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JDK8 +org.gradle.java.installations.fromEnv=JDK17 diff --git a/platform-tooling-support-tests/projects/vintage/build.gradle.kts b/platform-tooling-support-tests/projects/vintage/build.gradle.kts index 37bab7448d5b..efa61d4ac9c1 100644 --- a/platform-tooling-support-tests/projects/vintage/build.gradle.kts +++ b/platform-tooling-support-tests/projects/vintage/build.gradle.kts @@ -26,7 +26,7 @@ dependencies { java { toolchain { - languageVersion = JavaLanguageVersion.of(8) + languageVersion = JavaLanguageVersion.of(17) } } diff --git a/platform-tooling-support-tests/projects/vintage/gradle.properties b/platform-tooling-support-tests/projects/vintage/gradle.properties index 79b428ebc70c..bed2250e4577 100644 --- a/platform-tooling-support-tests/projects/vintage/gradle.properties +++ b/platform-tooling-support-tests/projects/vintage/gradle.properties @@ -1 +1 @@ -org.gradle.java.installations.fromEnv=JDK8 +org.gradle.java.installations.fromEnv=JDK17 diff --git a/platform-tooling-support-tests/projects/vintage/pom.xml b/platform-tooling-support-tests/projects/vintage/pom.xml index 74d0ef2dc367..a39aa5987391 100644 --- a/platform-tooling-support-tests/projects/vintage/pom.xml +++ b/platform-tooling-support-tests/projects/vintage/pom.xml @@ -9,8 +9,7 @@ UTF-8 - 1.8 - ${maven.compiler.source} + 17 diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java index 001e02c5bddc..7ba598b5da41 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java @@ -65,7 +65,7 @@ void nonExistingJdkVersionYieldsAnEmptyOptional() { } @ParameterizedTest - @ValueSource(ints = 8) + @ValueSource(ints = 17) void checkJavaHome(int version) { var home = Helper.getJavaHome(version); assumeTrue(home.isPresent(), "No 'jdk' element found in Maven toolchain for: " + version); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleKotlinExtensionsTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleKotlinExtensionsTests.java index 750f628ceeb2..1891b8225213 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleKotlinExtensionsTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleKotlinExtensionsTests.java @@ -36,7 +36,7 @@ void gradle_wrapper(@TempDir Path workspace, @FilePrefix("gradle") OutputFiles o .workingDir(copyToWorkspace(Projects.GRADLE_KOTLIN_EXTENSIONS, workspace)) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail") // - .putEnvironment("JDK8", Helper.getJavaHome(8).orElseThrow(TestAbortedException::new).toString()) // + .putEnvironment("JDK17", Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // .redirectOutput(outputFiles) // .startAndWait(); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleMissingEngineTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleMissingEngineTests.java index e70d548761c6..846a41c6adf9 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleMissingEngineTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleMissingEngineTests.java @@ -37,7 +37,7 @@ void gradle_wrapper(@TempDir Path workspace, @FilePrefix("gradle") OutputFiles o .workingDir(copyToWorkspace(Projects.GRADLE_MISSING_ENGINE, workspace)) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail") // - .putEnvironment("JDK8", Helper.getJavaHome(8).orElseThrow(TestAbortedException::new).toString()) // + .putEnvironment("JDK17", Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // .redirectOutput(outputFiles).startAndWait(); assertEquals(1, result.exitCode()); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java index c79c2b4e54f4..ca5b03192965 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java @@ -46,7 +46,7 @@ void jupiterAggregatorGradleModuleMetadataVariants() throws Exception { " \"attributes\": {", // " \"org.gradle.category\": \"library\",", // " \"org.gradle.dependency.bundling\": \"external\",", // - " \"org.gradle.jvm.version\": 8,", // + " \"org.gradle.jvm.version\": 17,", // " \"org.gradle.libraryelements\": \"jar\",", // " \"org.gradle.usage\": \"java-api\"", // " },", // @@ -88,7 +88,7 @@ void jupiterAggregatorGradleModuleMetadataVariants() throws Exception { " \"attributes\": {", // " \"org.gradle.category\": \"library\",", // " \"org.gradle.dependency.bundling\": \"external\",", // - " \"org.gradle.jvm.version\": 8,", // + " \"org.gradle.jvm.version\": 17,", // " \"org.gradle.libraryelements\": \"jar\",", // " \"org.gradle.usage\": \"java-runtime\"", // " },", // diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleStarterTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleStarterTests.java index 02b7a6c26861..62ad2b94cd6d 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleStarterTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleStarterTests.java @@ -24,8 +24,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.tests.process.OutputFiles; import org.junit.platform.tests.process.ProcessResult; import org.opentest4j.TestAbortedException; @@ -49,12 +47,10 @@ void prepareWorkspace() throws Exception { copyToWorkspace(Projects.JUPITER_STARTER, workspace); } - @ParameterizedTest(name = "Java {0}") - @ValueSource(ints = { 8, 17 }) - void buildJupiterStarterProject(int javaVersion, @FilePrefix("gradle") OutputFiles outputFiles, Snapshot snapshot) - throws Exception { + @Test + void buildJupiterStarterProject(@FilePrefix("gradle") OutputFiles outputFiles, Snapshot snapshot) throws Exception { - var result = runGradle(outputFiles, javaVersion, "build"); + var result = runGradle(outputFiles, "build"); assertThat(result.stdOut()) // .contains( // @@ -64,7 +60,7 @@ void buildJupiterStarterProject(int javaVersion, @FilePrefix("gradle") OutputFil "CalculatorParameterizedClassTests > [2] i=2 > parameterizedTest(int)", // "CalculatorParameterizedClassTests > [2] i=2 > Inner > [1] 1 > regularTest() PASSED", // "CalculatorParameterizedClassTests > [2] i=2 > Inner > [2] 2 > regularTest() PASSED", // - "Using Java version: " + (javaVersion == 8 ? "1.8" : javaVersion), // + "Using Java version: 17", // "CalculatorTests > 1 + 1 = 2 PASSED", // "CalculatorTests > add(int, int, int) > 0 + 1 = 1 PASSED", // "CalculatorTests > add(int, int, int) > 1 + 2 = 3 PASSED", // @@ -79,7 +75,7 @@ void buildJupiterStarterProject(int javaVersion, @FilePrefix("gradle") OutputFil @Test void runOnlyOneMethodInClassTemplate(@FilePrefix("gradle") OutputFiles outputFiles) throws Exception { - var result = runGradle(outputFiles, 8, "test", "--tests", "CalculatorParameterized*.regular*"); + var result = runGradle(outputFiles, "test", "--tests", "CalculatorParameterized*.regular*"); assertThat(result.stdOut()) // .contains( // @@ -90,7 +86,7 @@ void runOnlyOneMethodInClassTemplate(@FilePrefix("gradle") OutputFiles outputFil ) // .doesNotContain("parameterizedTest(int)", "CalculatorTests"); - result = runGradle(outputFiles, 8, "test", "--tests", "*ParameterizedClassTests.parameterized*"); + result = runGradle(outputFiles, "test", "--tests", "*ParameterizedClassTests.parameterized*"); assertThat(result.stdOut()) // .contains( // @@ -100,16 +96,14 @@ void runOnlyOneMethodInClassTemplate(@FilePrefix("gradle") OutputFiles outputFil .doesNotContain("regularTest()", "CalculatorTests"); } - private ProcessResult runGradle(OutputFiles outputFiles, int javaVersion, String... extraArgs) - throws InterruptedException { + private ProcessResult runGradle(OutputFiles outputFiles, String... extraArgs) throws InterruptedException { var result = ProcessStarters.gradlew() // .workingDir(workspace) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // - .addArguments("-Djava.toolchain.version=" + javaVersion) // + .addArguments("-Djava.toolchain.version=17") // .addArguments("--stacktrace", "--no-build-cache", "--warning-mode=fail") // - .addArguments(extraArgs) // - .putEnvironment("JDK8", Helper.getJavaHome(8).orElseThrow(TestAbortedException::new).toString()) // - .putEnvironment("JDK17", Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // + .addArguments(extraArgs).putEnvironment("JDK17", + Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // .redirectOutput(outputFiles) // .startAndWait(); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java deleted file mode 100644 index e2316b2520d6..000000000000 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JavaVersionsTests.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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 platform.tooling.support.tests; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static platform.tooling.support.ProcessStarters.currentJdkHome; -import static platform.tooling.support.tests.Projects.copyToWorkspace; - -import java.nio.file.Path; -import java.util.List; -import java.util.Map; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.condition.JRE; -import org.junit.jupiter.api.io.TempDir; -import org.junit.platform.tests.process.OutputFiles; - -import platform.tooling.support.Helper; -import platform.tooling.support.MavenRepo; -import platform.tooling.support.ProcessStarters; - -/** - * @since 1.4 - */ -class JavaVersionsTests { - - @ManagedResource - LocalMavenRepo localMavenRepo; - - @TempDir - Path workspace; - - @Test - void java_8(@FilePrefix("maven") OutputFiles outputFiles) throws Exception { - var java8Home = Helper.getJavaHome(8); - assumeTrue(java8Home.isPresent(), "Java 8 installation directory not found!"); - var actualLines = execute(java8Home.get(), outputFiles, Map.of()); - - assertTrue(actualLines.contains("[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1")); - } - - @Test - void java_default(@FilePrefix("maven") OutputFiles outputFiles) throws Exception { - var actualLines = execute(currentJdkHome(), outputFiles, MavenEnvVars.forJre(JRE.currentJre())); - - assertTrue(actualLines.contains("[WARNING] Tests run: 2, Failures: 0, Errors: 0, Skipped: 1")); - } - - List execute(Path javaHome, OutputFiles outputFiles, Map environmentVars) throws Exception { - var result = ProcessStarters.maven(javaHome) // - .workingDir(copyToWorkspace(Projects.JAVA_VERSIONS, workspace)) // - .putEnvironment(environmentVars) // - .addArguments(localMavenRepo.toCliArgument(), "-Dmaven.repo=" + MavenRepo.dir()) // - .addArguments("--update-snapshots", "--batch-mode", "verify") // - .startAndWait(); - - assertEquals(0, result.exitCode()); - assertEquals("", result.stdErr()); - return result.stdOutLines(); - } - -} diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java index d215ca8e99c0..335053898a13 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java @@ -56,10 +56,8 @@ void manifestEntriesAdhereToConventions(String module) throws Exception { assertValue(attributes, "Bundle-SymbolicName", module); assertValue(attributes, "Bundle-Version", MavenVersion.parseMavenString(version).getOSGiVersion().toString()); - switch (module) { - case "junit-platform-commons" -> assertValue(attributes, "Multi-Release", "true"); - case "junit-platform-console" -> assertValue(attributes, "Main-Class", - "org.junit.platform.console.ConsoleLauncher"); + if (module.equals("junit-platform-console")) { + assertValue(attributes, "Main-Class", "org.junit.platform.console.ConsoleLauncher"); } var domain = Domain.domain(manifest); domain.getExportPackage().forEach((pkg, attrs) -> { diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenStarterTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenStarterTests.java index 03eb57945fa2..1a998b2c96a2 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenStarterTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenStarterTests.java @@ -58,7 +58,7 @@ void verifyJupiterStarterProject(@FilePrefix("maven") OutputFiles outputFiles, S var result = runMaven(outputFiles, "verify"); assertThat(result.stdOutLines()).contains("[INFO] Tests run: 13, Failures: 0, Errors: 0, Skipped: 0"); - assertThat(result.stdOut()).contains("Using Java version: 1.8"); + assertThat(result.stdOut()).contains("Using Java version: 17"); var testResultsDir = workspace.resolve("target/surefire-reports"); verifyContainsExpectedStartedOpenTestReport(testResultsDir, snapshot); @@ -81,7 +81,7 @@ void runOnlyOneMethodInClassTemplate(@FilePrefix("maven") OutputFiles outputFile } private ProcessResult runMaven(OutputFiles outputFiles, String... extraArgs) throws InterruptedException { - var result = ProcessStarters.maven(Helper.getJavaHome(8).orElseThrow(TestAbortedException::new)) // + var result = ProcessStarters.maven(Helper.getJavaHome(17).orElseThrow(TestAbortedException::new)) // .workingDir(workspace) // .addArguments(localMavenRepo.toCliArgument(), "-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Dsnapshot.repo.url=" + mavenRepoProxy.getBaseUri()) // diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java index 5228ed35b8e7..f627406bb5a2 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java @@ -44,7 +44,7 @@ class MavenSurefireCompatibilityTests { void testMavenSurefireCompatibilityProject(String surefireVersion, String extraArg, @TempDir Path workspace, @FilePrefix("maven") OutputFiles outputFiles) throws Exception { var extraArgs = extraArg == null ? new String[0] : new String[] { extraArg }; - var result = ProcessStarters.maven(Helper.getJavaHome(8).orElseThrow(TestAbortedException::new)) // + var result = ProcessStarters.maven(Helper.getJavaHome(17).orElseThrow(TestAbortedException::new)) // .workingDir(copyToWorkspace(Projects.MAVEN_SUREFIRE_COMPATIBILITY, workspace)) // .addArguments(localMavenRepo.toCliArgument(), "-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Dsurefire.version=" + surefireVersion) // diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ReflectionCompatibilityTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ReflectionCompatibilityTests.java index 1eb8272082bb..86e2b2d96390 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ReflectionCompatibilityTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ReflectionCompatibilityTests.java @@ -37,12 +37,12 @@ void gradle_wrapper(@TempDir Path workspace, @FilePrefix("gradle") OutputFiles o .workingDir(copyToWorkspace(Projects.REFLECTION_TESTS, workspace)) // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("build", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail") // - .putEnvironment("JDK8", Helper.getJavaHome(8).orElseThrow(TestAbortedException::new).toString()) // + .putEnvironment("JDK17", Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // .redirectOutput(outputFiles) // .startAndWait(); assertEquals(0, result.exitCode()); assertTrue(result.stdOut().lines().anyMatch(line -> line.contains("BUILD SUCCESSFUL"))); - assertThat(result.stdOut()).contains("Using Java version: 1.8"); + assertThat(result.stdOut()).contains("Using Java version: 17"); } } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java index a86b65a8aa51..d53b4d911959 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java @@ -158,7 +158,7 @@ void compile(@FilePrefix("javac") OutputFiles javacOutputFiles) throws Exception var result = ProcessStarters.javaCommand("javac") // .workingDir(workspace) // .addArguments("-Xlint:-options") // - .addArguments("--release", "8") // + .addArguments("--release", "17") // .addArguments("-proc:none") // .addArguments("-d", workspace.resolve("bin").toString()) // .addArguments("--class-path", MavenRepo.jar("junit-platform-console-standalone").toString()) // @@ -425,9 +425,9 @@ void execute(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exc @Test @Order(4) @Execution(SAME_THREAD) - void executeOnJava8(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exception { - var java8Home = Helper.getJavaHome(8).orElseThrow(TestAbortedException::new); - var result = ProcessStarters.java(java8Home) // + void executeOnJava17(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exception { + var javaHome = Helper.getJavaHome(17).orElseThrow(TestAbortedException::new); + var result = ProcessStarters.java(javaHome) // .workingDir(workspace) // .addArguments("-showversion") // .addArguments("-enableassertions") // @@ -445,7 +445,7 @@ void executeOnJava8(@FilePrefix("console-launcher") OutputFiles outputFiles) thr assertEquals(1, result.exitCode()); var expectedOutLines = Files.readAllLines(workspace.resolve("expected-out.txt")); - var expectedErrLines = getExpectedErrLinesOnJava8(workspace); + var expectedErrLines = getExpectedErrLinesOnJava17(workspace); assertLinesMatch(expectedOutLines, result.stdOutLines()); assertLinesMatch(expectedErrLines, result.stdErrLines()); @@ -461,9 +461,9 @@ void executeOnJava8(@FilePrefix("console-launcher") OutputFiles outputFiles) thr @Order(5) @Execution(SAME_THREAD) // https://github.com/junit-team/junit5/issues/2600 - void executeOnJava8SelectPackage(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exception { - var java8Home = Helper.getJavaHome(8).orElseThrow(TestAbortedException::new); - var result = ProcessStarters.java(java8Home) // + void executeOnJava17SelectPackage(@FilePrefix("console-launcher") OutputFiles outputFiles) throws Exception { + var javaHome = Helper.getJavaHome(17).orElseThrow(TestAbortedException::new); + var result = ProcessStarters.java(javaHome) // .workingDir(workspace).addArguments("-showversion") // .addArguments("-enableassertions") // .addArguments("-Djava.util.logging.config.file=logging.properties") // @@ -480,7 +480,7 @@ void executeOnJava8SelectPackage(@FilePrefix("console-launcher") OutputFiles out assertEquals(1, result.exitCode()); var expectedOutLines = Files.readAllLines(workspace.resolve("expected-out.txt")); - var expectedErrLines = getExpectedErrLinesOnJava8(workspace); + var expectedErrLines = getExpectedErrLinesOnJava17(workspace); assertLinesMatch(expectedOutLines, result.stdOutLines()); assertLinesMatch(expectedErrLines, result.stdErrLines()); @@ -492,7 +492,7 @@ void executeOnJava8SelectPackage(@FilePrefix("console-launcher") OutputFiles out + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); } - private static List getExpectedErrLinesOnJava8(Path workspace) throws IOException { + private static List getExpectedErrLinesOnJava17(Path workspace) throws IOException { var expectedErrLines = new ArrayList(); expectedErrLines.add(">> JAVA VERSION >>"); expectedErrLines.addAll(Files.readAllLines(workspace.resolve("expected-err.txt"))); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java index ab84f6f83392..372f1d2f5fee 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/UnalignedClasspathTests.java @@ -67,7 +67,7 @@ void verifyErrorMessageForUnalignedClasspath(JRE jre, Path javaHome, @TempDir Pa static Stream javaVersions() { return Stream.concat( // - Helper.getJavaHome(8).map(path -> Arguments.of(JRE.JAVA_8, path)).stream(), // + Helper.getJavaHome(17).map(path -> Arguments.of(JRE.JAVA_17, path)).stream(), // Stream.of(Arguments.of(JRE.currentJre(), currentJdkHome())) // ); } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageGradleIntegrationTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageGradleIntegrationTests.java index 92d88ef4ab91..35c64f2b2be5 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageGradleIntegrationTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageGradleIntegrationTests.java @@ -59,7 +59,7 @@ void supportedVersions(String version, @FilePrefix("gradle") OutputFiles outputF private ProcessResult run(OutputFiles outputFiles, String version) throws Exception { return ProcessStarters.gradlew() // .workingDir(copyToWorkspace(Projects.VINTAGE, workspace)) // - .putEnvironment("JDK8", Helper.getJavaHome(8).orElseThrow(TestAbortedException::new).toString()) // + .putEnvironment("JDK17", Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // .addArguments("build", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail") // .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("-Djunit4Version=" + version) // diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageMavenIntegrationTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageMavenIntegrationTests.java index 4b2d909f28c6..ca5d9bc800a4 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageMavenIntegrationTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/VintageMavenIntegrationTests.java @@ -62,7 +62,7 @@ void supportedVersions(String version, @FilePrefix("maven") OutputFiles outputFi } private ProcessResult run(OutputFiles outputFiles, String version) throws Exception { - return ProcessStarters.maven(Helper.getJavaHome(8).orElseThrow(TestAbortedException::new)) // + return ProcessStarters.maven(Helper.getJavaHome(17).orElseThrow(TestAbortedException::new)) // .workingDir(copyToWorkspace(Projects.VINTAGE, workspace)) // .addArguments("clean", "test", "--update-snapshots", "--batch-mode") // .addArguments(localMavenRepo.toCliArgument(), "-Dmaven.repo=" + MavenRepo.dir()) // From ef2a250316f7c5b54c3dd87b15546fd0e86b8992 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 17 Jan 2025 17:02:42 +0100 Subject: [PATCH 002/521] Fix Vintage test fixture compilation using Groovy 2.x --- .github/actions/setup-test-jdk/action.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/actions/setup-test-jdk/action.yml b/.github/actions/setup-test-jdk/action.yml index f417044940cd..068010d5d97d 100644 --- a/.github/actions/setup-test-jdk/action.yml +++ b/.github/actions/setup-test-jdk/action.yml @@ -9,6 +9,13 @@ runs: using: "composite" steps: - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 + with: + distribution: ${{ inputs.distribution }} + java-version: 8 + check-latest: true + - shell: bash + run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV + - uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4 with: distribution: ${{ inputs.distribution }} java-version: 17 From f07c28df92948915e46dfc12dd6bd8fbd24dab2d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 14:21:09 +0100 Subject: [PATCH 003/521] Add initial 6.0.0-M1 release notes from template --- .../docs/asciidoc/release-notes/index.adoc | 2 + .../release-notes/release-notes-6.0.0-M1.adoc | 86 +++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index c17df220c575..b31c979490bc 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-6.0.0-M1.adoc[] + include::{basedir}/release-notes-5.13.0-RC1.adoc[] include::{basedir}/release-notes-5.13.0-M3.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc new file mode 100644 index 000000000000..34b669feff8d --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -0,0 +1,86 @@ +[[release-notes-6.0.0-M1]] +== 6.0.0-M1 + +*Date of Release:* ❓ + +*Scope:* ❓ + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit5-repo}+/milestone/87?closed=1+[6.0.0-M1] milestone page in the JUnit +repository on GitHub. + + +[[release-notes-6.0.0-M1-overall-improvements]] +=== Overall Improvements + +[[release-notes-6.0.0-M1-overall-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-M1-overall-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* Minimum required Java version is now Java 17. + +[[release-notes-6.0.0-M1-overall-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-M1-junit-platform]] +=== JUnit Platform + +[[release-notes-6.0.0-M1-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-M1-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-M1-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-6.0.0-M1-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-M1-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-6.0.0-M1-junit-vintage]] +=== JUnit Vintage + +[[release-notes-6.0.0-M1-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-6.0.0-M1-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-6.0.0-M1-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ From 6602fa6b6353d16d461083d2dd5d3d4608b5f4ae Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 15:26:02 +0100 Subject: [PATCH 004/521] Use lazy configuration APIs --- .../src/main/kotlin/JavaLibraryExtension.kt | 16 ++++-- ...tbuild.java-library-conventions.gradle.kts | 56 ++++++++----------- ...uild.kotlin-library-conventions.gradle.kts | 23 +++----- .../junitbuild.osgi-conventions.gradle.kts | 4 +- platform-tests/platform-tests.gradle.kts | 2 +- 5 files changed, 47 insertions(+), 54 deletions(-) diff --git a/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt b/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt index 9cc28076bbc4..122dccc585ff 100644 --- a/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt +++ b/gradle/plugins/common/src/main/kotlin/JavaLibraryExtension.kt @@ -1,7 +1,15 @@ import org.gradle.api.JavaVersion +import org.gradle.api.provider.Property + +@Suppress("LeakingThis") +abstract class JavaLibraryExtension { + + abstract val mainJavaVersion: Property + abstract val testJavaVersion: Property + + init { + mainJavaVersion.convention(JavaVersion.VERSION_17) + testJavaVersion.convention(JavaVersion.VERSION_21) + } -open class JavaLibraryExtension { - var mainJavaVersion: JavaVersion = JavaVersion.VERSION_17 - var testJavaVersion: JavaVersion = JavaVersion.VERSION_21 - var configureRelease: Boolean = true } 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 96b3b1b06bbc..c6412c6a6792 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 @@ -276,47 +276,39 @@ tasks.compileTestJava { )) } -afterEvaluate { - configurations { - apiElements { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.majorVersion.toInt()) - } - } - runtimeElements { - attributes { - attribute(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.majorVersion.toInt()) - } +configurations { + apiElements { + attributes { + attributeProvider(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.map { it.majorVersion.toInt() }) } } - tasks { - compileJava { - if (extension.configureRelease) { - options.release = extension.mainJavaVersion.majorVersion.toInt() - } else { - sourceCompatibility = extension.mainJavaVersion.majorVersion - targetCompatibility = extension.mainJavaVersion.majorVersion - } - } - compileTestJava { - if (extension.configureRelease) { - options.release = extension.testJavaVersion.majorVersion.toInt() - } else { - sourceCompatibility = extension.testJavaVersion.majorVersion - targetCompatibility = extension.testJavaVersion.majorVersion - } + runtimeElements { + attributes { + attributeProvider(TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE, extension.mainJavaVersion.map { it.majorVersion.toInt() }) } } +} + +tasks { + compileJava { + options.release = extension.mainJavaVersion.map { it.majorVersion.toInt() } + } + compileTestJava { + options.release = extension.testJavaVersion.map { it.majorVersion.toInt() } + } +} + +afterEvaluate { pluginManager.withPlugin("groovy") { tasks.named("compileGroovy").configure { // Groovy compiler does not support the --release flag. - sourceCompatibility = extension.mainJavaVersion.majorVersion - targetCompatibility = extension.mainJavaVersion.majorVersion + sourceCompatibility = extension.mainJavaVersion.get().majorVersion + targetCompatibility = extension.mainJavaVersion.get().majorVersion } tasks.named("compileTestGroovy").configure { // Groovy compiler does not support the --release flag. - sourceCompatibility = extension.testJavaVersion.majorVersion - targetCompatibility = extension.testJavaVersion.majorVersion + sourceCompatibility = extension.testJavaVersion.get().majorVersion + targetCompatibility = extension.testJavaVersion.get().majorVersion } } } @@ -335,6 +327,6 @@ pluginManager.withPlugin("java-test-fixtures") { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) } tasks.named("compileTestFixturesJava") { - options.release = extension.testJavaVersion.majorVersion.toInt() + options.release = extension.testJavaVersion.map { it.majorVersion.toInt() } } } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts index 73680fcf6e6d..43c09c0d7b7c 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts @@ -11,26 +11,19 @@ tasks.named("kotlinSourcesJar") { enabled = false } +val javaLibraryExtension = project.the() + tasks.withType().configureEach { compilerOptions { + jvmTarget = javaLibraryExtension.mainJavaVersion.map { JvmTarget.fromTarget(it.toString()) } apiVersion = KotlinVersion.fromVersion("1.6") languageVersion = apiVersion - allWarningsAsErrors = false - // Compiler arg is required for Kotlin 1.6 and below - // see https://kotlinlang.org/docs/whatsnew17.html#stable-opt-in-requirements - freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn") + allWarningsAsErrors.convention(true) + javaParameters = true + freeCompilerArgs.addAll("-Xsuppress-version-warnings", "-opt-in=kotlin.RequiresOptIn") } } -afterEvaluate { - val extension = project.the() - tasks { - withType().configureEach { - compilerOptions.jvmTarget = JvmTarget.fromTarget(extension.mainJavaVersion.toString()) - compilerOptions.javaParameters = true - } - named("compileTestKotlin") { - compilerOptions.jvmTarget = JvmTarget.fromTarget(extension.testJavaVersion.toString()) - } - } +tasks.named("compileTestKotlin") { + compilerOptions.jvmTarget = javaLibraryExtension.testJavaVersion.map { JvmTarget.fromTarget(it.toString()) } } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts index d1adaa09ff68..03514d7e967a 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts @@ -79,8 +79,8 @@ tasks.withType().named { val osgiProperties by tasks.registering(WriteProperties::class) { destinationFile = layout.buildDirectory.file("verifyOSGiProperties.bndrun") property("-standalone", true) - project.extensions.getByType(JavaLibraryExtension::class.java).let { javaLibrary -> - property("-runee", "JavaSE-${javaLibrary.mainJavaVersion}") + project.extensions.getByType(JavaLibraryExtension::class).let { javaLibrary -> + property("-runee", Callable { "JavaSE-${javaLibrary.mainJavaVersion.get()}" }) } property("-runrequires", "osgi.identity;filter:='(osgi.identity=${project.name})'") property("-runsystempackages", "jdk.internal.misc,jdk.jfr,sun.misc") diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index 3e63fe5fe14f..3d849832f844 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -132,7 +132,7 @@ tasks { dependsOn(testWoodstox) } named(processStarter.compileJavaTaskName).configure { - options.release = javaLibrary.testJavaVersion.majorVersion.toInt() + options.release = javaLibrary.testJavaVersion.map { it.majorVersion.toInt() } } named("checkstyle${processStarter.name.capitalized()}").configure { config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleMain.xml")) From a6b79829554d6470eb2d0245568ac007cf11b531 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 15:27:39 +0100 Subject: [PATCH 005/521] Bump Kotlin API and language version to 2.1 --- .../kotlin/junitbuild.kotlin-library-conventions.gradle.kts | 4 ++-- junit-jupiter-api/junit-jupiter-api.gradle.kts | 4 ++++ .../projects/gradle-kotlin-extensions/build.gradle.kts | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts index 43c09c0d7b7c..3b66e92f1e96 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts @@ -1,5 +1,5 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget -import org.jetbrains.kotlin.gradle.dsl.KotlinVersion +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { @@ -16,7 +16,7 @@ val javaLibraryExtension = project.the() tasks.withType().configureEach { compilerOptions { jvmTarget = javaLibraryExtension.mainJavaVersion.map { JvmTarget.fromTarget(it.toString()) } - apiVersion = KotlinVersion.fromVersion("1.6") + apiVersion = KOTLIN_2_1 languageVersion = apiVersion allWarningsAsErrors.convention(true) javaParameters = true diff --git a/junit-jupiter-api/junit-jupiter-api.gradle.kts b/junit-jupiter-api/junit-jupiter-api.gradle.kts index 402b5323eb57..7932c998c884 100644 --- a/junit-jupiter-api/junit-jupiter-api.gradle.kts +++ b/junit-jupiter-api/junit-jupiter-api.gradle.kts @@ -22,6 +22,10 @@ dependencies { } tasks { + compileKotlin { + // https://github.com/junit-team/junit5/issues/4371 + compilerOptions.allWarningsAsErrors = false + } jar { bundle { val version = project.version diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index f58173e5d285..0280fff30753 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -27,8 +27,8 @@ java { tasks.withType().configureEach { kotlinOptions { jvmTarget = "17" - apiVersion = "1.6" - languageVersion = "1.6" + apiVersion = "2.1" + languageVersion = "2.1" } } From e5bf215e4802a69ae382cffa38eeada27e589be7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 15:28:50 +0100 Subject: [PATCH 006/521] Resolve most Kotlin compiler warnings --- .../kotlin/org/junit/jupiter/api/Assertions.kt | 17 +++++++++++------ .../params/aggregator/DisplayNameTests.kt | 10 +++++----- 2 files changed, 16 insertions(+), 11 deletions(-) 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..44c13138a03d 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 @@ -17,7 +17,6 @@ import org.apiguardian.api.API.Status.STABLE import org.junit.jupiter.api.function.Executable import org.junit.jupiter.api.function.ThrowingSupplier import java.time.Duration -import java.util.function.Supplier import java.util.stream.Stream import kotlin.contracts.ExperimentalContracts import kotlin.contracts.InvocationKind.AT_MOST_ONCE @@ -43,7 +42,7 @@ fun fail(message: () -> String): Nothing { callsInPlace(message, EXACTLY_ONCE) } - return Assertions.fail(message) + return Assertions.fail(message()) } /** @@ -334,7 +333,7 @@ inline fun assertThrows( throw throwable } }, - Supplier(message) + message ) } @@ -404,18 +403,24 @@ inline fun assertDoesNotThrow( return Assertions.assertDoesNotThrow( evaluateAndWrap(executable), - Supplier(message) + message ) } +@OptIn(ExperimentalContracts::class) @PublishedApi -internal inline fun evaluateAndWrap(executable: () -> R): ThrowingSupplier = - try { +internal inline fun evaluateAndWrap(executable: () -> R): ThrowingSupplier { + contract { + callsInPlace(executable, EXACTLY_ONCE) + } + + return try { val result = executable() ThrowingSupplier { result } } catch (throwable: Throwable) { ThrowingSupplier { throw throwable } } +} /** * Example usage: diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/params/aggregator/DisplayNameTests.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/params/aggregator/DisplayNameTests.kt index 6a1f91cbb19f..00d0b2e167a7 100644 --- a/jupiter-tests/src/test/kotlin/org/junit/jupiter/params/aggregator/DisplayNameTests.kt +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/params/aggregator/DisplayNameTests.kt @@ -21,11 +21,11 @@ object DisplayNameTests { @JvmStatic fun data() = arrayOf( - arrayOf("A", 1), - arrayOf("B", 2), - arrayOf("C", 3), - arrayOf("", 4), // empty is okay - arrayOf(null, 5) // null was the problem + arrayOf("A", 1), + arrayOf("B", 2), + arrayOf("C", 3), + arrayOf("", 4), // empty is okay + arrayOf(null, 5) // null was the problem ) @ParameterizedTest From aa46b51706e50b2bcd5a777d6e76ddbd72486284 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 19:17:54 +0100 Subject: [PATCH 007/521] Fix test --- .../gradle-kotlin-extensions/build.gradle.kts | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 0280fff30753..8a6d5e258b7c 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -1,4 +1,6 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 +import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 plugins { kotlin("jvm") version "2.1.20" @@ -25,10 +27,11 @@ java { } tasks.withType().configureEach { - kotlinOptions { - jvmTarget = "17" - apiVersion = "2.1" - languageVersion = "2.1" + compilerOptions { + jvmTarget = JVM_17 + apiVersion = KOTLIN_2_1 + languageVersion = KOTLIN_2_1 + freeCompilerArgs.addAll("-Xskip-prerelease-check") } } From 0a32dcc41128143beed9a91929d8d97a1488ce04 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 5 Mar 2025 20:03:57 +0100 Subject: [PATCH 008/521] Configure OpenRewrite plugin Run with: ./gradlew rewriteRun --no-parallel --- gradle/libs.versions.toml | 1 + gradle/plugins/common/build.gradle.kts | 1 + .../junitbuild.java-library-conventions.gradle.kts | 10 ++++++++++ 3 files changed, 12 insertions(+) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 95679e033664..947103352f8b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -101,6 +101,7 @@ jmh = { id = "me.champeau.jmh", version = "0.7.3" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.20" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.1.7" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "6.25.0" } diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 48c05c7f0a80..00a24d40003b 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -10,6 +10,7 @@ dependencies { implementation(libs.plugins.develocity.markerCoordinates) implementation(libs.plugins.foojayResolver.markerCoordinates) implementation(libs.plugins.jmh.markerCoordinates) + implementation(libs.plugins.openrewrite.markerCoordinates) implementation(libs.plugins.shadow.markerCoordinates) implementation(libs.plugins.spotless.markerCoordinates) implementation(libs.plugins.versions.markerCoordinates) 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 c6412c6a6792..ae09fab5dfa7 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 @@ -14,6 +14,16 @@ plugins { id("junitbuild.build-parameters") id("junitbuild.checkstyle-conventions") id("junitbuild.jacoco-java-conventions") + id("org.openrewrite.rewrite") +} + +rewrite { + activeRecipe("org.openrewrite.java.migrate.UpgradeToJava17") +} + +dependencies { + rewrite(platform("org.openrewrite.recipe:rewrite-recipe-bom:latest.release")) + rewrite("org.openrewrite.recipe:rewrite-migrate-java") } val mavenizedProjects: List by rootProject.extra From b27e970099d6b3f37e449bc526f3aa31434fead3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 6 Mar 2025 21:47:08 +0100 Subject: [PATCH 009/521] Remove no longer needed suppression --- .../kotlin/junitbuild.kotlin-library-conventions.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts index 3b66e92f1e96..083de1511d7a 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts @@ -20,7 +20,7 @@ tasks.withType().configureEach { languageVersion = apiVersion allWarningsAsErrors.convention(true) javaParameters = true - freeCompilerArgs.addAll("-Xsuppress-version-warnings", "-opt-in=kotlin.RequiresOptIn") + freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn") } } From 7cec9b11a1bc1b7fcb89fcd101abcc01939981a8 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 14 Apr 2025 12:21:44 +0200 Subject: [PATCH 010/521] Bump and align versions to 6.0.0-SNAPSHOT --- .github/workflows/release.yml | 5 +-- RELEASING.md | 4 +- documentation/documentation.gradle.kts | 8 +--- .../junit-platform-reporting.adoc | 10 ++--- .../user-guide/advanced-topics/testkit.adoc | 2 +- .../docs/asciidoc/user-guide/appendix.adoc | 8 ++-- .../asciidoc/user-guide/running-tests.adoc | 38 +++++++++---------- gradle.properties | 11 +----- ...nitbuild.publishing-conventions.gradle.kts | 17 +++------ .../junit-jupiter-engine.gradle.kts | 3 +- ...nit-platform-console-standalone.gradle.kts | 7 +--- .../core/ClasspathAlignmentChecker.java | 11 +----- .../junit-vintage-engine.gradle.kts | 3 +- .../projects/graalvm-starter/build.gradle.kts | 12 +++--- .../gradle-kotlin-extensions/build.gradle.kts | 7 ++-- .../gradle-missing-engine/build.gradle.kts | 7 ++-- .../junit-jupiter-api.expected.txt | 2 +- .../junit-jupiter-engine.expected.txt | 2 +- ...unit-jupiter-migrationsupport.expected.txt | 2 +- .../junit-jupiter-params.expected.txt | 2 +- .../junit-jupiter.expected.txt | 2 +- .../junit-platform-commons.expected.txt | 2 +- .../junit-platform-console.expected.txt | 2 +- .../junit-platform-engine.expected.txt | 2 +- .../junit-platform-jfr.expected.txt | 2 +- .../junit-platform-launcher.expected.txt | 2 +- .../junit-platform-reporting.expected.txt | 2 +- .../junit-platform-runner.expected.txt | 2 +- .../junit-platform-suite-api.expected.txt | 2 +- .../junit-platform-suite-commons.expected.txt | 2 +- .../junit-platform-suite-engine.expected.txt | 2 +- .../junit-platform-suite.expected.txt | 2 +- .../junit-platform-testkit.expected.txt | 2 +- .../junit-vintage-engine.expected.txt | 2 +- .../projects/jupiter-starter/build.gradle.kts | 7 ++-- .../projects/jupiter-starter/pom.xml | 4 +- .../maven-surefire-compatibility/pom.xml | 2 +- .../projects/multi-release-jar/pom.xml | 4 +- .../reflection-tests/build.gradle.kts | 9 ++--- .../projects/vintage/build.gradle.kts | 7 ++-- .../projects/vintage/pom.xml | 2 +- .../java/platform/tooling/support/Helper.java | 13 +------ .../platform/tooling/support/MavenRepo.java | 2 +- .../tooling/support/ProcessStarters.java | 9 +---- .../platform/tooling/support/HelperTests.java | 4 +- .../support/tests/JarDescribeModuleTests.java | 4 +- .../tooling/support/tests/ManifestTests.java | 2 +- .../support/tests/StandaloneTests.java | 33 ++++++---------- 48 files changed, 109 insertions(+), 182 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5b363033f4b7..94cd2bfc792e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -248,16 +248,13 @@ jobs: with: script: | const releaseVersion = "${{ github.event.inputs.releaseVersion }}"; - const jupiterVersion = releaseVersion; - const vintageVersion = releaseVersion; - const platformVersion = "1." + releaseVersion.substring(2); const requestBody = { owner: context.repo.owner, repo: context.repo.repo, tag_name: `r${releaseVersion}`, name: `JUnit ${releaseVersion}`, generate_release_notes: true, - body: `JUnit ${jupiterVersion} = Platform ${platformVersion} + Jupiter ${jupiterVersion} + Vintage ${vintageVersion}\n\nSee [Release Notes](https://junit.org/junit5/docs/${releaseVersion}/release-notes/).`, + body: `JUnit ${releaseVersion} = Platform ${releaseVersion} + Jupiter ${releaseVersion} + Vintage ${releaseVersion}\n\nSee [Release Notes](https://junit.org/junit5/docs/${releaseVersion}/release-notes/).`, prerelease: releaseVersion.includes("-"), }; console.log(requestBody); diff --git a/RELEASING.md b/RELEASING.md index bdbb753eba27..35f3b3e6c522 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -3,13 +3,13 @@ ## Pre-release steps - [ ] Switch or create the release branch for this feature release (e.g. `releases/5.12.x`) -- [ ] Change `version`, `platformVersion`, and `vintageVersion` in `gradle.properties` to the versions about to be released +- [ ] Change `version` in `gradle.properties` to the versions about to be released - [ ] Change release date in Release Notes - [ ] Change release date in `README.MD` - [ ] Commit with message "Release ${VERSION}" - [ ] Execute `./gradlew --no-build-cache --no-configuration-cache clean build publish closeSonatypeStagingRepository` - [ ] Tag current commit: `git tag -s -m ${VERSION} r${VERSION}` -- [ ] Change `version`, `platformVersion`, and `vintageVersion` properties in `gradle.properties` on release branch to new development versions and commit with message "Back to snapshots for further development" or similar +- [ ] Change `version` in `gradle.properties` on release branch to new development versions and commit with message "Back to snapshots for further development" or similar - [ ] Push release branch and tag to GitHub: `git push --set-upstream --follow-tags origin HEAD` - [ ] Trigger a [release build](https://github.com/junit-team/junit5/actions/workflows/release.yml): `gh workflow run --ref r${VERSION} -f releaseVersion=${VERSION} -f stagingRepoId=orgjunit-1234 release.yml` - Select the release branch diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 9fccf43eea7f..bcc1d0203766 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -295,15 +295,9 @@ tasks { // Temporary workaround for https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/599 inputs.dir(sourceDir).withPropertyName("sourceDir").withPathSensitivity(RELATIVE) - val platformVersion: String by project - val vintageVersion: String by project - attributeProviders += AsciidoctorAttributeProvider { mapOf( - "jupiter-version" to version, - "platform-version" to platformVersion, - "vintage-version" to vintageVersion, - "bom-version" to version, + "version" to version, "junit4-version" to libs.versions.junit4.get(), "apiguardian-version" to libs.versions.apiguardian.get(), "ota4j-version" to libs.versions.opentest4j.get(), diff --git a/documentation/src/docs/asciidoc/user-guide/advanced-topics/junit-platform-reporting.adoc b/documentation/src/docs/asciidoc/user-guide/advanced-topics/junit-platform-reporting.adoc index 79f67cc42404..fc3384dae01b 100644 --- a/documentation/src/docs/asciidoc/user-guide/advanced-topics/junit-platform-reporting.adoc +++ b/documentation/src/docs/asciidoc/user-guide/advanced-topics/junit-platform-reporting.adoc @@ -63,7 +63,7 @@ using Gradle's Build Cache. .Groovy DSL ---- dependencies { - testRuntimeOnly("org.junit.platform:junit-platform-reporting:{platform-version}") + testRuntimeOnly("org.junit.platform:junit-platform-reporting:{version}") } tasks.withType(Test).configureEach { def outputDir = reports.junitXml.outputLocation @@ -81,7 +81,7 @@ tasks.withType(Test).configureEach { .Kotlin DSL ---- dependencies { - testRuntimeOnly("org.junit.platform:junit-platform-reporting:{platform-version}") + testRuntimeOnly("org.junit.platform:junit-platform-reporting:{version}") } tasks.withType().configureEach { val outputDir = reports.junitXml.outputLocation @@ -109,7 +109,7 @@ XML reports as follows: org.junit.platform junit-platform-reporting - {platform-version} + {version} test @@ -140,7 +140,7 @@ output by setting the configuration parameters via `--config`: [source,console,subs=attributes+] ---- -$ java -jar junit-platform-console-standalone-{platform-version}.jar \ +$ java -jar junit-platform-console-standalone-{version}.jar \ --config=junit.platform.reporting.open.xml.enabled=true \ --config=junit.platform.reporting.output.dir=reports ---- @@ -150,7 +150,7 @@ classpath resource via the `--config-resource` option: [source,console,subs=attributes+] ---- -$ java -jar junit-platform-console-standalone-{platform-version}.jar \ +$ java -jar junit-platform-console-standalone-{version}.jar \ --config-resource=configuration.properties ---- diff --git a/documentation/src/docs/asciidoc/user-guide/advanced-topics/testkit.adoc b/documentation/src/docs/asciidoc/user-guide/advanced-topics/testkit.adoc index 3f134f3f8ba1..7d79da360376 100644 --- a/documentation/src/docs/asciidoc/user-guide/advanced-topics/testkit.adoc +++ b/documentation/src/docs/asciidoc/user-guide/advanced-topics/testkit.adoc @@ -5,7 +5,7 @@ The `junit-platform-testkit` artifact provides support for executing a test plan on the JUnit Platform and then verifying the expected results. As of JUnit Platform -{platform-version}, this support is limited to the execution of a single `TestEngine` (see +{version}, this support is limited to the execution of a single `TestEngine` (see <>). [[testkit-engine]] diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index 9df8622629d5..25fa10af297f 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -45,7 +45,7 @@ Please refer to the corresponding sections for < org.junit junit-bom - {bom-version} + {version} pom import @@ -160,7 +160,7 @@ versions of all JUnit 5 artifacts. .Explicit platform dependency on the BOM ---- dependencies { - testImplementation(platform("org.junit:junit-bom:{bom-version}")) + testImplementation(platform("org.junit:junit-bom:{version}")) testImplementation("org.junit.jupiter:junit-jupiter") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } @@ -181,7 +181,7 @@ artifacts. .Implicit platform dependency on the BOM ---- dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:{jupiter-version}") // <1> + testImplementation("org.junit.jupiter:junit-jupiter:{version}") // <1> testRuntimeOnly("org.junit.platform:junit-platform-launcher") // <2> } ---- @@ -212,7 +212,7 @@ on the dependency-aggregating JUnit Jupiter artifact similar to the following. [subs=attributes+] ---- dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:{jupiter-version}") + testImplementation("org.junit.jupiter:junit-jupiter:{version}") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } ---- @@ -228,7 +228,7 @@ support. testing { suites { named("test") { - useJUnitJupiter("{jupiter-version}") + useJUnitJupiter("{version}") } } } @@ -241,7 +241,7 @@ testing { testing { suites { test { - useJUnitJupiter("{jupiter-version}") + useJUnitJupiter("{version}") } } } @@ -256,7 +256,7 @@ implementation similar to the following. ---- dependencies { testImplementation("junit:junit:{junit4-version}") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:{vintage-version}") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:{version}") testRuntimeOnly("org.junit.platform:junit-platform-launcher") } ---- @@ -337,7 +337,7 @@ Maven build as follows. org.junit.platform junit-platform-launcher - {platform-version} + {version} test ---- @@ -358,7 +358,7 @@ versions of all JUnit 5 artifacts. org.junit junit-bom - {bom-version} + {version} pom import @@ -391,7 +391,7 @@ following. org.junit.jupiter junit-jupiter - {jupiter-version} + {version} test @@ -430,7 +430,7 @@ long as you configure `test` scoped dependencies on JUnit 4 and the JUnit Vintag org.junit.vintage junit-vintage-engine - {vintage-version} + {version} test @@ -659,7 +659,7 @@ With Gradle you can override the JUnit Jupiter version by including the followin [source,groovy,indent=0] [subs=attributes+] ---- - ext['junit-jupiter.version'] = '{jupiter-version}' + ext['junit-jupiter.version'] = '{version}' ---- With Maven you can override the JUnit Jupiter version by including the following in your @@ -669,7 +669,7 @@ With Maven you can override the JUnit Jupiter version by including the following [subs=attributes+] ---- - {jupiter-version} + {version} ---- @@ -680,7 +680,7 @@ The `{ConsoleLauncher}` is a command-line Java application that lets you launch Platform from the console. For example, it can be used to run JUnit Vintage and JUnit Jupiter tests and print test execution results to the console. -An executable _Fat JAR_ (`junit-platform-console-standalone-{platform-version}.jar`) that +An executable _Fat JAR_ (`junit-platform-console-standalone-{version}.jar`) that contains the contents of all of its dependencies is published in the {Maven_Central} repository under the https://repo1.maven.org/maven2/org/junit/platform/junit-platform-console-standalone[junit-platform-console-standalone] @@ -711,7 +711,7 @@ standalone `ConsoleLauncher` as shown below. [source,console,subs=attributes+] ---- -$ java -jar junit-platform-console-standalone-{platform-version}.jar execute +$ java -jar junit-platform-console-standalone-{version}.jar execute ├─ JUnit Vintage │ └─ example.JUnit4Tests @@ -820,7 +820,7 @@ files using the `--redirect-stdout` and `--redirect-stderr` options: [source,console,subs=attributes+] ---- -$ java -jar junit-platform-console-standalone-{platform-version}.jar \ +$ java -jar junit-platform-console-standalone-{version}.jar \ --redirect-stdout=stdout.txt \ --redirect-stderr=stderr.txt ---- @@ -1255,7 +1255,7 @@ to a problem. In order to record Flight Recorder events generated while running tests, you need to: 1. Ensure that you are using either Java 8 Update 262 or higher or Java 11 or later. -2. Provide the `org.junit.platform.jfr` module (`junit-platform-jfr-{platform-version}.jar`) +2. Provide the `org.junit.platform.jfr` module (`junit-platform-jfr-{version}.jar`) on the class-path or module-path at test runtime. 3. Start flight recording when launching a test run. Flight Recorder can be started via java command line option: diff --git a/gradle.properties b/gradle.properties index 6e27e89740d2..000b32c34896 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,13 +1,4 @@ -group = org.junit -version = 5.13.0-SNAPSHOT - -jupiterGroup = org.junit.jupiter - -platformGroup = org.junit.platform -platformVersion = 1.13.0-SNAPSHOT - -vintageGroup = org.junit.vintage -vintageVersion = 5.13.0-SNAPSHOT +version = 6.0.0-SNAPSHOT # 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/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.publishing-conventions.gradle.kts index 90146181e380..0885637fe791 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 @@ -9,18 +9,11 @@ val jupiterProjects: List by rootProject val platformProjects: List by rootProject val vintageProjects: List by rootProject -when (project) { - in jupiterProjects -> { - group = property("jupiterGroup")!! - } - in platformProjects -> { - group = property("platformGroup")!! - version = property("platformVersion")!! - } - in vintageProjects -> { - group = property("vintageGroup")!! - version = property("vintageVersion")!! - } +group = when (project) { + in jupiterProjects -> "org.junit.jupiter" + in platformProjects -> "org.junit.platform" + in vintageProjects -> "org.junit.vintage" + else -> "org.junit" } // ensure project is built successfully before publishing it diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 04d86e5f0da7..982117516e55 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -18,7 +18,6 @@ dependencies { tasks { jar { bundle { - val platformVersion: String by rootProject.extra bnd(""" Provide-Capability:\ org.junit.platform.engine;\ @@ -26,7 +25,7 @@ tasks { version:Version="${'$'}{version_cleanup;${project.version}}" Require-Capability:\ org.junit.platform.launcher;\ - filter:='(&(org.junit.platform.launcher=junit-platform-launcher)(version>=${'$'}{version_cleanup;${platformVersion}})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;${platformVersion}}})))';\ + filter:='(&(org.junit.platform.launcher=junit-platform-launcher)(version>=${'$'}{version_cleanup;${project.version}})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;${project.version}}})))';\ effective:=active """) } diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index 2e30aaf527a9..968d99fbe1eb 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -21,9 +21,6 @@ dependencies { osgiVerification(libs.openTestReporting.tooling.spi) } -val jupiterVersion = rootProject.version -val vintageVersion: String by project - tasks { jar { manifest { @@ -76,8 +73,8 @@ tasks { "Implementation-Title" to project.name, // Generate test engine version information in single shared manifest file. // Pattern of key and value: `"Engine-Version-{YourTestEngine#getId()}": "47.11"` - "Engine-Version-junit-jupiter" to jupiterVersion, - "Engine-Version-junit-vintage" to vintageVersion, + "Engine-Version-junit-jupiter" to project.version, + "Engine-Version-junit-vintage" to project.version, // Version-aware binaries are already included - set Multi-Release flag here. // See https://openjdk.java.net/jeps/238 for details // Note: the "jar --update ... --release X" command does not work with the diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 3b95f7153e6a..6f3fff9bed05 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -69,9 +69,6 @@ static Optional check(LinkageError error, Function { String version = pkg.getImplementationVersion(); if (version != null) { - if (pkg.getName().startsWith("org.junit.platform") && version.contains(".")) { - version = platformToJupiterVersion(version); - } packagesByVersions.computeIfAbsent(version, __ -> new ArrayList<>()).add(pkg); } }); @@ -83,8 +80,7 @@ static Optional check(LinkageError error, Function check(LinkageError error, Function=${'$'}{versionmask;+;${'$'}{version_cleanup;$platformVersion}})))';\ + filter:='(&(org.junit.platform.launcher=junit-platform-launcher)(version>=${'$'}{version_cleanup;$version})(!(version>=${'$'}{versionmask;+;${'$'}{version_cleanup;$version}})))';\ effective:=active """) } diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index 7bdc3af69a56..3ba8850b7fbf 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -3,9 +3,7 @@ plugins { id("org.graalvm.buildtools.native") } -val jupiterVersion: String by project -val platformVersion: String by project -val vintageVersion: String by project +val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } @@ -13,11 +11,11 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") testImplementation("junit:junit:4.13.2") - testImplementation("org.junit.platform:junit-platform-suite:$platformVersion") - testRuntimeOnly("org.junit.vintage:junit-vintage-engine:$vintageVersion") - testRuntimeOnly("org.junit.platform:junit-platform-reporting:$platformVersion") + testImplementation("org.junit.platform:junit-platform-suite:$junitVersion") + testRuntimeOnly("org.junit.vintage:junit-vintage-engine:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-reporting:$junitVersion") } tasks.test { diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 8a6d5e258b7c..2040dbfff8d3 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -11,13 +11,12 @@ repositories { mavenCentral() } -val jupiterVersion: String by project -val platformVersion: String by project +val junitVersion: String by project dependencies { testImplementation(kotlin("stdlib")) - testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") - testRuntimeOnly("org.junit.platform:junit-platform-launcher:$platformVersion") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitVersion") } java { diff --git a/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts index 0e7c2e9ac3b3..0e7612cf3be1 100644 --- a/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-missing-engine/build.gradle.kts @@ -2,8 +2,7 @@ plugins { java } -val jupiterVersion: String by project -val platformVersion: String by project +val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } @@ -11,10 +10,10 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter-api:$jupiterVersion") { + testImplementation("org.junit.jupiter:junit-jupiter-api:$junitVersion") { exclude(group = "org.junit.jupiter", module = "junit-jupiter-engine") } - testRuntimeOnly("org.junit.platform:junit-platform-launcher:$platformVersion")} + testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitVersion")} java { toolchain { diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt index 26719afdbe79..3819dc406164 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt @@ -1,4 +1,4 @@ -org.junit.jupiter.api@${jupiterVersion} jar:file:.+/junit-jupiter-api-\d.+\.jar..module-info\.class +org.junit.jupiter.api@${version} jar:file:.+/junit-jupiter-api-\d.+\.jar..module-info\.class exports org.junit.jupiter.api exports org.junit.jupiter.api.condition exports org.junit.jupiter.api.extension diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt index 5c637457863f..699fe7363234 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt @@ -1,4 +1,4 @@ -org.junit.jupiter.engine@${jupiterVersion} jar:file:.+/junit-jupiter-engine-\d.+\.jar..module-info\.class +org.junit.jupiter.engine@${version} jar:file:.+/junit-jupiter-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.jupiter.api diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt index 747125710426..4012e4139344 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt @@ -1,4 +1,4 @@ -org.junit.jupiter.migrationsupport@${jupiterVersion} jar:file:.+/junit-jupiter-migrationsupport-\d.+\.jar..module-info\.class +org.junit.jupiter.migrationsupport@${version} jar:file:.+/junit-jupiter-migrationsupport-\d.+\.jar..module-info\.class exports org.junit.jupiter.migrationsupport exports org.junit.jupiter.migrationsupport.conditions exports org.junit.jupiter.migrationsupport.rules diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt index 05e8b8ac4675..c23606354350 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt @@ -1,4 +1,4 @@ -org.junit.jupiter.params@${jupiterVersion} jar:file:.+/junit-jupiter-params-\d.+\.jar..module-info\.class +org.junit.jupiter.params@${version} jar:file:.+/junit-jupiter-params-\d.+\.jar..module-info\.class exports org.junit.jupiter.params exports org.junit.jupiter.params.aggregator exports org.junit.jupiter.params.converter diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter.expected.txt index 768342398c7e..11da5f5567bf 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter.expected.txt @@ -1,4 +1,4 @@ -org.junit.jupiter@${jupiterVersion} jar:file:.+/junit-jupiter-\d.+\.jar..module-info\.class +org.junit.jupiter@${version} jar:file:.+/junit-jupiter-\d.+\.jar..module-info\.class requires java.base mandated requires org.junit.jupiter.api transitive requires org.junit.jupiter.engine transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt index e8104a7e3dd8..4e06393f529f 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.commons@${platformVersion} jar:file:.+/junit-platform-commons-\d.+\.jar..module-info\.class +org.junit.platform.commons@${version} jar:file:.+/junit-platform-commons-\d.+\.jar..module-info\.class exports org.junit.platform.commons exports org.junit.platform.commons.annotation exports org.junit.platform.commons.function diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt index 4324e45eccfe..031b331cc0b3 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.console@${platformVersion} jar:file:.+/junit-platform-console-\d.+\.jar..module-info\.class +org.junit.platform.console@${version} jar:file:.+/junit-platform-console-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.platform.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt index 04812758a63f..2809c8a87fec 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.engine@${platformVersion} jar:file:.+/junit-platform-engine-\d.+\.jar..module-info\.class +org.junit.platform.engine@${version} jar:file:.+/junit-platform-engine-\d.+\.jar..module-info\.class exports org.junit.platform.engine exports org.junit.platform.engine.discovery exports org.junit.platform.engine.reporting diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt index 10bec3decdaf..bc727ca43cf6 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.jfr@${platformVersion} jar:file:.+/junit-platform-jfr-\d.+\.jar..module-info\.class +org.junit.platform.jfr@${version} jar:file:.+/junit-platform-jfr-\d.+\.jar..module-info\.class requires java.base mandated requires jdk.jfr requires org.apiguardian.api static 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 41bb2afac024..e8f16dfa1f46 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 @@ -1,4 +1,4 @@ -org.junit.platform.launcher@${platformVersion} jar:file:.+/junit-platform-launcher-\d.+\.jar..module-info\.class +org.junit.platform.launcher@${version} jar:file:.+/junit-platform-launcher-\d.+\.jar..module-info\.class exports org.junit.platform.launcher exports org.junit.platform.launcher.core exports org.junit.platform.launcher.listeners diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt index 2362fbb8152f..6bd9a8b227c3 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.reporting@${platformVersion} jar:file:.+/junit-platform-reporting-\d.+\.jar..module-info\.class +org.junit.platform.reporting@${version} jar:file:.+/junit-platform-reporting-\d.+\.jar..module-info\.class exports org.junit.platform.reporting.legacy exports org.junit.platform.reporting.legacy.xml exports org.junit.platform.reporting.open.xml diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt index ee4ae1791204..ea26b6302bce 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.runner@${platformVersion} jar:file:.+/junit-platform-runner-\d.+\.jar..module-info\.class +org.junit.platform.runner@${version} jar:file:.+/junit-platform-runner-\d.+\.jar..module-info\.class exports org.junit.platform.runner requires java.base mandated requires junit transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt index 5e3da71afa28..77c942f97f87 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.suite.api@${platformVersion} jar:file:.+/junit-platform-suite-api-\d.+\.jar..module-info\.class +org.junit.platform.suite.api@${version} jar:file:.+/junit-platform-suite-api-\d.+\.jar..module-info\.class exports org.junit.platform.suite.api requires java.base mandated requires org.apiguardian.api static transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt index 493962b6b97d..e818b5d1973e 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.suite.commons@${platformVersion} jar:file:.+/junit-platform-suite-commons-\d.+\.jar..module-info\.class +org.junit.platform.suite.commons@${version} jar:file:.+/junit-platform-suite-commons-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static transitive requires org.junit.platform.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt index 4a5694586dd4..cca1aba09043 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.suite.engine@${platformVersion} jar:file:.+/junit-platform-suite-engine-\d.+\.jar..module-info\.class +org.junit.platform.suite.engine@${version} jar:file:.+/junit-platform-suite-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static requires org.junit.platform.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite.expected.txt index d6114f727332..83276251b80b 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.suite@${platformVersion} jar:file:.+/junit-platform-suite-\d.+\.jar..module-info\.class +org.junit.platform.suite@${version} jar:file:.+/junit-platform-suite-\d.+\.jar..module-info\.class requires java.base mandated requires org.junit.platform.suite.api transitive requires org.junit.platform.suite.engine transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt index c530e1bf68f8..da43a9f5bd2c 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt @@ -1,4 +1,4 @@ -org.junit.platform.testkit@${platformVersion} jar:file:.+/junit-platform-testkit-\d.+\.jar..module-info\.class +org.junit.platform.testkit@${version} jar:file:.+/junit-platform-testkit-\d.+\.jar..module-info\.class exports org.junit.platform.testkit.engine requires java.base mandated requires org.apiguardian.api static transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt index 854b4981242a..f3b130c0aa8d 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt @@ -1,4 +1,4 @@ -org.junit.vintage.engine@${vintageVersion} jar:file:.+/junit-vintage-engine-\d.+\.jar..module-info\.class +org.junit.vintage.engine@${version} jar:file:.+/junit-vintage-engine-\d.+\.jar..module-info\.class requires java.base mandated requires junit requires org.apiguardian.api static diff --git a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts index 74e76f07d3c1..2714c5c41b51 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts @@ -2,8 +2,7 @@ plugins { java } -val jupiterVersion: String by project -val platformVersion: String by project +val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } @@ -11,8 +10,8 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") - testRuntimeOnly("org.junit.platform:junit-platform-reporting:$platformVersion") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-reporting:$junitVersion") } java { diff --git a/platform-tooling-support-tests/projects/jupiter-starter/pom.xml b/platform-tooling-support-tests/projects/jupiter-starter/pom.xml index 95b03c224a57..823e264d76f8 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/pom.xml +++ b/platform-tooling-support-tests/projects/jupiter-starter/pom.xml @@ -10,7 +10,7 @@ UTF-8 17 - ${junit.platform.version} + ${junit.version} @@ -37,7 +37,7 @@ org.junit junit-bom - ${junit.bom.version} + ${junit.version} pom import diff --git a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml index 0bf039f4fdad..ffdfb47af1f6 100644 --- a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml +++ b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml @@ -25,7 +25,7 @@ org.junit junit-bom - ${junit.bom.version} + ${junit.version} pom import diff --git a/platform-tooling-support-tests/projects/multi-release-jar/pom.xml b/platform-tooling-support-tests/projects/multi-release-jar/pom.xml index b9e4b86ed82f..4794ece6f303 100644 --- a/platform-tooling-support-tests/projects/multi-release-jar/pom.xml +++ b/platform-tooling-support-tests/projects/multi-release-jar/pom.xml @@ -15,13 +15,13 @@ org.junit.jupiter junit-jupiter-engine - ${junit.jupiter.version} + ${junit.version} test org.junit.platform junit-platform-reporting - ${junit.platform.version} + ${junit.version} test diff --git a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts index 88cc4dff4bb4..38982a672139 100644 --- a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts +++ b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts @@ -2,8 +2,7 @@ plugins { java } -val jupiterVersion: String by project -val platformVersion: String by project +val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } @@ -11,9 +10,9 @@ repositories { } dependencies { - testImplementation("org.junit.jupiter:junit-jupiter:$jupiterVersion") - testImplementation("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion") - testRuntimeOnly("org.junit.platform:junit-platform-reporting:$platformVersion") + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") + testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-reporting:$junitVersion") } java { diff --git a/platform-tooling-support-tests/projects/vintage/build.gradle.kts b/platform-tooling-support-tests/projects/vintage/build.gradle.kts index efa61d4ac9c1..4e959fcb8d7c 100644 --- a/platform-tooling-support-tests/projects/vintage/build.gradle.kts +++ b/platform-tooling-support-tests/projects/vintage/build.gradle.kts @@ -9,19 +9,18 @@ repositories { mavenCentral() } -val platformVersion: String by project -val vintageVersion: String by project +val junitVersion: String by project dependencies { val junit4Version = System.getProperty("junit4Version", "4.12") testImplementation("junit:junit:$junit4Version") - testImplementation("org.junit.vintage:junit-vintage-engine:$vintageVersion") { + testImplementation("org.junit.vintage:junit-vintage-engine:$junitVersion") { exclude(group = "junit") because("we want to override it to test against different versions") } - testRuntimeOnly("org.junit.platform:junit-platform-launcher:$platformVersion") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitVersion") } java { diff --git a/platform-tooling-support-tests/projects/vintage/pom.xml b/platform-tooling-support-tests/projects/vintage/pom.xml index a39aa5987391..e4219de31c9b 100644 --- a/platform-tooling-support-tests/projects/vintage/pom.xml +++ b/platform-tooling-support-tests/projects/vintage/pom.xml @@ -16,7 +16,7 @@ org.junit.vintage junit-vintage-engine - ${junit.vintage.version} + ${junit.version} test diff --git a/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java b/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java index 0841181a1903..e6df0bafa2fa 100644 --- a/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java +++ b/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java @@ -41,17 +41,8 @@ public class Helper { } } - public static String version(String module) { - if (module.startsWith("junit-jupiter")) { - return gradleProperties.getProperty("version"); - } - if (module.startsWith("junit-platform")) { - return gradleProperties.getProperty("platformVersion"); - } - if (module.startsWith("junit-vintage")) { - return gradleProperties.getProperty("vintageVersion"); - } - throw new AssertionError("Unknown module: " + module); + public static String version() { + return gradleProperties.getProperty("version"); } public static List loadModuleDirectoryNames() { diff --git a/platform-tooling-support-tests/src/main/java/platform/tooling/support/MavenRepo.java b/platform-tooling-support-tests/src/main/java/platform/tooling/support/MavenRepo.java index d5ebac39bc92..d7b3ea0cfaf4 100644 --- a/platform-tooling-support-tests/src/main/java/platform/tooling/support/MavenRepo.java +++ b/platform-tooling-support-tests/src/main/java/platform/tooling/support/MavenRepo.java @@ -47,7 +47,7 @@ private static Path artifact(String artifactId, Predicate fileNamePredic var parentDir = dir() // .resolve(groupId(artifactId).replace('.', File.separatorChar)) // .resolve(artifactId) // - .resolve(Helper.version(artifactId)); + .resolve(Helper.version()); try (var files = Files.list(parentDir)) { return files.filter( file -> fileNamePredicate.test(file.getFileName().toString())).findFirst().orElseThrow(); diff --git a/platform-tooling-support-tests/src/main/java/platform/tooling/support/ProcessStarters.java b/platform-tooling-support-tests/src/main/java/platform/tooling/support/ProcessStarters.java index e2519e89f958..94df6091b784 100644 --- a/platform-tooling-support-tests/src/main/java/platform/tooling/support/ProcessStarters.java +++ b/platform-tooling-support-tests/src/main/java/platform/tooling/support/ProcessStarters.java @@ -47,9 +47,7 @@ public static ProcessStarter gradlew() { return new ProcessStarter() // .executable(Path.of("..").resolve(windowsOrOtherExecutable("gradlew.bat", "gradlew")).toAbsolutePath()) // .putEnvironment("JAVA_HOME", getGradleJavaHome().orElseThrow(TestAbortedException::new)) // - .addArguments("-PjupiterVersion=" + Helper.version("junit-jupiter")) // - .addArguments("-PvintageVersion=" + Helper.version("junit-vintage")) // - .addArguments("-PplatformVersion=" + Helper.version("junit-platform")); + .addArguments("-PjunitVersion=" + Helper.version()); } public static ProcessStarter maven() { @@ -61,10 +59,7 @@ public static ProcessStarter maven(Path javaHome) { .executable(Path.of(System.getProperty("mavenDistribution")).resolve("bin").resolve( windowsOrOtherExecutable("mvn.cmd", "mvn")).toAbsolutePath()) // .putEnvironment("JAVA_HOME", javaHome) // - .addArguments("-Djunit.jupiter.version=" + Helper.version("junit-jupiter")) // - .addArguments("-Djunit.bom.version=" + Helper.version("junit-jupiter")) // - .addArguments("-Djunit.vintage.version=" + Helper.version("junit-vintage")) // - .addArguments("-Djunit.platform.version=" + Helper.version("junit-platform")); + .addArguments("-Djunit.version=" + Helper.version()); } private static String windowsOrOtherExecutable(String cmdOrExe, String other) { diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java index 7ba598b5da41..594ab00b595a 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java @@ -54,9 +54,7 @@ void loadModuleDirectoryNames() { @Test void version() { - assertNotNull(Helper.version("junit-jupiter")); - assertNotNull(Helper.version("junit-vintage")); - assertNotNull(Helper.version("junit-platform")); + assertNotNull(Helper.version()); } @Test diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JarDescribeModuleTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JarDescribeModuleTests.java index 4a03dcd5270f..94de63eef317 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JarDescribeModuleTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/JarDescribeModuleTests.java @@ -65,9 +65,7 @@ void packageNamesStartWithNameOfTheModule(String module) { } private static String replaceVersionPlaceholders(String line) { - line = line.replace("${jupiterVersion}", Helper.version("junit-jupiter")); - line = line.replace("${vintageVersion}", Helper.version("junit-vintage")); - line = line.replace("${platformVersion}", Helper.version("junit-platform")); + line = line.replace("${version}", Helper.version()); return line; } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java index 335053898a13..ac1ee44b6139 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java @@ -39,7 +39,7 @@ class ManifestTests { @ParameterizedTest @MethodSource("platform.tooling.support.Helper#loadModuleDirectoryNames") void manifestEntriesAdhereToConventions(String module) throws Exception { - var version = Helper.version(module); + var version = Helper.version(); var jarFile = MavenRepo.jar(module).toFile(); try (var jar = new Jar(jarFile)) { var manifest = jar.getManifest(); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java index d53b4d911959..884485ce815d 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/StandaloneTests.java @@ -87,14 +87,11 @@ void listAllObservableEngines(@FilePrefix("java") OutputFiles outputFiles) throw assertEquals(0, result.exitCode()); - var jupiterVersion = Helper.version("junit-jupiter-engine"); - var suiteVersion = Helper.version("junit-platform-suite-engine"); - var vintageVersion = Helper.version("junit-vintage-engine"); assertLinesMatch(""" - junit-jupiter (org.junit.jupiter:junit-jupiter-engine:%s) - junit-platform-suite (org.junit.platform:junit-platform-suite-engine:%s) - junit-vintage (org.junit.vintage:junit-vintage-engine:%s) - """.formatted(jupiterVersion, suiteVersion, vintageVersion).lines(), // + junit-jupiter (org.junit.jupiter:junit-jupiter-engine:%1$s) + junit-platform-suite (org.junit.platform:junit-platform-suite-engine:%1$s) + junit-vintage (org.junit.vintage:junit-vintage-engine:%1$s) + """.formatted(Helper.version()).lines(), // result.stdOut().lines()); } @@ -110,7 +107,7 @@ void printVersionViaJar(@FilePrefix("java") OutputFiles outputFiles) throws Exce assertEquals(0, result.exitCode()); - var version = Helper.version("junit-platform-console"); + var version = Helper.version(); assertLinesMatch(""" JUnit Platform Console Launcher %s JVM: .* @@ -142,7 +139,7 @@ void printVersionViaModule(@FilePrefix("java") OutputFiles outputFiles) throws E assertEquals(0, result.exitCode()); - var version = Helper.version("junit-platform-console"); + var version = Helper.version(); assertLinesMatch(""" JUnit Platform Console Launcher %s JVM: .* @@ -449,12 +446,10 @@ void executeOnJava17(@FilePrefix("console-launcher") OutputFiles outputFiles) th assertLinesMatch(expectedOutLines, result.stdOutLines()); assertLinesMatch(expectedErrLines, result.stdErrLines()); - var jupiterVersion = Helper.version("junit-jupiter-engine"); - var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.stdErr().contains("junit-jupiter" - + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); + + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + Helper.version())); assertTrue(result.stdErr().contains("junit-vintage" - + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); + + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + Helper.version())); } @Test @@ -484,12 +479,10 @@ void executeOnJava17SelectPackage(@FilePrefix("console-launcher") OutputFiles ou assertLinesMatch(expectedOutLines, result.stdOutLines()); assertLinesMatch(expectedErrLines, result.stdErrLines()); - var jupiterVersion = Helper.version("junit-jupiter-engine"); - var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.stdErr().contains("junit-jupiter" - + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); + + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + Helper.version())); assertTrue(result.stdErr().contains("junit-vintage" - + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); + + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + Helper.version())); } private static List getExpectedErrLinesOnJava17(Path workspace) throws IOException { @@ -548,11 +541,9 @@ private static void assertOutputOnCurrentJvm(ProcessResult result) throws IOExce } assertLinesMatch(expectedErrLines, actualErrLines); - var jupiterVersion = Helper.version("junit-jupiter-engine"); - var vintageVersion = Helper.version("junit-vintage-engine"); assertTrue(result.stdErr().contains("junit-jupiter" - + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + jupiterVersion)); + + " (group ID: org.junit.jupiter, artifact ID: junit-jupiter-engine, version: " + Helper.version())); assertTrue(result.stdErr().contains("junit-vintage" - + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + vintageVersion)); + + " (group ID: org.junit.vintage, artifact ID: junit-vintage-engine, version: " + Helper.version())); } } From e0ce7cc0c8d0ba44b2453a74e0190a9eae19f65b Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 2 May 2025 14:35:28 +0200 Subject: [PATCH 011/521] Run builds and publish snapshots for commits on `develop/**` branches --- .github/workflows/codeql-analysis.yml | 2 ++ .github/workflows/cross-version.yml | 1 + .github/workflows/main.yml | 3 ++- .github/workflows/reproducible-build.yml | 1 + 4 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e27db6e3b99f..776a7169ba33 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,11 +5,13 @@ on: branches: - main - 'releases/**' + - 'develop/**' pull_request: # The branches below must be a subset of the branches above branches: - main - 'releases/**' + - 'develop/**' schedule: - cron: '0 19 * * 3' diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 7c51412feaaf..ad6f8b246011 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -7,6 +7,7 @@ on: branches: - main - 'releases/**' + - 'develop/**' pull_request: branches: - '**' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e41fbe61130b..740d34adf3fd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,6 +5,7 @@ on: branches: - main - 'releases/**' + - 'develop/**' tags-ignore: - '**' pull_request: @@ -76,7 +77,7 @@ jobs: permissions: attestations: write # required for build provenance attestation id-token: write # required for build provenance attestation - if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main') + if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || startsWith(github.ref, 'refs/heads/develop/') || github.ref == 'refs/heads/main') steps: - name: Check out repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 diff --git a/.github/workflows/reproducible-build.yml b/.github/workflows/reproducible-build.yml index 546ff5b9cd18..e717a7a71d5c 100644 --- a/.github/workflows/reproducible-build.yml +++ b/.github/workflows/reproducible-build.yml @@ -5,6 +5,7 @@ on: branches: - main - 'releases/**' + - 'develop/**' pull_request: branches: - '**' From ac3687a78369dcafc5d5cc7af5cc8e0fd8584d68 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 2 May 2025 14:41:36 +0200 Subject: [PATCH 012/521] Run Renovate also on `develop/.*` branches --- .github/renovate.json5 | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index ea024d3d17e6..d256a62d0f55 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -3,6 +3,7 @@ extends: [ 'github>junit-team/renovate-config', ], + baseBranches: ["main", "/^develop\\/.*/"], packageRules: [ { matchCurrentValue: '/^2\\./', From 6cebb319fe337fe7f6227ef018e09e396d1a8795 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 12:43:40 +0000 Subject: [PATCH 013/521] Update actions/setup-java digest to c5195ef --- .github/actions/setup-test-jdk/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/setup-test-jdk/action.yml b/.github/actions/setup-test-jdk/action.yml index 068010d5d97d..9e650112b77b 100644 --- a/.github/actions/setup-test-jdk/action.yml +++ b/.github/actions/setup-test-jdk/action.yml @@ -15,7 +15,7 @@ runs: check-latest: true - shell: bash run: echo "JDK8=$JAVA_HOME" >> $GITHUB_ENV - - uses: actions/setup-java@7a6d8a8234af8eb26422e24e3006232cccaa061b # v4 + - uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4 with: distribution: ${{ inputs.distribution }} java-version: 17 From b852e9fe53779cb1c6041d876bcc868a06f15c87 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 2 May 2025 15:36:42 +0200 Subject: [PATCH 014/521] Document version strategy change in release notes --- .../src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 1 + 1 file changed, 1 insertion(+) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 34b669feff8d..e10c51a19a2f 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -22,6 +22,7 @@ repository on GitHub. ==== Deprecations and Breaking Changes * Minimum required Java version is now Java 17. +* Platform, Jupiter, and Vintage artifacts now use the same version number. [[release-notes-6.0.0-M1-overall-new-features-and-improvements]] ==== New Features and Improvements From a1fd7019a6ae5093c943fcd493f8c9b7af9bb413 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 19:13:41 +0000 Subject: [PATCH 015/521] Update plugin openrewrite to v7.5.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 947103352f8b..85e93f9ce225 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -101,7 +101,7 @@ jmh = { id = "me.champeau.jmh", version = "0.7.3" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.20" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } -openrewrite = { id = "org.openrewrite.rewrite", version = "7.1.7" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.5.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "6.25.0" } From f1fa4883d2fdf46cef636b4976e6bea5e7fa24bb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 2 May 2025 22:46:13 +0000 Subject: [PATCH 016/521] Update plugin spotless to v7 (#4512) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 85e93f9ce225..c0a28472969c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -104,5 +104,5 @@ nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" openrewrite = { id = "org.openrewrite.rewrite", version = "7.5.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } -spotless = { id = "com.diffplug.spotless", version = "6.25.0" } +spotless = { id = "com.diffplug.spotless", version = "7.0.3" } versions = { id = "com.github.ben-manes.versions", version = "0.52.0" } From 9105adf57c2530a20a70d0a1b914624c6c6f4878 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 5 May 2025 14:59:39 +0200 Subject: [PATCH 017/521] Remove support for deprecated `ConsoleLauncher` options (#4513) * subcommand is now required * non-conventional options (e.g. `--h` and `-help`) are no longer supported --- .../release-notes/release-notes-6.0.0-M1.adoc | 5 +- .../asciidoc/user-guide/running-tests.adoc | 12 +- .../console/options/AnsiColorOptionMixin.java | 5 - .../console/options/BannerOptionMixin.java | 27 ---- .../platform/console/options/BaseCommand.java | 8 +- .../console/options/ExecuteTestsCommand.java | 5 +- .../platform/console/options/MainCommand.java | 72 ++-------- .../TestConsoleOutputOptionsMixin.java | 22 +-- .../options/TestDiscoveryOptionsMixin.java | 126 +++--------------- .../platform/console/ConsoleDetailsTests.java | 13 +- .../ConsoleLauncherIntegrationTests.java | 40 ++---- .../CommandLineOptionsParsingTests.java | 41 +----- 12 files changed, 72 insertions(+), 304 deletions(-) delete mode 100644 junit-platform-console/src/main/java/org/junit/platform/console/options/BannerOptionMixin.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index e10c51a19a2f..bbb734ec5650 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -41,7 +41,10 @@ repository on GitHub. [[release-notes-6.0.0-M1-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes -* ❓ +* Remove deprecated support for running the `ConsoleLauncher` without specifying a + subcommand. +* Remove support for deprecated non-conventional `ConsoleLauncher` options such as + `--h` (rather than `-h`) or `-help` (rather than `--help`). [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index 834ac7321805..980437f5eef1 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -748,12 +748,6 @@ all jars in a directory): $ java -cp classes:testlib/* org.junit.platform.console.ConsoleLauncher ---- -.Exit Code -NOTE: The `{ConsoleLauncher}` exits with a status code of `1` if any containers or tests -failed. If no tests are discovered and the `--fail-if-no-tests` command-line option is -supplied, the `ConsoleLauncher` exits with a status code of `2`. Otherwise, the exit code -is `0`. - [[running-tests-console-launcher-options]] ==== Subcommands and Options @@ -773,6 +767,12 @@ include::{consoleLauncherDiscoverOptionsFile}[] [[running-tests-console-launcher-options-executing-tests]] ===== Executing tests +.Exit Code +NOTE: The `{ConsoleLauncher}` exits with a status code of `1` if any containers or tests +failed. If no tests are discovered and the `--fail-if-no-tests` command-line option is +supplied, the `ConsoleLauncher` exits with a status code of `2`. Otherwise, the exit code +is `0`. + ---- include::{consoleLauncherExecuteOptionsFile}[] ---- diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/AnsiColorOptionMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/AnsiColorOptionMixin.java index 4e9ee00ee6ac..3467e3129f95 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/AnsiColorOptionMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/AnsiColorOptionMixin.java @@ -39,9 +39,4 @@ public void setDisableAnsiColors(boolean disableAnsiColors) { this.disableAnsiColors = disableAnsiColors; } - @Option(names = "-disable-ansi-colors", hidden = true) - public void setDisableAnsiColors2(boolean disableAnsiColors) { - setDisableAnsiColors(disableAnsiColors); - } - } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/BannerOptionMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/BannerOptionMixin.java deleted file mode 100644 index 813bb0937d29..000000000000 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/BannerOptionMixin.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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.console.options; - -import picocli.CommandLine.Option; - -class BannerOptionMixin { - - @Option(names = "--disable-banner", description = "Disable print out of the welcome message.") - private boolean disableBanner; - - @Option(names = "-disable-banner", hidden = true) - private boolean disableBanner2; - - public boolean isDisableBanner() { - return disableBanner || disableBanner2; - } - -} diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/BaseCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/BaseCommand.java index 5f904aa2d2f0..d9153ecc7a04 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/BaseCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/BaseCommand.java @@ -30,8 +30,8 @@ abstract class BaseCommand implements Callable { @Mixin AnsiColorOptionMixin ansiColorOption; - @Mixin - BannerOptionMixin bannerOption; + @Option(names = "--disable-banner", description = "Disable print out of the welcome message.") + private boolean disableBanner; @SuppressWarnings("unused") @Option(names = { "-h", "--help" }, usageHelp = true, description = "Display help information.") @@ -39,7 +39,7 @@ abstract class BaseCommand implements Callable { @SuppressWarnings("unused") @Option(names = "--version", versionHelp = true, description = "Display version information.") - private boolean versionHelpRequested; + private boolean versionRequested; void execute(String... args) { toCommandLine().execute(args); @@ -74,7 +74,7 @@ static CommandLine initialize(CommandLine commandLine) { @Override public final T call() { PrintWriter out = getOut(); - if (!bannerOption.isDisableBanner()) { + if (!disableBanner) { displayBanner(out); } try { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java index 079a1b740b12..2f592de24919 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java @@ -99,11 +99,8 @@ static class ReportingOptions { @CommandLine.Option(names = "--reports-dir", paramLabel = "DIR", description = "Enable report output into a specified local directory (will be created if it does not exist).") private Path reportsDir; - @CommandLine.Option(names = "-reports-dir", hidden = true) - private Path reportsDir2; - Optional getReportsDir() { - return reportsDir == null ? Optional.ofNullable(reportsDir2) : Optional.of(reportsDir); + return Optional.ofNullable(reportsDir); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java index 177a17913681..b04249508a16 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java @@ -10,27 +10,23 @@ package org.junit.platform.console.options; -import java.io.PrintWriter; -import java.util.ArrayList; -import java.util.List; import java.util.Optional; -import java.util.concurrent.Callable; import org.junit.platform.console.tasks.ConsoleTestExecutor; import picocli.CommandLine; import picocli.CommandLine.Command; -import picocli.CommandLine.Help.ColorScheme; import picocli.CommandLine.IExitCodeGenerator; import picocli.CommandLine.Mixin; import picocli.CommandLine.Model.CommandSpec; import picocli.CommandLine.Option; +import picocli.CommandLine.ParameterException; import picocli.CommandLine.Spec; -import picocli.CommandLine.Unmatched; @Command(// name = "junit", // abbreviateSynopsis = true, // + synopsisSubcommandLabel = "COMMAND", // sortOptions = false, // usageHelpWidth = 95, // showAtFileInUsageHelp = true, // @@ -44,25 +40,19 @@ exitCodeOnExecutionException = CommandResult.FAILURE, // versionProvider = ManifestVersionProvider.class // ) -class MainCommand implements Callable, IExitCodeGenerator { +class MainCommand implements Runnable, IExitCodeGenerator { private final ConsoleTestExecutor.Factory consoleTestExecutorFactory; @Option(names = { "-h", "--help" }, help = true, description = "Display help information.") private boolean helpRequested; - @Option(names = { "--h", "-help" }, help = true, hidden = true) - private boolean helpRequested2; - @Option(names = "--version", versionHelp = true, description = "Display version information.") - private boolean versionHelpRequested; + private boolean versionRequested; @Mixin AnsiColorOptionMixin ansiColorOption; - @Unmatched - private final List allParameters = new ArrayList<>(); - @Spec CommandSpec commandSpec; @@ -73,21 +63,18 @@ class MainCommand implements Callable, IExitCodeGenerator { } @Override - public Object call() { - if (helpRequested || helpRequested2) { + public void run() { + if (helpRequested) { commandSpec.commandLine().usage(commandSpec.commandLine().getOut()); commandResult = CommandResult.success(); - return null; } - if (versionHelpRequested) { + else if (versionRequested) { commandSpec.commandLine().printVersionHelp(commandSpec.commandLine().getOut()); commandResult = CommandResult.success(); - return null; } - if (allParameters.contains("--list-engines")) { - return runCommand("engines", Optional.of("--list-engines")); + else { + throw new ParameterException(commandSpec.commandLine(), "Missing required subcommand"); } - return runCommand("execute", Optional.empty()); } @Override @@ -95,43 +82,8 @@ public int getExitCode() { return commandResult.getExitCode(); } - @SuppressWarnings("OptionalUsedAsFieldOrParameterType") - private Object runCommand(String subcommand, Optional triggeringOption) { - CommandLine commandLine = commandSpec.commandLine(); - commandLine.setUnmatchedArgumentsAllowed(false); - Object command = commandLine.getSubcommands().get(subcommand).getCommandSpec().userObject(); - - List args = new ArrayList<>(commandLine.getParseResult().expandedArgs()); - triggeringOption.ifPresent(args::remove); - CommandResult result = runCommand( // - new CommandLine(command), // - args.toArray(new String[0]), // - Optional.of(new OutputStreamConfig(commandLine)) // - ); - this.commandResult = result; - - printDeprecationWarning(subcommand, triggeringOption, commandLine); - - return result.getValue().orElse(null); - } - - private static void printDeprecationWarning(String subcommand, Optional triggeringOption, - CommandLine commandLine) { - PrintWriter err = commandLine.getErr(); - String reason = triggeringOption.map(it -> " due to use of '" + it + "'").orElse(""); - - commandLine.getOut().flush(); - err.println(); - ColorScheme colorScheme = commandLine.getColorScheme(); - err.println(colorScheme.string( - String.format("@|yellow,bold WARNING:|@ Delegated to the '%s' command%s.", subcommand, reason))); - err.println( - colorScheme.string(" This behaviour has been deprecated and will be removed in a future release.")); - err.println(colorScheme.string(" Please use the '" + subcommand + "' command directly.")); - err.flush(); - } - - CommandResult run(String[] args, Optional outputStreamConfig) { + CommandResult run(String[] args, + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional outputStreamConfig) { CommandLine commandLine = new CommandLine(this) // .addSubcommand(new DiscoverTestsCommand(consoleTestExecutorFactory)) // .addSubcommand(new ExecuteTestsCommand(consoleTestExecutorFactory)) // @@ -140,7 +92,7 @@ CommandResult run(String[] args, Optional outputStreamCon } private static CommandResult runCommand(CommandLine commandLine, String[] args, - Optional outputStreamConfig) { + @SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional outputStreamConfig) { BaseCommand.initialize(commandLine); outputStreamConfig.ifPresent(it -> it.applyTo(commandLine)); int exitCode = commandLine.execute(args); diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java index 20103a737d99..3faa6cc3fe48 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java @@ -28,29 +28,19 @@ static class ConsoleOutputOptions { @Option(names = "--color-palette", paramLabel = "FILE", description = "Specify a path to a properties file to customize ANSI style of output (not supported by all terminals).") private Path colorPalette; - @Option(names = "-color-palette", hidden = true) - private Path colorPalette2; @Option(names = "--single-color", description = "Style test output using only text attributes, no color (not supported by all terminals).") private boolean singleColorPalette; - @Option(names = "-single-color", hidden = true) - private boolean singleColorPalette2; @Option(names = "--details", paramLabel = "MODE", defaultValue = DEFAULT_DETAILS_NAME, description = "Select an output details mode for when tests are executed. " // + "Use one of: ${COMPLETION-CANDIDATES}. If 'none' is selected, " // + "then only the summary and test failures are shown. Default: ${DEFAULT-VALUE}.") private final Details details = DEFAULT_DETAILS; - @Option(names = "-details", hidden = true, defaultValue = DEFAULT_DETAILS_NAME) - private final Details details2 = DEFAULT_DETAILS; - @Option(names = "--details-theme", paramLabel = "THEME", description = "Select an output details tree theme for when tests are executed. " + "Use one of: ${COMPLETION-CANDIDATES}. Default is detected based on default character encoding.") private final Theme theme = DEFAULT_THEME; - @Option(names = "-details-theme", hidden = true) - private final Theme theme2 = DEFAULT_THEME; - @Option(names = "--redirect-stdout", paramLabel = "FILE", description = "Redirect test output to stdout to a file.") private Path stdout; @@ -58,10 +48,10 @@ static class ConsoleOutputOptions { private Path stderr; private void applyTo(TestConsoleOutputOptions result) { - result.setColorPalettePath(choose(colorPalette, colorPalette2, null)); - result.setSingleColorPalette(singleColorPalette || singleColorPalette2); - result.setDetails(choose(details, details2, DEFAULT_DETAILS)); - result.setTheme(choose(theme, theme2, DEFAULT_THEME)); + result.setColorPalettePath(colorPalette); + result.setSingleColorPalette(singleColorPalette); + result.setDetails(details); + result.setTheme(theme); result.setStdoutPath(stdout); result.setStderrPath(stderr); } @@ -75,8 +65,4 @@ TestConsoleOutputOptions toTestConsoleOutputOptions() { return result; } - private static T choose(T left, T right, T defaultValue) { - return left == right ? left : (left == defaultValue ? right : left); - } - } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java index 7d423f17c9bd..82f07dae6665 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java @@ -12,7 +12,6 @@ import java.nio.file.Path; import java.util.ArrayList; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -59,24 +58,13 @@ static class SelectorOptions { + "This option can be repeated.") private List selectedClasspathEntries; - @Option(names = { "-scan-class-path", - "-scan-classpath" }, converter = ClasspathEntriesConverter.class, arity = "0..1", hidden = true) - private List selectedClasspathEntries2; - @Option(names = "--scan-modules", description = "Scan all resolved modules for test discovery.") private boolean scanModulepath; - @Option(names = "-scan-modules", hidden = true) - private boolean scanModulepath2; - @Option(names = { "-u", "--select-uri" }, paramLabel = "URI", arity = "1..*", converter = SelectorConverter.Uri.class, description = "Select a URI for test discovery. This option can be repeated.") private final List selectedUris = new ArrayList<>(); - @Option(names = { "--u", - "-select-uri" }, arity = "1..*", hidden = true, converter = SelectorConverter.Uri.class) - private final List selectedUris2 = new ArrayList<>(); - @Option(names = { "-f", "--select-file" }, paramLabel = "FILE", arity = "1..*", converter = SelectorConverter.File.class, // description = "Select a file for test discovery. " @@ -84,58 +72,30 @@ static class SelectorOptions { + "This option can be repeated.") private final List selectedFiles = new ArrayList<>(); - @Option(names = { "--f", - "-select-file" }, arity = "1..*", hidden = true, converter = SelectorConverter.File.class) - private final List selectedFiles2 = new ArrayList<>(); - @Option(names = { "-d", "--select-directory" }, paramLabel = "DIR", arity = "1..*", converter = SelectorConverter.Directory.class, description = "Select a directory for test discovery. This option can be repeated.") private final List selectedDirectories = new ArrayList<>(); - @Option(names = { "--d", - "-select-directory" }, arity = "1..*", hidden = true, converter = SelectorConverter.Directory.class) - private final List selectedDirectories2 = new ArrayList<>(); - @Option(names = { "-o", "--select-module" }, paramLabel = "NAME", arity = "1..*", converter = SelectorConverter.Module.class, description = "Select single module for test discovery. This option can be repeated.") private final List selectedModules = new ArrayList<>(); - @Option(names = { "--o", - "-select-module" }, arity = "1..*", converter = SelectorConverter.Module.class, hidden = true) - private final List selectedModules2 = new ArrayList<>(); - @Option(names = { "-p", "--select-package" }, paramLabel = "PKG", arity = "1..*", converter = SelectorConverter.Package.class, description = "Select a package for test discovery. This option can be repeated.") private final List selectedPackages = new ArrayList<>(); - @Option(names = { "--p", - "-select-package" }, arity = "1..*", hidden = true, converter = SelectorConverter.Package.class) - private final List selectedPackages2 = new ArrayList<>(); - @Option(names = { "-c", "--select-class" }, paramLabel = "CLASS", arity = "1..*", converter = SelectorConverter.Class.class, description = "Select a class for test discovery. This option can be repeated.") private final List selectedClasses = new ArrayList<>(); - @Option(names = { "--c", - "-select-class" }, arity = "1..*", hidden = true, converter = SelectorConverter.Class.class) - private final List selectedClasses2 = new ArrayList<>(); - @Option(names = { "-m", "--select-method" }, paramLabel = "NAME", arity = "1..*", converter = SelectorConverter.Method.class, description = "Select a method for test discovery. This option can be repeated.") private final List selectedMethods = new ArrayList<>(); - @Option(names = { "--m", - "-select-method" }, arity = "1..*", hidden = true, converter = SelectorConverter.Method.class) - private final List selectedMethods2 = new ArrayList<>(); - @Option(names = { "-r", "--select-resource" }, paramLabel = "RESOURCE", arity = "1..*", converter = SelectorConverter.ClasspathResource.class, description = "Select a classpath resource for test discovery. This option can be repeated.") private final List selectedClasspathResources = new ArrayList<>(); - @Option(names = { "--r", - "-select-resource" }, arity = "1..*", hidden = true, converter = SelectorConverter.ClasspathResource.class) - private final List selectedClasspathResources2 = new ArrayList<>(); - @Option(names = { "-i", "--select-iteration" }, paramLabel = "PREFIX:VALUE[INDEX(..INDEX)?(,INDEX(..INDEX)?)*]", arity = "1..*", converter = SelectorConverter.Iteration.class, // description = "Select iterations for test discovery via a prefixed identifier and a list of indexes or index ranges " @@ -143,10 +103,6 @@ static class SelectorOptions { + "This option can be repeated.") private final List selectedIterations = new ArrayList<>(); - @Option(names = { "--i", - "-select-iteration" }, arity = "1..*", hidden = true, converter = SelectorConverter.Iteration.class) - private final List selectedIterations2 = new ArrayList<>(); - @Option(names = { "--select-unique-id", "--uid" }, paramLabel = "UNIQUE-ID", arity = "1..*", converter = SelectorConverter.UniqueId.class, // description = "Select a unique id for test discovery. This option can be repeated.") @@ -161,19 +117,18 @@ static class SelectorOptions { } private void applyTo(TestDiscoveryOptions result) { - result.setScanClasspath(this.selectedClasspathEntries != null || this.selectedClasspathEntries2 != null); // flag was specified - result.setScanModulepath(this.scanModulepath || this.scanModulepath2); - result.setSelectedModules(merge(this.selectedModules, this.selectedModules2)); - result.setSelectedClasspathEntries(merge(this.selectedClasspathEntries, this.selectedClasspathEntries2)); - result.setSelectedUris(merge(this.selectedUris, this.selectedUris2)); - result.setSelectedFiles(merge(this.selectedFiles, this.selectedFiles2)); - result.setSelectedDirectories(merge(this.selectedDirectories, this.selectedDirectories2)); - result.setSelectedPackages(merge(this.selectedPackages, this.selectedPackages2)); - result.setSelectedClasses(merge(this.selectedClasses, this.selectedClasses2)); - result.setSelectedMethods(merge(this.selectedMethods, this.selectedMethods2)); - result.setSelectedClasspathResources( - merge(this.selectedClasspathResources, this.selectedClasspathResources2)); - result.setSelectedIterations(merge(this.selectedIterations, this.selectedIterations2)); + result.setScanClasspath(this.selectedClasspathEntries != null); // flag was specified + result.setScanModulepath(this.scanModulepath); + result.setSelectedModules(this.selectedModules); + result.setSelectedClasspathEntries(this.selectedClasspathEntries); + result.setSelectedUris(this.selectedUris); + result.setSelectedFiles(this.selectedFiles); + result.setSelectedDirectories(this.selectedDirectories); + result.setSelectedPackages(this.selectedPackages); + result.setSelectedClasses(this.selectedClasses); + result.setSelectedMethods(this.selectedMethods); + result.setSelectedClasspathResources(this.selectedClasspathResources); + result.setSelectedIterations(this.selectedIterations); result.setSelectedUniqueId(this.selectedUniqueIds); result.setSelectorIdentifiers(this.selectorIdentifiers); } @@ -189,31 +144,19 @@ static class FilterOptions { + "Default: ${DEFAULT-VALUE}") private final List includeClassNamePatterns = new ArrayList<>(); - @Option(names = { "--n", "-include-classname" }, arity = "1", hidden = true) - private final List includeClassNamePatterns2 = new ArrayList<>(); - @Option(names = { "-N", "--exclude-classname" }, paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to exclude those classes whose fully qualified names match. " // + "When this option is repeated, all patterns will be combined using OR semantics.") private final List excludeClassNamePatterns = new ArrayList<>(); - @Option(names = { "--N", "-exclude-classname" }, arity = "1", hidden = true) - private final List excludeClassNamePatterns2 = new ArrayList<>(); - @Option(names = { "--include-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be included in the test run. This option can be repeated.") private final List includePackages = new ArrayList<>(); - @Option(names = { "-include-package" }, arity = "1", hidden = true) - private final List includePackages2 = new ArrayList<>(); - @Option(names = { "--exclude-package" }, paramLabel = "PKG", arity = "1", description = "Provide a package to be excluded from the test run. This option can be repeated.") private final List excludePackages = new ArrayList<>(); - @Option(names = { "-exclude-package" }, arity = "1", hidden = true) - private final List excludePackages2 = new ArrayList<>(); - @Option(names = { "--include-methodname" }, paramLabel = "PATTERN", arity = "1", description = "Provide a regular expression to include only methods whose fully qualified names without parameters match. " // + "When this option is repeated, all patterns will be combined using OR semantics.") @@ -230,43 +173,31 @@ static class FilterOptions { "When this option is repeated, all patterns will be combined using OR semantics.") private final List includedTags = new ArrayList<>(); - @Option(names = { "--t", "-include-tag" }, arity = "1", hidden = true) - private final List includedTags2 = new ArrayList<>(); - @Option(names = { "-T", "--exclude-tag" }, paramLabel = "TAG", arity = "1", description = "Provide a tag or tag expression to exclude those tests whose tags match. " + // "When this option is repeated, all patterns will be combined using OR semantics.") private final List excludedTags = new ArrayList<>(); - @Option(names = { "--T", "-exclude-tag" }, arity = "1", hidden = true) - private final List excludedTags2 = new ArrayList<>(); - @Option(names = { "-e", "--include-engine" }, paramLabel = "ID", arity = "1", description = "Provide the ID of an engine to be included in the test run. This option can be repeated.") private final List includedEngines = new ArrayList<>(); - @Option(names = { "--e", "-include-engine" }, arity = "1", hidden = true) - private final List includedEngines2 = new ArrayList<>(); - @Option(names = { "-E", "--exclude-engine" }, paramLabel = "ID", arity = "1", description = "Provide the ID of an engine to be excluded from the test run. This option can be repeated.") private final List excludedEngines = new ArrayList<>(); - @Option(names = { "--E", "-exclude-engine" }, arity = "1", hidden = true) - private final List excludedEngines2 = new ArrayList<>(); - private void applyTo(TestDiscoveryOptions result) { - result.setIncludedClassNamePatterns(merge(this.includeClassNamePatterns, this.includeClassNamePatterns2)); - result.setExcludedClassNamePatterns(merge(this.excludeClassNamePatterns, this.excludeClassNamePatterns2)); - result.setIncludedPackages(merge(this.includePackages, this.includePackages2)); - result.setExcludedPackages(merge(this.excludePackages, this.excludePackages2)); + result.setIncludedClassNamePatterns(this.includeClassNamePatterns); + result.setExcludedClassNamePatterns(this.excludeClassNamePatterns); + result.setIncludedPackages(this.includePackages); + result.setExcludedPackages(this.excludePackages); result.setIncludedMethodNamePatterns(new ArrayList<>(this.includeMethodNamePatterns)); result.setExcludedMethodNamePatterns(new ArrayList<>(this.excludeMethodNamePatterns)); - result.setIncludedTagExpressions(merge(this.includedTags, this.includedTags2)); - result.setExcludedTagExpressions(merge(this.excludedTags, this.excludedTags2)); - result.setIncludedEngines(merge(this.includedEngines, this.includedEngines2)); - result.setExcludedEngines(merge(this.excludedEngines, this.excludedEngines2)); + result.setIncludedTagExpressions(this.includedTags); + result.setExcludedTagExpressions(this.excludedTags); + result.setIncludedEngines(this.includedEngines); + result.setExcludedEngines(this.excludedEngines); } } @@ -277,10 +208,6 @@ static class RuntimeConfigurationOptions { + "-- for example, for adding engines and their dependencies. This option can be repeated.") private final List additionalClasspathEntries = new ArrayList<>(); - @Option(names = { "--cp", "-classpath", - "-class-path" }, converter = ClasspathEntriesConverter.class, hidden = true) - private final List additionalClasspathEntries2 = new ArrayList<>(); - // Implementation note: the @Option annotation is on a setter method to allow validation. private final Map configurationParameters = new LinkedHashMap<>(); @@ -291,11 +218,6 @@ static class RuntimeConfigurationOptions { @CommandLine.Spec private CommandLine.Model.CommandSpec spec; - @Option(names = { "-config" }, arity = "1", hidden = true) - public void setConfigurationParameters2(Map keyValuePairs) { - setConfigurationParameters(keyValuePairs); - } - /** * Adds the specified key-value pair (or pairs) to the configuration parameters. * A {@code ParameterException} is thrown if the same key is specified multiple times @@ -323,7 +245,7 @@ private void validateUnique(String key, String newValue) { } private void applyTo(TestDiscoveryOptions result) { - result.setAdditionalClasspathEntries(merge(additionalClasspathEntries, additionalClasspathEntries2)); + result.setAdditionalClasspathEntries(additionalClasspathEntries); result.setConfigurationParametersResources(configurationParametersResources); result.setConfigurationParameters(configurationParameters); } @@ -343,10 +265,4 @@ TestDiscoveryOptions toTestDiscoveryOptions() { return result; } - private static List merge(List list1, List list2) { - List result = new ArrayList<>(list1 == null ? Collections.emptyList() : list1); - result.addAll(list2 == null ? Collections.emptyList() : list2); - return result; - } - } diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java index b908ab457893..2071549d8981 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java @@ -87,6 +87,7 @@ private List scanContainerClassAndCreateDynamicTests(Class conta for (var theme : Theme.values()) { var caption = containerName + "-" + methodName + "-" + details + "-" + theme; String[] args = { // + "execute", // "--include-engine", "junit-jupiter", // "--details", details.name(), // "--details-theme", theme.name(), // @@ -198,17 +199,7 @@ void reportMultiEntriesWithMultiMappings(TestReporter reporter) { } - private static class Runner implements Executable { - - private final String dirName; - private final String outName; - private final String[] args; - - private Runner(String dirName, String outName, String... args) { - this.dirName = dirName; - this.outName = outName; - this.args = args; - } + private record Runner(String dirName, String outName, String... args) implements Executable { @Override public void execute() throws Throwable { diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java index 49b4a159e118..79e707fd94d4 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java @@ -36,35 +36,24 @@ class ConsoleLauncherIntegrationTests { @Test - void executeWithoutArgumentsFailsAndPrintsHelpInformation() { + void executeWithoutSubcommandFailsAndPrintsHelpInformation() { var result = new ConsoleLauncherWrapper().execute(-1); assertAll("empty args array results in display of help information and an exception stacktrace", // () -> assertThat(result.err).contains("help information"), // - () -> assertThat(result.err).contains( - "Please specify an explicit selector option or use --scan-class-path or --scan-modules") // + () -> assertThat(result.err).contains("Missing required subcommand") // ); } - @ParameterizedTest - @ValueSource(strings = { // - "-e junit-jupiter -p org.junit.platform.console.subpackage", // - "execute -e junit-jupiter -p org.junit.platform.console.subpackage" // - }) - void executeWithoutExcludeClassnameOptionDoesNotExcludeClassesAndMustIncludeAllClassesMatchingTheStandardClassnamePattern( - String line) { - var args = line.split(" "); + @Test + void executeWithoutExcludeClassnameOptionDoesNotExcludeClassesAndMustIncludeAllClassesMatchingTheStandardClassnamePattern() { + String[] args = { "execute", "-e", "junit-jupiter", "-p", "org.junit.platform.console.subpackage" }; assertEquals(9, new ConsoleLauncherWrapper().execute(args).getTestsFoundCount()); } - @ParameterizedTest - @ValueSource(strings = { - "-e junit-jupiter -p org.junit.platform.console.subpackage --exclude-classname" - + " ^org\\.junit\\.platform\\.console\\.subpackage\\..*", - "execute -e junit-jupiter -p org.junit.platform.console.subpackage --exclude-classname" - + " ^org\\.junit\\.platform\\.console\\.subpackage\\..*" // - }) - void executeWithExcludeClassnameOptionExcludesClasses(String line) { - var args = line.split(" "); + @Test + void executeWithExcludeClassnameOptionExcludesClasses() { + String[] args = { "execute", "-e", "junit-jupiter", "-p", "org.junit.platform.console.subpackage", + "--exclude-classname", "^org\\.junit\\.platform\\.console\\.subpackage\\..*" }; var result = new ConsoleLauncherWrapper().execute(args); assertAll("all subpackage test classes are excluded by the class name filter", // () -> assertArrayEquals(args, result.args), // @@ -88,18 +77,17 @@ void executeWithExcludeMethodNameOptionExcludesMethods() { @ParameterizedTest @ValueSource(strings = { // - "-e junit-jupiter -o java.base", "-e junit-jupiter --select-module java.base", // - "execute -e junit-jupiter -o java.base", "execute -e junit-jupiter --select-module java.base" // + "execute -e junit-jupiter -o java.base", // + "execute -e junit-jupiter --select-module java.base" // }) void executeSelectingModuleNames(String line) { var args = line.split(" "); assertEquals(0, new ConsoleLauncherWrapper().execute(args).getTestsFoundCount()); } - @ParameterizedTest - @ValueSource(strings = { "-e junit-jupiter --scan-modules", "execute -e junit-jupiter --scan-modules" }) - void executeScanModules(String line) { - var args = line.split(" "); + @Test + void executeScanModules() { + String[] args = { "execute", "-e", "junit-jupiter", "--scan-modules" }; assertEquals(0, new ConsoleLauncherWrapper().execute(args).getTestsFoundCount()); } diff --git a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java index a10094a023da..5fe516ef78f1 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java @@ -322,9 +322,6 @@ void parseValidAdditionalClasspathEntries(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(dir), type.parseArgLine("-cp .").discovery.getAdditionalClasspathEntries()), - () -> assertEquals(List.of(dir), type.parseArgLine("--cp .").discovery.getAdditionalClasspathEntries()), - () -> assertEquals(List.of(dir), type.parseArgLine("-classpath .").discovery.getAdditionalClasspathEntries()), - () -> assertEquals(List.of(dir), type.parseArgLine("-classpath=.").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--classpath .").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--classpath=.").discovery.getAdditionalClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--class-path .").discovery.getAdditionalClasspathEntries()), @@ -361,9 +358,6 @@ void parseValidUriSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-u file:///foo.txt").discovery.getSelectedUris()), - () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--u file:///foo.txt").discovery.getSelectedUris()), - () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-select-uri file:///foo.txt").discovery.getSelectedUris()), - () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("-select-uri=file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--select-uri file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt")), type.parseArgLine("--select-uri=file:///foo.txt").discovery.getSelectedUris()), () -> assertEquals(List.of(selectUri("file:///foo.txt"), selectUri("https://example")), type.parseArgLine("-u file:///foo.txt -u https://example").discovery.getSelectedUris()), @@ -383,9 +377,6 @@ void parseValidFileSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-f foo.txt").discovery.getSelectedFiles()), - () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--f foo.txt").discovery.getSelectedFiles()), - () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-select-file foo.txt").discovery.getSelectedFiles()), - () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("-select-file=foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--select-file foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt")), type.parseArgLine("--select-file=foo.txt").discovery.getSelectedFiles()), () -> assertEquals(List.of(selectFile("foo.txt"), selectFile("bar.csv")), type.parseArgLine("-f foo.txt -f bar.csv").discovery.getSelectedFiles()), @@ -407,9 +398,6 @@ void parseValidDirectorySelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-d foo/bar").discovery.getSelectedDirectories()), - () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--d foo/bar").discovery.getSelectedDirectories()), - () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-select-directory foo/bar").discovery.getSelectedDirectories()), - () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("-select-directory=foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--select-directory foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar")), type.parseArgLine("--select-directory=foo/bar").discovery.getSelectedDirectories()), () -> assertEquals(List.of(selectDirectory("foo/bar"), selectDirectory("bar/qux")), type.parseArgLine("-d foo/bar -d bar/qux").discovery.getSelectedDirectories()), @@ -429,9 +417,6 @@ void parseValidModuleSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-o com.acme.foo").discovery.getSelectedModules()), - () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--o com.acme.foo").discovery.getSelectedModules()), - () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-select-module com.acme.foo").discovery.getSelectedModules()), - () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("-select-module=com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--select-module com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo")), type.parseArgLine("--select-module=com.acme.foo").discovery.getSelectedModules()), () -> assertEquals(List.of(selectModule("com.acme.foo"), selectModule("com.example.bar")), type.parseArgLine("-o com.acme.foo -o com.example.bar").discovery.getSelectedModules()), @@ -451,9 +436,6 @@ void parseValidPackageSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-p com.acme.foo").discovery.getSelectedPackages()), - () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--p com.acme.foo").discovery.getSelectedPackages()), - () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-select-package com.acme.foo").discovery.getSelectedPackages()), - () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("-select-package=com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--select-package com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo")), type.parseArgLine("--select-package=com.acme.foo").discovery.getSelectedPackages()), () -> assertEquals(List.of(selectPackage("com.acme.foo"), selectPackage("com.example.bar")), type.parseArgLine("-p com.acme.foo -p com.example.bar").discovery.getSelectedPackages()), @@ -473,9 +455,6 @@ void parseValidClassSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-c com.acme.Foo").discovery.getSelectedClasses()), - () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--c com.acme.Foo").discovery.getSelectedClasses()), - () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-select-class com.acme.Foo").discovery.getSelectedClasses()), - () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("-select-class=com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--select-class com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo")), type.parseArgLine("--select-class=com.acme.Foo").discovery.getSelectedClasses()), () -> assertEquals(List.of(selectClass("com.acme.Foo"), selectClass("com.example.Bar")), type.parseArgLine("-c com.acme.Foo -c com.example.Bar").discovery.getSelectedClasses()), @@ -495,9 +474,6 @@ void parseValidMethodSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-m com.acme.Foo#m()").discovery.getSelectedMethods()), - () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--m com.acme.Foo#m()").discovery.getSelectedMethods()), - () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-select-method com.acme.Foo#m()").discovery.getSelectedMethods()), - () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("-select-method=com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--select-method com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()")), type.parseArgLine("--select-method=com.acme.Foo#m()").discovery.getSelectedMethods()), () -> assertEquals(List.of(selectMethod("com.acme.Foo#m()"), selectMethod("com.example.Bar#method(java.lang.Object)")), @@ -519,9 +495,6 @@ void parseValidClasspathResourceSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-r /foo.csv").discovery.getSelectedClasspathResources()), - () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--r /foo.csv").discovery.getSelectedClasspathResources()), - () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-select-resource /foo.csv").discovery.getSelectedClasspathResources()), - () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("-select-resource=/foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--select-resource /foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv")), type.parseArgLine("--select-resource=/foo.csv").discovery.getSelectedClasspathResources()), () -> assertEquals(List.of(selectClasspathResource("/foo.csv"), selectClasspathResource("bar.json")), type.parseArgLine("-r /foo.csv -r bar.json").discovery.getSelectedClasspathResources()), @@ -543,9 +516,9 @@ void parseValidIterationSelectors(ArgsType type) { // @formatter:off assertAll( () -> assertEquals(List.of(selectIteration(selectClasspathResource("/foo.csv"), 0)), type.parseArgLine("-i resource:/foo.csv[0]").discovery.getSelectedIterations()), - () -> assertEquals(List.of(selectIteration(selectMethod("com.acme.Foo#m()"), 1, 2)), type.parseArgLine("--i method:com.acme.Foo#m()[1..2]").discovery.getSelectedIterations()), - () -> assertEquals(List.of(selectIteration(selectClass("com.acme.Foo"), 0, 2)), type.parseArgLine("-select-iteration class:com.acme.Foo[0,2]").discovery.getSelectedIterations()), - () -> assertEquals(List.of(selectIteration(selectPackage("com.acme.foo"), 3)), type.parseArgLine("-select-iteration=package:com.acme.foo[3]").discovery.getSelectedIterations()), + () -> assertEquals(List.of(selectIteration(selectMethod("com.acme.Foo#m()"), 1, 2)), type.parseArgLine("-i method:com.acme.Foo#m()[1..2]").discovery.getSelectedIterations()), + () -> assertEquals(List.of(selectIteration(selectClass("com.acme.Foo"), 0, 2)), type.parseArgLine("--select-iteration class:com.acme.Foo[0,2]").discovery.getSelectedIterations()), + () -> assertEquals(List.of(selectIteration(selectPackage("com.acme.foo"), 3)), type.parseArgLine("--select-iteration=package:com.acme.foo[3]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectModule("com.acme.foo"), 0, 1, 2, 4, 5, 6)), type.parseArgLine("--select-iteration module:com.acme.foo[0..2,4..6]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectDirectory("foo/bar"), 1, 5)), type.parseArgLine("--select-iteration=directory:foo/bar[1,5]").discovery.getSelectedIterations()), () -> assertEquals(List.of(selectIteration(selectFile("foo.txt"), 6), selectIteration(selectUri("file:///foo.txt"), 7)), type.parseArgLine("-i file:foo.txt[6] -i uri:file:///foo.txt[7]").discovery.getSelectedIterations()), @@ -590,8 +563,6 @@ void parseClasspathScanningEntries(ArgsType type) { () -> assertTrue(type.parseArgLine("--scan-class-path .").discovery.isScanClasspath()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path .").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path=.").discovery.getSelectedClasspathEntries()), - () -> assertEquals(List.of(dir), type.parseArgLine("-scan-class-path .").discovery.getSelectedClasspathEntries()), - () -> assertEquals(List.of(dir), type.parseArgLine("-scan-class-path=.").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path . --scan-class-path src/test/java").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path ." + File.pathSeparator + "src/test/java").discovery.getSelectedClasspathEntries()) ); @@ -603,10 +574,6 @@ void parseClasspathScanningEntries(ArgsType type) { void parseValidConfigurationParameters(ArgsType type) { // @formatter:off assertAll( - () -> assertThat(type.parseArgLine("-config foo=bar").discovery.getConfigurationParameters()) - .containsOnly(entry("foo", "bar")), - () -> assertThat(type.parseArgLine("-config=foo=bar").discovery.getConfigurationParameters()) - .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("--config foo=bar").discovery.getConfigurationParameters()) .containsOnly(entry("foo", "bar")), () -> assertThat(type.parseArgLine("--config=foo=bar").discovery.getConfigurationParameters()) @@ -632,7 +599,7 @@ void parseValidConfigurationParametersResource(ArgsType type) { @Test void parseInvalidConfigurationParameters() { - assertOptionWithMissingRequiredArgumentThrowsException("-config", "--config"); + assertOptionWithMissingRequiredArgumentThrowsException("--config"); } @ParameterizedTest From 42a7aff5db67536507d9bd313a5e35a579b4dd4e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 6 May 2025 13:25:54 +0200 Subject: [PATCH 018/521] Remove unnecessary reflection --- .../java/org/junit/platform/commons/util/ReflectionUtils.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 f122e8c77958..bdc8449af025 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 @@ -390,8 +390,7 @@ public static boolean isRecordObject(Object object) { */ @API(status = INTERNAL, since = "1.12") public static boolean isRecordClass(Class clazz) { - Class superclass = clazz.getSuperclass(); - return superclass != null && "java.lang.Record".equals(superclass.getName()); + return clazz.isRecord(); } /** From c990485b76851dbddd2a90c1e0f11b1ede109c73 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 6 May 2025 14:55:20 +0200 Subject: [PATCH 019/521] Remove obsolete task config --- junit-platform-jfr/junit-platform-jfr.gradle.kts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/junit-platform-jfr/junit-platform-jfr.gradle.kts b/junit-platform-jfr/junit-platform-jfr.gradle.kts index 8d82379addad..7d9e2d06a2a9 100644 --- a/junit-platform-jfr/junit-platform-jfr.gradle.kts +++ b/junit-platform-jfr/junit-platform-jfr.gradle.kts @@ -19,9 +19,3 @@ dependencies { osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } - -tasks { - compileModule { - options.release = 11 - } -} From b599377477da098adf418fad8fe67f02ea137e59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 03:48:06 +0000 Subject: [PATCH 020/521] Update dependency com.tngtech.archunit:archunit-junit5 to v1.4.1 (#4521) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c0a28472969c..9e5df0621f7c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ ant-junitlauncher = { module = "org.apache.ant:ant-junitlauncher", version.ref = apiguardian = { module = "org.apiguardian:apiguardian-api", version.ref = "apiguardian" } # check whether the Java condition in platform-tooling-support-tests.gradle.kts can be changed when updating -archunit = { module = "com.tngtech.archunit:archunit-junit5", version = "1.4.0" } +archunit = { module = "com.tngtech.archunit:archunit-junit5", version = "1.4.1" } assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" } bndlib = { module = "biz.aQute.bnd:biz.aQute.bndlib", version.ref = "bnd" } From efeb0bc52ca89eec3c2405d609180cd3c3984da1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 8 May 2025 03:49:07 +0000 Subject: [PATCH 021/521] Update plugin openrewrite to v7.6.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e5df0621f7c..ff89b7aa6bb1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -101,7 +101,7 @@ jmh = { id = "me.champeau.jmh", version = "0.7.3" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.20" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } -openrewrite = { id = "org.openrewrite.rewrite", version = "7.5.0" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.1" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "7.0.3" } From 86ce33b24f98198af66fea6e9fe848dad2edde81 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:11:21 +0200 Subject: [PATCH 022/521] Delete deprecated `MethodOrderer.Alphanumeric` --- .../src/docs/asciidoc/link-attributes.adoc | 1 - .../release-notes/release-notes-6.0.0-M1.adoc | 3 +- .../asciidoc/user-guide/writing-tests.adoc | 3 - .../org/junit/jupiter/api/MethodOrderer.java | 21 ----- .../engine/extension/OrderedMethodTests.java | 85 ++----------------- .../integration/JupiterIntegrationTests.java | 4 +- 6 files changed, 9 insertions(+), 108 deletions(-) diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index fbfc2021e938..d79abdac00d2 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -118,7 +118,6 @@ endif::[] :ClassOrderer: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/ClassOrderer.html[ClassOrderer] :ClassTemplate: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/ClassTemplate.html[@ClassTemplate] :Disabled: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/Disabled.html[@Disabled] -:MethodOrderer_Alphanumeric: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.Alphanumeric.html[MethodOrderer.Alphanumeric] :MethodOrderer_DisplayName: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.DisplayName.html[MethodOrderer.DisplayName] :MethodOrderer_MethodName: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.MethodName.html[MethodOrderer.MethodName] :MethodOrderer_OrderAnnotation: {javadoc-root}/org.junit.jupiter.api/org/junit/jupiter/api/MethodOrderer.OrderAnnotation.html[MethodOrderer.OrderAnnotation] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index bbb734ec5650..93ff41fac4cb 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -63,7 +63,8 @@ repository on GitHub. [[release-notes-6.0.0-M1-junit-jupiter-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes -* ❓ +* The following deprecated APIs have been removed: + - `MethodOrderer.Alphanumeric` class [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index b9c86dbb8a89..0723c09557db 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -974,9 +974,6 @@ following built-in `MethodOrderer` implementations. specified via the `{Order}` annotation * `{MethodOrderer_Random}`: orders test methods _pseudo-randomly_ and supports configuration of a custom _seed_ -* `{MethodOrderer_Alphanumeric}`: sorts test methods _alphanumerically_ based on their - names and formal parameter lists; **deprecated in favor of `{MethodOrderer_MethodName}`, - to be removed in 6.0** NOTE: See also: <> diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrderer.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrderer.java index e853106480f6..f1b60a0f4adf 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrderer.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/MethodOrderer.java @@ -11,7 +11,6 @@ package org.junit.jupiter.api; import static java.util.Comparator.comparingInt; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Method; @@ -126,26 +125,6 @@ default Optional getDefaultExecutionMode() { return Optional.of(ExecutionMode.SAME_THREAD); } - /** - * {@code MethodOrderer} that sorts methods alphanumerically based on their - * names using {@link String#compareTo(String)}. - * - *

If two methods have the same name, {@code String} representations of - * their formal parameter lists will be used as a fallback for comparing the - * methods. - * - * @since 5.4 - * @deprecated as of JUnit Jupiter 5.7 in favor of {@link MethodOrderer.MethodName}; - * to be removed in 6.0 - */ - @API(status = DEPRECATED, since = "5.7") - @Deprecated - class Alphanumeric extends MethodName { - - public Alphanumeric() { - } - } - /** * {@code MethodOrderer} that sorts methods alphanumerically based on their * names using {@link String#compareTo(String)}. 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..daebaab379d5 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 @@ -83,40 +83,18 @@ void clearCallSequence() { threadNames.clear(); } - @Test - void alphanumeric() { - Class testClass = AlphanumericTestCase.class; - - // The name of the base class MUST start with a letter alphanumerically - // greater than "A" so that BaseTestCase comes after AlphanumericTestCase - // if methods are sorted by class name for the fallback ordering if two - // methods have the same name but different parameter lists. Note, however, - // that Alphanumeric actually does not order methods like that, but we want - // this check to remain in place to ensure that the ordering does not rely - // on the class names. - assertThat(testClass.getSuperclass().getName()).isGreaterThan(testClass.getName()); - - var tests = executeTestsInParallel(testClass, Random.class); - - tests.assertStatistics(stats -> stats.succeeded(callSequence.size())); - - assertThat(callSequence).containsExactly("$()", "AAA()", "AAA(org.junit.jupiter.api.TestInfo)", - "AAA(org.junit.jupiter.api.TestReporter)", "ZZ_Top()", "___()", "a1()", "a2()", "b()", "c()", "zzz()"); - assertThat(threadNames).hasSize(1); - } - @Test void methodName() { - Class testClass = MethodNameTestCase.class; + Class testClass = AMethodNameTestCase.class; // The name of the base class MUST start with a letter alphanumerically - // greater than "A" so that BaseTestCase comes after AlphanumericTestCase + // greater than "A" so that BaseTestCase comes after AMethodNameTestCase // if methods are sorted by class name for the fallback ordering if two // methods have the same name but different parameter lists. Note, however, - // that Alphanumeric actually does not order methods like that, but we want + // that MethodName actually does not order methods like that, but we want // this check to remain in place to ensure that the ordering does not rely // on the class names. - assertThat(testClass.getSuperclass().getName()).isLessThan(testClass.getName()); + assertThat(testClass.getSuperclass().getName()).isGreaterThan(testClass.getName()); var tests = executeTestsInParallel(testClass, Random.class); @@ -419,60 +397,7 @@ void c() { @SuppressWarnings({ "unused", "JUnitMalformedDeclaration" }) @TestMethodOrder(MethodName.class) - static class MethodNameTestCase extends BaseTestCase { - - @BeforeEach - void trackInvocations(TestInfo testInfo) { - var method = testInfo.getTestMethod().orElseThrow(AssertionError::new); - var signature = String.format("%s(%s)", method.getName(), - ClassUtils.nullSafeToString(method.getParameterTypes())); - - callSequence.add(signature); - threadNames.add(Thread.currentThread().getName()); - } - - @TestFactory - DynamicTest b() { - return dynamicTest("dynamic", () -> { - }); - } - - @Test - void $() { - } - - @Test - void ___() { - } - - @Test - void AAA(TestReporter testReporter) { - } - - @Test - void AAA(TestInfo testInfo) { - } - - @Test - void ZZ_Top() { - } - - @Test - void a1() { - } - - @Test - void a2() { - } - - @RepeatedTest(1) - void zzz() { - } - } - - @SuppressWarnings({ "deprecation", "unused", "JUnitMalformedDeclaration" }) - @TestMethodOrder(org.junit.jupiter.api.MethodOrderer.Alphanumeric.class) - static class AlphanumericTestCase extends BaseTestCase { + static class AMethodNameTestCase extends BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { diff --git a/platform-tooling-support-tests/projects/multi-release-jar/src/test/java/integration/integration/JupiterIntegrationTests.java b/platform-tooling-support-tests/projects/multi-release-jar/src/test/java/integration/integration/JupiterIntegrationTests.java index 1ec807b3a8dc..f80fde9fd7db 100644 --- a/platform-tooling-support-tests/projects/multi-release-jar/src/test/java/integration/integration/JupiterIntegrationTests.java +++ b/platform-tooling-support-tests/projects/multi-release-jar/src/test/java/integration/integration/JupiterIntegrationTests.java @@ -15,13 +15,13 @@ import static org.junit.platform.launcher.EngineFilter.includeEngines; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; -import org.junit.jupiter.api.MethodOrderer.Alphanumeric; +import org.junit.jupiter.api.MethodOrderer.MethodName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestMethodOrder; import org.junit.platform.engine.discovery.DiscoverySelectors; import org.junit.platform.launcher.core.LauncherFactory; -@TestMethodOrder(Alphanumeric.class) +@TestMethodOrder(MethodName.class) class JupiterIntegrationTests { @Test From 45e108229344646ee46b1f41183f4762ec92b176 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:13:45 +0200 Subject: [PATCH 023/521] Delete deprecated `InvocationInterceptor.interceptDynamicTest` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../api/extension/InvocationInterceptor.java | 19 +------------------ .../api/extension/KitchenSinkExtension.java | 6 ------ 3 files changed, 2 insertions(+), 24 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 93ff41fac4cb..95a35d973967 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -65,6 +65,7 @@ repository on GitHub. * The following deprecated APIs have been removed: - `MethodOrderer.Alphanumeric` class + - `InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext)` method [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java index dc02002508d0..6f59a125b15e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.extension; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.lang.reflect.Constructor; @@ -163,21 +162,6 @@ default void interceptTestTemplateMethod(Invocation invocation, invocation.proceed(); } - /** - * Intercept the invocation of a {@link DynamicTest}. - * - * @param invocation the invocation that is being intercepted; never - * {@code null} - * @param extensionContext the current extension context; never {@code null} - * @throws Throwable in case of failures - * @deprecated use {@link #interceptDynamicTest(Invocation, DynamicTestInvocationContext, ExtensionContext)} instead - */ - @Deprecated - @API(status = DEPRECATED, since = "5.8") - default void interceptDynamicTest(Invocation invocation, ExtensionContext extensionContext) throws Throwable { - invocation.proceed(); - } - /** * Intercept the invocation of a {@link DynamicTest}. * @@ -191,8 +175,7 @@ default void interceptDynamicTest(Invocation invocation, ExtensionContext @API(status = STABLE, since = "5.11") default void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - // by default call the old interceptDynamicTest(Invocation, ExtensionContext) method so that existing extensions still work - interceptDynamicTest(invocation, extensionContext); + invocation.proceed(); } /** diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java index 45dfd821661a..ada59dbdda55 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java @@ -260,12 +260,6 @@ public void interceptTestTemplateMethod(Invocation invocation, InvocationInterceptor.super.interceptTestTemplateMethod(invocation, invocationContext, extensionContext); } - @SuppressWarnings("deprecation") - @Override - public void interceptDynamicTest(Invocation invocation, ExtensionContext extensionContext) throws Throwable { - InvocationInterceptor.super.interceptDynamicTest(invocation, extensionContext); - } - @Override public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { From b452fbc0ffab14e5833bc549019007cddee417da Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:18:48 +0200 Subject: [PATCH 024/521] Delete deprecated `ReflectionSupport.loadClass` --- .../release-notes/release-notes-6.0.0-M1.adoc | 2 ++ .../commons/support/ReflectionSupport.java | 23 --------------- .../commons/util/ReflectionUtils.java | 29 ------------------- .../support/ReflectionSupportTests.java | 15 ---------- .../commons/util/ReflectionUtilsTests.java | 13 --------- 5 files changed, 2 insertions(+), 80 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 95a35d973967..c486b49ab170 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -45,6 +45,8 @@ repository on GitHub. subcommand. * Remove support for deprecated non-conventional `ConsoleLauncher` options such as `--h` (rather than `-h`) or `-help` (rather than `--help`). +* The following deprecated APIs have been removed: + - `ReflectionSupport.loadClass(String)` method [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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..2d4d19e32aa5 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 @@ -10,7 +10,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; @@ -51,28 +50,6 @@ private ReflectionSupport() { /* no-op */ } - /** - * Load a class by its primitive name or fully qualified name, - * using the default {@link ClassLoader}. - * - *

Class names for arrays may be specified using either the JVM's internal - * String representation (e.g., {@code [[I} for {@code int[][]}, - * {@code [Ljava.lang.String;} for {@code java.lang.String[]}, etc.) or - * source code syntax (e.g., {@code int[][]}, {@code java.lang.String[]}, - * etc.). - * - * @param name the name of the class to load; never {@code null} or blank - * @return an {@code Optional} containing the loaded class; never {@code null} - * but potentially empty if no such class could be loaded - * @deprecated Please use {@link #tryToLoadClass(String)} instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - @SuppressWarnings("deprecation") - public static Optional> loadClass(String name) { - return ReflectionUtils.loadClass(name); - } - /** * Try to load a class by its primitive name or fully qualified * name, using the default {@link ClassLoader}. 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 bdc8449af025..1d93beb913f4 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 @@ -788,16 +788,6 @@ public static Object invokeMethod(Method method, Object target, Object... args) } } - /** - * @see org.junit.platform.commons.support.ReflectionSupport#loadClass(String) - * @deprecated Please use {@link #tryToLoadClass(String)} instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - public static Optional> loadClass(String name) { - return tryToLoadClass(name).toOptional(); - } - /** * @since 1.4 * @see org.junit.platform.commons.support.ReflectionSupport#tryToLoadClass(String) @@ -807,25 +797,6 @@ public static Try> tryToLoadClass(String name) { return tryToLoadClass(name, ClassLoaderUtils.getDefaultClassLoader()); } - /** - * Load a class by its primitive name or fully qualified name, - * using the supplied {@link ClassLoader}. - * - *

See {@link org.junit.platform.commons.support.ReflectionSupport#loadClass(String)} - * for details on support for class names for arrays. - * - * @param name the name of the class to load; never {@code null} or blank - * @param classLoader the {@code ClassLoader} to use; never {@code null} - * @see #loadClass(String) - * @deprecated Please use {@link #tryToLoadClass(String, ClassLoader)} - * instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - public static Optional> loadClass(String name, ClassLoader classLoader) { - return tryToLoadClass(name, classLoader).toOptional(); - } - /** * Load a class by its primitive name or fully qualified name, * using the supplied {@link ClassLoader}. diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java index 0d1d9fc05454..11134ab5608e 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java @@ -46,21 +46,6 @@ class ReflectionSupportTests { static final String staticField = "static"; final String instanceField = "instance"; - @Test - @SuppressWarnings("deprecation") - void loadClassDelegates() { - assertEquals(ReflectionUtils.loadClass("-"), ReflectionSupport.loadClass("-")); - assertEquals(ReflectionUtils.loadClass("A"), ReflectionSupport.loadClass("A")); - assertEquals(ReflectionUtils.loadClass("java.nio.Bits"), ReflectionSupport.loadClass("java.nio.Bits")); - } - - @Test - @SuppressWarnings("deprecation") - void loadClassPreconditions() { - assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.loadClass(null)); - assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.loadClass("")); - } - @Test void tryToLoadClassDelegates() { assertEquals(ReflectionUtils.tryToLoadClass("-").toOptional(), 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 11c2259b28a1..3242068dab66 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 @@ -785,12 +785,6 @@ void tryToLoadClassPreconditions() { () -> ReflectionUtils.tryToLoadClass(getClass().getName(), null)); } - @Test - @SuppressWarnings("deprecation") - void loadClassWhenClassNotFoundException() { - assertThat(ReflectionUtils.loadClass("foo.bar.EnigmaClassThatDoesNotExist")).isEmpty(); - } - @Test void tryToLoadClassWhenClassNotFoundException() { assertThrows(ClassNotFoundException.class, @@ -811,13 +805,6 @@ void tryToLoadClassFailsWithinReasonableTimeForInsanelyLargeAndInvalidMultidimen () -> ReflectionUtils.tryToLoadClass(className).get())); } - @Test - @SuppressWarnings("deprecation") - void loadClass() { - var optional = ReflectionUtils.loadClass(Integer.class.getName()); - assertThat(optional).contains(Integer.class); - } - @Test void tryToLoadClass() { assertTryToLoadClass(getClass().getName(), getClass()); From 47f79a92a72b39c10e96956409fa84ce05b17153 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:23:46 +0200 Subject: [PATCH 025/521] Delete deprecated `ReflectionUtils.readFieldValue` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../commons/util/ReflectionUtils.java | 62 ------------------- .../commons/util/ReflectionUtilsTests.java | 50 ++------------- 3 files changed, 6 insertions(+), 107 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index c486b49ab170..23a0a5767dcd 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -47,6 +47,7 @@ repository on GitHub. `--h` (rather than `-h`) or `-help` (rather than `--help`). * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method + - `ReflectionUtils.readFieldValue(...)` methods [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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 1d93beb913f4..85cccb12d156 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 @@ -613,27 +613,6 @@ public static T newInstance(Constructor constructor, Object... args) { } } - /** - * Read the value of a potentially inaccessible or nonexistent field. - * - *

If the field does not exist or the value of the field is {@code null}, - * an empty {@link Optional} will be returned. - * - * @param clazz the class where the field is declared; never {@code null} - * @param fieldName the name of the field; never {@code null} or empty - * @param instance the instance from where the value is to be read; may - * be {@code null} for a static field - * @see #readFieldValue(Field) - * @see #readFieldValue(Field, Object) - * @deprecated Please use {@link #tryToReadFieldValue(Class, String, Object)} - * instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - public static Optional readFieldValue(Class clazz, String fieldName, T instance) { - return tryToReadFieldValue(clazz, fieldName, instance).toOptional(); - } - /** * Try to read the value of a potentially inaccessible or nonexistent field. * @@ -659,25 +638,6 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa // @formatter:on } - /** - * Read the value of the supplied static field, making it accessible if - * necessary and {@linkplain ExceptionUtils#throwAsUncheckedException masking} - * any checked exception as an unchecked exception. - * - *

If the value of the field is {@code null}, an empty {@link Optional} - * will be returned. - * - * @param field the field to read; never {@code null} - * @see #readFieldValue(Field, Object) - * @see #readFieldValue(Class, String, Object) - * @deprecated Please use {@link #tryToReadFieldValue(Field)} instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - public static Optional readFieldValue(Field field) { - return tryToReadFieldValue(field).toOptional(); - } - /** * Try to read the value of a potentially inaccessible static field. * @@ -694,28 +654,6 @@ public static Try tryToReadFieldValue(Field field) { return tryToReadFieldValue(field, null); } - /** - * Read the value of the supplied field, making it accessible if necessary - * and {@linkplain ExceptionUtils#throwAsUncheckedException masking} any - * checked exception as an unchecked exception. - * - *

If the value of the field is {@code null}, an empty {@link Optional} - * will be returned. - * - * @param field the field to read; never {@code null} - * @param instance the instance from which the value is to be read; may - * be {@code null} for a static field - * @see #readFieldValue(Field) - * @see #readFieldValue(Class, String, Object) - * @deprecated Please use {@link #tryToReadFieldValue(Field, Object)} - * instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - public static Optional readFieldValue(Field field, Object instance) { - return tryToReadFieldValue(field, instance).toOptional(); - } - /** * @since 1.4 * @see org.junit.platform.commons.support.ReflectionSupport#tryToReadFieldValue(Field, Object) 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 3242068dab66..d6393d0af1c6 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 @@ -30,7 +30,6 @@ import static org.junit.platform.commons.util.ReflectionUtils.findMethods; import static org.junit.platform.commons.util.ReflectionUtils.invokeMethod; import static org.junit.platform.commons.util.ReflectionUtils.isWideningConversion; -import static org.junit.platform.commons.util.ReflectionUtils.readFieldValue; import static org.junit.platform.commons.util.ReflectionUtils.readFieldValues; import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue; @@ -1908,13 +1907,6 @@ String specialBaz() { @Nested class ReadFieldTests { - @Test - @SuppressWarnings("deprecation") - void readFieldValueOfNonexistentStaticField() { - assertThat(readFieldValue(MyClass.class, "doesNotExist", null)).isNotPresent(); - assertThat(readFieldValue(MySubClass.class, "staticField", null)).isNotPresent(); - } - @Test void tryToReadFieldValueOfNonexistentStaticField() { assertThrows(NoSuchFieldException.class, @@ -1923,13 +1915,6 @@ void tryToReadFieldValueOfNonexistentStaticField() { () -> tryToReadFieldValue(MySubClass.class, "staticField", null).get()); } - @Test - @SuppressWarnings("deprecation") - void readFieldValueOfNonexistentInstanceField() { - assertThat(readFieldValue(MyClass.class, "doesNotExist", new MyClass(42))).isNotPresent(); - assertThat(readFieldValue(MyClass.class, "doesNotExist", new MySubClass(42))).isNotPresent(); - } - @Test void tryToReadFieldValueOfNonexistentInstanceField() { assertThrows(NoSuchFieldException.class, @@ -1938,16 +1923,6 @@ void tryToReadFieldValueOfNonexistentInstanceField() { () -> tryToReadFieldValue(MyClass.class, "doesNotExist", new MySubClass(42)).get()); } - @Test - @SuppressWarnings("deprecation") - void readFieldValueOfExistingStaticField() throws Exception { - assertThat(readFieldValue(MyClass.class, "staticField", null)).contains(42); - - var field = MyClass.class.getDeclaredField("staticField"); - assertThat(readFieldValue(field)).contains(42); - assertThat(readFieldValue(field, null)).contains(42); - } - @Test void tryToReadFieldValueOfExistingStaticField() throws Exception { assertThat(tryToReadFieldValue(MyClass.class, "staticField", null).get()).isEqualTo(42); @@ -1958,35 +1933,20 @@ void tryToReadFieldValueOfExistingStaticField() throws Exception { } @Test - @SuppressWarnings("deprecation") - void readFieldValueOfExistingInstanceField() throws Exception { + void tryToReadFieldValueOfExistingInstanceField() throws Exception { var instance = new MyClass(42); - assertThat(readFieldValue(MyClass.class, "instanceField", instance)).contains(42); + assertThat(tryToReadFieldValue(MyClass.class, "instanceField", instance).get()).isEqualTo(42); var field = MyClass.class.getDeclaredField("instanceField"); - assertThat(readFieldValue(field, instance)).contains(42); - } + assertThat(tryToReadFieldValue(field, instance).get()).isEqualTo(42); - @Test - @SuppressWarnings("deprecation") - void attemptToReadFieldValueOfExistingInstanceFieldAsStaticField() throws Exception { - var field = MyClass.class.getDeclaredField("instanceField"); - Exception exception = assertThrows(PreconditionViolationException.class, () -> readFieldValue(field, null)); + var exception = assertThrows(PreconditionViolationException.class, + () -> tryToReadFieldValue(field, null).get()); assertThat(exception)// .hasMessageStartingWith("Cannot read non-static field")// .hasMessageEndingWith("on a null instance."); } - @Test - void tryToReadFieldValueOfExistingInstanceField() throws Exception { - var instance = new MyClass(42); - assertThat(tryToReadFieldValue(MyClass.class, "instanceField", instance).get()).isEqualTo(42); - - var field = MyClass.class.getDeclaredField("instanceField"); - assertThat(tryToReadFieldValue(field, instance).get()).isEqualTo(42); - assertThrows(PreconditionViolationException.class, () -> tryToReadFieldValue(field, null).get()); - } - } @Nested From b0e867014b2ea08a1d4c92da0ded5b6c99bb4881 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:26:00 +0200 Subject: [PATCH 026/521] Delete deprecated `BlacklistedExceptions` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../commons/util/BlacklistedExceptions.java | 60 ------------------- 2 files changed, 1 insertion(+), 60 deletions(-) delete mode 100644 junit-platform-commons/src/main/java/org/junit/platform/commons/util/BlacklistedExceptions.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 23a0a5767dcd..45fea0dc9775 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -48,6 +48,7 @@ repository on GitHub. * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods + - `BlacklistedExceptions` class [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/BlacklistedExceptions.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/BlacklistedExceptions.java deleted file mode 100644 index f51c6ca8fc75..000000000000 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/BlacklistedExceptions.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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.DEPRECATED; - -import org.apiguardian.api.API; - -/** - * Internal utilities for working with unrecoverable exceptions. - * - *

Unrecoverable exceptions are those that should always terminate - * test plan execution immediately. - * - *

Currently Unrecoverable Exceptions

- *
    - *
  • {@link OutOfMemoryError}
  • - *
- * - *

DISCLAIMER

- * - *

These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.0 - * @deprecated Use {@link UnrecoverableExceptions} instead. - */ -@Deprecated -@API(status = DEPRECATED, since = "1.7") -public final class BlacklistedExceptions { - - private BlacklistedExceptions() { - /* no-op */ - } - - /** - * Rethrow the supplied {@link Throwable exception} if it is - * unrecoverable. - * - *

If the supplied {@code exception} is not unrecoverable, this - * method does nothing. - * - * @deprecated Use {@link UnrecoverableExceptions#rethrowIfUnrecoverable} - * instead. - */ - @Deprecated - public static void rethrowIfBlacklisted(Throwable exception) { - UnrecoverableExceptions.rethrowIfUnrecoverable(exception); - } - -} From fe62f72410e3045d47000cc49fd4364766b96af7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:28:28 +0200 Subject: [PATCH 027/521] Delete deprecated `PreconditionViolationException` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../PreconditionViolationException.java | 3 +- .../util/PreconditionViolationException.java | 39 ------------------- 3 files changed, 2 insertions(+), 41 deletions(-) delete mode 100644 junit-platform-commons/src/main/java/org/junit/platform/commons/util/PreconditionViolationException.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 45fea0dc9775..7e1b6eecd2dc 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -49,6 +49,7 @@ repository on GitHub. - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods - `BlacklistedExceptions` class + - `PreconditionViolationException` class (from `org.junit.platform.commons.util`) [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java index 4ae58db3adec..025b00ff8e0f 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java @@ -20,8 +20,7 @@ * @since 1.5 */ @API(status = STABLE, since = "1.5") -@SuppressWarnings({ "deprecation", "exports" }) -public class PreconditionViolationException extends org.junit.platform.commons.util.PreconditionViolationException { +public class PreconditionViolationException extends JUnitException { private static final long serialVersionUID = 1L; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PreconditionViolationException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PreconditionViolationException.java deleted file mode 100644 index e28c0372d53a..000000000000 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PreconditionViolationException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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.DEPRECATED; - -import org.apiguardian.api.API; -import org.junit.platform.commons.JUnitException; - -/** - * Thrown if a precondition is violated. - * - * @since 1.0 - * @see Preconditions - * @deprecated Use {@linkplain org.junit.platform.commons.PreconditionViolationException} instead. - */ -@API(status = DEPRECATED, since = "1.5") -@Deprecated -public class PreconditionViolationException extends JUnitException { - - private static final long serialVersionUID = 1L; - - public PreconditionViolationException(String message) { - super(message); - } - - public PreconditionViolationException(String message, Throwable cause) { - super(message, cause); - } - -} From b2ce6d9779b4cb834718ad41ec0eb5b62fe08b75 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:29:09 +0200 Subject: [PATCH 028/521] Delete deprecated `ReflectionUtils.getMethod` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../commons/util/ReflectionUtils.java | 24 ------------------- 2 files changed, 1 insertion(+), 24 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 7e1b6eecd2dc..f88ece1ed3a3 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -48,6 +48,7 @@ repository on GitHub. * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods + - `ReflectionUtils.getMethod(...)` method - `BlacklistedExceptions` class - `PreconditionViolationException` class (from `org.junit.platform.commons.util`) 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 85cccb12d156..9a575d61fe5b 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 @@ -14,7 +14,6 @@ import static java.util.Collections.synchronizedMap; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; @@ -1397,29 +1396,6 @@ public static boolean isMethodPresent(Class clazz, Predicate predicat return findMethod(clazz, predicate).isPresent(); } - /** - * Get the {@link Method} in the specified class with the specified name - * and parameter types. - * - *

This method delegates to {@link Class#getMethod(String, Class...)} but - * swallows any exception thrown. - * - * @param clazz the class in which to search for the method; never {@code null} - * @param methodName the name of the method to get; never {@code null} or blank - * @param parameterTypes the parameter types of the method; may be {@code null} - * or empty - * @return an {@code Optional} containing the method; never {@code null} but - * empty if the invocation of {@code Class#getMethod()} throws a - * {@link NoSuchMethodException} - * @deprecated Please use {@link #tryToGetMethod(Class, String, Class[])} - * instead. - */ - @API(status = DEPRECATED, since = "1.4") - @Deprecated - static Optional getMethod(Class clazz, String methodName, Class... parameterTypes) { - return tryToGetMethod(clazz, methodName, parameterTypes).toOptional(); - } - /** * Try to get the {@link Method} in the specified class with the specified * name and parameter types. From e5514b69b55b2094b9dda08d613fc2a3a5429dd0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:30:22 +0200 Subject: [PATCH 029/521] Delete deprecated `ClasspathScanningSupport` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../filter/ClasspathScanningSupport.java | 71 ------------------- .../engine/support/filter/package-info.java | 6 -- .../module-info.java | 1 - .../junit-platform-engine.expected.txt | 1 - 5 files changed, 1 insertion(+), 79 deletions(-) delete mode 100644 junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java delete mode 100644 junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/package-info.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index f88ece1ed3a3..af43bed5d53e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -51,6 +51,7 @@ repository on GitHub. - `ReflectionUtils.getMethod(...)` method - `BlacklistedExceptions` class - `PreconditionViolationException` class (from `org.junit.platform.commons.util`) + - `ClasspathScanningSupport` class [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java deleted file mode 100644 index 1eabfbdd8475..000000000000 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/ClasspathScanningSupport.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * 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.engine.support.filter; - -import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.junit.platform.engine.Filter.composeFilters; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; - -import org.apiguardian.api.API; -import org.junit.platform.commons.support.scanning.ClassFilter; -import org.junit.platform.engine.DiscoveryFilter; -import org.junit.platform.engine.EngineDiscoveryRequest; -import org.junit.platform.engine.discovery.ClassNameFilter; -import org.junit.platform.engine.discovery.PackageNameFilter; - -/** - * Support utility methods for classpath scanning. - * - * @since 1.0 - * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. - */ -@Deprecated -@API(status = DEPRECATED, since = "1.5") -public final class ClasspathScanningSupport { - - private ClasspathScanningSupport() { - /* no-op */ - } - - /** - * Build a {@link Predicate} for fully qualified class names to be used for - * classpath scanning from an {@link EngineDiscoveryRequest}. - * - * @param request the request to build a predicate from - * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. - */ - @Deprecated - public static Predicate buildClassNamePredicate(EngineDiscoveryRequest request) { - List> filters = new ArrayList<>(); - filters.addAll(request.getFiltersByType(ClassNameFilter.class)); - filters.addAll(request.getFiltersByType(PackageNameFilter.class)); - return composeFilters(filters).toPredicate(); - } - - /** - * Build a {@link ClassFilter} by combining the name predicate built by - * {@link #buildClassNamePredicate(EngineDiscoveryRequest)} and the passed-in - * class predicate. - * - * @param request the request to build a name predicate from - * @param classPredicate the class predicate - * @deprecated Please use {@link org.junit.platform.engine.support.discovery.EngineDiscoveryRequestResolver} instead. - */ - @Deprecated - @SuppressWarnings("exports") - public static ClassFilter buildClassFilter(EngineDiscoveryRequest request, Predicate> classPredicate) { - return ClassFilter.of(buildClassNamePredicate(request), classPredicate); - } - -} diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/package-info.java deleted file mode 100644 index c074ecf00bf0..000000000000 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/filter/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * {@link org.junit.platform.engine.Filter}-related support classes intended to be - * used by test engine implementations. - */ - -package org.junit.platform.engine.support.filter; diff --git a/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java b/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java index d595f8bdcd1b..4727b0182960 100644 --- a/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java +++ b/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java @@ -28,7 +28,6 @@ exports org.junit.platform.engine.support.config; exports org.junit.platform.engine.support.descriptor; exports org.junit.platform.engine.support.discovery; - exports org.junit.platform.engine.support.filter; exports org.junit.platform.engine.support.hierarchical; exports org.junit.platform.engine.support.store; diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt index 2809c8a87fec..7849ee4adb77 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt @@ -5,7 +5,6 @@ exports org.junit.platform.engine.reporting exports org.junit.platform.engine.support.config exports org.junit.platform.engine.support.descriptor exports org.junit.platform.engine.support.discovery -exports org.junit.platform.engine.support.filter exports org.junit.platform.engine.support.hierarchical exports org.junit.platform.engine.support.store requires java.base mandated From 95391e4d41ca11533148c6122202f098e3a31b47 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:33:21 +0200 Subject: [PATCH 030/521] Delete deprecated `ConfigurationParameters.size()` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../platform/engine/ConfigurationParameters.java | 10 ---------- .../config/PrefixedConfigurationParameters.java | 6 ------ .../core/LauncherConfigurationParameters.java | 14 -------------- .../engine/descriptor/ExtensionContextTests.java | 6 ------ .../tasks/DiscoveryRequestCreatorTests.java | 4 ---- .../PrefixedConfigurationParametersTests.java | 11 ----------- .../launcher/core/DefaultLauncherTests.java | 6 ------ .../core/LauncherConfigurationParametersTests.java | 2 -- .../SuiteLauncherDiscoveryRequestBuilderTests.java | 6 ------ .../suite/engine/SuiteTestDescriptorTests.java | 6 ------ 11 files changed, 1 insertion(+), 71 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index af43bed5d53e..f8659ccc10c3 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -52,6 +52,7 @@ repository on GitHub. - `BlacklistedExceptions` class - `PreconditionViolationException` class (from `org.junit.platform.commons.util`) - `ClasspathScanningSupport` class + - `ConfigurationParameters.size()` method [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java index c28f9229d9ce..53968332bfea 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java @@ -10,7 +10,6 @@ package org.junit.platform.engine; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.util.Optional; @@ -131,15 +130,6 @@ default Optional get(String key, Function transformer) { }); } - /** - * Get the number of configuration parameters stored directly in this - * {@code ConfigurationParameters}. - * @deprecated as of JUnit Platform 1.9 in favor of {@link #keySet()} - */ - @Deprecated - @API(status = DEPRECATED, since = "1.9") - int size(); - /** * Get the keys of all configuration parameters stored in this * {@code ConfigurationParameters}. diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java index 31454eca91cd..d78dc800219d 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java @@ -65,12 +65,6 @@ private String prefixed(String key) { return prefix + key; } - @Override - @SuppressWarnings("deprecation") - public int size() { - return delegate.size(); - } - @Override public Set keySet() { return delegate.keySet(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java index a33793a346e9..9d1adea4f511 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java @@ -64,14 +64,6 @@ public Optional getBoolean(String key) { return get(key).map(Boolean::parseBoolean); } - @Override - @SuppressWarnings("deprecation") - public int size() { - return providers.stream() // - .mapToInt(ParameterProvider::size) // - .sum(); - } - @Override public Set keySet() { return providers.stream().map(ParameterProvider::keySet).flatMap(Collection::stream).collect( @@ -245,12 +237,6 @@ public String getValue(String key) { return configParams.get(key).orElse(null); } - @Override - @SuppressWarnings("deprecation") - public int size() { - return configParams.size(); - } - @Override public Set keySet() { return configParams.keySet(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index 2417b145c380..533ec415b06b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -543,12 +543,6 @@ public Optional getBoolean(String key) { throw new UnsupportedOperationException("getBoolean(String) should not be called"); } - @SuppressWarnings({ "deprecation", "RedundantSuppression" }) - @Override - public int size() { - throw new UnsupportedOperationException("size() should not be called"); - } - @Override public Set keySet() { throw new UnsupportedOperationException("keySet() should not be called"); diff --git a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java index e1ec970f3ecd..4b29e747cc76 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java @@ -329,7 +329,6 @@ void propagatesSelectorIdentifiers() { } @Test - @SuppressWarnings("deprecation") void convertsConfigurationParameters() { options.setScanClasspath(true); options.setConfigurationParameters(mapOf(entry("foo", "bar"), entry("baz", "true"))); @@ -337,13 +336,11 @@ void convertsConfigurationParameters() { var request = convert(); var configurationParameters = request.getConfigurationParameters(); - assertThat(configurationParameters.size()).isEqualTo(2); assertThat(configurationParameters.get("foo")).contains("bar"); assertThat(configurationParameters.getBoolean("baz")).contains(true); } @Test - @SuppressWarnings("deprecation") void convertsConfigurationParametersResources() { options.setScanClasspath(true); options.setConfigurationParameters(mapOf(entry("foo", "bar"), entry("com.example.prop.first", "baz"))); @@ -352,7 +349,6 @@ void convertsConfigurationParametersResources() { var request = convert(); var configurationParameters = request.getConfigurationParameters(); - assertThat(configurationParameters.size()).isEqualTo(2); assertThat(configurationParameters.get("foo")).contains("bar"); assertThat(configurationParameters.get("com.example.prop.first")).contains("baz"); assertThat(configurationParameters.get("com.example.prop.second")).contains("second value"); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java index ae64f77463d3..fe064e60e58b 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java @@ -76,15 +76,4 @@ void delegatesGetWithTransformerCalls() { verify(delegate).get("foo.bar.qux", transformer); } - @Test - @SuppressWarnings("deprecation") - void delegatesSizeCalls() { - when(delegate.size()).thenReturn(42); - var parameters = new PrefixedConfigurationParameters(delegate, "foo.bar."); - - assertThat(parameters.size()).isEqualTo(42); - - verify(delegate).size(); - } - } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java index 1722bd9bfc42..8b21fa52516e 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java @@ -420,7 +420,6 @@ void launcherAppliesPostDiscoveryFilters() { } @Test - @SuppressWarnings("deprecation") void withoutConfigurationParameters_LauncherPassesEmptyConfigurationParametersIntoTheExecutionRequest() { var engine = new TestEngineSpy(); @@ -429,11 +428,9 @@ void withoutConfigurationParameters_LauncherPassesEmptyConfigurationParametersIn var configurationParameters = engine.requestForExecution.getConfigurationParameters(); assertThat(configurationParameters.get("key")).isNotPresent(); - assertThat(configurationParameters.size()).isEqualTo(0); } @Test - @SuppressWarnings("deprecation") void withConfigurationParameters_LauncherPassesPopulatedConfigurationParametersIntoTheExecutionRequest() { var engine = new TestEngineSpy(); @@ -441,13 +438,11 @@ void withConfigurationParameters_LauncherPassesPopulatedConfigurationParametersI launcher.execute(request().configurationParameter("key", "value").build()); var configurationParameters = engine.requestForExecution.getConfigurationParameters(); - assertThat(configurationParameters.size()).isEqualTo(1); assertThat(configurationParameters.get("key")).isPresent(); assertThat(configurationParameters.get("key")).contains("value"); } @Test - @SuppressWarnings("deprecation") void withoutConfigurationParameters_LookupFallsBackToSystemProperty() { System.setProperty(FOO, BAR); @@ -458,7 +453,6 @@ void withoutConfigurationParameters_LookupFallsBackToSystemProperty() { launcher.execute(request().build()); var configurationParameters = engine.requestForExecution.getConfigurationParameters(); - assertThat(configurationParameters.size()).isEqualTo(0); var optionalFoo = configurationParameters.get(FOO); assertTrue(optionalFoo.isPresent(), "foo should have been picked up via system property"); assertEquals(BAR, optionalFoo.get(), "foo property"); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java index 2bd8b5aea1da..b2608e60fcba 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java @@ -44,7 +44,6 @@ * * @since 1.0 */ -@SuppressWarnings("deprecation") class LauncherConfigurationParametersTests { private static final String CONFIG_FILE_NAME = "test-junit-platform.properties"; @@ -79,7 +78,6 @@ void getPreconditions() { @Test void noConfigParams() { ConfigurationParameters configParams = fromMap(Map.of()); - assertThat(configParams.size()).isEqualTo(0); assertThat(configParams.get(KEY)).isEmpty(); assertThat(configParams.keySet()).doesNotContain(KEY); assertThat(configParams.toString()).doesNotContain(KEY); diff --git a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java index b2239ca97817..60d244895eea 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java @@ -689,12 +689,6 @@ public Optional getBoolean(String key) { return Optional.empty(); } - @Override - @SuppressWarnings("deprecation") - public int size() { - return map.size(); - } - @Override public Set keySet() { return null; diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteTestDescriptorTests.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteTestDescriptorTests.java index d9b2be9a741e..1d75e9555ae7 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteTestDescriptorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/SuiteTestDescriptorTests.java @@ -113,12 +113,6 @@ public Optional getBoolean(String key) { return Optional.empty(); } - @Override - @SuppressWarnings("deprecation") - public int size() { - return 0; - } - @Override public Set keySet() { return Collections.emptySet(); From 6019f8a8ac8c7d2294ec6548a88dbb26e0a13811 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:34:20 +0200 Subject: [PATCH 031/521] Delete deprecated `MethodSelector.getMethodParameterTypes()` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../engine/discovery/MethodSelector.java | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index f8659ccc10c3..5cb86b255a1e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -53,6 +53,7 @@ repository on GitHub. - `PreconditionViolationException` class (from `org.junit.platform.commons.util`) - `ClasspathScanningSupport` class - `ConfigurationParameters.size()` method + - `MethodSelector.getMethodParameterTypes()` method [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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..d5df4bdd99ea 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 @@ -10,7 +10,6 @@ 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.STABLE; @@ -145,23 +144,6 @@ public String getMethodName() { return this.methodName; } - /** - * Get the names of parameter types for the selected method. - * - *

See {@link #getParameterTypeNames()} for details. - * - * @return the names of parameter types - * @since 1.0 - * @see #getParameterTypeNames() - * @see #getParameterTypes() - * @deprecated since 1.10 in favor of {@link #getParameterTypeNames()} - */ - @Deprecated - @API(status = DEPRECATED, since = "1.10") - public String getMethodParameterTypes() { - return getParameterTypeNames(); - } - /** * Get the names of parameter types for the selected method as a {@link String}, * typically a comma-separated list of primitive types, fully qualified class From 10609d4e2f0c7b76aba865234fa9293ee8756b6b Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:34:51 +0200 Subject: [PATCH 032/521] Delete deprecated `NestedMethodSelector.getMethodParameterTypes()` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../engine/discovery/NestedMethodSelector.java | 18 ------------------ 2 files changed, 1 insertion(+), 18 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 5cb86b255a1e..c749f6875bc8 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -54,6 +54,7 @@ repository on GitHub. - `ClasspathScanningSupport` class - `ConfigurationParameters.size()` method - `MethodSelector.getMethodParameterTypes()` method + - `NestedMethodSelector.getMethodParameterTypes()` method [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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..7d57ec1751ec 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 @@ -10,7 +10,6 @@ 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.STABLE; @@ -164,23 +163,6 @@ public Method getMethod() { return this.methodSelector.getJavaMethod(); } - /** - * Get the names of parameter types for the selected method. - * - *

See {@link #getParameterTypeNames()} for details. - * - * @return the names of parameter types - * @since 1.6 - * @see #getParameterTypeNames() - * @see #getParameterTypes() - * @deprecated since 1.10 in favor or {@link #getParameterTypeNames()} - */ - @Deprecated - @API(status = DEPRECATED, since = "1.10") - public String getMethodParameterTypes() { - return getParameterTypeNames(); - } - /** * Get the names of parameter types for the selected method as a {@link String}. * From 6d997219af5cbe272fffbb888c9971b6c373a668 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:35:41 +0200 Subject: [PATCH 033/521] Make deprecated `ReportEntry` constructor `private` --- .../asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 1 + .../org/junit/platform/engine/reporting/ReportEntry.java | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index c749f6875bc8..420a59a9fdce 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -55,6 +55,7 @@ repository on GitHub. - `ConfigurationParameters.size()` method - `MethodSelector.getMethodParameterTypes()` method - `NestedMethodSelector.getMethodParameterTypes()` method + - `ReportEntry()` constructor [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/ReportEntry.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/ReportEntry.java index 0af74b590121..28587cfe0615 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/ReportEntry.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/ReportEntry.java @@ -10,7 +10,6 @@ package org.junit.platform.engine.reporting; -import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import java.time.LocalDateTime; @@ -36,12 +35,7 @@ public final class ReportEntry { private final LocalDateTime timestamp = LocalDateTime.now(); private final Map keyValuePairs = new LinkedHashMap<>(); - /** - * @deprecated Use {@link #from(String, String)} or {@link #from(Map)} - */ - @API(status = DEPRECATED, since = "1.8") - @Deprecated - public ReportEntry() { + private ReportEntry() { } /** From 65037d5682e599afabb06bb957d52a9dfe807973 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:36:23 +0200 Subject: [PATCH 034/521] Delete deprecated `SingleTestExecutor` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../hierarchical/SingleTestExecutor.java | 83 ------------------- .../hierarchical/SingleTestExecutorTests.java | 62 -------------- 3 files changed, 1 insertion(+), 145 deletions(-) delete mode 100644 junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java delete mode 100644 platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutorTests.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 420a59a9fdce..0c1603cfddc3 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -56,6 +56,7 @@ repository on GitHub. - `MethodSelector.getMethodParameterTypes()` method - `NestedMethodSelector.getMethodParameterTypes()` method - `ReportEntry()` constructor + - `SingleTestExecutor` class [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java deleted file mode 100644 index 3aa0ab4aea6b..000000000000 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutor.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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.engine.support.hierarchical; - -import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.junit.platform.engine.TestExecutionResult.aborted; -import static org.junit.platform.engine.TestExecutionResult.failed; -import static org.junit.platform.engine.TestExecutionResult.successful; - -import org.apiguardian.api.API; -import org.junit.platform.commons.util.UnrecoverableExceptions; -import org.junit.platform.engine.TestExecutionResult; -import org.opentest4j.TestAbortedException; - -/** - * {@code SingleTestExecutor} encapsulates the execution of a single test - * wrapped in an {@link Executable}. - * - * @since 1.0 - * @see #executeSafely(Executable) - * @deprecated Please use {@link ThrowableCollector#execute} and - * {@link ThrowableCollector#toTestExecutionResult} instead. - */ -@Deprecated -@API(status = DEPRECATED, since = "1.2") -@SuppressWarnings("missing-explicit-ctor") -public class SingleTestExecutor { - - /** - * Functional interface for a single test to be executed by - * {@link SingleTestExecutor}. - */ - @FunctionalInterface - public interface Executable { - - /** - * Execute the test. - * - * @throws TestAbortedException to signal aborted execution - * @throws Throwable to signal failure - */ - void execute() throws TestAbortedException, Throwable; - - } - - /** - * Execute the supplied {@link Executable} and return a - * {@link TestExecutionResult} based on the outcome. - * - *

If the {@code Executable} throws an unrecoverable exception - * — for example, an {@link OutOfMemoryError} — this method will - * rethrow it. - * - * @param executable the test to be executed - * @return {@linkplain TestExecutionResult#aborted aborted} if the - * {@code Executable} throws a {@link TestAbortedException}; - * {@linkplain TestExecutionResult#failed failed} if any other - * {@link Throwable} is thrown; and {@linkplain TestExecutionResult#successful - * successful} otherwise - */ - public TestExecutionResult executeSafely(Executable executable) { - try { - executable.execute(); - return successful(); - } - catch (TestAbortedException e) { - return aborted(e); - } - catch (Throwable t) { - UnrecoverableExceptions.rethrowIfUnrecoverable(t); - return failed(t); - } - } - -} diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutorTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutorTests.java deleted file mode 100644 index 35b139b12243..000000000000 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/SingleTestExecutorTests.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.engine.support.hierarchical; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; -import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; -import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; - -import java.util.Optional; - -import org.junit.jupiter.api.Test; -import org.opentest4j.TestAbortedException; - -/** - * @since 1.0 - */ -@SuppressWarnings("deprecation") -class SingleTestExecutorTests { - - @Test - void executeSafelySuccessful() { - var result = new SingleTestExecutor().executeSafely(() -> { - }); - - assertEquals(SUCCESSFUL, result.getStatus()); - assertEquals(Optional.empty(), result.getThrowable()); - } - - @Test - void executeSafelyAborted() { - var testAbortedException = new TestAbortedException("assumption violated"); - - var result = new SingleTestExecutor().executeSafely(() -> { - throw testAbortedException; - }); - - assertEquals(ABORTED, result.getStatus()); - assertSame(testAbortedException, result.getThrowable().get()); - } - - @Test - void executeSafelyFailed() { - var assertionError = new AssertionError("assumption violated"); - - var result = new SingleTestExecutor().executeSafely(() -> { - throw assertionError; - }); - - assertEquals(FAILED, result.getStatus()); - assertSame(assertionError, result.getThrowable().get()); - } -} From 46a5d3f6951a3cfd1adffca9db90e8a506e135c4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:37:04 +0200 Subject: [PATCH 035/521] Make deprecated `LauncherDiscoveryRequestBuilder` constructor `private` --- .../asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 1 + .../launcher/core/LauncherDiscoveryRequestBuilder.java | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 0c1603cfddc3..d1b1005b4a04 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -57,6 +57,7 @@ repository on GitHub. - `NestedMethodSelector.getMethodParameterTypes()` method - `ReportEntry()` constructor - `SingleTestExecutor` class + - `LauncherDiscoveryRequestBuilder()` constructor [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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..4c237b54bbd9 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 @@ -10,7 +10,6 @@ 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.STABLE; import static org.junit.platform.launcher.LauncherConstants.OUTPUT_DIR_PROPERTY_NAME; @@ -122,12 +121,7 @@ public static LauncherDiscoveryRequestBuilder request() { return new LauncherDiscoveryRequestBuilder(); } - /** - * @deprecated Use {@link #request()} - */ - @API(status = DEPRECATED, since = "1.8") - @Deprecated - public LauncherDiscoveryRequestBuilder() { + private LauncherDiscoveryRequestBuilder() { } /** From b942e2e9fb983d63db7002eb52125cab870cab13 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:38:49 +0200 Subject: [PATCH 036/521] Delete deprecated `LegacyReportingUtils` --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../listeners/LegacyReportingUtils.java | 86 ----------------- .../legacy/LegacyReportingUtils.java | 33 ++++++- .../legacy/LegacyReportingUtilsTests.java | 94 ------------------- 4 files changed, 32 insertions(+), 182 deletions(-) delete mode 100644 junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LegacyReportingUtils.java delete mode 100644 platform-tests/src/test/java/org/junit/platform/reporting/legacy/LegacyReportingUtilsTests.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index d1b1005b4a04..454aa113232f 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -58,6 +58,7 @@ repository on GitHub. - `ReportEntry()` constructor - `SingleTestExecutor` class - `LauncherDiscoveryRequestBuilder()` constructor + - `LegacyReportingUtils` class [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LegacyReportingUtils.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LegacyReportingUtils.java deleted file mode 100644 index 9417a1482856..000000000000 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LegacyReportingUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * 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.launcher.listeners; - -import static org.apiguardian.api.API.Status.DEPRECATED; - -import org.apiguardian.api.API; -import org.junit.platform.commons.util.Preconditions; -import org.junit.platform.engine.support.descriptor.ClassSource; -import org.junit.platform.launcher.TestIdentifier; -import org.junit.platform.launcher.TestPlan; - -/** - * Utility methods for dealing with legacy reporting infrastructure, such as - * reporting systems built on the Ant-based XML reporting format for JUnit 4. - * - * @since 1.0.3 - * @deprecated Use {@link org.junit.platform.reporting.legacy.LegacyReportingUtils} - * instead. - */ -@Deprecated -@SuppressWarnings("JavadocReference") -@API(status = DEPRECATED, since = "1.6") -public class LegacyReportingUtils { - - private LegacyReportingUtils() { - /* no-op */ - } - - /** - * Get the class name for the supplied {@link TestIdentifier} using the - * supplied {@link TestPlan}. - * - *

This implementation attempts to find the closest test identifier with - * a {@link ClassSource} by traversing the hierarchy upwards towards the - * root starting with the supplied test identifier. In case no such source - * is found, it falls back to using the parent's - * {@linkplain TestIdentifier#getLegacyReportingName legacy reporting name}. - * - * @param testPlan the test plan that contains the {@code TestIdentifier}; - * never {@code null} - * @param testIdentifier the identifier to determine the class name for; - * never {@code null} - * @see TestIdentifier#getLegacyReportingName - */ - public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifier) { - Preconditions.notNull(testPlan, "testPlan must not be null"); - Preconditions.notNull(testIdentifier, "testIdentifier must not be null"); - for (TestIdentifier current = testIdentifier; current != null; current = getParent(testPlan, current)) { - ClassSource source = getClassSource(current); - if (source != null) { - return source.getClassName(); - } - } - return getParentLegacyReportingName(testPlan, testIdentifier); - } - - private static TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { - return testPlan.getParent(testIdentifier).orElse(null); - } - - private static ClassSource getClassSource(TestIdentifier current) { - // @formatter:off - return current.getSource() - .filter(ClassSource.class::isInstance) - .map(ClassSource.class::cast) - .orElse(null); - // @formatter:on - } - - private static String getParentLegacyReportingName(TestPlan testPlan, TestIdentifier testIdentifier) { - // @formatter:off - return testPlan.getParent(testIdentifier) - .map(TestIdentifier::getLegacyReportingName) - .orElse(""); - // @formatter:on - } -} diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java index 318a6b5351ed..1f76a53869b1 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; +import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.TestIdentifier; import org.junit.platform.launcher.TestPlan; @@ -49,9 +50,37 @@ private LegacyReportingUtils() { * never {@code null} * @see TestIdentifier#getLegacyReportingName */ - @SuppressWarnings("deprecation") public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifier) { - return org.junit.platform.launcher.listeners.LegacyReportingUtils.getClassName(testPlan, testIdentifier); + Preconditions.notNull(testPlan, "testPlan must not be null"); + Preconditions.notNull(testIdentifier, "testIdentifier must not be null"); + for (TestIdentifier current = testIdentifier; current != null; current = getParent(testPlan, current)) { + ClassSource source = getClassSource(current); + if (source != null) { + return source.getClassName(); + } + } + return getParentLegacyReportingName(testPlan, testIdentifier); + } + + private static TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { + return testPlan.getParent(testIdentifier).orElse(null); + } + + private static ClassSource getClassSource(TestIdentifier current) { + // @formatter:off + return current.getSource() + .filter(ClassSource.class::isInstance) + .map(ClassSource.class::cast) + .orElse(null); + // @formatter:on + } + + private static String getParentLegacyReportingName(TestPlan testPlan, TestIdentifier testIdentifier) { + // @formatter:off + return testPlan.getParent(testIdentifier) + .map(TestIdentifier::getLegacyReportingName) + .orElse(""); + // @formatter:on } } diff --git a/platform-tests/src/test/java/org/junit/platform/reporting/legacy/LegacyReportingUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/reporting/legacy/LegacyReportingUtilsTests.java deleted file mode 100644 index 6f5e67291f2f..000000000000 --- a/platform-tests/src/test/java/org/junit/platform/reporting/legacy/LegacyReportingUtilsTests.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * 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.reporting.legacy; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.platform.launcher.core.OutputDirectoryProviders.dummyOutputDirectoryProvider; -import static org.mockito.Mockito.mock; - -import java.util.Set; - -import org.junit.jupiter.api.Test; -import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.TestSource; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; -import org.junit.platform.engine.support.descriptor.ClassSource; -import org.junit.platform.engine.support.descriptor.EngineDescriptor; -import org.junit.platform.launcher.TestPlan; - -/** - * @since 1.0.3 - */ -class LegacyReportingUtilsTests { - - private TestDescriptor engineDescriptor = new EngineDescriptor(UniqueId.forEngine("foo"), "Foo"); - - @Test - void legacyReportingClassNameForTestIdentifierWithoutClassSourceIsParentLegacyReportingName() { - var uniqueId = engineDescriptor.getUniqueId().append("child", "bar"); - var testDescriptor = createTestDescriptor(uniqueId, "Bar", null); - engineDescriptor.addChild(testDescriptor); - - assertThat(getClassName(engineDescriptor.getUniqueId())).isEqualTo(""); - assertThat(getClassName(uniqueId)).isEqualTo("Foo"); - - assertThat(getClassNameFromOldLocation(engineDescriptor.getUniqueId())).isEqualTo(""); - assertThat(getClassNameFromOldLocation(uniqueId)).isEqualTo("Foo"); - } - - @Test - void legacyReportingClassNameForDescendantOfTestIdentifierWithClassSourceIsClassName() { - var classUniqueId = engineDescriptor.getUniqueId().append("class", "class"); - var classDescriptor = createTestDescriptor(classUniqueId, "Class", - ClassSource.from(LegacyReportingUtilsTests.class)); - engineDescriptor.addChild(classDescriptor); - - var subUniqueId = classUniqueId.append("sub", "baz"); - var subDescriptor = createTestDescriptor(subUniqueId, "Baz", null); - classDescriptor.addChild(subDescriptor); - - var subSubUniqueId = subUniqueId.append("subsub", "qux"); - var subSubDescriptor = createTestDescriptor(subSubUniqueId, "Qux", null); - subDescriptor.addChild(subSubDescriptor); - - assertThat(getClassName(engineDescriptor.getUniqueId())).isEqualTo(""); - assertThat(getClassName(classUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - assertThat(getClassName(subUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - assertThat(getClassName(subSubUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - - assertThat(getClassNameFromOldLocation(engineDescriptor.getUniqueId())).isEqualTo(""); - assertThat(getClassNameFromOldLocation(classUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - assertThat(getClassNameFromOldLocation(subUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - assertThat(getClassNameFromOldLocation(subSubUniqueId)).isEqualTo(LegacyReportingUtilsTests.class.getName()); - } - - private String getClassName(UniqueId uniqueId) { - var testPlan = TestPlan.from(true, Set.of(engineDescriptor), mock(), dummyOutputDirectoryProvider()); - return LegacyReportingUtils.getClassName(testPlan, testPlan.getTestIdentifier(uniqueId)); - } - - @SuppressWarnings("deprecation") - private String getClassNameFromOldLocation(UniqueId uniqueId) { - var testPlan = TestPlan.from(true, Set.of(engineDescriptor), mock(), dummyOutputDirectoryProvider()); - return org.junit.platform.launcher.listeners.LegacyReportingUtils.getClassName(testPlan, - testPlan.getTestIdentifier(uniqueId)); - } - - private TestDescriptor createTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { - return new AbstractTestDescriptor(uniqueId, displayName, source) { - @Override - public Type getType() { - return Type.CONTAINER_AND_TEST; - } - }; - } -} From ce5fadd81ea1fa7141e0c5bd410e62f3d02da93e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:41:04 +0200 Subject: [PATCH 037/521] Delete deprecated `TestPlan` methods --- .../release-notes/release-notes-6.0.0-M1.adoc | 2 + .../org/junit/platform/launcher/TestPlan.java | 50 ------------------- .../launcher/core/InternalTestPlan.java | 18 ------- .../launcher/core/DefaultLauncherTests.java | 19 ------- 4 files changed, 2 insertions(+), 87 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 454aa113232f..072a44d39126 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -59,6 +59,8 @@ repository on GitHub. - `SingleTestExecutor` class - `LauncherDiscoveryRequestBuilder()` constructor - `LegacyReportingUtils` class + - `TestPlan.add(TestIdentifier)`, `TestPlan.getChildren(String)`, and + `TestPlan.getTestIdentifier(String)` methods [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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..9f4e66681f63 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 @@ -13,7 +13,6 @@ import static java.util.Collections.emptySet; 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; @@ -28,7 +27,6 @@ import java.util.function.Predicate; import org.apiguardian.api.API; -import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; @@ -105,21 +103,6 @@ protected TestPlan(boolean containsTests, ConfigurationParameters configurationP this.outputDirectoryProvider = outputDirectoryProvider; } - /** - * Add the supplied {@link TestIdentifier} to this test plan. - * - * @param testIdentifier the identifier to add; never {@code null} - * @deprecated Calling this method is no longer supported and will throw an - * exception. - * @throws JUnitException always - */ - @Deprecated - @API(status = DEPRECATED, since = "1.4") - public void add(@SuppressWarnings("unused") TestIdentifier testIdentifier) { - throw new JUnitException("Unsupported attempt to modify the TestPlan was detected. " - + "Please contact your IDE/tool vendor and request a fix or downgrade to JUnit 5.7.x (see https://github.com/junit-team/junit5/issues/1732 for details)."); - } - @API(status = INTERNAL, since = "1.8") public void addInternal(TestIdentifier testIdentifier) { Preconditions.notNull(testIdentifier, "testIdentifier must not be null"); @@ -176,22 +159,6 @@ public Set getChildren(TestIdentifier parent) { return getChildren(parent.getUniqueIdObject()); } - /** - * Get the children of the supplied unique ID. - * - * @param parentId the unique ID to look up the children for; never - * {@code null} or blank - * @return an unmodifiable set of the parent's children, potentially empty - * @see #getChildren(TestIdentifier) - * @deprecated Use {@link #getChildren(UniqueId)} - */ - @API(status = DEPRECATED, since = "1.10") - @Deprecated - public Set getChildren(String parentId) { - Preconditions.notBlank(parentId, "parent ID must not be null or blank"); - return getChildren(UniqueId.parse(parentId)); - } - /** * Get the children of the supplied unique ID. * @@ -205,23 +172,6 @@ public Set getChildren(UniqueId parentId) { return children.containsKey(parentId) ? unmodifiableSet(children.get(parentId)) : emptySet(); } - /** - * Get the {@link TestIdentifier} with the supplied unique ID. - * - * @param uniqueId the unique ID to look up the identifier for; never - * {@code null} or blank - * @return the identifier with the supplied unique ID; never {@code null} - * @throws PreconditionViolationException if no {@code TestIdentifier} - * with the supplied unique ID is present in this test plan - * @deprecated Use {@link #getTestIdentifier(UniqueId)} - */ - @API(status = DEPRECATED, since = "1.10") - @Deprecated - public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { - Preconditions.notBlank(uniqueId, "unique ID must not be null or blank"); - return getTestIdentifier(UniqueId.parse(uniqueId)); - } - /** * Get the {@link TestIdentifier} with the supplied unique ID. * diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalTestPlan.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalTestPlan.java index 4440a6209801..d2c7d2c98254 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalTestPlan.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InternalTestPlan.java @@ -56,12 +56,6 @@ public TestPlan getDelegate() { return delegate; } - @Override - @SuppressWarnings("deprecation") - public void add(TestIdentifier testIdentifier) { - delegate.add(testIdentifier); - } - @Override public void addInternal(TestIdentifier testIdentifier) { delegate.addInternal(testIdentifier); @@ -82,23 +76,11 @@ public Set getChildren(TestIdentifier parent) { return delegate.getChildren(parent); } - @SuppressWarnings("deprecation") - @Override - public Set getChildren(String parentId) { - return delegate.getChildren(parentId); - } - @Override public Set getChildren(UniqueId parentId) { return delegate.getChildren(parentId); } - @SuppressWarnings("deprecation") - @Override - public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { - return delegate.getTestIdentifier(uniqueId); - } - @Override public TestIdentifier getTestIdentifier(UniqueId uniqueId) { return delegate.getTestIdentifier(uniqueId); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java index 8b21fa52516e..0fdcb863a9df 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java @@ -594,25 +594,6 @@ void launcherCanExecuteTestPlanExactlyOnce() { assertEquals("TestPlan must only be executed once", e.getMessage()); } - @Test - @SuppressWarnings("deprecation") - void testPlanThrowsExceptionWhenModified() { - TestEngine engine = new TestEngineSpy(); - var launcher = createLauncher(engine); - var testPlan = launcher.discover(request().build()); - var engineIdentifier = getOnlyElement(testPlan.getRoots()); - var engineUniqueId = engineIdentifier.getUniqueIdObject(); - assertThat(testPlan.getChildren(engineIdentifier)).hasSize(1); - - var addedIdentifier = TestIdentifier.from( - new TestDescriptorStub(engineUniqueId.append("test", "test2"), "test2")); - - var exception = assertThrows(JUnitException.class, () -> testPlan.add(addedIdentifier)); - assertThat(exception).hasMessage("Unsupported attempt to modify the TestPlan was detected. " - + "Please contact your IDE/tool vendor and request a fix or downgrade to JUnit 5.7.x (see https://github.com/junit-team/junit5/issues/1732 for details)."); - assertThat(testPlan.getChildren(engineIdentifier)).hasSize(1).doesNotContain(addedIdentifier); - } - @Test void thirdPartyEngineUsingReservedEngineIdPrefixEmitsWarning(@TrackLogRecords LogRecordListener listener) { var id = "junit-using-reserved-prefix"; From ea6aae9ba4ae8b7688c253a5e77ff3323f075443 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 14:56:35 +0200 Subject: [PATCH 038/521] Delete deprecated `junit-platform-runner` module --- build.gradle.kts | 1 - documentation/documentation.gradle.kts | 1 - .../release-notes/release-notes-6.0.0-M1.adoc | 2 + .../docs/asciidoc/user-guide/appendix.adoc | 3 - .../asciidoc/user-guide/running-tests.adoc | 122 +-- .../asciidoc/user-guide/writing-tests.adoc | 5 +- .../src/plantuml/component-diagram.puml | 4 - .../java/example/JUnitPlatformClassDemo.java | 39 - .../java/example/JUnitPlatformSuiteDemo.java | 27 - .../module-info.java | 2 - .../core/ClasspathAlignmentChecker.java | 1 - .../junit-platform-runner.gradle.kts | 37 - .../junit/platform/runner/JUnitPlatform.java | 206 ---- .../runner/JUnitPlatformRunnerListener.java | 102 -- .../runner/JUnitPlatformTestTree.java | 167 ---- .../junit/platform/runner/package-info.java | 6 - .../module-info.java | 25 - junit-platform-runner/src/test/README.md | 1 - .../suite/api/ConfigurationParameter.java | 1 - .../api/ConfigurationParametersResource.java | 1 - .../suite/api/ExcludeClassNamePatterns.java | 1 - .../platform/suite/api/ExcludeEngines.java | 1 - .../platform/suite/api/ExcludePackages.java | 1 - .../junit/platform/suite/api/ExcludeTags.java | 1 - .../suite/api/IncludeClassNamePatterns.java | 1 - .../platform/suite/api/IncludeEngines.java | 1 - .../platform/suite/api/IncludePackages.java | 1 - .../junit/platform/suite/api/IncludeTags.java | 1 - .../platform/suite/api/SelectClasses.java | 1 - .../suite/api/SelectClasspathResource.java | 1 - .../platform/suite/api/SelectDirectories.java | 1 - .../junit/platform/suite/api/SelectFile.java | 1 - .../platform/suite/api/SelectMethod.java | 1 - .../platform/suite/api/SelectModules.java | 1 - .../platform/suite/api/SelectPackages.java | 1 - .../junit/platform/suite/api/SelectUris.java | 1 - .../platform/suite/api/SuiteDisplayName.java | 11 +- .../platform/suite/api/UseTechnicalNames.java | 5 - .../platform/suite/api/package-info.java | 10 +- .../SuiteLauncherDiscoveryRequestBuilder.java | 2 +- .../module-info.java | 3 +- .../junit-vintage-engine.gradle.kts | 2 +- .../junit/platform/runner/JUnitPlatform.java | 44 + .../TestCaseRunWithJUnitPlatformRunner.java | 1 - platform-tests/platform-tests.gradle.kts | 1 - .../runner/JUnitPlatformRunnerTests.java | 905 ------------------ .../junit-platform-commons.expected.txt | 4 +- .../junit-platform-runner.expected.txt | 8 - .../junit-platform-suite-commons.expected.txt | 2 +- .../tooling/support/tests/ArchUnitTests.java | 1 - .../platform/tooling/support/HelperTests.java | 1 - .../support/tests/ModularUserGuideTests.java | 2 +- settings.gradle.kts | 1 - 53 files changed, 63 insertions(+), 1709 deletions(-) delete mode 100644 documentation/src/test/java/example/JUnitPlatformClassDemo.java delete mode 100644 documentation/src/test/java/example/JUnitPlatformSuiteDemo.java delete mode 100644 junit-platform-runner/junit-platform-runner.gradle.kts delete mode 100644 junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatform.java delete mode 100644 junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformRunnerListener.java delete mode 100644 junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformTestTree.java delete mode 100644 junit-platform-runner/src/main/java/org/junit/platform/runner/package-info.java delete mode 100644 junit-platform-runner/src/module/org.junit.platform.runner/module-info.java delete mode 100644 junit-platform-runner/src/test/README.md create mode 100644 junit-vintage-engine/src/testFixtures/java/org/junit/platform/runner/JUnitPlatform.java delete mode 100644 platform-tests/src/test/java/org/junit/platform/runner/JUnitPlatformRunnerTests.java delete mode 100644 platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt diff --git a/build.gradle.kts b/build.gradle.kts index cd79a120700b..82ec852b1f77 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,7 +24,6 @@ val platformProjects by extra(listOf( projects.junitPlatformJfr, projects.junitPlatformLauncher, projects.junitPlatformReporting, - projects.junitPlatformRunner, projects.junitPlatformSuite, projects.junitPlatformSuiteApi, projects.junitPlatformSuiteCommons, diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 3365a42892b7..d4a5ed03cf17 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -62,7 +62,6 @@ dependencies { testImplementation(projects.junitJupiterMigrationsupport) testImplementation(projects.junitPlatformConsole) - testImplementation(projects.junitPlatformRunner) testImplementation(projects.junitPlatformSuite) testImplementation(projects.junitPlatformTestkit) testImplementation(projects.junitVintageEngine) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 072a44d39126..2c2d91e7078b 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -45,6 +45,8 @@ repository on GitHub. subcommand. * Remove support for deprecated non-conventional `ConsoleLauncher` options such as `--h` (rather than `-h`) or `-help` (rather than `--help`). +* The `junit-platform-runner` module that provided the `JUnitPlatform` runner has been + discontinued. * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index 25fa10af297f..c2ca8404dc0a 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -70,9 +70,6 @@ Please refer to the corresponding sections for <> for details. - `junit-platform-runner`:: - Runner for executing tests and test suites on the JUnit Platform in a JUnit 4 - environment. See <> for details. `junit-platform-suite`:: JUnit Platform Suite artifact that transitively pulls in dependencies on `junit-platform-suite-api` and `junit-platform-suite-engine` for simplified dependency diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index 980437f5eef1..9c65f2e91fa5 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -101,10 +101,8 @@ documentation. ==== Other IDEs If you are using an editor or IDE other than one of those listed in the previous sections, -the JUnit team provides two alternative solutions to assist you in using JUnit 5. You can -use the <> manually -- for example, from the command line --- or execute tests with a <> if -your IDE has built-in support for JUnit 4. +and it doesn't support running tests on the JUnit Platform, you can use the +<> to run them from the command line. [[running-tests-build]] === Build Support @@ -854,122 +852,6 @@ DYNAMIC = 35 REPORTED = 37 ---- - -[[running-tests-junit-platform-runner]] -=== Using JUnit 4 to run the JUnit Platform - -[WARNING] -.The `JUnitPlatform` runner has been deprecated -==== -The `JUnitPlatform` runner was developed by the JUnit team as an interim solution for -running test suites and tests on the JUnit Platform in a JUnit 4 environment. - -In recent years, all mainstream build tools and IDEs provide built-in support for running -tests directly on the JUnit Platform. - -In addition, the introduction of `@Suite` support provided by the -`junit-platform-suite-engine` module makes the `JUnitPlatform` runner obsolete. See -<> for details. - -The `JUnitPlatform` runner and `@UseTechnicalNames` annotation have therefore been -deprecated in JUnit Platform 1.8 and will be removed in JUnit Platform 2.0. - -If you are using the `JUnitPlatform` runner, please migrate to the `@Suite` support. -==== - -The `JUnitPlatform` runner is a JUnit 4 based `Runner` which enables you to run any test -whose programming model is supported on the JUnit Platform in a JUnit 4 environment -- -for example, a JUnit Jupiter test class. - -Annotating a class with `@RunWith(JUnitPlatform.class)` allows it to be run with IDEs and -build systems that support JUnit 4 but do not yet support the JUnit Platform directly. - -NOTE: Since the JUnit Platform has features that JUnit 4 does not have, the runner is -only able to support a subset of the JUnit Platform functionality, especially with regard -to reporting (see <>). - -[[running-tests-junit-platform-runner-setup]] -==== Setup - -You need the following artifacts and their dependencies on the classpath. See -<> for details regarding group IDs, artifact IDs, and versions. - -[[running-tests-junit-platform-runner-setup-explicit-dependencies]] -===== Explicit Dependencies - -* `junit-platform-runner` in _test_ scope: location of the `JUnitPlatform` runner -* `junit-{junit4-version}.jar` in _test_ scope: to run tests using JUnit 4 -* `junit-jupiter-api` in _test_ scope: API for writing tests using JUnit Jupiter, - including `@Test`, etc. -* `junit-jupiter-engine` in _test runtime_ scope: implementation of the `TestEngine` API - for JUnit Jupiter - -[[running-tests-junit-platform-runner-setup-transitive-dependencies]] -===== Transitive Dependencies - -* `junit-platform-suite-api` in _test_ scope -* `junit-platform-suite-commons` in _test_ scope -* `junit-platform-launcher` in _test_ scope -* `junit-platform-engine` in _test_ scope -* `junit-platform-commons` in _test_ scope -* `opentest4j` in _test_ scope - -[[running-tests-junit-platform-runner-technical-names]] -==== Display Names vs. Technical Names - -To define a custom _display name_ for the class run via `@RunWith(JUnitPlatform.class)` -annotate the class with `@SuiteDisplayName` and provide a custom value. - -By default, _display names_ will be used for test artifacts; however, when the -`JUnitPlatform` runner is used to execute tests with a build tool such as Gradle or -Maven, the generated test report often needs to include the _technical names_ of test -artifacts — for example, fully qualified class names — instead of shorter display names -like the simple name of a test class or a custom display name containing special -characters. To enable technical names for reporting purposes, declare the -`@UseTechnicalNames` annotation alongside `@RunWith(JUnitPlatform.class)`. - -Note that the presence of `@UseTechnicalNames` overrides any custom display name -configured via `@SuiteDisplayName`. - -[[running-tests-junit-platform-runner-single-test]] -==== Single Test Class - -One way to use the `JUnitPlatform` runner is to annotate a test class with -`@RunWith(JUnitPlatform.class)` directly. Please note that the test methods in the -following example are annotated with `org.junit.jupiter.api.Test` (JUnit Jupiter), not -`org.junit.Test` (JUnit 4). Moreover, in this case the test class must be `public`; -otherwise, some IDEs and build tools might not recognize it as a JUnit 4 test class. - -[source,java,indent=0] ----- -include::{testDir}/example/JUnitPlatformClassDemo.java[tags=user_guide] ----- - -[[running-tests-junit-platform-runner-test-suite]] -==== Test Suite - -If you have multiple test classes you can create a test suite as can be seen in the -following example. - -[source,java,indent=0] ----- -include::{testDir}/example/JUnitPlatformSuiteDemo.java[tags=user_guide] ----- - -The `JUnitPlatformSuiteDemo` will discover and run all tests in the `example` package and -its subpackages. By default, it will only include test classes whose names either begin -with `Test` or end with `Test` or `Tests`. - -.Additional Configuration Options -NOTE: There are more configuration options for discovering and filtering tests than just -`@SelectPackages`. Please consult the Javadoc of the `{suite-api-package}` package for -further details. - -WARNING: Test classes and suites annotated with `@RunWith(JUnitPlatform.class)` -**cannot** be executed directly on the JUnit Platform (or as a "JUnit 5" test as -documented in some IDEs). Such classes and suites can only be executed using JUnit 4 -infrastructure. - [[running-tests-discovery-selectors]] === Discovery Selectors diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 0723c09557db..7e0ec66aa075 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1272,9 +1272,8 @@ include::{testDir}/example/TestInfoDemo.java[tags=user_guide] method, respectively. This allows them to be viewed in IDEs or included in reports. + In JUnit Jupiter you should use `TestReporter` where you used to print information to -`stdout` or `stderr` in JUnit 4. Using `@RunWith(JUnitPlatform.class)` will output all -reported entries to `stdout`. In addition, some IDEs print report entries to `stdout` or -display them in the user interface for test results. +`stdout` or `stderr` in JUnit 4. Some IDEs print report entries to `stdout` or display +them in the user interface for test results. [source,java,indent=0] ---- diff --git a/documentation/src/plantuml/component-diagram.puml b/documentation/src/plantuml/component-diagram.puml index cc06c35ccbd2..b71a4491af56 100644 --- a/documentation/src/plantuml/component-diagram.puml +++ b/documentation/src/plantuml/component-diagram.puml @@ -23,7 +23,6 @@ package org.junit.platform { [junit-platform-jfr] as jfr [junit-platform-launcher] as launcher [junit-platform-reporting] as reporting - [junit-platform-runner] as runner [junit-platform-suite] as suite [junit-platform-suite-api] as suite_api [junit-platform-suite-commons] as suite_commons @@ -83,9 +82,6 @@ engine ..> commons reporting ..> launcher reporting ......> otr_tooling_spi -runner ..> suite_commons -runner ...> junit4 - suite ..> suite_api suite ..> suite_engine diff --git a/documentation/src/test/java/example/JUnitPlatformClassDemo.java b/documentation/src/test/java/example/JUnitPlatformClassDemo.java deleted file mode 100644 index bf776d627f6c..000000000000 --- a/documentation/src/test/java/example/JUnitPlatformClassDemo.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * 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 example; - -// tag::user_guide[] -import static org.junit.jupiter.api.Assertions.fail; - -import org.junit.jupiter.api.Test; -import org.junit.runner.RunWith; - -//end::user_guide[] -@SuppressWarnings("deprecation") -//tag::user_guide[] -@RunWith(org.junit.platform.runner.JUnitPlatform.class) -public class JUnitPlatformClassDemo { - - @Test - void succeedingTest() { - /* no-op */ - } - - // end::user_guide[] - @extensions.ExpectToFail - // tag::user_guide[] - @Test - void failingTest() { - fail("Failing for failing's sake."); - } - -} -// end::user_guide[] diff --git a/documentation/src/test/java/example/JUnitPlatformSuiteDemo.java b/documentation/src/test/java/example/JUnitPlatformSuiteDemo.java deleted file mode 100644 index 259486cee3f8..000000000000 --- a/documentation/src/test/java/example/JUnitPlatformSuiteDemo.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * 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 example; - -//tag::user_guide[] -import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.SuiteDisplayName; -import org.junit.runner.RunWith; - -@RunWith(org.junit.platform.runner.JUnitPlatform.class) -@SuiteDisplayName("JUnit Platform Suite Demo") -@SelectPackages("example") -//end::user_guide[] -@SuppressWarnings("deprecation") -@org.junit.platform.suite.api.ExcludeTags("exclude") -//tag::user_guide[] -public class JUnitPlatformSuiteDemo { -} -//end::user_guide[] diff --git a/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java b/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java index bb545c577f82..87897929f227 100644 --- a/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java +++ b/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java @@ -30,7 +30,6 @@ org.junit.platform.engine, org.junit.platform.launcher, org.junit.platform.reporting, - org.junit.platform.runner, org.junit.platform.suite.api, org.junit.platform.suite.engine, org.junit.platform.testkit, @@ -48,7 +47,6 @@ org.junit.platform.jfr, org.junit.platform.launcher, org.junit.platform.reporting, - org.junit.platform.runner, org.junit.platform.suite.api, org.junit.platform.suite.commons, org.junit.platform.suite.engine, diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 6f3fff9bed05..70113dbd9fe7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -43,7 +43,6 @@ class ClasspathAlignmentChecker { "org.junit.platform.jfr", // "org.junit.platform.launcher", // "org.junit.platform.reporting", // - "org.junit.platform.runner", // "org.junit.platform.suite.api", // "org.junit.platform.suite.commons", // "org.junit.platform.suite.engine", // diff --git a/junit-platform-runner/junit-platform-runner.gradle.kts b/junit-platform-runner/junit-platform-runner.gradle.kts deleted file mode 100644 index bbc2ae9d95be..000000000000 --- a/junit-platform-runner/junit-platform-runner.gradle.kts +++ /dev/null @@ -1,37 +0,0 @@ -plugins { - id("junitbuild.java-library-conventions") - id("junitbuild.junit4-compatibility") -} - -description = "JUnit Platform Runner" - -dependencies { - api(platform(projects.junitBom)) - api(libs.junit4) - api(projects.junitPlatformLauncher) - api(projects.junitPlatformSuiteApi) - - compileOnlyApi(libs.apiguardian) - - implementation(projects.junitPlatformSuiteCommons) - - testImplementation(testFixtures(projects.junitPlatformEngine)) - testImplementation(testFixtures(projects.junitPlatformLauncher)) - - osgiVerification(projects.junitJupiterEngine) - osgiVerification(projects.junitPlatformLauncher) -} - -tasks.jar { - bundle { - val importAPIGuardian: String by extra - bnd(""" - # Import JUnit4 packages with a version - Import-Package: \ - $importAPIGuardian,\ - org.junit.platform.commons.logging;status=INTERNAL,\ - org.junit.runner.*;version="[${libs.versions.junit4Min.get()},5)",\ - * - """) - } -} diff --git a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatform.java b/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatform.java deleted file mode 100644 index 0df3bbb19ef3..000000000000 --- a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatform.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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.runner; - -import static java.util.stream.Collectors.toList; -import static org.apiguardian.api.API.Status.DEPRECATED; -import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; -import static org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder.request; - -import java.lang.annotation.Annotation; -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import org.apiguardian.api.API; -import org.junit.platform.engine.DiscoverySelector; -import org.junit.platform.engine.discovery.DiscoverySelectors; -import org.junit.platform.launcher.Launcher; -import org.junit.platform.launcher.LauncherDiscoveryRequest; -import org.junit.platform.launcher.TestIdentifier; -import org.junit.platform.launcher.TestPlan; -import org.junit.platform.launcher.core.LauncherFactory; -import org.junit.platform.suite.api.ConfigurationParameter; -import org.junit.platform.suite.api.ConfigurationParametersResource; -import org.junit.platform.suite.api.ExcludeClassNamePatterns; -import org.junit.platform.suite.api.ExcludeEngines; -import org.junit.platform.suite.api.ExcludePackages; -import org.junit.platform.suite.api.ExcludeTags; -import org.junit.platform.suite.api.IncludeClassNamePatterns; -import org.junit.platform.suite.api.IncludeEngines; -import org.junit.platform.suite.api.IncludePackages; -import org.junit.platform.suite.api.IncludeTags; -import org.junit.platform.suite.api.Select; -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.SelectClasspathResource; -import org.junit.platform.suite.api.SelectDirectories; -import org.junit.platform.suite.api.SelectFile; -import org.junit.platform.suite.api.SelectModules; -import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.SelectUris; -import org.junit.platform.suite.api.Suite; -import org.junit.platform.suite.api.SuiteDisplayName; -import org.junit.platform.suite.commons.SuiteLauncherDiscoveryRequestBuilder; -import org.junit.runner.Description; -import org.junit.runner.Runner; -import org.junit.runner.manipulation.Filter; -import org.junit.runner.manipulation.Filterable; -import org.junit.runner.manipulation.NoTestsRemainException; -import org.junit.runner.notification.RunNotifier; - -/** - * JUnit 4 based {@link Runner} which runs tests on the JUnit Platform in a - * JUnit 4 environment. - * - *

Annotating a class with {@code @RunWith(JUnitPlatform.class)} allows it - * to be run with IDEs and build systems that support JUnit 4 but do not yet - * support the JUnit Platform directly. - * - *

Please note that test classes and suites annotated with - * {@code @RunWith(JUnitPlatform.class)} cannot be executed directly on - * the JUnit Platform (or as a "JUnit 5" test as documented in some IDEs). Such - * classes and suites can only be executed using JUnit 4 infrastructure. - * - *

Consult the various annotations in the {@code org.junit.platform.suite.api} - * package for configuration options. - * - *

If you do not use any configuration annotations from the - * {@code org.junit.platform.suite.api} package, you can use this runner on a - * test class whose programming model is supported on the JUnit Platform — - * for example, a JUnit Jupiter test class. Note, however, that any test class - * run with this runner must be {@code public} in order to be picked up by IDEs - * and build tools. - * - *

When used on a class that serves as a test suite and the - * {@link IncludeClassNamePatterns @IncludeClassNamePatterns} annotation is not - * present, the default include pattern - * {@value org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN} - * will be used in order to avoid loading classes unnecessarily (see {@link - * org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN - * ClassNameFilter#STANDARD_INCLUDE_PATTERN}). - * - * @since 1.0 - * @see Select - * @see SelectClasses - * @see SelectClasspathResource - * @see SelectDirectories - * @see SelectFile - * @see SelectModules - * @see SelectPackages - * @see SelectUris - * @see IncludeClassNamePatterns - * @see ExcludeClassNamePatterns - * @see IncludeEngines - * @see ExcludeEngines - * @see IncludePackages - * @see ExcludePackages - * @see IncludeTags - * @see ExcludeTags - * @see SuiteDisplayName - * @see org.junit.platform.suite.api.UseTechnicalNames UseTechnicalNames - * @see ConfigurationParameter - * @see ConfigurationParametersResource - * @deprecated since 1.8, in favor of the {@link Suite @Suite} support provided by - * the {@code junit-platform-suite-engine} module; to be removed in JUnit Platform 2.0 - */ -@API(status = DEPRECATED, since = "1.8") -@Deprecated -public class JUnitPlatform extends Runner implements Filterable { - - // @formatter:off - private static final List> IMPLICIT_SUITE_ANNOTATIONS = Arrays.asList( - SelectClasses.class, - SelectClasspathResource.class, - SelectDirectories.class, - SelectFile.class, - SelectFile.class, - SelectModules.class, - SelectPackages.class, - SelectUris.class - ); - // @formatter:on - - private final Class testClass; - private final Launcher launcher; - - private JUnitPlatformTestTree testTree; - - public JUnitPlatform(Class testClass) { - this(testClass, LauncherFactory.create()); - } - - // For testing only - JUnitPlatform(Class testClass, Launcher launcher) { - this.launcher = launcher; - this.testClass = testClass; - this.testTree = generateTestTree(createDiscoveryRequest()); - } - - @Override - public Description getDescription() { - return this.testTree.getSuiteDescription(); - } - - @Override - public void run(RunNotifier notifier) { - this.launcher.execute(this.testTree.getTestPlan(), new JUnitPlatformRunnerListener(this.testTree, notifier)); - } - - private JUnitPlatformTestTree generateTestTree(LauncherDiscoveryRequest discoveryRequest) { - TestPlan testPlan = this.launcher.discover(discoveryRequest); - return new JUnitPlatformTestTree(testPlan, this.testClass); - } - - @SuppressWarnings("deprecation") - private LauncherDiscoveryRequest createDiscoveryRequest() { - SuiteLauncherDiscoveryRequestBuilder requestBuilder = request(); - // Allows @RunWith(JUnitPlatform.class) to be added to any test case - boolean isSuite = isSuite(); - if (!isSuite) { - requestBuilder.selectors(selectClass(this.testClass)); - } - - // @formatter:off - return requestBuilder - .filterStandardClassNamePatterns(isSuite) - .suite(this.testClass) - .build(); - // @formatter:on - } - - private boolean isSuite() { - // @formatter:off - return IMPLICIT_SUITE_ANNOTATIONS.stream() - .anyMatch(annotation -> isAnnotated(this.testClass, annotation)); - // @formatter:on - } - - @Override - public void filter(Filter filter) throws NoTestsRemainException { - Set filteredIdentifiers = this.testTree.getFilteredLeaves(filter); - if (filteredIdentifiers.isEmpty()) { - throw new NoTestsRemainException(); - } - this.testTree = generateTestTree(createDiscoveryRequestForUniqueIds(filteredIdentifiers)); - } - - private LauncherDiscoveryRequest createDiscoveryRequestForUniqueIds(Set testIdentifiers) { - // @formatter:off - List selectors = testIdentifiers.stream() - .map(TestIdentifier::getUniqueIdObject) - .map(DiscoverySelectors::selectUniqueId) - .collect(toList()); - // @formatter:on - return request().selectors(selectors).build(); - } - -} diff --git a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformRunnerListener.java b/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformRunnerListener.java deleted file mode 100644 index 180472e20bb6..000000000000 --- a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformRunnerListener.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * 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.runner; - -import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; -import static org.junit.platform.engine.TestExecutionResult.Status.FAILED; - -import org.junit.platform.engine.TestExecutionResult; -import org.junit.platform.engine.TestExecutionResult.Status; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.engine.reporting.FileEntry; -import org.junit.platform.engine.reporting.ReportEntry; -import org.junit.platform.launcher.TestExecutionListener; -import org.junit.platform.launcher.TestIdentifier; -import org.junit.runner.Description; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunNotifier; - -/** - * @since 1.0 - */ -class JUnitPlatformRunnerListener implements TestExecutionListener { - - private final JUnitPlatformTestTree testTree; - private final RunNotifier notifier; - - JUnitPlatformRunnerListener(JUnitPlatformTestTree testTree, RunNotifier notifier) { - this.testTree = testTree; - this.notifier = notifier; - } - - @Override - public void dynamicTestRegistered(TestIdentifier testIdentifier) { - UniqueId parentId = testIdentifier.getParentIdObject().get(); - testTree.addDynamicDescription(testIdentifier, parentId); - } - - @Override - public void executionSkipped(TestIdentifier testIdentifier, String reason) { - if (testIdentifier.isTest()) { - fireTestIgnored(testIdentifier); - } - else { - testTree.getTestsInSubtree(testIdentifier).forEach(this::fireTestIgnored); - } - } - - private void fireTestIgnored(TestIdentifier testIdentifier) { - Description description = findJUnit4Description(testIdentifier); - this.notifier.fireTestIgnored(description); - } - - @Override - public void executionStarted(TestIdentifier testIdentifier) { - Description description = findJUnit4Description(testIdentifier); - if (description.isTest()) { - this.notifier.fireTestStarted(description); - } - } - - @Override - public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { - Description description = findJUnit4Description(testIdentifier); - Status status = testExecutionResult.getStatus(); - if (status == ABORTED) { - this.notifier.fireTestAssumptionFailed(toFailure(testExecutionResult, description)); - } - else if (status == FAILED) { - this.notifier.fireTestFailure(toFailure(testExecutionResult, description)); - } - if (description.isTest()) { - this.notifier.fireTestFinished(description); - } - } - - @Override - public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { - System.out.println(entry); - } - - @Override - public void fileEntryPublished(TestIdentifier testIdentifier, FileEntry file) { - System.out.println(file); - } - - private Failure toFailure(TestExecutionResult testExecutionResult, Description description) { - return new Failure(description, testExecutionResult.getThrowable().orElse(null)); - } - - private Description findJUnit4Description(TestIdentifier testIdentifier) { - return this.testTree.getDescription(testIdentifier); - } - -} diff --git a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformTestTree.java b/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformTestTree.java deleted file mode 100644 index e76f2d56a9be..000000000000 --- a/junit-platform-runner/src/main/java/org/junit/platform/runner/JUnitPlatformTestTree.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * 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.runner; - -import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toSet; - -import java.util.HashMap; -import java.util.LinkedHashSet; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.function.Function; -import java.util.function.Predicate; - -import org.junit.platform.commons.support.AnnotationSupport; -import org.junit.platform.commons.util.StringUtils; -import org.junit.platform.engine.TestSource; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.engine.support.descriptor.ClassSource; -import org.junit.platform.engine.support.descriptor.MethodSource; -import org.junit.platform.launcher.TestIdentifier; -import org.junit.platform.launcher.TestPlan; -import org.junit.platform.suite.api.SuiteDisplayName; -import org.junit.runner.Description; -import org.junit.runner.manipulation.Filter; - -/** - * @since 1.0 - */ -class JUnitPlatformTestTree { - - private final Map descriptions = new HashMap<>(); - private final TestPlan testPlan; - private final Function nameExtractor; - private final Description suiteDescription; - - JUnitPlatformTestTree(TestPlan testPlan, Class testClass) { - this.testPlan = testPlan; - this.nameExtractor = useTechnicalNames(testClass) ? this::getTechnicalName : TestIdentifier::getDisplayName; - this.suiteDescription = generateSuiteDescription(testPlan, testClass); - } - - public TestPlan getTestPlan() { - return testPlan; - } - - @SuppressWarnings("deprecation") - private static boolean useTechnicalNames(Class testClass) { - return testClass.isAnnotationPresent(org.junit.platform.suite.api.UseTechnicalNames.class); - } - - Description getSuiteDescription() { - return this.suiteDescription; - } - - Description getDescription(TestIdentifier identifier) { - return this.descriptions.get(identifier); - } - - private Description generateSuiteDescription(TestPlan testPlan, Class testClass) { - String displayName = useTechnicalNames(testClass) ? testClass.getName() : getSuiteDisplayName(testClass); - Description suiteDescription = Description.createSuiteDescription(displayName); - buildDescriptionTree(suiteDescription, testPlan); - return suiteDescription; - } - - private String getSuiteDisplayName(Class testClass) { - // @formatter:off - return AnnotationSupport.findAnnotation(testClass, SuiteDisplayName.class) - .map(SuiteDisplayName::value) - .filter(StringUtils::isNotBlank) - .orElse(testClass.getName()); - // @formatter:on - } - - private void buildDescriptionTree(Description suiteDescription, TestPlan testPlan) { - testPlan.getRoots().forEach(testIdentifier -> buildDescription(testIdentifier, suiteDescription, testPlan)); - } - - void addDynamicDescription(TestIdentifier newIdentifier, UniqueId parentId) { - Description parent = getDescription(this.testPlan.getTestIdentifier(parentId)); - buildDescription(newIdentifier, parent, this.testPlan); - } - - private void buildDescription(TestIdentifier identifier, Description parent, TestPlan testPlan) { - Description newDescription = createJUnit4Description(identifier, testPlan); - parent.addChild(newDescription); - this.descriptions.put(identifier, newDescription); - testPlan.getChildren(identifier).forEach( - testIdentifier -> buildDescription(testIdentifier, newDescription, testPlan)); - } - - private Description createJUnit4Description(TestIdentifier identifier, TestPlan testPlan) { - String name = nameExtractor.apply(identifier); - if (identifier.isTest()) { - String containerName = testPlan.getParent(identifier).map(nameExtractor).orElse(""); - return Description.createTestDescription(containerName, name, identifier.getUniqueIdObject()); - } - return Description.createSuiteDescription(name, identifier.getUniqueIdObject()); - } - - private String getTechnicalName(TestIdentifier testIdentifier) { - Optional optionalSource = testIdentifier.getSource(); - if (optionalSource.isPresent()) { - TestSource source = optionalSource.get(); - if (source instanceof ClassSource) { - return ((ClassSource) source).getJavaClass().getName(); - } - else if (source instanceof MethodSource) { - MethodSource methodSource = (MethodSource) source; - String methodParameterTypes = methodSource.getMethodParameterTypes(); - if (StringUtils.isBlank(methodParameterTypes)) { - return methodSource.getMethodName(); - } - return String.format("%s(%s)", methodSource.getMethodName(), methodParameterTypes); - } - } - - // Else fall back to display name - return testIdentifier.getDisplayName(); - } - - Set getTestsInSubtree(TestIdentifier ancestor) { - // @formatter:off - return testPlan.getDescendants(ancestor).stream() - .filter(TestIdentifier::isTest) - .collect(toCollection(LinkedHashSet::new)); - // @formatter:on - } - - Set getFilteredLeaves(Filter filter) { - Set identifiers = applyFilterToDescriptions(filter); - return removeNonLeafIdentifiers(identifiers); - } - - private Set removeNonLeafIdentifiers(Set identifiers) { - return identifiers.stream().filter(isALeaf(identifiers)).collect(toSet()); - } - - private Predicate isALeaf(Set identifiers) { - return testIdentifier -> { - Set descendants = testPlan.getDescendants(testIdentifier); - return identifiers.stream().noneMatch(descendants::contains); - }; - } - - private Set applyFilterToDescriptions(Filter filter) { - // @formatter:off - return descriptions.entrySet() - .stream() - .filter(entry -> filter.shouldRun(entry.getValue())) - .map(Entry::getKey) - .collect(toSet()); - // @formatter:on - } - -} diff --git a/junit-platform-runner/src/main/java/org/junit/platform/runner/package-info.java b/junit-platform-runner/src/main/java/org/junit/platform/runner/package-info.java deleted file mode 100644 index ef778ce20957..000000000000 --- a/junit-platform-runner/src/main/java/org/junit/platform/runner/package-info.java +++ /dev/null @@ -1,6 +0,0 @@ -/** - * {@code Runner} and annotations for configuring and executing tests on the - * JUnit Platform in a JUnit 4 environment. - */ - -package org.junit.platform.runner; diff --git a/junit-platform-runner/src/module/org.junit.platform.runner/module-info.java b/junit-platform-runner/src/module/org.junit.platform.runner/module-info.java deleted file mode 100644 index e9dc34ed78d1..000000000000 --- a/junit-platform-runner/src/module/org.junit.platform.runner/module-info.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * 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 - */ - -/** - * {@code Runner} and annotations for configuring and executing tests on the - * JUnit Platform in a JUnit 4 environment. - * - * @since 1.0 - */ -module org.junit.platform.runner { - requires transitive junit; // 4 - requires static transitive org.apiguardian.api; - requires transitive org.junit.platform.launcher; - requires transitive org.junit.platform.suite.api; - requires org.junit.platform.suite.commons; - - exports org.junit.platform.runner; -} diff --git a/junit-platform-runner/src/test/README.md b/junit-platform-runner/src/test/README.md deleted file mode 100644 index 6e2fd0b363f0..000000000000 --- a/junit-platform-runner/src/test/README.md +++ /dev/null @@ -1 +0,0 @@ -For compatibility with the Eclipse IDE, the test for this module are in the `platform-tests` project. diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParameter.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParameter.java index 0a8d010a3624..a12e45674789 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParameter.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ConfigurationParameter.java @@ -32,7 +32,6 @@ * @see ConfigurationParametersResource * @see DisableParentConfigurationParameters * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder#configurationParameter(String, String) */ @Retention(RetentionPolicy.RUNTIME) 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..e6d6d4c1efc6 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 @@ -32,7 +32,6 @@ * @see ConfigurationParameter * @see DisableParentConfigurationParameters * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder#configurationParametersResources(String...) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeClassNamePatterns.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeClassNamePatterns.java index 9e8ee74c28ef..76c2e74ae2ab 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeClassNamePatterns.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeClassNamePatterns.java @@ -32,7 +32,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.ClassNameFilter#excludeClassNamePatterns */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeEngines.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeEngines.java index f6c2ac53f4dc..f77714c1c9fd 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeEngines.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeEngines.java @@ -28,7 +28,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.EngineFilter#excludeEngines */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludePackages.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludePackages.java index 5335f7c0e844..4df7bc43a353 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludePackages.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludePackages.java @@ -27,7 +27,6 @@ * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.PackageNameFilter#excludePackageNames(String...) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java index f24bc12ae6e7..aad54d125709 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java @@ -55,7 +55,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.TagFilter#excludeTags */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeClassNamePatterns.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeClassNamePatterns.java index 313f52c9d371..4f638b868db5 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeClassNamePatterns.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeClassNamePatterns.java @@ -32,7 +32,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.ClassNameFilter#STANDARD_INCLUDE_PATTERN * @see org.junit.platform.engine.discovery.ClassNameFilter#includeClassNamePatterns */ diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeEngines.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeEngines.java index f35461d438fd..3b953bef831f 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeEngines.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeEngines.java @@ -28,7 +28,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.EngineFilter#includeEngines */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludePackages.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludePackages.java index f634544a7b84..06d8a02f79d6 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludePackages.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludePackages.java @@ -27,7 +27,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.PackageNameFilter#includePackageNames(String...) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java index 12110bee9bfc..089ea5f49387 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java @@ -55,7 +55,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.launcher.TagFilter#includeTags */ @Retention(RetentionPolicy.RUNTIME) 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..caa0299cc883 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 @@ -28,7 +28,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClass(Class) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClass(String) */ diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasspathResource.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasspathResource.java index c3255f501c39..5099cc27aef7 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasspathResource.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectClasspathResource.java @@ -29,7 +29,6 @@ * * @since 1.8 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectClasspathResource(String, org.junit.platform.engine.discovery.FilePosition) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectDirectories.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectDirectories.java index 57ea6bdbbe39..21ae13e9f564 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectDirectories.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectDirectories.java @@ -27,7 +27,6 @@ * * @since 1.8 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectDirectory(String) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFile.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFile.java index 7359febbda84..4ee43d25114c 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFile.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectFile.java @@ -29,7 +29,6 @@ * * @since 1.8 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectFile(String, org.junit.platform.engine.discovery.FilePosition) */ @Retention(RetentionPolicy.RUNTIME) 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..24760697427f 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 @@ -29,7 +29,6 @@ * * @since 1.10 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String, String, String) * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectMethod(String, String, Class...) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectModules.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectModules.java index e0dccf332c18..9c3ba49a4e81 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectModules.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectModules.java @@ -28,7 +28,6 @@ * * @since 1.8 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectModules(Set) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectPackages.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectPackages.java index bba47a24c2d9..6b78cd0769b6 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectPackages.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectPackages.java @@ -27,7 +27,6 @@ * * @since 1.0 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectPackage(String) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectUris.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectUris.java index a281678df0a2..e55ebe1f8043 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectUris.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SelectUris.java @@ -27,7 +27,6 @@ * * @since 1.8 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform * @see org.junit.platform.engine.discovery.DiscoverySelectors#selectUri(String) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SuiteDisplayName.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SuiteDisplayName.java index 0113b1827b44..8a632fd72ac6 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SuiteDisplayName.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/SuiteDisplayName.java @@ -28,17 +28,12 @@ *

Display names are typically used for test reporting in IDEs and build * tools and may contain spaces, special characters, and even emoji. * - *

JUnit 4 Suite Support

- *

Test suites can be run on the JUnit Platform in a JUnit 4 environment via - * {@code @RunWith(JUnitPlatform.class)}. - * - *

JUnit 5 Suite Support

- *

Test suites can be run on the JUnit Platform in a JUnit 5 environment via - * the {@code junit-platform-suite-engine} module. + *

Execution

+ *

Test suites can be run on the JUnit Platform the + * {@code junit-platform-suite-engine} module. * * @since 1.1 * @see Suite - * @see org.junit.platform.runner.JUnitPlatform */ @Retention(RUNTIME) @Target(TYPE) diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java index 749fcdb13a9f..6edbe5f25add 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java @@ -37,12 +37,7 @@ *

Note that the presence of {@code @UseTechnicalNames} overrides any custom * display name configured for the suite via {@link SuiteDisplayName @SuiteDisplayName}. * - *

JUnit 4 Suite Support

- *

Test suites can be run on the JUnit Platform in a JUnit 4 environment via - * {@code @RunWith(JUnitPlatform.class)}. - * * @since 1.0 - * @see org.junit.platform.runner.JUnitPlatform * @deprecated since 1.8, in favor of the {@link Suite @Suite} support provided by * the {@code junit-platform-suite-engine} module; to be removed in JUnit Platform 2.0 */ diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java index f5cd9bc50756..1e54ed53ef68 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java @@ -1,13 +1,9 @@ /** * Annotations for configuring a test suite on the JUnit Platform. * - *

JUnit 4 Suite Support

- *

Test suites can be run on the JUnit Platform in a JUnit 4 environment via - * {@code @RunWith(JUnitPlatform.class)} with the {@code junit-platform-runner}. - * - *

JUnit 5 Suite Support

- *

Test suites can be run on the JUnit Platform in a JUnit 5 environment via - * {@link Suite @Suite} with the {@code junit-platform-suite-engine}. + *

Execution

+ *

Test suites can be run on the JUnit Platform the + * {@code junit-platform-suite-engine} module. */ package org.junit.platform.suite.api; diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java index 79e8ef209728..11cdbf438cc9 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java @@ -112,7 +112,7 @@ * @see org.junit.platform.launcher.EngineFilter * @see org.junit.platform.launcher.TagFilter */ -@API(status = INTERNAL, since = "1.8", consumers = { "org.junit.platform.suite.engine", "org.junit.platform.runner" }) +@API(status = INTERNAL, since = "1.8", consumers = "org.junit.platform.suite.engine") public final class SuiteLauncherDiscoveryRequestBuilder { private final LauncherDiscoveryRequestBuilder delegate = LauncherDiscoveryRequestBuilder.request(); diff --git a/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java b/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java index 62c6732235d3..52c508bdace7 100644 --- a/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java +++ b/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java @@ -21,6 +21,5 @@ requires transitive org.junit.platform.launcher; exports org.junit.platform.suite.commons to - org.junit.platform.suite.engine, - org.junit.platform.runner; + org.junit.platform.suite.engine; } diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index 6da16779b700..871858b42133 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -17,7 +17,7 @@ dependencies { testFixturesApi(platform(libs.groovy2.bom)) testFixturesApi(libs.spock1) - testFixturesImplementation(projects.junitPlatformRunner) + testFixturesImplementation(projects.junitPlatformSuiteApi) testImplementation(projects.junitPlatformLauncher) testImplementation(projects.junitPlatformSuiteEngine) diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/platform/runner/JUnitPlatform.java b/junit-vintage-engine/src/testFixtures/java/org/junit/platform/runner/JUnitPlatform.java new file mode 100644 index 000000000000..02f7102aa886 --- /dev/null +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/platform/runner/JUnitPlatform.java @@ -0,0 +1,44 @@ +/* + * 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.runner; + +import java.util.List; + +import org.junit.runner.Description; +import org.junit.runner.notification.RunNotifier; +import org.junit.runners.ParentRunner; +import org.junit.runners.model.InitializationError; + +/** + * Dummy Runner class mimicking the one from the discontinued + * {@code junit-platform-runner} module. + */ +public class JUnitPlatform extends ParentRunner { + + public JUnitPlatform(Class testClass) throws InitializationError { + super(testClass); + } + + @Override + protected List getChildren() { + return List.of(); + } + + @Override + protected Description describeChild(Void child) { + throw new UnsupportedOperationException(); + } + + @Override + protected void runChild(Void child, RunNotifier notifier) { + throw new UnsupportedOperationException(); + } +} diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/TestCaseRunWithJUnitPlatformRunner.java b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/TestCaseRunWithJUnitPlatformRunner.java index fe1011fac50e..189dc2ee7ea2 100644 --- a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/TestCaseRunWithJUnitPlatformRunner.java +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/TestCaseRunWithJUnitPlatformRunner.java @@ -17,7 +17,6 @@ /** * @since 4.12 */ -@SuppressWarnings("deprecation") @RunWith(JUnitPlatform.class) @SelectClasses(PlainJUnit4TestCaseWithSingleTestWhichFails.class) public class TestCaseRunWithJUnitPlatformRunner { diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index 3d849832f844..ec508e2a5689 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -39,7 +39,6 @@ dependencies { testImplementation(projects.junitPlatformSuiteEngine) // --- Things we are testing with --------------------------------------------- - testImplementation(projects.junitPlatformRunner) testImplementation(projects.junitPlatformTestkit) testImplementation(testFixtures(projects.junitPlatformCommons)) testImplementation(testFixtures(projects.junitPlatformEngine)) diff --git a/platform-tests/src/test/java/org/junit/platform/runner/JUnitPlatformRunnerTests.java b/platform-tests/src/test/java/org/junit/platform/runner/JUnitPlatformRunnerTests.java deleted file mode 100644 index 5dc8bb014f62..000000000000 --- a/platform-tests/src/test/java/org/junit/platform/runner/JUnitPlatformRunnerTests.java +++ /dev/null @@ -1,905 +0,0 @@ -/* - * 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.runner; - -import static java.util.stream.Collectors.toSet; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.fail; -import static org.junit.jupiter.api.Assertions.assertAll; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assumptions.assumeFalse; -import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; -import static org.junit.platform.engine.TestExecutionResult.successful; -import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; -import static org.junit.platform.launcher.core.LauncherFactoryForTestingPurposesOnly.createLauncher; -import static org.junit.platform.launcher.core.OutputDirectoryProviders.dummyOutputDirectoryProvider; -import static org.junit.runner.Description.createSuiteDescription; -import static org.junit.runner.Description.createTestDescription; -import static org.junit.runner.manipulation.Filter.matchMethodDescription; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.inOrder; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import java.util.Arrays; -import java.util.List; -import java.util.Set; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Tag; -import org.junit.jupiter.api.Test; -import org.junit.platform.engine.ConfigurationParameters; -import org.junit.platform.engine.EngineDiscoveryRequest; -import org.junit.platform.engine.ExecutionRequest; -import org.junit.platform.engine.Filter; -import org.junit.platform.engine.TestDescriptor; -import org.junit.platform.engine.TestEngine; -import org.junit.platform.engine.TestExecutionResult; -import org.junit.platform.engine.TestTag; -import org.junit.platform.engine.UniqueId; -import org.junit.platform.engine.discovery.ClassNameFilter; -import org.junit.platform.engine.discovery.ClassSelector; -import org.junit.platform.engine.discovery.PackageNameFilter; -import org.junit.platform.engine.discovery.PackageSelector; -import org.junit.platform.engine.discovery.UniqueIdSelector; -import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; -import org.junit.platform.engine.support.descriptor.ClassSource; -import org.junit.platform.engine.support.descriptor.EngineDescriptor; -import org.junit.platform.engine.support.descriptor.MethodSource; -import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestDescriptor; -import org.junit.platform.engine.support.hierarchical.DemoHierarchicalTestEngine; -import org.junit.platform.fakes.TestDescriptorStub; -import org.junit.platform.fakes.TestEngineStub; -import org.junit.platform.launcher.Launcher; -import org.junit.platform.launcher.LauncherDiscoveryRequest; -import org.junit.platform.launcher.TestPlan; -import org.junit.platform.suite.api.ExcludeClassNamePatterns; -import org.junit.platform.suite.api.ExcludeEngines; -import org.junit.platform.suite.api.ExcludePackages; -import org.junit.platform.suite.api.ExcludeTags; -import org.junit.platform.suite.api.IncludeClassNamePatterns; -import org.junit.platform.suite.api.IncludeEngines; -import org.junit.platform.suite.api.IncludePackages; -import org.junit.platform.suite.api.IncludeTags; -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.SelectPackages; -import org.junit.platform.suite.api.SuiteDisplayName; -import org.junit.platform.suite.api.UseTechnicalNames; -import org.junit.runner.Description; -import org.junit.runner.manipulation.NoTestsRemainException; -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; -import org.mockito.ArgumentCaptor; - -/** - * Tests for the {@link JUnitPlatform} runner. - * - * @since 1.0 - */ -@Tag("junit4") -@SuppressWarnings("deprecation") -class JUnitPlatformRunnerTests { - - @Nested - class Discovery { - - @Test - void requestsClassSelectorForAnnotatedClassWhenNoAdditionalAnnotationsArePresent() { - - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var selectors = request.getSelectorsByType(ClassSelector.class); - assertThat(selectors).hasSize(1); - var classSelector = getOnlyElement(selectors); - assertEquals(TestCase.class, classSelector.getJavaClass()); - } - - @Test - void requestsClassSelectorsWhenSelectClassesAnnotationIsPresent() { - - @SelectClasses({ Short.class, Byte.class }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var selectors = request.getSelectorsByType(ClassSelector.class); - assertThat(selectors).hasSize(2); - assertEquals(Short.class, selectors.get(0).getJavaClass()); - assertEquals(Byte.class, selectors.get(1).getJavaClass()); - } - - @Test - void updatesIncludeClassNameFilterWhenSelectClassesAnnotationIsPresent() { - - @SelectClasses({ Short.class, Byte.class }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - - // Excluded by default - assertExcludes(filter, "example.MyClass"); - assertExcludes(filter, "example.MyTestClass"); - assertExcludes(filter, "example.Short"); - assertExcludes(filter, "example.Byte"); - - // Included due to ClassNameFilter.STANDARD_INCLUDE_PATTERN - assertIncludes(filter, "TestClass"); - assertIncludes(filter, "example.TestClass"); - assertIncludes(filter, "example.MyTests"); - assertIncludes(filter, "example.MyTest"); - - // Included due to @SelectClasses({ Short.class, Byte.class }) - assertIncludes(filter, Short.class.getName()); - assertIncludes(filter, Byte.class.getName()); - } - - @Test - void requestsPackageSelectorsWhenPackagesAnnotationIsPresent() { - - @SelectPackages({ "foo", "bar" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var selectors = request.getSelectorsByType(PackageSelector.class); - assertThat(selectors).hasSize(2); - assertEquals("foo", selectors.get(0).getPackageName()); - assertEquals("bar", selectors.get(1).getPackageName()); - } - - @Test - void addsPackageFiltersToRequestWhenIncludePackageAnnotationIsPresent() { - - @IncludePackages({ "includedpackage1", "includedpackage2" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(PackageNameFilter.class); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertIncludes(filter, "includedpackage1.TestClass"); - assertIncludes(filter, "includedpackage2.TestClass"); - assertExcludes(filter, "excludedpackage1.TestClass"); - } - - @Test - void addsPackageFiltersToRequestWhenExcludePackageAnnotationIsPresent() { - - @ExcludePackages({ "excludedpackage1", "excludedpackage2" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(PackageNameFilter.class); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertIncludes(filter, "includedpackage1.TestClass"); - assertExcludes(filter, "excludedpackage1.TestClass"); - assertExcludes(filter, "excludedpackage2.TestClass"); - } - - @Test - void addsTagFilterToRequestWhenIncludeTagsAnnotationIsPresent() { - - @IncludeTags({ "foo", "bar" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getPostDiscoveryFilters(); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertIncludes(filter, testDescriptorWithTags("foo")); - assertIncludes(filter, testDescriptorWithTags("bar")); - assertExcludes(filter, testDescriptorWithTags("baz")); - } - - @Test - void addsTagFilterToRequestWhenExcludeTagsAnnotationIsPresent() { - - @ExcludeTags({ "foo", "bar" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getPostDiscoveryFilters(); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertExcludes(filter, testDescriptorWithTags("foo")); - assertExcludes(filter, testDescriptorWithTags("bar")); - assertIncludes(filter, testDescriptorWithTags("baz")); - } - - @Test - void includeTagsAcceptsTagExpressions() { - - @IncludeTags("foo & !bar") - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getPostDiscoveryFilters(); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertIncludes(filter, testDescriptorWithTags("foo")); - assertIncludes(filter, testDescriptorWithTags("foo", "any_other_tag")); - assertExcludes(filter, testDescriptorWithTags("foo", "bar")); - assertExcludes(filter, testDescriptorWithTags("bar")); - assertExcludes(filter, testDescriptorWithTags("bar", "any_other_tag")); - } - - @Test - void excludeTagsAcceptsTagExpressions() { - - @ExcludeTags("foo & !bar") - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getPostDiscoveryFilters(); - assertThat(filters).hasSize(1); - - var filter = filters.getFirst(); - assertExcludes(filter, testDescriptorWithTags("foo")); - assertExcludes(filter, testDescriptorWithTags("foo", "any_other_tag")); - assertIncludes(filter, testDescriptorWithTags("foo", "bar")); - assertIncludes(filter, testDescriptorWithTags("bar")); - assertIncludes(filter, testDescriptorWithTags("bar", "any_other_tag")); - } - - @Test - void addsEngineFiltersToRequestWhenIncludeEnginesOrExcludeEnginesAnnotationsArePresent() { - - @IncludeEngines({ "foo", "bar", "baz" }) - @ExcludeEngines({ "bar", "quux" }) - class TestCase { - } - - TestEngine fooEngine = new TestEngineStub("foo"); - TestEngine barEngine = new TestEngineStub("bar"); - TestEngine bazEngine = new TestEngineStub("baz"); - TestEngine quuxEngine = new TestEngineStub("quux"); - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getEngineFilters(); - assertThat(filters).hasSize(2); - - var includeFilter = filters.get(1); - assertIncludes(includeFilter, fooEngine); - assertIncludes(includeFilter, barEngine); - assertIncludes(includeFilter, bazEngine); - assertExcludes(includeFilter, quuxEngine); - - var excludeFilter = filters.getFirst(); - assertIncludes(excludeFilter, fooEngine); - assertExcludes(excludeFilter, barEngine); - assertIncludes(excludeFilter, bazEngine); - assertExcludes(excludeFilter, quuxEngine); - } - - @Test - void addsDefaultClassNameFilterToRequestWhenFilterClassNameAnnotationIsNotPresentOnTestSuite() { - - @SelectPackages("foo") - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(STANDARD_INCLUDE_PATTERN); - } - - @Test - void addsDefaultClassNameFilterToRequestWhenFilterClassNameAnnotationIsNotPresentOnTestClass() { - - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(filters).isEmpty(); - } - - @Test - void addsSingleExplicitClassNameFilterToRequestWhenIncludeClassNamePatternsAnnotationIsPresent() { - - @IncludeClassNamePatterns(".*Foo") - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(".*Foo"); - } - - @Test - void addsSingleClassNameFilterToRequestWhenExcludeClassNamePatternsAnnotationIsPresent() { - - @ExcludeClassNamePatterns(".*Foo") - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(".*Foo"); - } - - @Test - void addsMultipleExplicitClassNameFilterToRequestWhenIncludeClassNamePatternsAnnotationIsPresent() { - - @IncludeClassNamePatterns({ ".*Foo", "Bar.*" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(".*Foo", "Bar.*"); - } - - @Test - void addsMultipleClassNameFilterToRequestWhenExcludeClassNamePatternsAnnotationIsPresent() { - - @ExcludeClassNamePatterns({ ".*Foo", "Bar.*" }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(".*Foo", "Bar.*"); - } - - @Test - void usesStandardIncludePatternWhenIncludeClassNamePatternsAnnotationIsPresentWithoutArguments() { - - @IncludeClassNamePatterns - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains(STANDARD_INCLUDE_PATTERN); - } - - @Test - void doesNotAddClassNameFilterWhenIncludeClassNamePatternsAnnotationIsPresentWithEmptyArguments() { - - @IncludeClassNamePatterns({}) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(filters).isEmpty(); - } - - @Test - void doesNotAddClassNameFilterWhenExcludeClassNamePatternsAnnotationIsPresentWithEmptyArguments() { - - @ExcludeClassNamePatterns({}) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(filters).isEmpty(); - } - - @Test - void trimsArgumentsOfIncludeClassNamePatternsAnnotation() { - - @IncludeClassNamePatterns({ " foo", "bar " }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains("'foo'", "'bar'"); - } - - @Test - void trimsArgumentsOfExcludeClassNamePatternsAnnotation() { - - @ExcludeClassNamePatterns({ " foo", "bar " }) - class TestCase { - } - - var request = instantiateRunnerAndCaptureGeneratedRequest(TestCase.class); - - var filters = request.getFiltersByType(ClassNameFilter.class); - assertThat(getOnlyElement(filters).toString()).contains("'foo'", "'bar'"); - } - - @Test - void convertsTestIdentifiersIntoDescriptions() { - - TestDescriptor container1 = new TestDescriptorStub(UniqueId.root("root", "container1"), "container1"); - container1.addChild(new TestDescriptorStub(UniqueId.root("root", "test1"), "test1")); - TestDescriptor container2 = new TestDescriptorStub(UniqueId.root("root", "container2"), "container2"); - container2.addChild(new TestDescriptorStub(UniqueId.root("root", "test2a"), "test2a")); - container2.addChild(new TestDescriptorStub(UniqueId.root("root", "test2b"), "test2b")); - var testPlan = TestPlan.from(true, List.of(container1, container2), mock(), dummyOutputDirectoryProvider()); - - var launcher = mock(Launcher.class); - when(launcher.discover(any())).thenReturn(testPlan); - - var runner = new JUnitPlatform(TestClass.class, launcher); - - var runnerDescription = runner.getDescription(); - assertEquals(createSuiteDescription(TestClass.class), runnerDescription); - - List containerDescriptions = runnerDescription.getChildren(); - assertThat(containerDescriptions).hasSize(2); - assertEquals(suiteDescription("[root:container1]"), containerDescriptions.get(0)); - assertEquals(suiteDescription("[root:container2]"), containerDescriptions.get(1)); - - List testDescriptions = containerDescriptions.get(0).getChildren(); - assertEquals(testDescription("[root:test1]"), getOnlyElement(testDescriptions)); - - testDescriptions = containerDescriptions.get(1).getChildren(); - assertThat(testDescriptions).hasSize(2); - assertEquals(testDescription("[root:test2a]"), testDescriptions.get(0)); - assertEquals(testDescription("[root:test2b]"), testDescriptions.get(1)); - } - - private static void assertIncludes(Filter filter, T included) { - assertThat(filter.apply(included).included()).isTrue(); - } - - private static void assertExcludes(Filter filter, T excluded) { - assertThat(filter.apply(excluded).excluded()).isTrue(); - } - - } - - @Nested - class Filtering { - - private final ConfigurationParameters configParams = mock(); - - @Test - void appliesFilter() throws Exception { - - TestDescriptor originalParent1 = new TestDescriptorStub(UniqueId.root("root", "parent1"), "parent1"); - originalParent1.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf1"), "leaf1")); - TestDescriptor originalParent2 = new TestDescriptorStub(UniqueId.root("root", "parent2"), "parent2"); - originalParent2.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2a"), "leaf2a")); - originalParent2.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2b"), "leaf2b")); - var fullTestPlan = TestPlan.from(true, List.of(originalParent1, originalParent2), configParams, - dummyOutputDirectoryProvider()); - - TestDescriptor filteredParent = new TestDescriptorStub(UniqueId.root("root", "parent2"), "parent2"); - filteredParent.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf2b"), "leaf2b")); - var filteredTestPlan = TestPlan.from(true, Set.of(filteredParent), configParams, - dummyOutputDirectoryProvider()); - - var launcher = mock(Launcher.class); - var captor = ArgumentCaptor.forClass(LauncherDiscoveryRequest.class); - when(launcher.discover(captor.capture())).thenReturn(fullTestPlan).thenReturn(filteredTestPlan); - - var runner = new JUnitPlatform(TestClass.class, launcher); - runner.filter(matchMethodDescription(testDescription("[root:leaf2b]"))); - - var lastDiscoveryRequest = captor.getValue(); - var uniqueIdSelectors = lastDiscoveryRequest.getSelectorsByType(UniqueIdSelector.class); - assertEquals("[root:leaf2b]", getOnlyElement(uniqueIdSelectors).getUniqueId().toString()); - - var parentDescription = getOnlyElement(runner.getDescription().getChildren()); - assertEquals(suiteDescription("[root:parent2]"), parentDescription); - - var testDescription = getOnlyElement(parentDescription.getChildren()); - assertEquals(testDescription("[root:leaf2b]"), testDescription); - } - - @Test - void throwsNoTestsRemainExceptionWhenNoTestIdentifierMatchesFilter() { - var testPlan = TestPlan.from(true, Set.of(new TestDescriptorStub(UniqueId.root("root", "test"), "test")), - configParams, dummyOutputDirectoryProvider()); - - var launcher = mock(Launcher.class); - when(launcher.discover(any())).thenReturn(testPlan); - - var runner = new JUnitPlatform(TestClass.class, launcher); - - assertThrows(NoTestsRemainException.class, - () -> runner.filter(matchMethodDescription(suiteDescription("[root:doesNotExist]")))); - } - - } - - @Nested - class Execution { - - @Test - void notifiesRunListenerOfTestExecution() throws Exception { - var engine = new DemoHierarchicalTestEngine("dummy"); - engine.addTest("failingTest", () -> fail("expected to fail")); - engine.addTest("succeedingTest", () -> { - }); - engine.addTest("abortedTest", () -> assumeFalse(true)); - engine.addTest("skippedTest", () -> fail("never called")).markSkipped("should be skipped"); - - var runListener = mock(RunListener.class); - - var notifier = new RunNotifier(); - notifier.addListener(runListener); - new JUnitPlatform(TestClass.class, createLauncher(engine)).run(notifier); - - var inOrder = inOrder(runListener); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:failingTest]")); - inOrder.verify(runListener).testFailure(any()); - inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:failingTest]")); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:succeedingTest]")); - inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:succeedingTest]")); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dummy]/[test:abortedTest]")); - inOrder.verify(runListener).testAssumptionFailure(any()); - inOrder.verify(runListener).testFinished(testDescription("[engine:dummy]/[test:abortedTest]")); - - inOrder.verify(runListener).testIgnored(testDescription("[engine:dummy]/[test:skippedTest]")); - - inOrder.verifyNoMoreInteractions(); - } - - @Test - void supportsDynamicTestRegistration() throws Exception { - var runListener = mock(RunListener.class); - var notifier = new RunNotifier(); - // notifier.addListener(new LoggingRunListener()); - notifier.addListener(runListener); - new JUnitPlatform(TestClass.class, createLauncher(new DynamicTestEngine())).run(notifier); - - var inOrder = inOrder(runListener); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:1]")); - inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:1]")); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:2]")); - inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:2]")); - - inOrder.verify(runListener).testStarted(testDescription("[engine:dynamic]/[container:1]/[test:3]")); - inOrder.verify(runListener).testFinished(testDescription("[engine:dynamic]/[container:1]/[test:3]")); - - inOrder.verify(runListener).testStarted( - testDescription("[engine:dynamic]/[container:1]/[test:3]/[test:3a]")); - inOrder.verify(runListener).testFinished( - testDescription("[engine:dynamic]/[container:1]/[test:3]/[test:3a]")); - - inOrder.verifyNoMoreInteractions(); - } - - @Test - void reportsIgnoredEventsForLeavesWhenContainerIsSkipped() throws Exception { - var uniqueEngineId = UniqueId.forEngine("engine"); - TestDescriptor engineDescriptor = new EngineDescriptor(uniqueEngineId, "engine"); - TestDescriptor container = new TestDescriptorStub(UniqueId.root("root", "container"), "container"); - container.addChild(new TestDescriptorStub(UniqueId.root("root", "leaf"), "leaf")); - engineDescriptor.addChild(container); - - var engine = mock(TestEngine.class); - when(engine.getId()).thenReturn("engine"); - when(engine.discover(any(), eq(uniqueEngineId))).thenReturn(engineDescriptor); - doAnswer(invocation -> { - ExecutionRequest request = invocation.getArgument(0); - var listener = request.getEngineExecutionListener(); - listener.executionStarted(engineDescriptor); - listener.executionSkipped(container, "deliberately skipped container"); - listener.executionFinished(engineDescriptor, successful()); - return null; - }).when(engine).execute(any()); - - var runListener = mock(RunListener.class); - - var notifier = new RunNotifier(); - notifier.addListener(runListener); - new JUnitPlatform(TestClass.class, createLauncher(engine)).run(notifier); - - verify(runListener).testIgnored(testDescription("[root:leaf]")); - verifyNoMoreInteractions(runListener); - } - - } - - @Nested - class Descriptions { - - @Test - @DisplayName("Suite with default display name") - void descriptionForTestSuiteWithDefaultDisplayName() { - Class testClass = TestSuiteWithDefaultDisplayName.class; - var platformRunner = new JUnitPlatform(testClass, - createLauncher(new DemoHierarchicalTestEngine("suite names"))); - - assertEquals(testClass.getName(), platformRunner.getDescription().getDisplayName()); - } - - @Test - @DisplayName("Suite with @SuiteDisplayName") - void descriptionForTestSuiteWithCustomDisplayName() { - var platformRunner = new JUnitPlatform(TestSuiteWithCustomDisplayName.class, - createLauncher(new DemoHierarchicalTestEngine("suite names"))); - - assertEquals("Sweeeeeeet Name!", platformRunner.getDescription().getDisplayName()); - } - - @Test - @DisplayName("Suite with @SuiteDisplayName and @UseTechnicalNames") - void descriptionForTestSuiteWithCustomDisplayNameAndTechnicalNames() { - Class testClass = TestSuiteWithCustomDisplayNameAndTechnicalNames.class; - var platformRunner = new JUnitPlatform(testClass, - createLauncher(new DemoHierarchicalTestEngine("suite names"))); - - assertEquals(testClass.getName(), platformRunner.getDescription().getDisplayName()); - } - - @Test - void descriptionForJavaMethodAndClassSources() throws Exception { - var engine = new DemoHierarchicalTestEngine("dummy"); - var failingTest = getClass().getDeclaredMethod("failingTest"); - var containerDescriptor = engine.addContainer("uniqueContainerName", "containerDisplayName", - ClassSource.from(getClass())); - containerDescriptor.addChild( - new DemoHierarchicalTestDescriptor(containerDescriptor.getUniqueId().append("test", "failingTest"), - "testDisplayName", MethodSource.from(failingTest), (c, t) -> { - })); - - var platformRunner = new JUnitPlatform(TestClass.class, createLauncher(engine)); - - List children = platformRunner.getDescription().getChildren(); - assertEquals(1, children.size()); - var engineDescription = children.getFirst(); - assertEquals("dummy", engineDescription.getDisplayName()); - - var containerDescription = getOnlyElement(engineDescription.getChildren()); - var testDescription = getOnlyElement(containerDescription.getChildren()); - - // @formatter:off - assertAll( - () -> assertEquals("dummy", engineDescription.getDisplayName(), "engine display name"), - () -> assertEquals("dummy", engineDescription.getClassName(), "engine class name"), - () -> assertNull(engineDescription.getMethodName(), "engine method name"), - () -> assertEquals("containerDisplayName", containerDescription.getDisplayName(), "container display name"), - () -> assertEquals("containerDisplayName", containerDescription.getClassName(), "container class name"), - () -> assertNull(containerDescription.getMethodName(), "container method name"), - () -> assertEquals("testDisplayName(containerDisplayName)", testDescription.getDisplayName(), "test display name"), - () -> assertEquals("containerDisplayName", testDescription.getClassName(), "test class name"), - () -> assertEquals("testDisplayName", testDescription.getMethodName(), "test method name") - ); - // @formatter:on - } - - @Test - void descriptionForJavaMethodAndClassSourcesUsingTechnicalNames() throws Exception { - var engine = new DemoHierarchicalTestEngine("dummy"); - var failingTest = getClass().getDeclaredMethod("failingTest"); - var containerDescriptor = engine.addContainer("uniqueContainerName", "containerDisplayName", - ClassSource.from(getClass())); - containerDescriptor.addChild( - new DemoHierarchicalTestDescriptor(containerDescriptor.getUniqueId().append("test", "failingTest"), - "testDisplayName", MethodSource.from(failingTest), (c, t) -> { - })); - - var platformRunner = new JUnitPlatform(TestClassWithTechnicalNames.class, createLauncher(engine)); - - List children = platformRunner.getDescription().getChildren(); - assertEquals(1, children.size()); - var engineDescription = children.getFirst(); - assertEquals("dummy", engineDescription.getDisplayName()); - - var containerDescription = getOnlyElement(engineDescription.getChildren()); - var testDescription = getOnlyElement(containerDescription.getChildren()); - - // @formatter:off - assertAll( - () -> assertEquals("dummy", engineDescription.getDisplayName(), "engine display name"), - () -> assertEquals("dummy", engineDescription.getClassName(), "engine class name"), - () -> assertNull(engineDescription.getMethodName(), "engine method name"), - () -> assertEquals(getClass().getName(), containerDescription.getDisplayName(), "container display name"), - () -> assertEquals(getClass().getName(), containerDescription.getClassName(), "container class name"), - () -> assertNull(containerDescription.getMethodName(), "container method name"), - () -> assertEquals("failingTest(" + getClass().getName() + ")", testDescription.getDisplayName(), "test display name"), - () -> assertEquals(getClass().getName(), testDescription.getClassName(), "test class name"), - () -> assertEquals("failingTest", testDescription.getMethodName(), "test method name") - ); - // @formatter:on - } - - void failingTest() { - // not actually invoked - } - - } - - // ------------------------------------------------------------------------- - - private static Description suiteDescription(String uniqueId) { - return createSuiteDescription(uniqueId, UniqueId.parse(uniqueId)); - } - - private static Description testDescription(String uniqueId) { - return createTestDescription(uniqueId, uniqueId, UniqueId.parse(uniqueId)); - } - - private TestDescriptor testDescriptorWithTags(String... tag) { - var testDescriptor = mock(TestDescriptor.class); - var tags = Arrays.stream(tag).map(TestTag::create).collect(toSet()); - when(testDescriptor.getTags()).thenReturn(tags); - return testDescriptor; - } - - private LauncherDiscoveryRequest instantiateRunnerAndCaptureGeneratedRequest(Class testClass) { - var launcher = mock(Launcher.class); - var captor = ArgumentCaptor.forClass(LauncherDiscoveryRequest.class); - when(launcher.discover(captor.capture())).thenReturn( - TestPlan.from(true, Set.of(), mock(), dummyOutputDirectoryProvider())); - - new JUnitPlatform(testClass, launcher); - - return captor.getValue(); - } - - private static class TestClass { - } - - @UseTechnicalNames - private static class TestClassWithTechnicalNames { - } - - private static class TestSuiteWithDefaultDisplayName { - } - - @SuiteDisplayName("Sweeeeeeet Name!") - private static class TestSuiteWithCustomDisplayName { - } - - @SuiteDisplayName("Sweeeeeeet Name!") - @UseTechnicalNames - private static class TestSuiteWithCustomDisplayNameAndTechnicalNames { - } - - private static class DynamicTestEngine implements TestEngine { - - @Override - public String getId() { - return "dynamic"; - } - - @Override - public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { - return new EngineDescriptor(uniqueId, "Dynamic Engine"); - } - - @Override - public void execute(ExecutionRequest request) { - var engineExecutionListener = request.getEngineExecutionListener(); - var root = request.getRootTestDescriptor(); - - TestDescriptor container = new DemoContainerTestDescriptor(root.getUniqueId().append("container", "1"), - "container #1"); - root.addChild(container); - - engineExecutionListener.dynamicTestRegistered(container); - engineExecutionListener.executionStarted(container); - - var containerUid = container.getUniqueId(); - - TestDescriptor dynamicTest1 = new DemoTestTestDescriptor(containerUid.append("test", "1"), - "dynamic test #1"); - container.addChild(dynamicTest1); - engineExecutionListener.dynamicTestRegistered(dynamicTest1); - engineExecutionListener.executionStarted(dynamicTest1); - engineExecutionListener.executionFinished(dynamicTest1, TestExecutionResult.successful()); - - TestDescriptor dynamicTest2 = new DemoTestTestDescriptor(containerUid.append("test", "2"), - "dynamic test #2"); - container.addChild(dynamicTest2); - engineExecutionListener.dynamicTestRegistered(dynamicTest2); - engineExecutionListener.executionStarted(dynamicTest2); - engineExecutionListener.executionFinished(dynamicTest2, TestExecutionResult.successful()); - - TestDescriptor dynamicTest3 = new DemoContainerAndTestTestDescriptor(containerUid.append("test", "3"), - "dynamic test #3"); - container.addChild(dynamicTest3); - engineExecutionListener.dynamicTestRegistered(dynamicTest3); - engineExecutionListener.executionStarted(dynamicTest3); - engineExecutionListener.executionFinished(dynamicTest3, TestExecutionResult.successful()); - - TestDescriptor dynamicTest3a = new DemoTestTestDescriptor(dynamicTest3.getUniqueId().append("test", "3a"), - "dynamic test #3a"); - dynamicTest3.addChild(dynamicTest3a); - engineExecutionListener.dynamicTestRegistered(dynamicTest3a); - engineExecutionListener.executionStarted(dynamicTest3a); - engineExecutionListener.executionFinished(dynamicTest3a, TestExecutionResult.successful()); - - engineExecutionListener.executionFinished(container, TestExecutionResult.successful()); - } - - } - - private static class DemoContainerTestDescriptor extends AbstractTestDescriptor { - - DemoContainerTestDescriptor(UniqueId uniqueId, String displayName) { - super(uniqueId, displayName); - } - - @Override - public Type getType() { - return Type.CONTAINER; - } - } - - private static class DemoTestTestDescriptor extends AbstractTestDescriptor { - - DemoTestTestDescriptor(UniqueId uniqueId, String displayName) { - super(uniqueId, displayName); - } - - @Override - public Type getType() { - return Type.TEST; - } - } - - private static class DemoContainerAndTestTestDescriptor extends AbstractTestDescriptor { - - DemoContainerAndTestTestDescriptor(UniqueId uniqueId, String displayName) { - super(uniqueId, displayName); - } - - @Override - public Type getType() { - return Type.CONTAINER_AND_TEST; - } - } - -} diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt index 4e06393f529f..040ca4b3525e 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt @@ -10,5 +10,5 @@ requires java.logging requires java.management requires org.apiguardian.api static transitive uses org.junit.platform.commons.support.scanning.ClasspathScanner -qualified exports org.junit.platform.commons.logging to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.runner org.junit.platform.suite.api org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine -qualified exports org.junit.platform.commons.util to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.jfr org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.runner org.junit.platform.suite.api org.junit.platform.suite.commons org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine +qualified exports org.junit.platform.commons.logging to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.suite.api org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine +qualified exports org.junit.platform.commons.util to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.jfr org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.suite.api org.junit.platform.suite.commons org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt deleted file mode 100644 index ea26b6302bce..000000000000 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-runner.expected.txt +++ /dev/null @@ -1,8 +0,0 @@ -org.junit.platform.runner@${version} jar:file:.+/junit-platform-runner-\d.+\.jar..module-info\.class -exports org.junit.platform.runner -requires java.base mandated -requires junit transitive -requires org.apiguardian.api static transitive -requires org.junit.platform.launcher transitive -requires org.junit.platform.suite.api transitive -requires org.junit.platform.suite.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt index e818b5d1973e..0d25ab3dc62b 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt @@ -5,4 +5,4 @@ requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher transitive requires org.junit.platform.suite.api -qualified exports org.junit.platform.suite.commons to org.junit.platform.runner org.junit.platform.suite.engine +qualified exports org.junit.platform.suite.commons to org.junit.platform.suite.engine diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index 71f04fba2256..abaaee787a29 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -106,7 +106,6 @@ void avoidAccessingStandardStreams(JavaClasses classes) { .that(are(not(name("org.junit.platform.console.ConsoleLauncher")))) // .that(are(not(name("org.junit.platform.console.tasks.ConsoleTestExecutor")))) // .that(are(not(name("org.junit.platform.launcher.core.StreamInterceptor")))) // - .that(are(not(name("org.junit.platform.runner.JUnitPlatformRunnerListener")))) // .that(are(not(name("org.junit.platform.testkit.engine.Events")))) // .that(are(not(name("org.junit.platform.testkit.engine.Executions")))) // //The PreInterruptThreadDumpPrinter writes to StdOut by contract to dump threads diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java index 594ab00b595a..4963e616f8fe 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/HelperTests.java @@ -42,7 +42,6 @@ void loadModuleDirectoryNames() { "junit-platform-jfr", // "junit-platform-launcher", // "junit-platform-reporting", // - "junit-platform-runner", // "junit-platform-suite", // "junit-platform-suite-api", // "junit-platform-suite-commons", // diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java index e7987317cdd2..6451f5e8d1fd 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java @@ -53,7 +53,7 @@ class ModularUserGuideTests { requires org.junit.platform.engine; requires org.junit.platform.reporting; - requires org.junit.platform.runner; + requires org.junit.platform.suite; requires org.junit.platform.testkit; // Byte Buddy is used by AssertJ's soft assertions which are used by the Engine Test Kit diff --git a/settings.gradle.kts b/settings.gradle.kts index ba5ae9fd677f..3cb5c303cc6f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -84,7 +84,6 @@ include("junit-platform-engine") include("junit-platform-jfr") include("junit-platform-launcher") include("junit-platform-reporting") -include("junit-platform-runner") include("junit-platform-suite") include("junit-platform-suite-api") include("junit-platform-suite-commons") From 9151d0ecf37b0fbda48c71893c473124b03fec43 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 15:11:19 +0200 Subject: [PATCH 039/521] Delete deprecated `@UseTechnicalNames` annotation --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../platform/suite/api/UseTechnicalNames.java | 51 ------------------- 2 files changed, 1 insertion(+), 51 deletions(-) delete mode 100644 junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 2c2d91e7078b..5937d65d553e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -63,6 +63,7 @@ repository on GitHub. - `LegacyReportingUtils` class - `TestPlan.add(TestIdentifier)`, `TestPlan.getChildren(String)`, and `TestPlan.getTestIdentifier(String)` methods + - `@UseTechnicalNames` annotation [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java deleted file mode 100644 index 6edbe5f25add..000000000000 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/UseTechnicalNames.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * 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.suite.api; - -import static org.apiguardian.api.API.Status.DEPRECATED; - -import java.lang.annotation.Documented; -import java.lang.annotation.ElementType; -import java.lang.annotation.Inherited; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import org.apiguardian.api.API; - -/** - * {@code @UseTechnicalNames} specifies that technical names should be - * used instead of display names when running a test suite on the - * JUnit Platform. - * - *

By default, display names will be used for test artifacts in - * reports and graphical displays in IDEs; however, when a JUnit Platform test - * suite is executed with a build tool such as Gradle or Maven, the generated - * test report may need to include the technical names of test - * artifacts — for example, fully qualified class names — instead - * of shorter display names like the simple name of a test class or a - * custom display name containing special characters. - * - *

Note that the presence of {@code @UseTechnicalNames} overrides any custom - * display name configured for the suite via {@link SuiteDisplayName @SuiteDisplayName}. - * - * @since 1.0 - * @deprecated since 1.8, in favor of the {@link Suite @Suite} support provided by - * the {@code junit-platform-suite-engine} module; to be removed in JUnit Platform 2.0 - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -@Inherited -@Documented -@API(status = DEPRECATED, since = "1.8") -@Deprecated -public @interface UseTechnicalNames { -} From 459c0bb63319c34b7782b04098cd7dd284e3600f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 15:25:00 +0200 Subject: [PATCH 040/521] Delete deprecated methods in `EngineTestKit` --- .../release-notes/release-notes-6.0.0-M1.adoc | 3 + .../testkit/engine/EngineTestKit.java | 95 ------------------- 2 files changed, 3 insertions(+), 95 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 5937d65d553e..4837c4e75c4a 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -64,6 +64,9 @@ repository on GitHub. - `TestPlan.add(TestIdentifier)`, `TestPlan.getChildren(String)`, and `TestPlan.getTestIdentifier(String)` methods - `@UseTechnicalNames` annotation + - `EngineTestKit.execute(String, EngineDiscoveryRequest)`, + `EngineTestKit.execute(TestEngine, EngineDiscoveryRequest)`, and + `EngineTestKit.Builder.filters(...)` methods [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements 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 9f7f3e18501a..bd878a4c8bbd 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 @@ -12,7 +12,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; @@ -196,42 +195,6 @@ public static EngineDiscoveryResults discover(TestEngine testEngine, LauncherDis return new EngineDiscoveryResults(engineDescriptor, discoveryIssues); } - /** - * Execute tests for the given {@link EngineDiscoveryRequest} using the - * {@link TestEngine} with the supplied ID. - * - *

The {@code TestEngine} will be loaded via Java's {@link ServiceLoader} - * mechanism, analogous to the manner in which test engines are loaded in - * the JUnit Platform Launcher API. - * - *

Note that {@link org.junit.platform.launcher.LauncherDiscoveryRequest} - * from the {@code junit-platform-launcher} module is a subtype of - * {@code EngineDiscoveryRequest}. It is therefore quite convenient to make - * use of the DSL provided in - * {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} - * to build an appropriate discovery request to supply to this method. As - * an alternative, consider using {@link #engine(String)} for a more fluent - * API. - * - * @param engineId the ID of the {@code TestEngine} to use; must not be - * {@code null} or blank - * @param discoveryRequest the {@code EngineDiscoveryRequest} to use - * @return the results of the execution - * @throws PreconditionViolationException for invalid arguments or if the - * {@code TestEngine} with the supplied ID cannot be loaded - * @see #execute(String, LauncherDiscoveryRequest) - * @see #engine(String) - * @see #engine(TestEngine) - * @deprecated Please use {@link #execute(String, LauncherDiscoveryRequest)} - * instead. - */ - @Deprecated - @API(status = DEPRECATED, since = "1.7") - public static EngineExecutionResults execute(String engineId, EngineDiscoveryRequest discoveryRequest) { - Preconditions.notBlank(engineId, "TestEngine ID must not be null or blank"); - return execute(loadTestEngine(engineId.trim()), discoveryRequest); - } - /** * Execute tests for the given {@link LauncherDiscoveryRequest} using the * {@link TestEngine} with the supplied ID. @@ -261,41 +224,6 @@ public static EngineExecutionResults execute(String engineId, LauncherDiscoveryR return execute(loadTestEngine(engineId.trim()), discoveryRequest); } - /** - * Execute tests for the given {@link EngineDiscoveryRequest} using the - * supplied {@link TestEngine}. - * - *

Note that {@link org.junit.platform.launcher.LauncherDiscoveryRequest} - * from the {@code junit-platform-launcher} module is a subtype of - * {@code EngineDiscoveryRequest}. It is therefore quite convenient to make - * use of the DSL provided in - * {@link org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder} - * to build an appropriate discovery request to supply to this method. As - * an alternative, consider using {@link #engine(TestEngine)} for a more fluent - * API. - * - * @param testEngine the {@code TestEngine} to use; must not be {@code null} - * @param discoveryRequest the {@code EngineDiscoveryRequest} to use; must - * not be {@code null} - * @return the recorded {@code EngineExecutionResults} - * @throws PreconditionViolationException for invalid arguments - * @see #execute(TestEngine, LauncherDiscoveryRequest) - * @see #engine(String) - * @see #engine(TestEngine) - * @deprecated Please use {@link #execute(TestEngine, LauncherDiscoveryRequest)} - * instead. - */ - @Deprecated - @API(status = DEPRECATED, since = "1.7") - public static EngineExecutionResults execute(TestEngine testEngine, EngineDiscoveryRequest discoveryRequest) { - Preconditions.notNull(testEngine, "TestEngine must not be null"); - Preconditions.notNull(discoveryRequest, "EngineDiscoveryRequest must not be null"); - - ExecutionRecorder executionRecorder = new ExecutionRecorder(); - executeDirectly(testEngine, discoveryRequest, executionRecorder); - return executionRecorder.getExecutionResults(); - } - /** * Execute tests for the given {@link LauncherDiscoveryRequest} using the * supplied {@link TestEngine}. @@ -418,29 +346,6 @@ public Builder selectors(DiscoverySelector... selectors) { return this; } - /** - * Add all of the supplied {@linkplain DiscoveryFilter discovery filters}. - * - *

Built-in discovery filters can be created via the static factory - * methods in {@link org.junit.platform.engine.discovery.ClassNameFilter} - * and {@link org.junit.platform.engine.discovery.PackageNameFilter}. - * - * @param filters the discovery filters to add; never {@code null} - * @return this builder for method chaining - * @see #filters(Filter...) - * @see #selectors(DiscoverySelector...) - * @see #configurationParameter(String, String) - * @see #configurationParameters(Map) - * @see #execute() - * @deprecated Please use {@link #filters(Filter...)} instead. - */ - @Deprecated - @API(status = DEPRECATED, since = "1.7") - public Builder filters(DiscoveryFilter... filters) { - this.requestBuilder.filters(filters); - return this; - } - /** * Add all of the supplied {@linkplain Filter filters}. * From 39d3d73e06f9532fe5132efa19aebeb6d8f13780 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 15:52:46 +0200 Subject: [PATCH 041/521] Remove support for deprecated `junit.jupiter.tempdir.scope` config param --- .../release-notes/release-notes-6.0.0-M1.adoc | 2 + .../asciidoc/user-guide/writing-tests.adoc | 5 - .../org/junit/jupiter/api/io/TempDir.java | 41 - .../org/junit/jupiter/engine/Constants.java | 12 - .../jupiter/engine/JupiterTestEngine.java | 10 +- .../config/DefaultJupiterConfiguration.java | 19 +- .../discovery/DiscoverySelectorResolver.java | 5 +- .../engine/extension/TempDirectory.java | 54 +- .../DefaultJupiterConfigurationTests.java | 32 +- .../descriptor/ExtensionContextTests.java | 2 +- .../TestInstanceLifecycleUtilsTests.java | 12 +- .../TempDirectoryPerContextTests.java | 1527 ----------------- ...tionTests.java => TempDirectoryTests.java} | 15 +- 13 files changed, 78 insertions(+), 1658 deletions(-) delete mode 100644 jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerContextTests.java rename jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/{TempDirectoryPerDeclarationTests.java => TempDirectoryTests.java} (98%) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 4837c4e75c4a..71d48454fa11 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -88,6 +88,8 @@ repository on GitHub. * The following deprecated APIs have been removed: - `MethodOrderer.Alphanumeric` class - `InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext)` method +* The deprecated `junit.jupiter.tempdir.scope` configuration parameter is no longer + supported. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 7e0ec66aa075..a1f1243a987b 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -3521,11 +3521,6 @@ You can inject multiple temporary directories by specifying multiple annotated p include::{testDir}/example/TempDirectoryDemo.java[tags=user_guide_multiple_directories] ---- -WARNING: To revert to the old behavior of using a single temporary directory for the -entire test class or method (depending on which level the annotation is used), you can set -the `junit.jupiter.tempdir.scope` configuration parameter to `per_context`. However, -please note that this option is deprecated and will be removed in a future release. - The following example stores a _shared_ temporary directory in a `static` field. This allows the same `sharedTempDir` to be used in all lifecycle methods and test methods of the test class. For better isolation, you should use an instance field or constructor 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..71aaf1250b10 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 @@ -10,7 +10,6 @@ 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.STABLE; @@ -63,21 +62,6 @@ * {@code static} field or on a parameter of a * {@link org.junit.jupiter.api.BeforeAll @BeforeAll} method. * - *

Old behavior

- * - *

You can revert to the old behavior of using a single temporary directory - * by setting the {@value #SCOPE_PROPERTY_NAME} configuration parameter to - * {@code per_context}. In that case, the scope of the temporary directory - * depends on where the first {@code @TempDir} annotation is encountered when - * executing a test class. The temporary directory will be shared by all tests - * in a class when the annotation is present on a {@code static} field or on a - * parameter of a {@link org.junit.jupiter.api.BeforeAll @BeforeAll} method. - * Otherwise — for example, when {@code @TempDir} is only used on instance - * fields or on parameters in test, - * {@link org.junit.jupiter.api.BeforeEach @BeforeEach}, or - * {@link org.junit.jupiter.api.AfterEach @AfterEach} methods — each test - * will use its own temporary directory. - * *

Clean Up

* *

By default, when the end of the scope of a temporary directory is reached, @@ -126,9 +110,6 @@ /** * Factory for the temporary directory. * - *

If the {@value #SCOPE_PROPERTY_NAME} configuration parameter is set to - * {@code per_context}, no custom factory is allowed. - * *

Defaults to {@link TempDirFactory.Standard}. * *

As an alternative to setting this attribute, a global @@ -145,28 +126,6 @@ @API(status = EXPERIMENTAL, since = "5.10") Class factory() default TempDirFactory.class; - /** - * Property name used to set the scope of temporary directories created via - * the {@link TempDir @TempDir} annotation: {@value} - * - *

Supported Values

- *
    - *
  • {@code per_context}: creates a single temporary directory for the - * entire test class or method, depending on where {@code @TempDir} is first - * declared
  • - *
  • {@code per_declaration}: creates separate temporary directories for - * each declaration site of the {@code @TempDir} annotation
  • - *
- * - *

If not specified, the default is {@code per_declaration}. - * - * @since 5.8 - */ - @SuppressWarnings("DeprecatedIsStillUsed") - @Deprecated - @API(status = DEPRECATED, since = "5.9") - String SCOPE_PROPERTY_NAME = "junit.jupiter.tempdir.scope"; - /** * The name of the configuration parameter that is used to configure the * default {@link CleanupMode}. 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..56c2091eddaf 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 @@ -10,7 +10,6 @@ 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.STABLE; import static org.junit.platform.engine.support.hierarchical.DefaultParallelExecutionConfigurationStrategy.CONFIG_CUSTOM_CLASS_PROPERTY_NAME; @@ -434,17 +433,6 @@ public final class Constants { @API(status = STABLE, since = "5.9") public static final String DEFAULT_TEST_CLASS_ORDER_PROPERTY_NAME = ClassOrderer.DEFAULT_ORDER_PROPERTY_NAME; - /** - * Property name used to set the scope of temporary directories created via - * the {@link TempDir @TempDir} annotation: {@value} - * - * @see TempDir#SCOPE_PROPERTY_NAME - */ - @Deprecated - @API(status = DEPRECATED, since = "5.8") - @SuppressWarnings("deprecation") - public static final String TEMP_DIR_SCOPE_PROPERTY_NAME = TempDir.SCOPE_PROPERTY_NAME; - /** * Property name used to set the default timeout thread mode. * diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/JupiterTestEngine.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/JupiterTestEngine.java index c3878b9c84b7..59f2bc794c92 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/JupiterTestEngine.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/JupiterTestEngine.java @@ -28,6 +28,7 @@ import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.config.PrefixedConfigurationParameters; +import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; import org.junit.platform.engine.support.hierarchical.ForkJoinPoolHierarchicalTestExecutorService; import org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine; import org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutorService; @@ -64,10 +65,13 @@ public Optional getArtifactId() { @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { - JupiterConfiguration configuration = new CachingJupiterConfiguration(new DefaultJupiterConfiguration( - discoveryRequest.getConfigurationParameters(), discoveryRequest.getOutputDirectoryProvider())); + DiscoveryIssueReporter issueReporter = DiscoveryIssueReporter.deduplicating( + DiscoveryIssueReporter.forwarding(discoveryRequest.getDiscoveryListener(), uniqueId)); + JupiterConfiguration configuration = new CachingJupiterConfiguration( + new DefaultJupiterConfiguration(discoveryRequest.getConfigurationParameters(), + discoveryRequest.getOutputDirectoryProvider(), issueReporter)); JupiterEngineDescriptor engineDescriptor = new JupiterEngineDescriptor(uniqueId, configuration); - new DiscoverySelectorResolver().resolveSelectors(discoveryRequest, engineDescriptor); + DiscoverySelectorResolver.resolveSelectors(discoveryRequest, engineDescriptor, issueReporter); return engineDescriptor; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java index c6ab8b0d5508..9dce4a7397ab 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java @@ -15,6 +15,7 @@ import static org.junit.jupiter.api.io.TempDir.DEFAULT_CLEANUP_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.io.TempDir.DEFAULT_FACTORY_PROPERTY_NAME; +import java.util.List; import java.util.Optional; import java.util.function.Function; import java.util.function.Predicate; @@ -34,7 +35,10 @@ import org.junit.platform.commons.util.ClassNamePatternFilterUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; +import org.junit.platform.engine.DiscoveryIssue; +import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.reporting.OutputDirectoryProvider; +import org.junit.platform.engine.support.discovery.DiscoveryIssueReporter; /** * Default implementation of the {@link JupiterConfiguration} API. @@ -44,6 +48,8 @@ @API(status = INTERNAL, since = "5.4") public class DefaultJupiterConfiguration implements JupiterConfiguration { + private final List UNSUPPORTED_CONFIGURATION_PARAMETERS = List.of("junit.jupiter.tempdir.scope"); + private static final EnumConfigurationParameterConverter executionModeConverter = // new EnumConfigurationParameterConverter<>(ExecutionMode.class, "parallel execution mode"); @@ -72,10 +78,21 @@ public class DefaultJupiterConfiguration implements JupiterConfiguration { private final OutputDirectoryProvider outputDirectoryProvider; public DefaultJupiterConfiguration(ConfigurationParameters configurationParameters, - OutputDirectoryProvider outputDirectoryProvider) { + OutputDirectoryProvider outputDirectoryProvider, DiscoveryIssueReporter issueReporter) { this.configurationParameters = Preconditions.notNull(configurationParameters, "ConfigurationParameters must not be null"); this.outputDirectoryProvider = outputDirectoryProvider; + validateConfigurationParameters(issueReporter); + } + + private void validateConfigurationParameters(DiscoveryIssueReporter issueReporter) { + UNSUPPORTED_CONFIGURATION_PARAMETERS.forEach(key -> configurationParameters.get(key) // + .ifPresent(value -> { + var warning = DiscoveryIssue.create(Severity.WARNING, + "The '%s' configuration parameter is no longer supported: %s. Please remove it from your configuration.".formatted( + key, value)); + issueReporter.reportIssue(warning); + })); } @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java index 6fabb7546b73..4cb16f9170fa 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java @@ -57,9 +57,8 @@ private static JupiterConfiguration getConfiguration(InitializationContext testClass, Predicate predicate) { - Scope scope = getScope(context); - findAnnotatedFields(testClass, TempDir.class, predicate).forEach(field -> { assertNonFinalField(field); assertSupportedType("field", field.getType()); try { CleanupMode cleanupMode = determineCleanupModeForField(field); - TempDirFactory factory = determineTempDirFactoryForField(field, scope); + TempDirFactory factory = determineTempDirFactoryForField(field); makeAccessible(field).set(testInstance, - getPathOrFile(field.getType(), new FieldContext(field), factory, cleanupMode, scope, context)); + getPathOrFile(field.getType(), new FieldContext(field), factory, cleanupMode, context)); } catch (Throwable t) { throw ExceptionUtils.throwAsUncheckedException(t); @@ -187,9 +184,8 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte Class parameterType = parameterContext.getParameter().getType(); assertSupportedType("parameter", parameterType); CleanupMode cleanupMode = determineCleanupModeForParameter(parameterContext); - Scope scope = getScope(extensionContext); - TempDirFactory factory = determineTempDirFactoryForParameter(parameterContext, scope); - return getPathOrFile(parameterType, parameterContext, factory, cleanupMode, scope, extensionContext); + TempDirFactory factory = determineTempDirFactoryForParameter(parameterContext); + return getPathOrFile(parameterType, parameterContext, factory, cleanupMode, extensionContext); } private CleanupMode determineCleanupModeForField(Field field) { @@ -209,38 +205,21 @@ private CleanupMode determineCleanupMode(TempDir tempDir) { return cleanupMode == DEFAULT ? this.configuration.getDefaultTempDirCleanupMode() : cleanupMode; } - @SuppressWarnings("deprecation") - private Scope getScope(ExtensionContext context) { - return context.getRoot().getStore(NAMESPACE).getOrComputeIfAbsent( // - Scope.class, // - __ -> new EnumConfigurationParameterConverter<>(Scope.class, "@TempDir scope") // - .get(TempDir.SCOPE_PROPERTY_NAME, context::getConfigurationParameter, Scope.PER_DECLARATION), // - Scope.class // - ); - } - - private TempDirFactory determineTempDirFactoryForField(Field field, Scope scope) { + private TempDirFactory determineTempDirFactoryForField(Field field) { TempDir tempDir = findAnnotation(field, TempDir.class).orElseThrow( () -> new JUnitException("Field " + field + " must be annotated with @TempDir")); - return determineTempDirFactory(tempDir, scope); + return determineTempDirFactory(tempDir); } - private TempDirFactory determineTempDirFactoryForParameter(ParameterContext parameterContext, Scope scope) { + private TempDirFactory determineTempDirFactoryForParameter(ParameterContext parameterContext) { TempDir tempDir = parameterContext.findAnnotation(TempDir.class).orElseThrow(() -> new JUnitException( "Parameter " + parameterContext.getParameter() + " must be annotated with @TempDir")); - return determineTempDirFactory(tempDir, scope); + return determineTempDirFactory(tempDir); } - @SuppressWarnings("deprecation") - private TempDirFactory determineTempDirFactory(TempDir tempDir, Scope scope) { + private TempDirFactory determineTempDirFactory(TempDir tempDir) { Class factory = tempDir.factory(); - if (factory != TempDirFactory.class && scope == Scope.PER_CONTEXT) { - throw new ExtensionConfigurationException("Custom @TempDir factory is not supported with " - + TempDir.SCOPE_PROPERTY_NAME + "=" + Scope.PER_CONTEXT.name().toLowerCase() + ". Use " - + TempDir.DEFAULT_FACTORY_PROPERTY_NAME + " instead."); - } - return factory == TempDirFactory.class // ? this.configuration.getDefaultTempDirFactorySupplier().get() : ReflectionSupport.newInstance(factory); @@ -260,12 +239,9 @@ private static void assertSupportedType(String target, Class type) { } private static Object getPathOrFile(Class elementType, AnnotatedElementContext elementContext, - TempDirFactory factory, CleanupMode cleanupMode, Scope scope, ExtensionContext extensionContext) { + TempDirFactory factory, CleanupMode cleanupMode, ExtensionContext extensionContext) { - Namespace namespace = scope == Scope.PER_DECLARATION // - ? NAMESPACE.append(elementContext) // - : NAMESPACE; - Path path = extensionContext.getStore(namespace) // + Path path = extensionContext.getStore(NAMESPACE.append(elementContext)) // .getOrComputeIfAbsent(KEY, __ -> createTempDir(factory, cleanupMode, elementType, elementContext, extensionContext), CloseablePath.class) // @@ -570,14 +546,6 @@ private Path relativizeSafely(Path path) { } } - enum Scope { - - PER_CONTEXT, - - PER_DECLARATION - - } - interface FileOperations { FileOperations DEFAULT = Files::delete; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java index ba7daa0fe4bb..ef7a98337044 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java @@ -45,20 +45,22 @@ class DefaultJupiterConfigurationTests { @Test void getDefaultTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, - () -> new DefaultJupiterConfiguration(null, dummyOutputDirectoryProvider())); + () -> new DefaultJupiterConfiguration(null, dummyOutputDirectoryProvider(), mock())); assertThat(exception).hasMessage("ConfigurationParameters must not be null"); } @Test void getDefaultTestInstanceLifecycleWithNoConfigParamSet() { - JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), + mock()); Lifecycle lifecycle = configuration.getDefaultTestInstanceLifecycle(); assertThat(lifecycle).isEqualTo(PER_METHOD); } @Test void getDefaultTempDirCleanupModeWithNoConfigParamSet() { - JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), + mock()); CleanupMode cleanupMode = configuration.getDefaultTempDirCleanupMode(); assertThat(cleanupMode).isEqualTo(ALWAYS); } @@ -83,8 +85,8 @@ void shouldGetDefaultDisplayNameGeneratorWithConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.of(CustomDisplayNameGenerator.class.getName())); - JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, - dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, dummyOutputDirectoryProvider(), + mock()); DisplayNameGenerator defaultDisplayNameGenerator = configuration.getDefaultDisplayNameGenerator(); @@ -96,8 +98,8 @@ void shouldGetStandardAsDefaultDisplayNameGeneratorWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_DISPLAY_NAME_GENERATOR_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); - JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, - dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, dummyOutputDirectoryProvider(), + mock()); DisplayNameGenerator defaultDisplayNameGenerator = configuration.getDefaultDisplayNameGenerator(); @@ -109,8 +111,8 @@ void shouldGetNothingAsDefaultTestMethodOrderWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEST_METHOD_ORDER_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); - JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, - dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, dummyOutputDirectoryProvider(), + mock()); final Optional defaultTestMethodOrder = configuration.getDefaultTestMethodOrderer(); @@ -122,8 +124,8 @@ void shouldGetDefaultTempDirFactorySupplierWithConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.of(CustomFactory.class.getName())); - JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, - dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, dummyOutputDirectoryProvider(), + mock()); Supplier supplier = configuration.getDefaultTempDirFactorySupplier(); @@ -143,8 +145,8 @@ void shouldGetStandardAsDefaultTempDirFactorySupplierWithoutConfigParamSet() { ConfigurationParameters parameters = mock(); String key = Constants.DEFAULT_TEMP_DIR_FACTORY_PROPERTY_NAME; when(parameters.get(key)).thenReturn(Optional.empty()); - JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, - dummyOutputDirectoryProvider()); + JupiterConfiguration configuration = new DefaultJupiterConfiguration(parameters, dummyOutputDirectoryProvider(), + mock()); Supplier supplier = configuration.getDefaultTempDirFactorySupplier(); @@ -154,8 +156,8 @@ void shouldGetStandardAsDefaultTempDirFactorySupplierWithoutConfigParamSet() { private void assertDefaultConfigParam(String configValue, Lifecycle expected) { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.ofNullable(configValue)); - Lifecycle lifecycle = new DefaultJupiterConfiguration(configParams, - dummyOutputDirectoryProvider()).getDefaultTestInstanceLifecycle(); + Lifecycle lifecycle = new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider(), + mock()).getDefaultTestInstanceLifecycle(); assertThat(lifecycle).isEqualTo(expected); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index 533ec415b06b..1d41630c244f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -431,7 +431,7 @@ void usingStore() { @MethodSource("extensionContextFactories") void configurationParameter(Function extensionContextFactory) { JupiterConfiguration echo = new DefaultJupiterConfiguration(new EchoParameters(), - dummyOutputDirectoryProvider()); + dummyOutputDirectoryProvider(), mock()); var key = "123"; var expected = Optional.of(key); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java index 186604bc98a9..f16710ad35f7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java @@ -52,7 +52,7 @@ class TestInstanceLifecycleUtilsTests { void getTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, () -> getTestInstanceLifecycle(null, - new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider()))); + new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), mock()))); assertThat(exception).hasMessage("testClass must not be null"); exception = assertThrows(PreconditionViolationException.class, @@ -63,7 +63,7 @@ void getTestInstanceLifecyclePreconditions() { @Test void getTestInstanceLifecycleWithNoConfigParamSet() { Lifecycle lifecycle = getTestInstanceLifecycle(getClass(), - new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider())); + new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), mock())); assertThat(lifecycle).isEqualTo(PER_METHOD); } @@ -72,7 +72,7 @@ void getTestInstanceLifecycleWithConfigParamSet() { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.of(PER_CLASS.name().toLowerCase())); Lifecycle lifecycle = getTestInstanceLifecycle(getClass(), - new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider())); + new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider(), mock())); assertThat(lifecycle).isEqualTo(PER_CLASS); } @@ -81,7 +81,7 @@ void getTestInstanceLifecycleWithLocalConfigThatOverridesCustomDefaultSetViaConf ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.of(PER_CLASS.name().toLowerCase())); Lifecycle lifecycle = getTestInstanceLifecycle(TestCase.class, - new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider())); + new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider(), mock())); assertThat(lifecycle).isEqualTo(PER_METHOD); } @@ -89,7 +89,7 @@ void getTestInstanceLifecycleWithLocalConfigThatOverridesCustomDefaultSetViaConf void getTestInstanceLifecycleFromMetaAnnotationWithNoConfigParamSet() { Class testClass = BaseMetaAnnotatedTestCase.class; Lifecycle lifecycle = getTestInstanceLifecycle(testClass, - new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider())); + new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), mock())); assertThat(lifecycle).isEqualTo(PER_CLASS); } @@ -97,7 +97,7 @@ void getTestInstanceLifecycleFromMetaAnnotationWithNoConfigParamSet() { void getTestInstanceLifecycleFromSpecializedClassWithNoConfigParamSet() { Class testClass = SpecializedTestCase.class; Lifecycle lifecycle = getTestInstanceLifecycle(testClass, - new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider())); + new DefaultJupiterConfiguration(mock(), dummyOutputDirectoryProvider(), mock())); assertThat(lifecycle).isEqualTo(PER_CLASS); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerContextTests.java deleted file mode 100644 index 6200f2e47645..000000000000 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerContextTests.java +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * 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.extension; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.Assumptions.assumeTrue; -import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; -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.cause; -import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; -import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; - -import java.io.File; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.attribute.DosFileAttributeView; -import java.util.Deque; -import java.util.LinkedList; -import java.util.function.Supplier; - -import org.assertj.core.api.Condition; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.MethodOrderer.OrderAnnotation; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.TestInfo; -import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.TestMethodOrder; -import org.junit.jupiter.api.extension.AnnotatedElementContext; -import org.junit.jupiter.api.extension.ExtensionConfigurationException; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.ParameterResolutionException; -import org.junit.jupiter.api.io.TempDir; -import org.junit.jupiter.api.io.TempDirFactory; -import org.junit.jupiter.api.io.TempDirFactory.Standard; -import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; -import org.junit.platform.commons.PreconditionViolationException; -import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; -import org.junit.platform.testkit.engine.EngineExecutionResults; - -/** - * Integration tests for the legacy behavior of the {@link TempDirectory} - * extension to create a single temp directory per context, i.e., test class or - * method. - * - * @since 5.4 - */ -@DisplayName("TempDirectory extension (per context)") -class TempDirectoryPerContextTests extends AbstractJupiterTestEngineTests { - - @Override - protected EngineExecutionResults executeTestsForClass(Class testClass) { - return executeTests(requestBuilder(testClass).build()); - } - - private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class testClass, - Class factoryClass) { - return executeTests(requestBuilder(testClass) // - .configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) // - .build()); - } - - @SuppressWarnings("deprecation") - private static LauncherDiscoveryRequestBuilder requestBuilder(Class testClass) { - return request() // - .selectors(selectClass(testClass)) // - .configurationParameter(TempDir.SCOPE_PROPERTY_NAME, TempDirectory.Scope.PER_CONTEXT.name()); - } - - @BeforeEach - @AfterEach - void resetStaticVariables() { - BaseSharedTempDirFieldInjectionTestCase.staticTempDir = null; - BaseSharedTempDirParameterInjectionTestCase.tempDir = null; - BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.clear(); - BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.clear(); - BaseConstructorInjectionTestCase.tempDirs.clear(); - } - - @Test - @DisplayName("does not prevent constructor parameter resolution") - void tempDirectoryDoesNotPreventConstructorParameterResolution() { - executeTestsForClass(TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("does not prevent user from deleting the temp dir within a test") - void tempDirectoryDoesNotPreventUserFromDeletingTempDir() { - executeTestsForClass(UserTempDirectoryDeletionDoesNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("is capable of removing a read-only file") - void nonWritableFileDoesNotCauseFailure() { - executeTestsForClass(NonWritableFileDoesNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("is capable of removing non-executable, non-writable, or non-readable directories and folders") - void nonMintPermissionsContentDoesNotCauseFailure() { - executeTestsForClass(NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(13).succeeded(13)); - } - - @Test - @DisplayName("is capable of removing a directory when its permissions have been changed") - void nonMintPermissionsDoNotCauseFailure() { - executeTestsForClass(NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(42).succeeded(42)); - } - - @Test - @DisplayName("is capable of removing a read-only file in a read-only dir") - void readOnlyFileInReadOnlyDirDoesNotCauseFailure() { - executeTestsForClass(ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("is capable of removing a read-only file in a dir in a read-only dir") - void readOnlyFileInNestedReadOnlyDirDoesNotCauseFailure() { - executeTestsForClass(ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("can be used via instance field inside nested test classes") - void canBeUsedViaInstanceFieldInsideNestedTestClasses() { - executeTestsForClass(TempDirUsageInsideNestedClassesTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(3).succeeded(3)); - } - - @Test - @DisplayName("can be used via static field inside nested test classes") - void canBeUsedViaStaticFieldInsideNestedTestClasses() { - executeTestsForClass(StaticTempDirUsageInsideNestedClassTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(2).succeeded(2)); - } - - @Test - @DisplayName("resolves java.io.File injection type") - void resolvesFileInstances() { - executeTestsForClass(FileInjectionTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Nested - @DisplayName("resolves shared temp dir") - @TestMethodOrder(OrderAnnotation.class) - class SharedTempDir { - - @Test - @DisplayName("when @TempDir is used on static field") - @Order(10) - void resolvesSharedTempDirWhenAnnotationIsUsedOnStaticField() { - assertSharedTempDirForFieldInjection(AnnotationOnStaticFieldTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on static field and @BeforeAll method parameter") - @Order(11) - void resolvesSharedTempDirWhenAnnotationIsUsedOnStaticFieldAndBeforeAllMethodParameter() { - assertSharedTempDirForFieldInjection(AnnotationOnStaticFieldAndBeforeAllMethodParameterTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on instance field and @BeforeAll method parameter") - @Order(14) - void resolvesSharedTempDirWhenAnnotationIsUsedOnInstanceFieldAndBeforeAllMethodParameter() { - assertSharedTempDirForFieldInjection(AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on instance field and @BeforeAll method parameter with @TestInstance(PER_CLASS)") - @Order(15) - void resolvesSharedTempDirWhenAnnotationIsUsedOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClass() { - assertSharedTempDirForFieldInjection( - AnnotationOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClassTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on @BeforeAll method parameter") - @Order(23) - void resolvesSharedTempDirWhenAnnotationIsUsedOnBeforeAllMethodParameter() { - assertSharedTempDirForParameterInjection(AnnotationOnBeforeAllMethodParameterTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on @BeforeAll method parameter with @TestInstance(PER_CLASS)") - @Order(24) - void resolvesSharedTempDirWhenAnnotationIsUsedOnBeforeAllMethodParameterWithTestInstancePerClass() { - assertSharedTempDirForParameterInjection( - AnnotationOnBeforeAllMethodParameterWithTestInstancePerClassTestCase.class); - } - - @Test - @DisplayName("when @TempDir is used on constructor parameter with @TestInstance(PER_CLASS)") - @Order(25) - void resolvesSharedTempDirWhenAnnotationIsUsedOnConstructorWithTestInstancePerClass() { - var results = executeTestsForClass(SharedTempDirsConstructorInjectionPerClassTestCase.class); - - results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); - assertThat(BaseConstructorInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseConstructorInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - private void assertSharedTempDirForFieldInjection( - Class testClass) { - - assertSharedTempDirForParameterInjection(testClass, - () -> BaseSharedTempDirFieldInjectionTestCase.staticTempDir); - } - - private void assertSharedTempDirForParameterInjection( - Class testClass) { - - assertSharedTempDirForParameterInjection(testClass, - () -> BaseSharedTempDirParameterInjectionTestCase.tempDir); - } - - private void assertSharedTempDirForParameterInjection(Class testClass, Supplier staticTempDir) { - var results = executeTestsForClass(testClass); - - results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); - assertThat(staticTempDir.get()).isNotNull().doesNotExist(); - } - - } - - @Nested - @DisplayName("resolves separate temp dirs") - @TestMethodOrder(OrderAnnotation.class) - class SeparateTempDirs { - - @Test - @DisplayName("when @TempDir is used on instance field") - @Order(11) - void resolvesSeparateTempDirWhenAnnotationIsUsedOnInstanceField() { - assertSeparateTempDirsForFieldInjection( - SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase.class); - assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - @Test - @DisplayName("when @TempDir is used on instance field with @TestInstance(PER_CLASS)") - @Order(12) - void resolvesSeparateTempDirWhenAnnotationIsUsedOnInstanceFieldWithTestInstancePerClass() { - assertSeparateTempDirsForFieldInjection( - SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassFieldInjectionTestCase.class); - assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseSeparateTempDirsFieldInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - @Test - @DisplayName("when @TempDir is used on @BeforeEach/@AfterEach method parameters") - @Order(21) - void resolvesSeparateTempDirsWhenUsedOnForEachLifecycleMethods() { - assertSeparateTempDirsForParameterInjection( - SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase.class); - assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - @Test - @DisplayName("when @TempDir is used on @BeforeEach/@AfterEach method parameters with @TestInstance(PER_CLASS)") - @Order(22) - void resolvesSeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClass() { - assertSeparateTempDirsForParameterInjection( - SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassParameterInjectionTestCase.class); - assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseSeparateTempDirsParameterInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - @Test - @DisplayName("for @AfterAll method parameter when @TempDir is not used on constructor or @BeforeAll method parameter") - @Order(31) - void resolvesSeparateTempDirWhenAnnotationIsUsedOnAfterAllMethodParameterOnly() { - var results = executeTestsForClass(AnnotationOnAfterAllMethodParameterTestCase.class); - - results.testEvents().assertStatistics(stats -> stats.started(1).failed(0).succeeded(1)); - assertThat(AnnotationOnAfterAllMethodParameterTestCase.firstTempDir).isNotNull().doesNotExist(); - assertThat(AnnotationOnAfterAllMethodParameterTestCase.secondTempDir).isNotNull().doesNotExist(); - } - - @Test - @DisplayName("when @TempDir is used on constructor parameter") - @Order(32) - void resolvesSeparateTempDirsWhenAnnotationIsUsedOnConstructorWithTestInstancePerMethod() { - var results = executeTestsForClass(SeparateTempDirsConstructorInjectionPerMethodTestCase.class); - - results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); - assertThat(BaseConstructorInjectionTestCase.tempDirs.getFirst()).doesNotExist(); - assertThat(BaseConstructorInjectionTestCase.tempDirs.getLast()).doesNotExist(); - } - - } - - @Nested - @DisplayName("supports default factory") - @TestMethodOrder(OrderAnnotation.class) - class DefaultFactory { - - @Test - @DisplayName("set to Jupiter's default") - void supportsStandardDefaultFactory() { - var results = executeTestsForClassWithDefaultFactory(StandardDefaultFactoryTestCase.class, Standard.class); - - results.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("set to custom factory") - void supportsCustomDefaultFactory() { - var results = executeTestsForClassWithDefaultFactory(CustomDefaultFactoryTestCase.class, Factory.class); - - results.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - private static class Factory implements TempDirFactory { - - @Override - public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) - throws Exception { - return Files.createTempDirectory("junit"); - } - } - - } - - @Nested - @DisplayName("reports failure") - @TestMethodOrder(OrderAnnotation.class) - class Failures { - - @Test - @DisplayName("when @TempDir is used on static field of an unsupported type") - @Order(20) - void onlySupportsStaticFieldsOfTypePathAndFile() { - var results = executeTestsForClass(AnnotationOnStaticFieldWithUnsupportedTypeTestCase.class); - - assertSingleFailedContainer(results, ExtensionConfigurationException.class, - "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); - } - - @Test - @DisplayName("when @TempDir is used on instance field of an unsupported type") - @Order(21) - void onlySupportsInstanceFieldsOfTypePathAndFile() { - var results = executeTestsForClass(AnnotationOnInstanceFieldWithUnsupportedTypeTestCase.class); - - assertSingleFailedTest(results, ExtensionConfigurationException.class, - "Can only resolve @TempDir field of type java.nio.file.Path or java.io.File"); - } - - @Test - @DisplayName("when @TempDir is used on parameter of an unsupported type") - @Order(22) - void onlySupportsParametersOfTypePathAndFile() { - var results = executeTestsForClass(InvalidTestCase.class); - - // @formatter:off - assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), - message(m -> m.matches("Failed to resolve parameter \\[java.lang.String .+] in method \\[.+]: .+")), - cause( - instanceOf(ExtensionConfigurationException.class), - message("Can only resolve @TempDir parameter of type java.nio.file.Path or java.io.File but was: java.lang.String"))); - // @formatter:on - } - - @Test - @DisplayName("when non-default @TempDir factory is set") - @Order(32) - void doesNotSupportNonDefaultTempDirFactory() { - var results = executeTestsForClass(NonDefaultFactoryTestCase.class); - - // @formatter:off - assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), - message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")), - cause( - instanceOf(ExtensionConfigurationException.class), - message("Custom @TempDir factory is not supported with junit.jupiter.tempdir.scope=per_context. " - + "Use junit.jupiter.tempdir.factory.default instead."))); - // @formatter:on - } - - @Test - @DisplayName("when default @TempDir factory does not return directory") - @Order(33) - void doesNotSupportCustomDefaultTempDirFactoryNotReturningDirectory() { - var results = executeTestsForClassWithDefaultFactory( - CustomDefaultFactoryNotReturningDirectoryTestCase.class, FactoryNotReturningDirectory.class); - - // @formatter:off - assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class), - message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")), - cause( - instanceOf(ExtensionConfigurationException.class), - message("Failed to create default temp directory"), - cause( - instanceOf(PreconditionViolationException.class), - message("temp directory must be a directory") - ) - )); - // @formatter:on - } - - private static class FactoryNotReturningDirectory implements TempDirFactory { - - @Override - public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) { - return null; - } - } - - } - - @Nested - @DisplayName("supports @TempDir") - @TestMethodOrder(OrderAnnotation.class) - class PrivateFields { - - @Test - @DisplayName("on private static field") - @Order(10) - void supportsPrivateInstanceFields() { - executeTestsForClass(AnnotationOnPrivateStaticFieldTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - @Test - @DisplayName("on private instance field") - @Order(11) - void supportsPrivateStaticFields() { - executeTestsForClass(AnnotationOnPrivateInstanceFieldTestCase.class).testEvents()// - .assertStatistics(stats -> stats.started(1).succeeded(1)); - } - - } - - private static void assertSingleFailedContainer(EngineExecutionResults results, Class clazz, - String message) { - - assertSingleFailedContainer(results, instanceOf(clazz), message(actual -> actual.contains(message))); - } - - @SafeVarargs - @SuppressWarnings("varargs") - private static void assertSingleFailedContainer(EngineExecutionResults results, - Condition... conditions) { - - results.containerEvents()// - .assertStatistics(stats -> stats.started(2).failed(1).succeeded(1))// - .assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); - } - - private static void assertSingleFailedTest(EngineExecutionResults results, Class clazz, - String message) { - - assertSingleFailedTest(results, instanceOf(clazz), message(actual -> actual.contains(message))); - } - - @SafeVarargs - @SuppressWarnings("varargs") - private static void assertSingleFailedTest(EngineExecutionResults results, Condition... conditions) { - results.testEvents().assertStatistics(stats -> stats.started(1).failed(1).succeeded(0)); - results.testEvents().assertThatEvents().haveExactly(1, finishedWithFailure(conditions)); - } - - private void assertSeparateTempDirsForFieldInjection( - Class testClass) { - - assertResolvesSeparateTempDirs(testClass, BaseSeparateTempDirsFieldInjectionTestCase.tempDirs); - } - - private void assertSeparateTempDirsForParameterInjection( - Class testClass) { - - assertResolvesSeparateTempDirs(testClass, BaseSeparateTempDirsParameterInjectionTestCase.tempDirs); - } - - private void assertResolvesSeparateTempDirs(Class testClass, Deque tempDirs) { - var results = executeTestsForClass(testClass); - - results.testEvents().assertStatistics(stats -> stats.started(2).failed(0).succeeded(2)); - assertThat(tempDirs).hasSize(2); - } - - // ------------------------------------------------------------------------- - - @SuppressWarnings("JUnitMalformedDeclaration") - static class BaseSharedTempDirFieldInjectionTestCase { - - static Path staticTempDir; - - @TempDir - Path tempDir; - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - if (BaseSharedTempDirFieldInjectionTestCase.staticTempDir != null) { - assertSame(BaseSharedTempDirFieldInjectionTestCase.staticTempDir, tempDir); - } - else { - BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; - } - check(tempDir); - } - - @Test - void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @Test - void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @AfterEach - void afterEach(@TempDir Path tempDir) { - check(tempDir); - } - - void check(Path tempDir) { - assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir)// - .isNotNull()// - .isSameAs(tempDir)// - .isSameAs(this.tempDir); - assertTrue(Files.exists(tempDir)); - } - - } - - static class AnnotationOnStaticFieldTestCase extends BaseSharedTempDirFieldInjectionTestCase { - - @TempDir - static Path staticTempPath; - - @TempDir - static File staticTempFile; - - @Override - void check(Path tempDir) { - assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir)// - .isNotNull()// - .isSameAs(AnnotationOnStaticFieldTestCase.staticTempPath)// - .isSameAs(tempDir)// - .isSameAs(this.tempDir); - assertTrue(Files.exists(tempDir)); - } - - } - - static class AnnotationOnStaticFieldAndBeforeAllMethodParameterTestCase extends AnnotationOnStaticFieldTestCase { - - @BeforeAll - static void beforeAll(@TempDir Path tempDir) { - assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir).isNull(); - BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; - assertThat(AnnotationOnStaticFieldTestCase.staticTempFile).isNotNull(); - assertThat(AnnotationOnStaticFieldTestCase.staticTempPath)// - .isNotNull()// - .isSameAs(tempDir); - assertThat(AnnotationOnStaticFieldTestCase.staticTempFile.toPath().toAbsolutePath())// - .isEqualTo(AnnotationOnStaticFieldTestCase.staticTempPath.toAbsolutePath()); - assertTrue(Files.exists(tempDir)); - } - - } - - static class AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase - extends BaseSharedTempDirFieldInjectionTestCase { - - @BeforeAll - static void beforeAll(@TempDir Path tempDir) { - assertThat(BaseSharedTempDirFieldInjectionTestCase.staticTempDir).isNull(); - BaseSharedTempDirFieldInjectionTestCase.staticTempDir = tempDir; - assertTrue(Files.exists(tempDir)); - } - - } - - @TestInstance(PER_CLASS) - static class AnnotationOnInstanceFieldAndBeforeAllMethodParameterWithTestInstancePerClassTestCase - extends AnnotationOnInstanceFieldAndBeforeAllMethodParameterTestCase { - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class AnnotationOnPrivateInstanceFieldTestCase { - - @SuppressWarnings("unused") - @TempDir - private Path tempDir; - - @Test - void test() { - assertTrue(Files.exists(tempDir)); - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class AnnotationOnPrivateStaticFieldTestCase { - - @SuppressWarnings("unused") - @TempDir - private static Path tempDir; - - @Test - void test() { - assertTrue(Files.exists(tempDir)); - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class AnnotationOnStaticFieldWithUnsupportedTypeTestCase { - - @SuppressWarnings("unused") - @TempDir - static String tempDir; - - @Test - void test1() { - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class AnnotationOnInstanceFieldWithUnsupportedTypeTestCase { - - @SuppressWarnings("unused") - @TempDir - String tempDir; - - @Test - void test1() { - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class BaseSharedTempDirParameterInjectionTestCase { - - static Path tempDir; - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - check(tempDir); - } - - @Test - void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @Test - void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @AfterEach - void afterEach(@TempDir Path tempDir) { - check(tempDir); - } - - static void check(Path tempDir) { - assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNotNull().isSameAs(tempDir); - assertTrue(Files.exists(tempDir)); - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class BaseConstructorInjectionTestCase { - - static final Deque tempDirs = new LinkedList<>(); - - private final Path tempDir; - - BaseConstructorInjectionTestCase(Path tempDir) { - this.tempDir = tempDir; - } - - @Test - void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @Test - void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @AfterEach - void afterEach(@TempDir Path tempDir) { - check(tempDir); - } - - void check(Path tempDir) { - assertThat(tempDirs.getLast())// - .isNotNull()// - .isSameAs(tempDir)// - .isSameAs(this.tempDir); - assertTrue(Files.exists(tempDir)); - } - - } - - static class SeparateTempDirsConstructorInjectionPerMethodTestCase extends BaseConstructorInjectionTestCase { - - SeparateTempDirsConstructorInjectionPerMethodTestCase(@TempDir Path tempDir) { - super(tempDir); - } - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - for (Path dir : tempDirs) { - assertThat(dir).doesNotExist(); - } - assertThat(tempDirs).doesNotContain(tempDir); - tempDirs.add(tempDir); - check(tempDir); - } - } - - @TestInstance(PER_CLASS) - static class SharedTempDirsConstructorInjectionPerClassTestCase extends BaseConstructorInjectionTestCase { - - SharedTempDirsConstructorInjectionPerClassTestCase(@TempDir Path tempDir) { - super(tempDir); - } - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - for (Path dir : tempDirs) { - assertThat(dir).isSameAs(tempDir).exists(); - } - tempDirs.add(tempDir); - check(tempDir); - } - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class NonDefaultFactoryTestCase { - - @Test - void test(@SuppressWarnings("unused") @TempDir(factory = Factory.class) Path tempDir) { - // never called - } - - private static class Factory implements TempDirFactory { - - @Override - public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) - throws Exception { - return Files.createTempDirectory("junit-"); - } - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class StandardDefaultFactoryTestCase { - - @Test - void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { - assertSame(tempDir1, tempDir2); - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class CustomDefaultFactoryTestCase { - - @Test - void test(@TempDir Path tempDir1, @TempDir Path tempDir2) { - assertSame(tempDir1, tempDir2); - } - - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class CustomDefaultFactoryNotReturningDirectoryTestCase { - - @Test - void test(@SuppressWarnings("unused") @TempDir Path tempDir) { - // never called - } - - } - - static class AnnotationOnBeforeAllMethodParameterTestCase extends BaseSharedTempDirParameterInjectionTestCase { - - @BeforeAll - static void beforeAll(@TempDir Path tempDir) { - assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNull(); - BaseSharedTempDirParameterInjectionTestCase.tempDir = tempDir; - check(tempDir); - } - } - - @TestInstance(PER_CLASS) - static class AnnotationOnBeforeAllMethodParameterWithTestInstancePerClassTestCase - extends BaseSharedTempDirParameterInjectionTestCase { - - @BeforeAll - void beforeAll(@TempDir Path tempDir) { - assertThat(BaseSharedTempDirParameterInjectionTestCase.tempDir).isNull(); - BaseSharedTempDirParameterInjectionTestCase.tempDir = tempDir; - check(tempDir); - } - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class AnnotationOnAfterAllMethodParameterTestCase { - - static Path firstTempDir = null; - static Path secondTempDir = null; - - @Test - void test(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - assertThat(firstTempDir).isNull(); - firstTempDir = tempDir; - writeFile(tempDir, testInfo); - } - - @AfterAll - static void afterAll(@TempDir Path tempDir) { - assertThat(firstTempDir).isNotNull(); - assertNotEquals(firstTempDir, tempDir); - secondTempDir = tempDir; - } - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class BaseSeparateTempDirsFieldInjectionTestCase { - - static final Deque tempDirs = new LinkedList<>(); - - @TempDir - Path tempDir; - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - for (Path dir : tempDirs) { - assertThat(dir).doesNotExist(); - } - assertThat(tempDirs).doesNotContain(tempDir); - tempDirs.add(tempDir); - check(tempDir); - } - - @Test - void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @Test - void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @AfterEach - void afterEach(@TempDir Path tempDir) { - check(tempDir); - } - - void check(Path tempDir) { - assertThat(tempDirs.getLast())// - .isNotNull()// - .isSameAs(tempDir)// - .isSameAs(this.tempDir); - assertTrue(Files.exists(tempDir)); - } - - } - - static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase - extends BaseSeparateTempDirsFieldInjectionTestCase { - } - - @TestInstance(PER_CLASS) - static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassFieldInjectionTestCase - extends SeparateTempDirsWhenUsedOnForEachLifecycleMethodsFieldInjectionTestCase { - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class BaseSeparateTempDirsParameterInjectionTestCase { - - static final Deque tempDirs = new LinkedList<>(); - - @BeforeEach - void beforeEach(@TempDir Path tempDir) { - for (Path dir : tempDirs) { - assertThat(dir).doesNotExist(); - } - assertThat(tempDirs).doesNotContain(tempDir); - tempDirs.add(tempDir); - check(tempDir); - } - - @Test - void test1(@TempDir Path tempDir, TestInfo testInfo) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @Test - void test2(TestInfo testInfo, @TempDir Path tempDir) throws Exception { - check(tempDir); - writeFile(tempDir, testInfo); - } - - @AfterEach - void afterEach(@TempDir Path tempDir) { - check(tempDir); - } - - void check(Path tempDir) { - assertSame(tempDirs.getLast(), tempDir); - assertTrue(Files.exists(tempDir)); - } - } - - static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase - extends BaseSeparateTempDirsParameterInjectionTestCase { - } - - @TestInstance(PER_CLASS) - static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePerClassParameterInjectionTestCase - extends SeparateTempDirsWhenUsedOnForEachLifecycleMethodsParameterInjectionTestCase { - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class InvalidTestCase { - - @Test - void wrongParameterType(@SuppressWarnings("unused") @TempDir String ignored) { - fail("this should never be called"); - } - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class FileInjectionTestCase { - - @TempDir - File fileTempDir; - - @TempDir - Path pathTempDir; - - @Test - void checkFile(@TempDir File tempDir, @TempDir Path ref) { - assertFileAndPathAreEqual(tempDir, ref); - assertFileAndPathAreEqual(this.fileTempDir, this.pathTempDir); - } - - private void assertFileAndPathAreEqual(File tempDir, Path ref) { - Path path = tempDir.toPath(); - assertEquals(ref.toAbsolutePath(), path.toAbsolutePath()); - assertTrue(Files.exists(path)); - } - - } - - private static void writeFile(Path tempDir, TestInfo testInfo) throws IOException { - Path file = tempDir.resolve(testInfo.getTestMethod().orElseThrow().getName() + ".txt"); - Files.write(file, testInfo.getDisplayName().getBytes()); - } - - // https://github.com/junit-team/junit5/issues/1748 - @SuppressWarnings("JUnitMalformedDeclaration") - static class TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase { - - TempDirectoryDoesNotPreventConstructorParameterResolutionTestCase(TestInfo testInfo) { - assertNotNull(testInfo); - } - - @Test - void test() { - } - - } - - // https://github.com/junit-team/junit5/issues/1801 - @SuppressWarnings("JUnitMalformedDeclaration") - static class UserTempDirectoryDeletionDoesNotCauseFailureTestCase { - - @Test - void deleteTempDir(@TempDir Path tempDir) throws IOException { - Files.delete(tempDir); - assertThat(tempDir).doesNotExist(); - } - - } - - // https://github.com/junit-team/junit5/issues/2046 - @SuppressWarnings("JUnitMalformedDeclaration") - static class NonWritableFileDoesNotCauseFailureTestCase { - - @Test - void createReadonlyFile(@TempDir Path tempDir) throws IOException { - // Removal of setWritable(false) files might fail (e.g. for Windows) - // The test verifies that @TempDir is capable of removing of such files - var path = Files.write(tempDir.resolve("test.txt"), new byte[0]); - assumeTrue(path.toFile().setWritable(false), - () -> "Unable to set file " + path + " readonly via .toFile().setWritable(false)"); - } - - } - - // https://github.com/junit-team/junit5/issues/2171 - @SuppressWarnings("JUnitMalformedDeclaration") - static class ReadOnlyFileInReadOnlyDirDoesNotCauseFailureTestCase { - - @Test - void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { - File file = tempDir.toPath().resolve("file").toFile(); - assumeTrue(file.createNewFile()); - assumeTrue(makeReadOnly(tempDir)); - assumeTrue(makeReadOnly(file)); - } - - } - - // https://github.com/junit-team/junit5/issues/2171 - @SuppressWarnings("JUnitMalformedDeclaration") - static class ReadOnlyFileInDirInReadOnlyDirDoesNotCauseFailureTestCase { - - @Test - void createReadOnlyFileInReadOnlyDir(@TempDir File tempDir) throws IOException { - File file = tempDir.toPath().resolve("dir").resolve("file").toFile(); - assumeTrue(file.getParentFile().mkdirs()); - assumeTrue(file.createNewFile()); - assumeTrue(makeReadOnly(tempDir)); - assumeTrue(makeReadOnly(file.getParentFile())); - assumeTrue(makeReadOnly(file)); - } - - } - - private static boolean makeReadOnly(File file) throws IOException { - var dos = Files.getFileAttributeView(file.toPath(), DosFileAttributeView.class); - if (dos != null) { - dos.setReadOnly(true); - return true; - } - return file.setReadOnly(); - } - - // https://github.com/junit-team/junit5/issues/2609 - @SuppressWarnings({ "ResultOfMethodCallIgnored", "JUnitMalformedDeclaration" }) - static class NonMintPermissionContentInTempDirectoryDoesNotCauseFailureTestCase { - - @Test - void createFile(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile(); - } - - @Test - void createFolder(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile(); - } - - @Test - void createNonWritableFile(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); - } - - @Test - void createNonReadableFile(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); - } - - @Test - void createNonWritableDirectory(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); - } - - @Test - void createNonReadableDirectory(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); - } - - @Test - void createNonExecutableDirectory(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); - } - - @Test - void createNonEmptyNonWritableDirectory(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setWritable(false); - } - - @Test - void createNonEmptyNonReadableDirectory(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setReadable(false); - } - - @Test - void createNonEmptyNonExecutableDirectory(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setExecutable(false); - } - - @Test - void createNonEmptyDirectory(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - } - - @Test - void createNonEmptyDirectoryWithNonWritableFile(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); - } - - @Test - void createNonEmptyDirectoryWithNonReadableFile(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); - } - } - - // https://github.com/junit-team/junit5/issues/2609 - @SuppressWarnings("ResultOfMethodCallIgnored") - static class NonMintTempDirectoryPermissionsDoNotCauseFailureTestCase { - - @Nested - class NonWritable { - - @Test - void makeEmptyTempDirectoryNonWritable(@TempDir Path tempDir) { - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithFileNonWritable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFileNonWritable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFileNonWritable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonReadableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setReadable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonWritableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setWritable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonExecutableFolderNonWritable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setExecutable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderNonWritable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonWritable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setWritable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonWritable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setWritable(false); - } - } - - @Nested - class NonReadable { - - @Test - void makeEmptyTempDirectoryNonReadable(@TempDir Path tempDir) { - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithFileNonReadable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFileNonReadable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFileNonReadable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonWritableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setWritable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonReadableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setReadable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonExecutableFolderNonReadable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setExecutable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderNonReadable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonReadable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setReadable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonReadable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setReadable(false); - } - } - - @Nested - class NonExecutable { - - @Test - void makeEmptyTempDirectoryNonExecutable(@TempDir Path tempDir) { - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithFileNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFileNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFileNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createFile(tempDir.resolve("test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setWritable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setReadable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonExecutableFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")).toFile().setExecutable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonWritableFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setWritable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonReadableFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setReadable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyNonExecutableFolderNonExecutable(@TempDir Path tempDir) - throws IOException { - Path subDir = Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - subDir.toFile().setExecutable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderNonExecutable(@TempDir Path tempDir) throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonWritableFileNonExecutable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setWritable(false); - tempDir.toFile().setExecutable(false); - } - - @Test - void makeTempDirectoryWithNonEmptyFolderContainingNonReadableFileNonExecutable(@TempDir Path tempDir) - throws IOException { - Files.createDirectory(tempDir.resolve("test-sub-dir")); - Files.createFile(tempDir.resolve("test-sub-dir/test-file.txt")).toFile().setReadable(false); - tempDir.toFile().setExecutable(false); - } - } - } - - // https://github.com/junit-team/junit5/issues/2079 - @SuppressWarnings("JUnitMalformedDeclaration") - static class TempDirUsageInsideNestedClassesTestCase { - - @TempDir - File tempDir; - - @Test - void topLevel() { - assertNotNull(tempDir); - assertTrue(tempDir.exists()); - } - - @Nested - class NestedTestClass { - - @Test - void nested() { - assertNotNull(tempDir); - assertTrue(tempDir.exists()); - } - - @Nested - class EvenDeeperNestedTestClass { - - @Test - void deeplyNested() { - assertNotNull(tempDir); - assertTrue(tempDir.exists()); - } - } - } - } - - @SuppressWarnings("JUnitMalformedDeclaration") - static class StaticTempDirUsageInsideNestedClassTestCase { - - @TempDir - static File tempDir; - - static File initialTempDir; - - @Test - void topLevel() { - assertNotNull(tempDir); - assertTrue(tempDir.exists()); - initialTempDir = tempDir; - } - - @Nested - class NestedTestClass { - - @Test - void nested() { - assertNotNull(tempDir); - assertTrue(tempDir.exists()); - assertSame(initialTempDir, tempDir); - } - } - } - -} diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerDeclarationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java similarity index 98% rename from jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerDeclarationTests.java rename to jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java index 5eddab66bcad..bd7b5d3479b8 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPerDeclarationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java @@ -82,6 +82,8 @@ import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; +import org.junit.platform.engine.DiscoveryIssue; +import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.testkit.engine.EngineExecutionResults; @@ -92,7 +94,7 @@ * @since 5.8 */ @DisplayName("TempDirectory extension (per declaration)") -class TempDirectoryPerDeclarationTests extends AbstractJupiterTestEngineTests { +class TempDirectoryTests extends AbstractJupiterTestEngineTests { private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class testClass, Class factoryClass) { @@ -256,6 +258,17 @@ void onlyAttemptsToDeleteUndeletablePathsOnce(Class testClass) { ); } + @Test + void usingTheRemovedScopeConfigurationParameterProducesWarning() { + var results = discoverTests(request() // + .selectors(selectClass(AllPossibleDeclarationLocationsTestCase.class)) // + .configurationParameter("junit.jupiter.tempdir.scope", "per_context")); + + assertThat(results.getDiscoveryIssues()) // + .contains(DiscoveryIssue.create(Severity.WARNING, + "The 'junit.jupiter.tempdir.scope' configuration parameter is no longer supported: per_context. Please remove it from your configuration.")); + } + @Nested @DisplayName("reports failure") @TestMethodOrder(OrderAnnotation.class) From 24d01603994b86782e183d4c4fb6d3adfb03a01a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 8 May 2025 16:52:14 +0200 Subject: [PATCH 042/521] Restore `TestPlan.getTestIdentifier(String)` because it's used by Gradle --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../org/junit/platform/launcher/TestPlan.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 71d48454fa11..250e0374d2eb 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -63,6 +63,7 @@ repository on GitHub. - `LegacyReportingUtils` class - `TestPlan.add(TestIdentifier)`, `TestPlan.getChildren(String)`, and `TestPlan.getTestIdentifier(String)` methods + - `TestPlan.add(TestIdentifier)` and `TestPlan.getChildren(String)` methods - `@UseTechnicalNames` annotation - `EngineTestKit.execute(String, EngineDiscoveryRequest)`, `EngineTestKit.execute(TestEngine, EngineDiscoveryRequest)`, and 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 9f4e66681f63..646f2bd01274 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 @@ -13,6 +13,7 @@ import static java.util.Collections.emptySet; 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; @@ -172,6 +173,23 @@ public Set getChildren(UniqueId parentId) { return children.containsKey(parentId) ? unmodifiableSet(children.get(parentId)) : emptySet(); } + /** + * Get the {@link TestIdentifier} with the supplied unique ID. + * + * @param uniqueId the unique ID to look up the identifier for; never + * {@code null} or blank + * @return the identifier with the supplied unique ID; never {@code null} + * @throws PreconditionViolationException if no {@code TestIdentifier} + * with the supplied unique ID is present in this test plan + * @deprecated Use {@link #getTestIdentifier(UniqueId)} + */ + @API(status = DEPRECATED, since = "1.10", consumers = "Gradle") + @Deprecated + public TestIdentifier getTestIdentifier(String uniqueId) throws PreconditionViolationException { + Preconditions.notBlank(uniqueId, "unique ID must not be null or blank"); + return getTestIdentifier(UniqueId.parse(uniqueId)); + } + /** * Get the {@link TestIdentifier} with the supplied unique ID. * From aa7d3eb331592d8475209edfb778651788c1ee46 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 9 May 2025 14:13:42 +0200 Subject: [PATCH 043/521] Document minimum required version of Maven Surefire --- .../release-notes/release-notes-6.0.0-M1.adoc | 1 + .../asciidoc/user-guide/running-tests.adoc | 22 ++----------------- .../maven-surefire-compatibility/pom.xml | 13 ----------- .../MavenSurefireCompatibilityTests.java | 19 ++++++---------- 4 files changed, 10 insertions(+), 45 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 250e0374d2eb..22cfd490dd0c 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -47,6 +47,7 @@ repository on GitHub. `--h` (rather than `-h`) or `-help` (rather than `--help`). * The `junit-platform-runner` module that provided the `JUnitPlatform` runner has been discontinued. +* Support for Maven Surefire/Failsafe versions < 3.0.0 has been dropped. * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index 9c65f2e91fa5..3cd93ecdbcb9 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -318,27 +318,9 @@ for executing tests on the JUnit Platform. The `pom.xml` file in the and can serve as a starting point for configuring your Maven build. [WARNING] -.Use recent version of Maven Surefire/Failsafe to avoid interoperability issues +.Minimum required version of Maven Surefire/Failsafe ==== -To avoid interoperability issues, it is recommended to use a recent version of Maven -Surefire/Failsafe (3.0.0 or later) because it automatically aligns the version of the -JUnit Platform Launcher that is used with the JUnit Platform version found on the test -runtime classpath. - -If you are using a version older than 3.0.0-M4, you can work around the missing alignment -by adding a test dependency on the matching version of the JUnit Platform Launcher to your -Maven build as follows. - -[source,xml] -[subs=attributes+] ----- - - org.junit.platform - junit-platform-launcher - {version} - test - ----- +As of JUnit 6.0, the minimum required version of Maven Surefire/Failsafe is 3.0.0. ==== [[running-tests-build-maven-bom]] diff --git a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml index ffdfb47af1f6..175fbbd18363 100644 --- a/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml +++ b/platform-tooling-support-tests/projects/maven-surefire-compatibility/pom.xml @@ -67,17 +67,4 @@ - - - manual-platform-dependency - - - org.junit.platform - junit-platform-launcher - test - - - - - diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java index f627406bb5a2..e5aa1542614a 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenSurefireCompatibilityTests.java @@ -18,9 +18,8 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.CsvSource; import org.junit.platform.tests.process.OutputFiles; import org.opentest4j.TestAbortedException; @@ -33,23 +32,19 @@ */ class MavenSurefireCompatibilityTests { + static final String MINIMUM_SUPPORTED_SUREFIRE_VERSION = "3.0.0"; + @ManagedResource LocalMavenRepo localMavenRepo; - @ParameterizedTest - @CsvSource(delimiter = '|', nullValues = "", textBlock = """ - 2.22.2 | --activate-profiles=manual-platform-dependency - 3.0.0-M4 | - """) - void testMavenSurefireCompatibilityProject(String surefireVersion, String extraArg, @TempDir Path workspace, - @FilePrefix("maven") OutputFiles outputFiles) throws Exception { - var extraArgs = extraArg == null ? new String[0] : new String[] { extraArg }; + @Test + void testMavenSurefireCompatibilityProject(@TempDir Path workspace, @FilePrefix("maven") OutputFiles outputFiles) + throws Exception { var result = ProcessStarters.maven(Helper.getJavaHome(17).orElseThrow(TestAbortedException::new)) // .workingDir(copyToWorkspace(Projects.MAVEN_SUREFIRE_COMPATIBILITY, workspace)) // .addArguments(localMavenRepo.toCliArgument(), "-Dmaven.repo=" + MavenRepo.dir()) // - .addArguments("-Dsurefire.version=" + surefireVersion) // + .addArguments("-Dsurefire.version=" + MINIMUM_SUPPORTED_SUREFIRE_VERSION) // .addArguments("--update-snapshots", "--batch-mode", "test") // - .addArguments(extraArgs) // .redirectOutput(outputFiles) // .startAndWait(); From 29554133148fcb779a5b78756063fb5a43a64444 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 10 May 2025 15:08:04 +0200 Subject: [PATCH 044/521] Remove remnants of `JUnitPlatform` runner --- documentation/src/docs/asciidoc/link-attributes.adoc | 2 -- documentation/src/docs/asciidoc/user-guide/appendix.adoc | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index d79abdac00d2..5647866c363a 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -79,8 +79,6 @@ endif::[] // Platform Reporting :LegacyXmlReportGeneratingListener: {javadoc-root}/org.junit.platform.reporting/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.html[LegacyXmlReportGeneratingListener] :OpenTestReportGeneratingListener: {javadoc-root}/org.junit.platform.reporting/org/junit/platform/reporting/open/xml/OpenTestReportGeneratingListener.html[OpenTestReportGeneratingListener] -// Platform Runner -:JUnitPlatform-Runner: {javadoc-root}/org.junit.platform.runnner/org/junit/platform/runner/JUnitPlatform.html[JUnitPlatform] // Platform Suite :suite-api-package: {javadoc-root}/org.junit.platform.suite.api/org/junit/platform/suite/api/package-summary.html[org.junit.platform.suite.api] :junit-platform-suite-engine: {javadoc-root}/org.junit.platform.suite.engine/org/junit/platform/suite/engine/package-summary.html[junit-platform-suite-engine] diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index c2ca8404dc0a..e779cbc9c70f 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -76,8 +76,7 @@ Please refer to the corresponding sections for <> and the - <>. + <>. `junit-platform-suite-commons`:: Common support utilities for executing test suites on the JUnit Platform. `junit-platform-suite-engine`:: From 364380f670a9ad6c55a71668d0fa7e80be2ba7f0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 12 May 2025 19:32:32 +0200 Subject: [PATCH 045/521] Compile module descriptors using regular `compileJava` task (#4523) Remove custom `compileModule` task and move module descriptors to `src/main/java`. --- .github/workflows/codeql-analysis.yml | 2 +- documentation/documentation.gradle.kts | 25 ++++---- gradle/config/checkstyle/checkstyleMain.xml | 4 ++ gradle/libs.versions.toml | 1 + ...ild.java-aggregator-conventions.gradle.kts | 9 +++ ...tbuild.java-library-conventions.gradle.kts | 64 +------------------ .../junitbuild.shadow-conventions.gradle.kts | 33 +--------- ...junitbuild.spotless-conventions.gradle.kts | 5 +- .../junitbuild/java/ModuleCompileOptions.kt | 7 -- .../java/ModulePathArgumentProvider.kt | 40 ------------ .../java/PatchModuleArgumentProvider.kt | 50 --------------- .../ModuleSpecificJavadocFileOption.kt | 7 +- .../java}/module-info.java | 2 + .../junit-jupiter-engine.gradle.kts | 2 +- .../java}/module-info.java | 0 .../junit-jupiter-migrationsupport.gradle.kts | 29 +++++---- .../java}/module-info.java | 0 .../junit-jupiter-params.gradle.kts | 17 +++-- .../java}/module-info.java | 0 junit-jupiter/junit-jupiter.gradle.kts | 4 +- .../java}/module-info.java | 0 .../junit-platform-commons.gradle.kts | 4 ++ .../java}/module-info.java | 0 .../junit-platform-console.gradle.kts | 12 ++-- .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../junit-platform-reporting.gradle.kts | 8 ++- .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../junit-platform-suite-commons.gradle.kts | 4 ++ .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../junit-platform-suite.gradle.kts | 2 +- .../java}/module-info.java | 0 .../java}/module-info.java | 0 .../junit-vintage-engine.gradle.kts | 3 + .../java}/module-info.java | 0 .../junit-jupiter-api.expected.txt | 1 + .../support/tests/GradleModuleFileTests.java | 14 ++-- 41 files changed, 106 insertions(+), 243 deletions(-) create mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild.java-aggregator-conventions.gradle.kts delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt rename junit-jupiter-api/src/{module/org.junit.jupiter.api => main/java}/module-info.java (96%) rename junit-jupiter-engine/src/{module/org.junit.jupiter.engine => main/java}/module-info.java (100%) rename junit-jupiter-migrationsupport/src/{module/org.junit.jupiter.migrationsupport => main/java}/module-info.java (100%) rename junit-jupiter-params/src/{module/org.junit.jupiter.params => main/java}/module-info.java (100%) rename junit-jupiter/src/{module/org.junit.jupiter => main/java}/module-info.java (100%) rename junit-platform-commons/src/{module/org.junit.platform.commons => main/java}/module-info.java (100%) rename junit-platform-console/src/{module/org.junit.platform.console => main/java}/module-info.java (100%) rename junit-platform-engine/src/{module/org.junit.platform.engine => main/java}/module-info.java (100%) rename junit-platform-jfr/src/{module/org.junit.platform.jfr => main/java}/module-info.java (100%) rename junit-platform-launcher/src/{module/org.junit.platform.launcher => main/java}/module-info.java (100%) rename junit-platform-reporting/src/{module/org.junit.platform.reporting => main/java}/module-info.java (100%) rename junit-platform-suite-api/src/{module/org.junit.platform.suite.api => main/java}/module-info.java (100%) rename junit-platform-suite-commons/src/{module/org.junit.platform.suite.commons => main/java}/module-info.java (100%) rename junit-platform-suite-engine/src/{module/org.junit.platform.suite.engine => main/java}/module-info.java (100%) rename junit-platform-suite/src/{module/org.junit.platform.suite => main/java}/module-info.java (100%) rename junit-platform-testkit/src/{module/org.junit.platform.testkit => main/java}/module-info.java (100%) rename junit-vintage-engine/src/{module/org.junit.vintage.engine => main/java}/module-info.java (100%) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 776a7169ba33..b969f78dfe41 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -47,6 +47,6 @@ jobs: arguments: | --no-build-cache \ -Dscan.tag.CodeQL \ - allMainClasses + classes - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@60168efe1c415ce0f5521ea06d5c2062adbeed1b # v3.28.17 diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index d4a5ed03cf17..4f3c60782ba6 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -440,19 +440,20 @@ tasks { noTimestamp(true) addStringsOption("-module", ",").value = modularProjects.map { it.javaModuleName } - val moduleSourcePathOption = addPathOption("-module-source-path") - moduleSourcePathOption.value = modularProjects.map { it.file("src/module") } - moduleSourcePathOption.value.forEach { inputs.dir(it) } - addOption(ModuleSpecificJavadocFileOption("-patch-module", modularProjects.associate { project -> - project.javaModuleName to files( - project.sourceSets.named { it.startsWith("main") }.map { it.allJava.srcDirs } - ).asPath + addOption(ModuleSpecificJavadocFileOption("-module-source-path", modularProjects.associate { project -> + project.javaModuleName to provider { + files( + project.sourceSets.named { it.startsWith("main") }.map { + it.allJava.srcDirs.filter { it.exists() } + } + ).asPath + } })) addStringOption("-add-modules", "info.picocli,org.opentest4j.reporting.events") addOption(ModuleSpecificJavadocFileOption("-add-reads", mapOf( - "org.junit.platform.console" to "info.picocli", - "org.junit.platform.reporting" to "org.opentest4j.reporting.events", - "org.junit.jupiter.params" to "univocity.parsers" + "org.junit.platform.console" to provider { "info.picocli" }, + "org.junit.platform.reporting" to provider { "org.opentest4j.reporting.events" }, + "org.junit.jupiter.params" to provider { "univocity.parsers" } ))) } @@ -463,10 +464,6 @@ tasks { setMaxMemory("1024m") options.destinationDirectory = layout.buildDirectory.dir("docs/javadoc").get().asFile - - doFirst { - (options as CoreJavadocOptions).modulePath = classpath.files.toList() - } } val fixJavadoc by registering(Copy::class) { diff --git a/gradle/config/checkstyle/checkstyleMain.xml b/gradle/config/checkstyle/checkstyleMain.xml index 27ff53749020..ed8dadaaff8d 100644 --- a/gradle/config/checkstyle/checkstyleMain.xml +++ b/gradle/config/checkstyle/checkstyleMain.xml @@ -43,4 +43,8 @@ + + + + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ff89b7aa6bb1..fc5fdf4ff161 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -95,6 +95,7 @@ bnd = { id = "biz.aQute.bnd", version.ref = "bnd" } buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" } commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" } develocity = { id = "com.gradle.develocity", version = "4.0.1" } +extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" } 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" } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-aggregator-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-aggregator-conventions.gradle.kts new file mode 100644 index 000000000000..cb169dc4d0de --- /dev/null +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-aggregator-conventions.gradle.kts @@ -0,0 +1,9 @@ +plugins { + id("junitbuild.java-library-conventions") +} + +tasks.javadoc { + // Since this JAR contains no classes, running Javadoc fails with: + // "No public or protected classes found to document" + enabled = false +} 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 ae09fab5dfa7..a7ca8a33a8c6 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 @@ -1,7 +1,4 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import junitbuild.java.ModuleCompileOptions -import junitbuild.java.ModulePathArgumentProvider -import junitbuild.java.PatchModuleArgumentProvider import org.gradle.plugins.ide.eclipse.model.Classpath import org.gradle.plugins.ide.eclipse.model.Library import org.gradle.plugins.ide.eclipse.model.ProjectDependency @@ -27,17 +24,12 @@ dependencies { } val mavenizedProjects: List by rootProject.extra -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 extension = extensions.create("javaLibrary") -val moduleSourceDir = layout.projectDirectory.dir("src/module/$javaModuleName") -val combinedModuleSourceDir = layout.buildDirectory.dir("module") -val moduleOutputDir = layout.buildDirectory.dir("classes/java/module") - eclipse { jdt { file { @@ -61,7 +53,7 @@ eclipse { } java { - modularity.inferModulePath = false + modularity.inferModulePath = true } if (project in mavenizedProjects) { @@ -102,9 +94,6 @@ if (project in mavenizedProjects) { } tasks.named("sourcesJar").configure { - from(moduleSourceDir) { - include("module-info.java") - } duplicatesStrategy = DuplicatesStrategy.EXCLUDE } @@ -178,49 +167,6 @@ normalization { } } -val allMainClasses by tasks.registering { - dependsOn(tasks.classes) -} - -val prepareModuleSourceDir by tasks.registering(Sync::class) { - from(moduleSourceDir) - from(sourceSets.named { it.startsWith("main") }.map { it.allJava }) - into(combinedModuleSourceDir.map { it.dir(javaModuleName) }) - duplicatesStrategy = DuplicatesStrategy.EXCLUDE -} - -val compileModule by tasks.registering(JavaCompile::class) { - dependsOn(allMainClasses) - enabled = project in modularProjects - source = fileTree(combinedModuleSourceDir).builtBy(prepareModuleSourceDir) - destinationDirectory = moduleOutputDir - classpath = files() - options.release = 17 - options.compilerArgs.addAll(listOf( - // Suppress warnings for automatic modules: org.apiguardian.api, org.opentest4j - "-Xlint:all,-requires-automatic,-requires-transitive-automatic", - "-Werror", // Terminates compilation when warnings occur. - "--module-version", "${project.version}", - )) - - val moduleOptions = objects.newInstance(ModuleCompileOptions::class) - extensions.add("moduleOptions", moduleOptions) - moduleOptions.modulePath.from(configurations.compileClasspath) - - options.compilerArgumentProviders.add(objects.newInstance(ModulePathArgumentProvider::class, project, combinedModuleSourceDir, modularProjects).apply { - modulePath.from(moduleOptions.modulePath) - }) - options.compilerArgumentProviders.addAll(modularProjects.map { objects.newInstance(PatchModuleArgumentProvider::class, project, it) }) - - modularity.inferModulePath = false - - doFirst { - options.allCompilerArgs.forEach { - logger.info(it) - } - } -} - tasks.withType().configureEach { from(rootDir) { include("LICENSE.md") @@ -233,13 +179,6 @@ tasks.withType().configureEach { } into("META-INF") } - val suffix = archiveClassifier.getOrElse("") - if (suffix.isBlank() || this is ShadowJar) { - dependsOn(allMainClasses, compileModule) - from(moduleOutputDir.map { it.dir(javaModuleName) }) { - include("module-info.class") - } - } } tasks.jar { @@ -274,6 +213,7 @@ tasks.compileJava { "-Xlint:all", // Enables all recommended warnings. "-Werror", // Terminates compilation when warnings occur. "-parameters", // Generates metadata for reflection on method parameters. + "--module-version", "${project.version}" )) } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts index ed1732e00e78..a9a7716bc91e 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts @@ -1,5 +1,3 @@ -import junitbuild.java.ModuleCompileOptions - plugins { id("junitbuild.java-library-conventions") id("com.gradleup.shadow") @@ -21,26 +19,8 @@ configurations { } } } -} - -sourceSets { - main { - compileClasspath += shadowedClasspath.get() - } - test { - runtimeClasspath += shadowedClasspath.get() - } -} - -eclipse { - classpath { - plusConfigurations.add(shadowedClasspath.get()) - } -} - -idea { - module { - scopes["PROVIDED"]!!["plus"]!!.add(shadowedClasspath.get()) + compileClasspath { + extendsFrom(shadowed.get()) } } @@ -65,13 +45,4 @@ tasks { from(shadowJar.map { zipTree(it.archiveFile) }) exclude("**/shadow/**") } - test { - dependsOn(shadowJar) - // in order to run the test against the shadowJar - classpath -= sourceSets.main.get().output - classpath += files(shadowJar.map { it.archiveFile }) - } - named("compileModule") { - the().modulePath.from(shadowedClasspath.get()) - } } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts index 70ebbb416212..98f9c4539cb1 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.spotless-conventions.gradle.kts @@ -27,6 +27,7 @@ spotless { val javaFormatterConfigFile = configDir.file("junit-eclipse-formatter-settings.xml") java { + targetExclude("**/module-info.java") licenseHeaderFile(license.headerFile, "(package|import) ") importOrderFile(importOrderConfigFile) val fullVersion = requiredVersionFromLibs("eclipse") @@ -38,8 +39,8 @@ spotless { } format("moduleDescriptor") { - target(fileTree(layout.projectDirectory.dir("src/module")) { - include("**/module-info.java") + target(fileTree(layout.projectDirectory.dir("src/main/java")) { + include("module-info.java") }) licenseHeaderFile(license.headerFile, "^$") trimTrailingWhitespace() diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt deleted file mode 100644 index 13c6fde1c09d..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModuleCompileOptions.kt +++ /dev/null @@ -1,7 +0,0 @@ -package junitbuild.java - -import org.gradle.api.file.ConfigurableFileCollection - -abstract class ModuleCompileOptions { - abstract val modulePath: ConfigurableFileCollection -} diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt deleted file mode 100644 index 9d05430ad810..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild/java/ModulePathArgumentProvider.kt +++ /dev/null @@ -1,40 +0,0 @@ -package junitbuild.java - -import org.gradle.api.Named -import org.gradle.api.Project -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.file.Directory -import org.gradle.api.provider.Provider -import org.gradle.api.tasks.* -import org.gradle.process.CommandLineArgumentProvider -import javax.inject.Inject - -abstract class ModulePathArgumentProvider @Inject constructor(project: Project, combinedModuleSourceDir: Provider, modularProjects: List) : - CommandLineArgumentProvider, Named { - - @get:CompileClasspath - abstract val modulePath: ConfigurableFileCollection - - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val moduleSourceDirs: ConfigurableFileCollection - - init { - modularProjects.forEach { - if (it == project) - moduleSourceDirs.from(combinedModuleSourceDir) - else - moduleSourceDirs.from(project.files("${it.projectDir}/src/module")) - } - } - - override fun asArguments() = listOf( - "--module-path", - modulePath.asPath, - "--module-source-path", - moduleSourceDirs.asPath - ) - - @Internal - override fun getName() = "module-path" -} diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt deleted file mode 100644 index 8149094e6128..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild/java/PatchModuleArgumentProvider.kt +++ /dev/null @@ -1,50 +0,0 @@ -package junitbuild.java - -import javaModuleName -import org.gradle.api.Named -import org.gradle.api.Project -import org.gradle.api.file.ConfigurableFileCollection -import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputFiles -import org.gradle.api.tasks.Internal -import org.gradle.api.tasks.PathSensitive -import org.gradle.api.tasks.PathSensitivity -import org.gradle.api.tasks.SourceSetContainer -import org.gradle.kotlin.dsl.get -import org.gradle.kotlin.dsl.the -import org.gradle.process.CommandLineArgumentProvider -import javax.inject.Inject - -abstract class PatchModuleArgumentProvider @Inject constructor(compiledProject: Project, patchModuleProject: Project) : - CommandLineArgumentProvider, Named { - - @get:Input - abstract val module: Property - - @get:InputFiles - @get:PathSensitive(PathSensitivity.RELATIVE) - abstract val patch: ConfigurableFileCollection - - init { - module.convention(patchModuleProject.javaModuleName) - patch.from(compiledProject.provider { - if (patchModuleProject == compiledProject) - compiledProject.files(compiledProject.the().matching { it.name.startsWith("main") } - .map { it.output }) - else - patchModuleProject.files(patchModuleProject.the()["main"].java.sourceDirectories) - }) - } - - override fun asArguments(): List { - val path = patch.filter { it.exists() }.asPath - if (path.isEmpty()) { - return emptyList() - } - return listOf("--patch-module", "${module.get()}=$path") - } - - @Internal - override fun getName() = "patch-module(${module.get()})" -} diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt b/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt index f4c6f124b65e..d5ce178a4b14 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt +++ b/gradle/plugins/common/src/main/kotlin/junitbuild/javadoc/ModuleSpecificJavadocFileOption.kt @@ -1,15 +1,16 @@ package junitbuild.javadoc +import org.gradle.api.provider.Provider import org.gradle.external.javadoc.JavadocOptionFileOption import org.gradle.external.javadoc.internal.JavadocOptionFileWriterContext -class ModuleSpecificJavadocFileOption(private val option: String, private var valuePerModule: Map) : JavadocOptionFileOption> { +class ModuleSpecificJavadocFileOption(private val option: String, private var valuePerModule: Map>) : JavadocOptionFileOption>> { override fun getOption() = option override fun getValue() = valuePerModule - override fun setValue(value: Map) { + override fun setValue(value: Map>) { this.valuePerModule = value } @@ -19,7 +20,7 @@ class ModuleSpecificJavadocFileOption(private val option: String, private var va .writeOptionHeader(option) .write(moduleName) .write("=") - .write(value) + .write(value.get()) .newLine() } } diff --git a/junit-jupiter-api/src/module/org.junit.jupiter.api/module-info.java b/junit-jupiter-api/src/main/java/module-info.java similarity index 96% rename from junit-jupiter-api/src/module/org.junit.jupiter.api/module-info.java rename to junit-jupiter-api/src/main/java/module-info.java index a9d9249f0eb1..afb8f4cd5e45 100644 --- a/junit-jupiter-api/src/module/org.junit.jupiter.api/module-info.java +++ b/junit-jupiter-api/src/main/java/module-info.java @@ -18,6 +18,8 @@ requires transitive org.junit.platform.commons; requires transitive org.opentest4j; + requires static kotlin.stdlib; + exports org.junit.jupiter.api; exports org.junit.jupiter.api.condition; exports org.junit.jupiter.api.extension; diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 982117516e55..24937664e13b 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("junitbuild.kotlin-library-conventions") + id("junitbuild.java-library-conventions") `java-test-fixtures` } diff --git a/junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java b/junit-jupiter-engine/src/main/java/module-info.java similarity index 100% rename from junit-jupiter-engine/src/module/org.junit.jupiter.engine/module-info.java rename to junit-jupiter-engine/src/main/java/module-info.java diff --git a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts index 0f28afd9ea94..b932ffe2021f 100644 --- a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts +++ b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts @@ -16,17 +16,22 @@ dependencies { osgiVerification(projects.junitPlatformLauncher) } -tasks.jar { - bundle { - val importAPIGuardian: String by extra - bnd(""" - # Import JUnit4 packages with a version - Import-Package: \ - $importAPIGuardian,\ - org.junit;version="[${libs.versions.junit4Min.get()},5)",\ - org.junit.platform.commons.logging;status=INTERNAL,\ - org.junit.rules;version="[${libs.versions.junit4Min.get()},5)",\ - * - """) +tasks { + compileJava { + options.compilerArgs.add("-Xlint:-requires-automatic,-requires-transitive-automatic") // JUnit 4 + } + jar { + bundle { + val importAPIGuardian: String by extra + bnd(""" + # Import JUnit4 packages with a version + Import-Package: \ + $importAPIGuardian,\ + org.junit;version="[${libs.versions.junit4Min.get()},5)",\ + org.junit.platform.commons.logging;status=INTERNAL,\ + org.junit.rules;version="[${libs.versions.junit4Min.get()},5)",\ + * + """) + } } } diff --git a/junit-jupiter-migrationsupport/src/module/org.junit.jupiter.migrationsupport/module-info.java b/junit-jupiter-migrationsupport/src/main/java/module-info.java similarity index 100% rename from junit-jupiter-migrationsupport/src/module/org.junit.jupiter.migrationsupport/module-info.java rename to junit-jupiter-migrationsupport/src/main/java/module-info.java diff --git a/junit-jupiter-params/junit-jupiter-params.gradle.kts b/junit-jupiter-params/junit-jupiter-params.gradle.kts index 80ade03f4b27..372b98e9abbd 100644 --- a/junit-jupiter-params/junit-jupiter-params.gradle.kts +++ b/junit-jupiter-params/junit-jupiter-params.gradle.kts @@ -3,6 +3,7 @@ plugins { id("junitbuild.shadow-conventions") id("junitbuild.jmh-conventions") `java-test-fixtures` + alias(libs.plugins.extraJavaModuleInfo) } description = "JUnit Jupiter Params" @@ -21,6 +22,11 @@ dependencies { osgiVerification(projects.junitPlatformLauncher) } +extraJavaModuleInfo { + automaticModule(libs.univocity.parsers, "univocity.parsers") + failOnMissingModuleInfo = false +} + tasks { jar { bundle { @@ -33,9 +39,6 @@ tasks { """) } } -} - -tasks { shadowJar { relocate("com.univocity", "org.junit.jupiter.params.shadow.com.univocity") from(projectDir) { @@ -43,10 +46,16 @@ tasks { into("META-INF") } } - compileModule { + compileJava { options.compilerArgs.addAll(listOf( "--add-modules", "univocity.parsers", "--add-reads", "${javaModuleName}=univocity.parsers" )) } + javadoc { + (options as StandardJavadocDocletOptions).apply { + addStringOption("-add-modules", "univocity.parsers") + addStringOption("-add-reads", "${javaModuleName}=univocity.parsers") + } + } } diff --git a/junit-jupiter-params/src/module/org.junit.jupiter.params/module-info.java b/junit-jupiter-params/src/main/java/module-info.java similarity index 100% rename from junit-jupiter-params/src/module/org.junit.jupiter.params/module-info.java rename to junit-jupiter-params/src/main/java/module-info.java diff --git a/junit-jupiter/junit-jupiter.gradle.kts b/junit-jupiter/junit-jupiter.gradle.kts index 83230d0b4226..17073c730817 100644 --- a/junit-jupiter/junit-jupiter.gradle.kts +++ b/junit-jupiter/junit-jupiter.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("junitbuild.java-library-conventions") + id("junitbuild.java-aggregator-conventions") } description = "JUnit Jupiter (Aggregator)" @@ -9,7 +9,7 @@ dependencies { api(projects.junitJupiterApi) api(projects.junitJupiterParams) - runtimeOnly(projects.junitJupiterEngine) + implementation(projects.junitJupiterEngine) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) diff --git a/junit-jupiter/src/module/org.junit.jupiter/module-info.java b/junit-jupiter/src/main/java/module-info.java similarity index 100% rename from junit-jupiter/src/module/org.junit.jupiter/module-info.java rename to junit-jupiter/src/main/java/module-info.java diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 89a6f0ecb227..57f328bc14c6 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -10,3 +10,7 @@ dependencies { compileOnlyApi(libs.apiguardian) } + +tasks.compileJava { + options.compilerArgs.add("-Xlint:-module") // due to qualified exports +} diff --git a/junit-platform-commons/src/module/org.junit.platform.commons/module-info.java b/junit-platform-commons/src/main/java/module-info.java similarity index 100% rename from junit-platform-commons/src/module/org.junit.platform.commons/module-info.java rename to junit-platform-commons/src/main/java/module-info.java diff --git a/junit-platform-console/junit-platform-console.gradle.kts b/junit-platform-console/junit-platform-console.gradle.kts index 586b30004004..e86ee29fdedb 100644 --- a/junit-platform-console/junit-platform-console.gradle.kts +++ b/junit-platform-console/junit-platform-console.gradle.kts @@ -13,8 +13,6 @@ dependencies { compileOnlyApi(libs.apiguardian) - compileOnly(libs.openTestReporting.events) - shadowed(libs.picocli) osgiVerification(projects.junitJupiterEngine) @@ -23,14 +21,18 @@ dependencies { } tasks { - compileModule { + compileJava { options.compilerArgs.addAll(listOf( - "--add-modules", "org.opentest4j.reporting.events", - "--add-reads", "${project.projects.junitPlatformReporting.javaModuleName}=org.opentest4j.reporting.events", "--add-modules", "info.picocli", "--add-reads", "${javaModuleName}=info.picocli" )) } + javadoc { + (options as StandardJavadocDocletOptions).apply { + addStringOption("-add-modules", "info.picocli") + addStringOption("-add-reads", "${javaModuleName}=info.picocli") + } + } shadowJar { exclude("META-INF/versions/9/module-info.class") relocate("picocli", "org.junit.platform.console.shadow.picocli") diff --git a/junit-platform-console/src/module/org.junit.platform.console/module-info.java b/junit-platform-console/src/main/java/module-info.java similarity index 100% rename from junit-platform-console/src/module/org.junit.platform.console/module-info.java rename to junit-platform-console/src/main/java/module-info.java diff --git a/junit-platform-engine/src/module/org.junit.platform.engine/module-info.java b/junit-platform-engine/src/main/java/module-info.java similarity index 100% rename from junit-platform-engine/src/module/org.junit.platform.engine/module-info.java rename to junit-platform-engine/src/main/java/module-info.java diff --git a/junit-platform-jfr/src/module/org.junit.platform.jfr/module-info.java b/junit-platform-jfr/src/main/java/module-info.java similarity index 100% rename from junit-platform-jfr/src/module/org.junit.platform.jfr/module-info.java rename to junit-platform-jfr/src/main/java/module-info.java diff --git a/junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java b/junit-platform-launcher/src/main/java/module-info.java similarity index 100% rename from junit-platform-launcher/src/module/org.junit.platform.launcher/module-info.java rename to junit-platform-launcher/src/main/java/module-info.java diff --git a/junit-platform-reporting/junit-platform-reporting.gradle.kts b/junit-platform-reporting/junit-platform-reporting.gradle.kts index f1dede61555d..1d76dc4557bc 100644 --- a/junit-platform-reporting/junit-platform-reporting.gradle.kts +++ b/junit-platform-reporting/junit-platform-reporting.gradle.kts @@ -33,10 +33,16 @@ tasks { into("META-INF") } } - compileModule { + compileJava { options.compilerArgs.addAll(listOf( "--add-modules", "org.opentest4j.reporting.events", "--add-reads", "${javaModuleName}=org.opentest4j.reporting.events" )) } + javadoc { + (options as StandardJavadocDocletOptions).apply { + addStringOption("-add-modules", "org.opentest4j.reporting.events") + addStringOption("-add-reads", "${javaModuleName}=org.opentest4j.reporting.events") + } + } } diff --git a/junit-platform-reporting/src/module/org.junit.platform.reporting/module-info.java b/junit-platform-reporting/src/main/java/module-info.java similarity index 100% rename from junit-platform-reporting/src/module/org.junit.platform.reporting/module-info.java rename to junit-platform-reporting/src/main/java/module-info.java diff --git a/junit-platform-suite-api/src/module/org.junit.platform.suite.api/module-info.java b/junit-platform-suite-api/src/main/java/module-info.java similarity index 100% rename from junit-platform-suite-api/src/module/org.junit.platform.suite.api/module-info.java rename to junit-platform-suite-api/src/main/java/module-info.java diff --git a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts index f65b677db193..fdc4062f36ce 100644 --- a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts +++ b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts @@ -16,3 +16,7 @@ dependencies { osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) } + +tasks.compileJava { + options.compilerArgs.add("-Xlint:-module") // due to qualified exports +} diff --git a/junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java b/junit-platform-suite-commons/src/main/java/module-info.java similarity index 100% rename from junit-platform-suite-commons/src/module/org.junit.platform.suite.commons/module-info.java rename to junit-platform-suite-commons/src/main/java/module-info.java diff --git a/junit-platform-suite-engine/src/module/org.junit.platform.suite.engine/module-info.java b/junit-platform-suite-engine/src/main/java/module-info.java similarity index 100% rename from junit-platform-suite-engine/src/module/org.junit.platform.suite.engine/module-info.java rename to junit-platform-suite-engine/src/main/java/module-info.java diff --git a/junit-platform-suite/junit-platform-suite.gradle.kts b/junit-platform-suite/junit-platform-suite.gradle.kts index 83e475a2a689..8bce8504e7d8 100644 --- a/junit-platform-suite/junit-platform-suite.gradle.kts +++ b/junit-platform-suite/junit-platform-suite.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("junitbuild.java-library-conventions") + id("junitbuild.java-aggregator-conventions") } description = "JUnit Platform Suite (Aggregator)" diff --git a/junit-platform-suite/src/module/org.junit.platform.suite/module-info.java b/junit-platform-suite/src/main/java/module-info.java similarity index 100% rename from junit-platform-suite/src/module/org.junit.platform.suite/module-info.java rename to junit-platform-suite/src/main/java/module-info.java diff --git a/junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java b/junit-platform-testkit/src/main/java/module-info.java similarity index 100% rename from junit-platform-testkit/src/module/org.junit.platform.testkit/module-info.java rename to junit-platform-testkit/src/main/java/module-info.java diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index 871858b42133..af2455f46c31 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -30,6 +30,9 @@ dependencies { } tasks { + compileJava { + options.compilerArgs.add("-Xlint:-requires-automatic") // JUnit 4 + } compileTestFixturesGroovy { javaLauncher = project.javaToolchains.launcherFor { // Groovy 2.x (used for Spock tests) does not support current JDKs diff --git a/junit-vintage-engine/src/module/org.junit.vintage.engine/module-info.java b/junit-vintage-engine/src/main/java/module-info.java similarity index 100% rename from junit-vintage-engine/src/module/org.junit.vintage.engine/module-info.java rename to junit-vintage-engine/src/main/java/module-info.java diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt index 3819dc406164..673304bda14d 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt @@ -7,6 +7,7 @@ exports org.junit.jupiter.api.function exports org.junit.jupiter.api.io exports org.junit.jupiter.api.parallel requires java.base mandated +requires kotlin.stdlib static requires org.apiguardian.api static transitive requires org.junit.platform.commons transitive requires org.opentest4j transitive diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java index ca5b03192965..f86fdef3acde 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GradleModuleFileTests.java @@ -94,6 +94,13 @@ void jupiterAggregatorGradleModuleMetadataVariants() throws Exception { " },", // " \"dependencies\": [", // " {", // + " \"group\": \"org.junit.jupiter\",", // + " \"module\": \"junit-jupiter-engine\",", // + " \"version\": {", // + ">> VERSION >>", // + " }", // + " },", // + " {", // " \"group\": \"org.junit\",", // " \"module\": \"junit-bom\",", // " \"version\": {", // @@ -117,13 +124,6 @@ void jupiterAggregatorGradleModuleMetadataVariants() throws Exception { " \"version\": {", // ">> VERSION >>", // " }", // - " },", // - " {", // - " \"group\": \"org.junit.jupiter\",", // - " \"module\": \"junit-jupiter-engine\",", // - " \"version\": {", // - ">> VERSION >>", // - " }", // " }", // " ],", // " \"files\": [", // From d5798b4537506744826eee19afd405be80be0816 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 12:58:55 +0000 Subject: [PATCH 046/521] Update plugin kotlin to v2.1.21 (#4528) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- .../projects/gradle-kotlin-extensions/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fc5fdf4ff161..f4f5156cf716 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -100,7 +100,7 @@ foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "0.10 gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } # check if workaround in gradle.properties can be removed when updating -kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.20" } +kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.1" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 2040dbfff8d3..539c5f9b0b22 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 plugins { - kotlin("jvm") version "2.1.20" + kotlin("jvm") version "2.1.21" } repositories { From 032f09e151da8767210fc3b46bbf4f54e72fa933 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 13 May 2025 16:01:18 +0200 Subject: [PATCH 047/521] Remove version 5 where possible (#4524) --- .github/ISSUE_TEMPLATE/bug_report.md | 2 +- CONTRIBUTING.md | 2 +- README.md | 18 +++++++++--------- build.gradle.kts | 2 +- documentation/README.md | 4 ++-- .../src/docs/asciidoc/release-notes/index.adoc | 4 ++-- .../user-guide/advanced-topics/engines.adoc | 2 +- .../advanced-topics/launcher-api.adoc | 12 ++++++------ .../asciidoc/user-guide/api-evolution.adoc | 11 ++++++----- .../src/docs/asciidoc/user-guide/appendix.adoc | 2 +- .../src/docs/asciidoc/user-guide/index.adoc | 2 +- .../src/docs/asciidoc/user-guide/overview.adoc | 18 +++++++++--------- .../asciidoc/user-guide/running-tests.adoc | 12 ++++++------ documentation/src/javadoc/junit-overview.html | 10 +++++----- .../junit-eclipse-formatter-settings.xml | 2 +- ...itbuild.java-library-conventions.gradle.kts | 2 +- junit-jupiter-migrationsupport/README.md | 4 ++-- .../rules/ExternalResourceSupport.java | 2 +- .../rules/VerifierSupport.java | 2 +- .../platform/commons/util/ReflectionUtils.java | 2 +- .../org/junit/platform/launcher/TagFilter.java | 2 +- .../junit/platform/suite/api/ExcludeTags.java | 2 +- .../junit/platform/suite/api/IncludeTags.java | 2 +- .../support/hierarchical/MemoryLeakTests.java | 2 +- .../platform-tooling-support-tests.gradle.kts | 2 +- 25 files changed, 63 insertions(+), 62 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 57a6f10876d6..65eddb565fd1 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -5,7 +5,7 @@ type: Bug labels: ["type: bug"] --- - + ## Steps to reproduce diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 135a6cd3456c..072b521a24c5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -151,7 +151,7 @@ See [`ExtensionContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/e ### Deprecation -The JUnit 5 project uses the `@API` annotation from [API Guardian](https://github.com/apiguardian-team/apiguardian). +The JUnit project uses the `@API` annotation from [API Guardian](https://github.com/apiguardian-team/apiguardian). Publicly available interfaces, classes, and methods have a defined lifecycle which is described in detail in the [User Guide](https://junit.org/junit5/docs/current/user-guide/#api-evolution). diff --git a/README.md b/README.md index 71888458aae1..ae0e7667f3a3 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# JUnit 5 +# JUnit -This repository is the home of _JUnit 5_. +This repository is the home of JUnit Platform, Jupiter, and Vintage. ## Sponsors @@ -24,7 +24,7 @@ This repository is the home of _JUnit 5_. ## Contributing -Contributions to JUnit 5 are both welcomed and appreciated. For specific guidelines +Contributions to JUnit are both welcomed and appreciated. For specific guidelines regarding contributions, please see [CONTRIBUTING.md] in the root directory of the project. Those willing to use milestone or SNAPSHOT releases are encouraged to file feature requests and bug reports using the project's @@ -34,15 +34,15 @@ label are specifically targeted for community contributions. ## Getting Help -Ask JUnit 5 related questions on [StackOverflow] or chat with the community on [Gitter]. +Ask JUnit-related questions on [StackOverflow] or chat with the community on [Gitter]. ## Continuous Integration Builds [![CI Status](https://github.com/junit-team/junit5/workflows/CI/badge.svg)](https://github.com/junit-team/junit5/actions) [![Cross-Version Status](https://github.com/junit-team/junit5/workflows/Cross-Version/badge.svg)](https://github.com/junit-team/junit5/actions) -Official CI build server for JUnit 5. Used to perform quick checks on submitted pull -requests and for build matrices including the latest released OpenJDK and early access -builds of the next OpenJDK. +Official CI build server used to perform quick checks on submitted pull requests and for +build matrices including the latest released OpenJDK and early access builds of the next +OpenJDK. ## Code Coverage @@ -56,7 +56,7 @@ in `build/reports/jacoco/jacocoRootReport/html/index.html`. [![Revved up by Develocity](https://img.shields.io/badge/Revved%20up%20by-Develocity-06A0CE?logo=Gradle&labelColor=02303A)](https://ge.junit.org/scans) -JUnit 5 utilizes [Develocity](https://gradle.com/) for [Build Scans](https://scans.gradle.com/), +JUnit utilizes [Develocity](https://gradle.com/) for [Build Scans](https://scans.gradle.com/), [Build Cache](https://docs.gradle.org/current/userguide/build_cache.html), and [Predictive Test Selection](https://docs.gradle.com/enterprise/predictive-test-selection/). @@ -70,7 +70,7 @@ task outputs from previous CI builds. ## Building from Source -You need [JDK 21] to build JUnit 5. [Gradle toolchains] are used to detect and +You need [JDK 21] to build JUnit. [Gradle toolchains] are used to detect and potentially download additional JDKs for compilation and test execution. All modules can be _built_ and _tested_ with the [Gradle Wrapper] using the following command. diff --git a/build.gradle.kts b/build.gradle.kts index 82ec852b1f77..36798c9a9bc9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { id("junitbuild.temp-maven-repo") } -description = "JUnit 5" +description = "JUnit" val license by extra(License( name = "Eclipse Public License v2.0", diff --git a/documentation/README.md b/documentation/README.md index f06f5b2fc14b..873a2ff282f6 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -1,6 +1,6 @@ -# JUnit 5 User Guide +# JUnit User Guide -This subproject contains the AsciiDoc sources for the JUnit 5 User Guide. +This subproject contains the AsciiDoc sources for the JUnit User Guide. ## Structure diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index b31c979490bc..5fe75a6a3698 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -1,5 +1,5 @@ [[release-notes]] -= JUnit 5 Release Notes += JUnit Release Notes Stefan Bechtold; Sam Brannen; Johannes Link; Matthias Merdes; Marc Philipp; Juliette de Rancourt; Christian Stein // :basedir: {includedir}/release-notes @@ -9,7 +9,7 @@ Stefan Bechtold; Sam Brannen; Johannes Link; Matthias Merdes; Marc Philipp; Juli :last-update-label!: // -This document contains the _change log_ for all JUnit 5 releases since 5.11 GA. +This document contains the _change log_ for all JUnit releases since 5.13 GA. Please refer to the <<../user-guide/index.adoc#user-guide,User Guide>> for comprehensive reference documentation for programmers writing tests, extension authors, and engine diff --git a/documentation/src/docs/asciidoc/user-guide/advanced-topics/engines.adoc b/documentation/src/docs/asciidoc/user-guide/advanced-topics/engines.adoc index 89f9b127220a..06c7d031ee53 100644 --- a/documentation/src/docs/asciidoc/user-guide/advanced-topics/engines.adoc +++ b/documentation/src/docs/asciidoc/user-guide/advanced-topics/engines.adoc @@ -60,7 +60,7 @@ configuration parameters. Although there is currently no official guide on how to implement a custom `TestEngine`, you can consult the implementation of <> or the implementation of third-party test engines listed in the -https://github.com/junit-team/junit5/wiki/Third-party-Extensions#junit-platform-test-engines[JUnit 5 wiki]. +https://github.com/junit-team/junit5/wiki/Third-party-Extensions#junit-platform-test-engines[JUnit wiki]. You will also find various tutorials and blogs on the Internet that demonstrate how to write a custom `TestEngine`. diff --git a/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc b/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc index 9f8db34b21f1..be61e66fd51d 100644 --- a/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc +++ b/documentation/src/docs/asciidoc/user-guide/advanced-topics/launcher-api.adoc @@ -4,13 +4,13 @@ [[launcher-api]] === JUnit Platform Launcher API -One of the prominent goals of JUnit 5 is to make the interface between JUnit and its -programmatic clients – build tools and IDEs – more powerful and stable. The purpose is to -decouple the internals of discovering and executing tests from all the filtering and -configuration that's necessary from the outside. +One of the prominent goals of the JUnit Platform is to make the interface between JUnit +and its programmatic clients – build tools and IDEs – more powerful and stable. The +purpose is to decouple the internals of discovering and executing tests from all the +filtering and configuration that's necessary from the outside. -JUnit 5 introduces the concept of a `Launcher` that can be used to discover, filter, and -execute tests. Moreover, third party test libraries – like Spock, Cucumber, and FitNesse +JUnit Platform introduces the concept of a `Launcher` that can be used to discover, +filter, and execute tests. Moreover, third party test libraries – like Spock or Cucumber – can plug into the JUnit Platform's launching infrastructure by providing a custom <>. diff --git a/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc b/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc index bac0e8b0012c..e2c1071271fa 100644 --- a/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc +++ b/documentation/src/docs/asciidoc/user-guide/api-evolution.adoc @@ -1,12 +1,13 @@ [[api-evolution]] == API Evolution -One of the major goals of JUnit 5 is to improve maintainers' capabilities to evolve JUnit -despite its being used in many projects. With JUnit 4 a lot of stuff that was originally -added as an internal construct only got used by external extension writers and tool -builders. That made changing JUnit 4 especially difficult and sometimes impossible. +One of the major goals of the JUnit Platform architecture is to improve maintainers' +capabilities to evolve JUnit despite its being used in many projects. With JUnit 4 a lot +of stuff that was originally added as an internal construct only got used by external +extension writers and tool builders. That made changing JUnit 4 especially difficult and +sometimes impossible. -That's why JUnit 5 introduces a defined lifecycle for all publicly available interfaces, +That's why JUnit now uses a defined lifecycle for all publicly available interfaces, classes, and methods. [[api-evolution-version-and-status]] diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index e779cbc9c70f..b31e6a379eae 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -4,7 +4,7 @@ [[reproducible-builds]] === Reproducible Builds -Starting with version 5.7, JUnit 5 aims for its non-javadoc JARs to be +Starting with version 5.7, JUnit aims for its non-javadoc JARs to be https://reproducible-builds.org/[reproducible]. Under identical build conditions, such as Java version, repeated builds should provide the diff --git a/documentation/src/docs/asciidoc/user-guide/index.adoc b/documentation/src/docs/asciidoc/user-guide/index.adoc index 9c34f8d33739..bbf1c670c5ad 100644 --- a/documentation/src/docs/asciidoc/user-guide/index.adoc +++ b/documentation/src/docs/asciidoc/user-guide/index.adoc @@ -1,5 +1,5 @@ [[user-guide]] -= JUnit 5 User Guide += JUnit User Guide Stefan Bechtold; Sam Brannen; Johannes Link; Matthias Merdes; Marc Philipp; Juliette de Rancourt; Christian Stein :basedir: {includedir}/user-guide :pdf-fontsdir: GEM_FONTS_DIR;{includedir}/resources/fonts diff --git a/documentation/src/docs/asciidoc/user-guide/overview.adoc b/documentation/src/docs/asciidoc/user-guide/overview.adoc index d06a5eb53eda..a366b0b4e972 100644 --- a/documentation/src/docs/asciidoc/user-guide/overview.adoc +++ b/documentation/src/docs/asciidoc/user-guide/overview.adoc @@ -12,12 +12,12 @@ endif::linkToPdf[] endif::backend-html5[] [[overview-what-is-junit-5]] -=== What is JUnit 5? +=== What is JUnit? -Unlike previous versions of JUnit, JUnit 5 is composed of several different modules from -three different sub-projects. +Unlike previous versions of JUnit, JUnit 5 and later is composed of several different +modules from three different sub-projects. -**JUnit 5 = _JUnit Platform_ + _JUnit Jupiter_ + _JUnit Vintage_** +**JUnit {version} = _JUnit Platform_ + _JUnit Jupiter_ + _JUnit Vintage_** The **JUnit Platform** serves as a foundation for <> on the JVM. It also defines the `{TestEngine}` API for developing a testing @@ -31,7 +31,7 @@ exists in popular IDEs (see <>, <>, and <>). **JUnit Jupiter** is the combination of the <> and -<> for writing tests and extensions in JUnit 5. The Jupiter +<> for writing JUnit tests and extensions. The Jupiter sub-project provides a `TestEngine` for running Jupiter based tests on the platform. **JUnit Vintage** provides a `TestEngine` for running JUnit 3 and JUnit 4 based tests on @@ -41,13 +41,13 @@ path. [[overview-java-versions]] === Supported Java Versions -JUnit 5 requires Java 8 (or higher) at runtime. However, you can still test code that +JUnit requires Java 17 (or higher) at runtime. However, you can still test code that has been compiled with previous versions of the JDK. [[overview-getting-help]] === Getting Help -Ask JUnit 5 related questions on {StackOverflow} or chat with the community on {Gitter}. +Ask JUnit-related questions on {StackOverflow} or chat with the community on {Gitter}. [[overview-getting-started]] === Getting Started @@ -60,9 +60,9 @@ to <>. To set up dependency management for your build, refe <> and the <>. [[overview-getting-started-features]] -==== JUnit 5 Features +==== JUnit Features -To find out what features are available in JUnit 5 and how to use them, read the +To find out what features are available in JUnit {version} and how to use them, read the corresponding sections of this User Guide, organized by topic. * <> diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index 3cd93ecdbcb9..b548c880af08 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -13,7 +13,7 @@ however, that it is recommended to use IDEA 2017.3 or newer since more recent ve IDEA download the following JARs automatically based on the API version used in the project: `junit-platform-launcher`, `junit-jupiter-engine`, and `junit-vintage-engine`. -In order to use a different JUnit 5 version (e.g., {version}), you may need to +In order to use a different JUnit version (e.g., {version}), you may need to include the corresponding versions of the `junit-platform-launcher`, `junit-jupiter-engine`, and `junit-vintage-engine` JARs in the classpath. @@ -68,8 +68,8 @@ testRuntimeOnly("org.junit.vintage:junit-vintage-engine") Eclipse IDE offers support for the JUnit Platform since the Eclipse Oxygen.1a (4.7.1a) release. -For more information on using JUnit 5 in Eclipse consult the official _Eclipse support -for JUnit 5_ section of the +For more information on using JUnit Platform in Eclipse consult the official _Eclipse +support for JUnit 5_ section of the https://www.eclipse.org/eclipse/news/4.7.1a/#junit-5-support[Eclipse Project Oxygen.1a (4.7.1a) - New and Noteworthy] documentation. @@ -151,7 +151,7 @@ of JUnit used in your Spring Boot application. Unless you're using Spring Boot which defines its own way of managing dependencies, it is recommended to use the JUnit Platform <> to align the -versions of all JUnit 5 artifacts. +versions of all JUnit artifacts. [source,groovy,indent=0] [subs=attributes+] @@ -171,7 +171,7 @@ Since all JUnit artifacts declare a https://docs.gradle.org/current/userguide/platforms.html[platform] dependency on the BOM, you usually don't need to declare an explicit dependency on it yourself. Instead, it's sufficient to declare _one_ regular dependency that includes a version number. Gradle will -then pull in the BOM automatically so you can omit the version for all other JUnit 5 +then pull in the BOM automatically so you can omit the version for all other JUnit artifacts. [source,groovy,indent=0] @@ -328,7 +328,7 @@ As of JUnit 6.0, the minimum required version of Maven Surefire/Failsafe is 3.0. Unless you're using Spring Boot which defines its own way of managing dependencies, it is recommended to use the JUnit Platform <> to align the -versions of all JUnit 5 artifacts. +versions of all JUnit artifacts. [source,xml,indent=0] [subs=attributes+] diff --git a/documentation/src/javadoc/junit-overview.html b/documentation/src/javadoc/junit-overview.html index 2e79b9d5af9a..50837dbd73e6 100644 --- a/documentation/src/javadoc/junit-overview.html +++ b/documentation/src/javadoc/junit-overview.html @@ -7,12 +7,12 @@

The JUnit Platform serves as a foundation for launching testing frameworks on the JVM. It also defines the TestEngine API for developing a testing framework that runs on the platform. Furthermore, the platform provides a Console Launcher to launch the platform - from the command line and a JUnit 4 based Runner for running any TestEngine on the - platform in a JUnit 4 based environment. + from the command line and the Suite Engine for running a custom test suite using one + or more test engines on the platform
Jupiter
-
JUnit Jupiter is the combination of the new programming model and extension model for - writing tests and extensions in JUnit 5. The Jupiter sub-project provides a TestEngine +
JUnit Jupiter is the combination of the programming model and extension model for + writing JUnit tests and extensions. The Jupiter sub-project provides a TestEngine for running Jupiter based tests on the platform.
Vintage
@@ -21,6 +21,6 @@ -

Already consulted the JUnit 5 User Guide?

+

Already consulted the JUnit User Guide?

diff --git a/gradle/config/eclipse/junit-eclipse-formatter-settings.xml b/gradle/config/eclipse/junit-eclipse-formatter-settings.xml index 34f4f9dda2b1..974eadd7caa4 100644 --- a/gradle/config/eclipse/junit-eclipse-formatter-settings.xml +++ b/gradle/config/eclipse/junit-eclipse-formatter-settings.xml @@ -1,6 +1,6 @@ - + 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 a7ca8a33a8c6..c74700a5813b 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 @@ -113,7 +113,7 @@ if (project in mavenizedProjects) { } } pom { - description = provider { "Module \"${project.name}\" of JUnit 5." } + description = provider { "Module \"${project.name}\" of JUnit" } } } } diff --git a/junit-jupiter-migrationsupport/README.md b/junit-jupiter-migrationsupport/README.md index 730e2c8e94b1..a8b755cae594 100644 --- a/junit-jupiter-migrationsupport/README.md +++ b/junit-jupiter-migrationsupport/README.md @@ -9,11 +9,11 @@ implementations is not possible within the JUnit Jupiter extension model. The main purpose of this module is to facilitate the migration of large JUnit 4 codebases containing such JUnit 4 rules by minimizing the effort -needed to run such legacy tests under JUnit 5. +needed to run such legacy tests under JUnit Platform. By using one of the two provided class-level extensions on a test class such rules in legacy code bases can be left unchanged including the JUnit 4 rule import statements. However, if you intend to develop a *new* extension for -JUnit 5 please use the new extension model of JUnit Jupiter instead +JUnit please use the new extension model of JUnit Jupiter instead of the rule-based model of JUnit 4. diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java index 347317733d4e..de134f2a4d44 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java @@ -30,7 +30,7 @@ * can be left unchanged including the JUnit 4 rule import statements. * *

However, if you intend to develop a new extension for - * JUnit 5 please use the new extension model of JUnit Jupiter instead + * JUnit please use the new extension model of JUnit Jupiter instead * of the rule-based model of JUnit 4. * * @since 5.0 diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java index a5025818722d..ac22ac1b2a0a 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java @@ -29,7 +29,7 @@ * can be left unchanged including the JUnit 4 rule import statements. * *

However, if you intend to develop a new extension for - * JUnit 5 please use the new extension model of JUnit Jupiter instead + * JUnit please use the new extension model of JUnit Jupiter instead * of the rule-based model of JUnit 4. * * @since 5.0 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 9a575d61fe5b..276d8a280901 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 @@ -94,7 +94,7 @@ public final class ReflectionUtils { *

When set to {@code false} (either explicitly or implicitly), field and * method searches will adhere to Java semantics regarding whether a given * field or method is visible or overridden, where the latter only applies - * to methods. When set to {@code true}, the semantics used in JUnit 5 prior + * to methods. When set to {@code true}, the semantics used in versions prior * to JUnit 5.11 (JUnit Platform 1.11) will be used, which means that fields * and methods can hide, shadow, or supersede fields and methods in supertypes * based solely on the field's name or the method's signature, disregarding diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java index 2de149079747..ff8c8a828742 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java @@ -33,7 +33,7 @@ *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and), and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the - * JUnit 5 User Guide + * JUnit User Guide * for usage examples. * *

Please note that a tag name is a valid tag expression. Thus, wherever a tag diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java index aad54d125709..fc8eac9d51f2 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/ExcludeTags.java @@ -31,7 +31,7 @@ *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and) and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the - * JUnit 5 User Guide + * JUnit User Guide * for usage examples. * *

Syntax Rules for Tags

diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java index 089ea5f49387..ec156f462f50 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/IncludeTags.java @@ -31,7 +31,7 @@ *

Tag expressions are boolean expressions with the following allowed * operators: {@code !} (not), {@code &} (and) and {@code |} (or). Parentheses * can be used to adjust for operator precedence. Please refer to the - * JUnit 5 User Guide + * JUnit User Guide * for usage examples. * *

Syntax Rules for Tags

diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/MemoryLeakTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/MemoryLeakTests.java index e8daa4b230a5..8ad841418e3b 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/MemoryLeakTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/MemoryLeakTests.java @@ -29,7 +29,7 @@ class MemoryLeakTests { // Allocate 500 MB of memory per test method. // // If the test instance is garbage collected, this should not cause any - // problems for the JUnit 5 build; however, if the instances of this test + // problems for the JUnit build; however, if the instances of this test // class are NOT garbage collected, we should run out of memory pretty // quickly since the instances of this test class would consume 5GB of // heap space. diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 3052d2b52622..4cfaa9f99986 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -114,7 +114,7 @@ val normalizeMavenRepo by tasks.registering(Sync::class) { val archUnit by testing.suites.registering(JvmTestSuite::class) { dependencies { implementation(libs.archunit) { - because("checking the architecture of JUnit 5") + because("checking the architecture") } implementation(libs.apiguardian) { because("we validate that public classes are annotated") From b1b105de9655ba372cc974ec74a2e2ffa34ee4ec Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 14 May 2025 12:03:38 +0200 Subject: [PATCH 048/521] Remove unused constant for deleted sample project --- .../src/test/java/platform/tooling/support/tests/Projects.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java index 8d806b6b67e4..b3edd252e4fa 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java @@ -21,7 +21,6 @@ public class Projects { public static final String GRADLE_KOTLIN_EXTENSIONS = "gradle-kotlin-extensions"; public static final String GRADLE_MISSING_ENGINE = "gradle-missing-engine"; public static final String JAR_DESCRIBE_MODULE = "jar-describe-module"; - public static final String JAVA_VERSIONS = "java-versions"; public static final String JUPITER_STARTER = "jupiter-starter"; public static final String MAVEN_SUREFIRE_COMPATIBILITY = "maven-surefire-compatibility"; public static final String MULTI_RELEASE_JAR = "multi-release-jar"; From 8032896882737c81c4020e2c113e434f2a4f2406 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 14 May 2025 19:08:19 +0000 Subject: [PATCH 049/521] Update plugin jreleaser to v1.18.0 (#4533) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9b346f12b275..f56089d490dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -99,7 +99,7 @@ extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "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" } -jreleaser = { id = "org.jreleaser", version = "1.17.0" } +jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.1" } From 0e7cee4f6a8282cd574d4f4e397e1d14f919f640 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 22:05:55 +0000 Subject: [PATCH 050/521] Update codecov/codecov-action action to v5.4.3 --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d56a341210b0..eb512b82c647 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,7 +42,7 @@ jobs: jacocoRootReport \ --no-configuration-cache # Disable configuration cache due to https://github.com/diffplug/spotless/issues/2318 - name: Upload to Codecov.io - uses: codecov/codecov-action@ad3126e916f78f00edff4ed0317cf185271ccc2d # v5.4.2 + uses: codecov/codecov-action@18283e04ce6e62d37312384ff67231eb8fd56d24 # v5.4.3 with: token: ${{ secrets.CODECOV_TOKEN }} From 2bc48f83b50a32256805294124d69ad180354e97 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 16 May 2025 14:22:43 +0200 Subject: [PATCH 051/521] Add support for Kotlin suspending functions as test/lifecycle methods (#4530) For this to work three Kotlin dependencies are required to be on the classpath or module path: `kotlin-stdlib`, `kotlin-reflect`, and `kotlinx-coroutines-core`. They are likely to be already present, if Kotlin coroutines are used in production code. The new `KotlinReflectionUtils` checks for their availability when it needs them but only if a method has been found that looks like a suspending function. Resolves #1914. --- documentation/documentation.gradle.kts | 2 + .../release-notes/release-notes-6.0.0-M1.adoc | 2 +- .../asciidoc/user-guide/writing-tests.adoc | 18 +- .../kotlin/example/KotlinCoroutinesDemo.kt | 36 ++++ .../jupiter/api/DisplayNameGenerator.java | 7 +- .../descriptor/LifecycleMethodUtils.java | 4 +- .../predicates/IsTestFactoryMethod.java | 6 +- .../predicates/IsTestableMethod.java | 4 +- .../execution/DefaultExecutableInvoker.java | 3 +- .../engine/execution/MethodInvocation.java | 5 +- .../execution/ParameterResolutionUtils.java | 16 +- .../engine/support/MethodReflectionUtils.java | 46 +++++ .../params/ParameterizedClassContext.java | 5 - .../junit/jupiter/params/ResolverFacade.java | 11 +- .../junit-platform-commons.gradle.kts | 26 ++- .../src/main/java/module-info.java | 4 + .../commons/util/KotlinReflectionUtils.java | 113 +++++++++++ .../commons/util/KotlinReflectionUtils.kt | 59 ++++++ ...nit-platform-console-standalone.gradle.kts | 1 + jupiter-tests/jupiter-tests.gradle.kts | 2 + .../AbstractJupiterTestEngineTests.java | 7 + .../api/KotlinSuspendFunctionsTests.kt | 190 ++++++++++++++++++ .../junit-platform-commons.expected.txt | 3 + .../kotlin-coroutines/build.gradle.kts | 37 ++++ .../kotlin-coroutines/settings.gradle.kts | 5 + .../example/project/SuspendFunctionTests.kt | 20 ++ .../tooling/support/tests/ArchUnitTests.java | 3 + .../support/tests/KotlinCoroutinesTests.java | 83 ++++++++ .../tooling/support/tests/Projects.java | 1 + 29 files changed, 698 insertions(+), 21 deletions(-) create mode 100644 documentation/src/test/kotlin/example/KotlinCoroutinesDemo.kt create mode 100644 junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java create mode 100644 junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinReflectionUtils.java create mode 100644 junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt create mode 100644 jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinSuspendFunctionsTests.kt create mode 100644 platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts create mode 100644 platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts create mode 100644 platform-tooling-support-tests/projects/kotlin-coroutines/src/test/kotlin/com/example/project/SuspendFunctionTests.kt create mode 100644 platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/KotlinCoroutinesTests.java diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index abad9ece66f7..e079ac81867e 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -70,6 +70,8 @@ dependencies { testImplementation(projects.junitPlatformTestkit) testImplementation(projects.junitVintageEngine) testImplementation(kotlin("stdlib")) + testRuntimeOnly(libs.kotlinx.coroutines) + testRuntimeOnly(kotlin("reflect")) toolsImplementation(projects.junitPlatformCommons) toolsImplementation(libs.classgraph) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 22cfd490dd0c..cae381374e60 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -96,7 +96,7 @@ repository on GitHub. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements -* ❓ +* Add support for using Kotlin's `suspend` modifier on test and lifecycle methods. [[release-notes-6.0.0-M1-junit-vintage]] diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index a1f1243a987b..6e87e90af1fe 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -271,7 +271,7 @@ lifecycle methods. For further information on runtime semantics, see <>. [source,java,indent=0] -.A standard test class +.A standard Java test class ---- include::{testDir}/example/StandardTests.java[tags=user_guide] ---- @@ -285,6 +285,22 @@ following example. include::{testRelease21Dir}/example/MyFirstJUnitJupiterRecordTests.java[tags=user_guide] ---- +Test and lifecycle methods may be written in Kotlin and may optionally use the `suspend` +keyword for testing code using coroutines. + +[source,kotlin] +.A test class written in Kotlin +---- +include::{kotlinTestDir}/example/KotlinCoroutinesDemo.kt[tags=user_guide] +---- + +NOTE: Using suspending functions as test or lifecycle methods requires +https://central.sonatype.com/artifact/org.jetbrains.kotlin/kotlin-stdlib[`kotlin-stdlib`], +https://central.sonatype.com/artifact/org.jetbrains.kotlin/kotlin-reflect[`kotlin-reflect`], +and +https://central.sonatype.com/artifact/org.jetbrains.kotlinx/kotlinx-coroutines-core[`kotlinx-coroutines-core`] +to be present on the classpath or module path. + [[writing-tests-display-names]] === Display Names diff --git a/documentation/src/test/kotlin/example/KotlinCoroutinesDemo.kt b/documentation/src/test/kotlin/example/KotlinCoroutinesDemo.kt new file mode 100644 index 000000000000..993f75388025 --- /dev/null +++ b/documentation/src/test/kotlin/example/KotlinCoroutinesDemo.kt @@ -0,0 +1,36 @@ +/* + * 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 example + +// tag::user_guide[] +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.Test + +// end::user_guide[] +// tag::user_guide[] +@Suppress("JUnitMalformedDeclaration") +class KotlinCoroutinesDemo { + @BeforeEach + fun regularSetUp() { + } + + @BeforeEach + suspend fun coroutineSetUp() { + } + + @Test + fun regularTest() { + } + + @Test + suspend fun coroutineTest() { + } +} +// end::user_guide[] 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..1ff2974c06d1 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 @@ -17,6 +17,8 @@ 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; +import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionParameterTypes; +import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinSuspendingFunction; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -195,7 +197,10 @@ default String generateDisplayNameForMethod(List> enclosingInstanceType */ static String parameterTypesAsString(Method method) { Preconditions.notNull(method, "Method must not be null"); - return '(' + ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes()) + ')'; + var parameterTypes = isKotlinSuspendingFunction(method) // + ? getKotlinSuspendingFunctionParameterTypes(method) // + : method.getParameterTypes(); + return '(' + ClassUtils.nullSafeToString(Class::getSimpleName, parameterTypes) + ')'; } /** diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java index 8d629e82fbf4..1d897c3c27c4 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.descriptor; +import static org.junit.jupiter.engine.support.MethodReflectionUtils.getReturnType; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedMethods; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; @@ -30,7 +31,6 @@ import org.junit.jupiter.api.extension.ClassTemplateInvocationLifecycleMethod; import org.junit.platform.commons.support.HierarchyTraversalMode; import org.junit.platform.commons.support.ModifierSupport; -import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.support.descriptor.MethodSource; @@ -177,7 +177,7 @@ private static Condition isNotPrivateWarning(DiscoveryIssueReporter issu private static Condition returnsPrimitiveVoid(DiscoveryIssueReporter issueReporter, Function annotationNameProvider) { - return issueReporter.createReportingCondition(ReflectionUtils::returnsPrimitiveVoid, method -> { + return issueReporter.createReportingCondition(method -> getReturnType(method) == void.class, method -> { String message = String.format("@%s method '%s' must not return a value.", annotationNameProvider.apply(method), method.toGenericString()); return createIssue(Severity.ERROR, message, method); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java index 144ec6db621c..07fbcc51a80c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java @@ -11,6 +11,8 @@ package org.junit.jupiter.engine.discovery.predicates; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.junit.jupiter.engine.support.MethodReflectionUtils.getGenericReturnType; +import static org.junit.jupiter.engine.support.MethodReflectionUtils.getReturnType; import static org.junit.platform.commons.util.CollectionUtils.isConvertibleToStream; import java.lang.annotation.Annotation; @@ -53,7 +55,7 @@ private static DiscoveryIssueReporter.Condition hasCompatibleReturnType( } private static boolean isCompatible(Method method, DiscoveryIssueReporter issueReporter) { - Class returnType = method.getReturnType(); + Class returnType = getReturnType(method); if (DynamicNode.class.isAssignableFrom(returnType) || DynamicNode[].class.isAssignableFrom(returnType)) { return true; } @@ -66,7 +68,7 @@ private static boolean isCompatible(Method method, DiscoveryIssueReporter issueR } private static boolean isCompatibleContainerType(Method method, DiscoveryIssueReporter issueReporter) { - Type genericReturnType = method.getGenericReturnType(); + Type genericReturnType = getGenericReturnType(method); if (genericReturnType instanceof ParameterizedType) { Type[] typeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java index 498d04e62992..089fef2e4bbc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.discovery.predicates; +import static org.junit.jupiter.engine.support.MethodReflectionUtils.getReturnType; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import java.lang.annotation.Annotation; @@ -18,7 +19,6 @@ import java.util.function.Predicate; import org.junit.platform.commons.support.ModifierSupport; -import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.support.descriptor.MethodSource; @@ -71,7 +71,7 @@ private static Condition isNotAbstract(Class annot protected static Condition hasVoidReturnType(Class annotationType, DiscoveryIssueReporter issueReporter) { - return issueReporter.createReportingCondition(ReflectionUtils::returnsPrimitiveVoid, + return issueReporter.createReportingCondition(method -> getReturnType(method) == void.class, method -> createIssue(annotationType, method, "must not return a value")); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java index 226db46cf82d..122c122030eb 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java @@ -21,6 +21,7 @@ import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; +import org.junit.jupiter.engine.support.MethodReflectionUtils; import org.junit.platform.commons.util.ReflectionUtils; /** @@ -48,7 +49,7 @@ public T invoke(Constructor constructor, Object outerInstance) { public Object invoke(Method method, Object target) { Object[] arguments = resolveParameters(method, Optional.ofNullable(target), extensionContext, extensionRegistry); - return ReflectionUtils.invokeMethod(method, target, arguments); + return MethodReflectionUtils.invoke(method, target, arguments); } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java index fb3f2e0c2810..5d42c754d1ba 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java @@ -19,7 +19,7 @@ import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; -import org.junit.platform.commons.support.ReflectionSupport; +import org.junit.jupiter.engine.support.MethodReflectionUtils; class MethodInvocation implements Invocation, ReflectiveInvocationContext { @@ -57,7 +57,8 @@ public List getArguments() { @Override @SuppressWarnings("unchecked") public T proceed() { - return (T) ReflectionSupport.invokeMethod(this.method, this.target.orElse(null), this.arguments); + var actualTarget = this.target.orElse(null); + return (T) MethodReflectionUtils.invoke(this.method, actualTarget, this.arguments); } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java index 65a4ddc0d38d..92f9cd7c7bf7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java @@ -13,6 +13,8 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; +import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionParameters; +import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinSuspendingFunction; import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; import java.lang.reflect.Constructor; @@ -61,7 +63,10 @@ public class ParameterResolutionUtils { public static Object[] resolveParameters(Method method, Optional target, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { - return resolveParameters(method, target, Optional.empty(), extensionContext, extensionRegistry); + return resolveParameters(method, target, Optional.empty(), __ -> extensionContext, extensionRegistry, + isKotlinSuspendingFunction(method) // + ? getKotlinSuspendingFunctionParameters(method) // + : method.getParameters()); } /** @@ -90,9 +95,16 @@ public static Object[] resolveParameters(Executable executable, Optional Optional outerInstance, ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry) { + return resolveParameters(executable, target, outerInstance, extensionContext, extensionRegistry, + executable.getParameters()); + } + + private static Object[] resolveParameters(Executable executable, Optional target, + Optional outerInstance, ExtensionContextSupplier extensionContext, + ExtensionRegistry extensionRegistry, Parameter[] parameters) { + Preconditions.notNull(target, "target must not be null"); - Parameter[] parameters = executable.getParameters(); Object[] values = new Object[parameters.length]; int start = 0; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java new file mode 100644 index 000000000000..1a9d753d305e --- /dev/null +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java @@ -0,0 +1,46 @@ +/* + * 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.support; + +import static org.apiguardian.api.API.Status.INTERNAL; +import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionGenericReturnType; +import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionReturnType; +import static org.junit.platform.commons.util.KotlinReflectionUtils.invokeKotlinSuspendingFunction; +import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinSuspendingFunction; + +import java.lang.reflect.Method; +import java.lang.reflect.Type; + +import org.apiguardian.api.API; +import org.junit.platform.commons.support.ReflectionSupport; + +@API(status = INTERNAL, since = "6.0") +public class MethodReflectionUtils { + + public static Class getReturnType(Method method) { + return isKotlinSuspendingFunction(method) // + ? getKotlinSuspendingFunctionReturnType(method) // + : method.getReturnType(); + } + + public static Type getGenericReturnType(Method method) { + return isKotlinSuspendingFunction(method) // + ? getKotlinSuspendingFunctionGenericReturnType(method) // + : method.getGenericReturnType(); + } + + public static Object invoke(Method method, Object target, Object[] arguments) { + if (isKotlinSuspendingFunction(method)) { + return invokeKotlinSuspendingFunction(method, target, arguments); + } + return ReflectionSupport.invokeMethod(method, target, arguments); + } +} diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java index f73fff4e1e23..58b022d3f17a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java @@ -12,7 +12,6 @@ import static java.util.Collections.emptyList; import static java.util.Collections.reverse; -import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedMethods; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; @@ -34,7 +33,6 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.support.HierarchyTraversalMode; -import org.junit.platform.commons.support.ModifierSupport; import org.junit.platform.commons.util.ReflectionUtils; class ParameterizedClassContext implements ParameterizedDeclarationContext { @@ -155,9 +153,6 @@ private static List findLifec List methods = findAnnotatedMethods(testClass, annotationType, traversalMode); return methods.stream() // - .filter(ModifierSupport::isNotPrivate) // - .filter(testInstanceLifecycle == PER_METHOD ? ModifierSupport::isStatic : __ -> true) // - .filter(ReflectionUtils::returnsPrimitiveVoid) // .map(method -> { A annotation = getAnnotation(method, annotationType); if (injectArgumentsPredicate.test(annotation)) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index a1cad8e98419..2ca2590df654 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -18,6 +18,8 @@ import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import static org.junit.platform.commons.support.ReflectionSupport.makeAccessible; +import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionParameters; +import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinSuspendingFunction; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import java.lang.annotation.Annotation; @@ -107,6 +109,9 @@ static ResolverFacade create(Constructor constructor, ParameterizedClass anno } static ResolverFacade create(Method method, Annotation annotation) { + if (isKotlinSuspendingFunction(method)) { + return create(method, annotation, 0, getKotlinSuspendingFunctionParameters(method)); + } return create(method, annotation, 0); } @@ -124,9 +129,13 @@ static ResolverFacade create(Method method, Annotation annotation) { * */ private static ResolverFacade create(Executable executable, Annotation annotation, int indexOffset) { + return create(executable, annotation, indexOffset, executable.getParameters()); + } + + private static ResolverFacade create(Executable executable, Annotation annotation, int indexOffset, + java.lang.reflect.Parameter[] parameters) { NavigableMap indexedParameters = new TreeMap<>(); NavigableMap aggregatorParameters = new TreeMap<>(); - java.lang.reflect.Parameter[] parameters = executable.getParameters(); for (int index = indexOffset; index < parameters.length; index++) { ExecutableParameterDeclaration declaration = new ExecutableParameterDeclaration(parameters[index], index, indexOffset); diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 57f328bc14c6..3ba44841ada3 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -1,5 +1,7 @@ +import junitbuild.extensions.javaModuleName + plugins { - id("junitbuild.java-library-conventions") + id("junitbuild.kotlin-library-conventions") `java-test-fixtures` } @@ -9,8 +11,30 @@ dependencies { api(platform(projects.junitBom)) compileOnlyApi(libs.apiguardian) + + compileOnly(kotlin("stdlib")) + compileOnly(kotlin("reflect")) + compileOnly(libs.kotlinx.coroutines) } tasks.compileJava { options.compilerArgs.add("-Xlint:-module") // due to qualified exports + val moduleName = javaModuleName + val mainOutput = files(sourceSets.main.get().output) + options.compilerArgumentProviders.add(CommandLineArgumentProvider { + listOf("--patch-module", "${moduleName}=${mainOutput.asPath}") + }) +} + +tasks.jar { + bundle { + val importAPIGuardian: String by extra + bnd(""" + Import-Package: \ + $importAPIGuardian,\ + kotlin.*;resolution:="optional",\ + kotlinx.*;resolution:="optional",\ + * + """) + } } diff --git a/junit-platform-commons/src/main/java/module-info.java b/junit-platform-commons/src/main/java/module-info.java index 87897929f227..2cb4016429a3 100644 --- a/junit-platform-commons/src/main/java/module-info.java +++ b/junit-platform-commons/src/main/java/module-info.java @@ -18,6 +18,10 @@ requires java.management; // needed by RuntimeUtils to determine input arguments requires static transitive org.apiguardian.api; + requires static kotlin.stdlib; + requires static kotlin.reflect; + requires static kotlinx.coroutines.core; + exports org.junit.platform.commons; exports org.junit.platform.commons.annotation; exports org.junit.platform.commons.function; 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..8d897ed77751 --- /dev/null +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinReflectionUtils.java @@ -0,0 +1,113 @@ +/* + * 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.tryToLoadClass; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.lang.reflect.Type; + +import org.apiguardian.api.API; +import org.junit.platform.commons.function.Try; + +/** + * Internal Kotlin-specific reflection utilities + * + * @since 6.0 + */ +@API(status = INTERNAL, since = "6.0") +public class KotlinReflectionUtils { + + private static final Class kotlinMetadata; + private static final Class kotlinCoroutineContinuation; + private static final boolean kotlinReflectPresent; + private static final boolean kotlinxCoroutinesPresent; + + static { + var metadata = tryToLoadKotlinMetadataClass(); + kotlinMetadata = metadata.toOptional().orElse(null); + kotlinCoroutineContinuation = metadata // + .andThen(__ -> tryToLoadClass("kotlin.coroutines.Continuation")) // + .toOptional() // + .orElse(null); + kotlinReflectPresent = metadata.andThen(__ -> tryToLoadClass("kotlin.reflect.jvm.ReflectJvmMapping")) // + .toOptional() // + .isPresent(); + kotlinxCoroutinesPresent = metadata.andThen(__ -> tryToLoadClass("kotlinx.coroutines.BuildersKt")) // + .toOptional() // + .isPresent(); + } + + @SuppressWarnings("unchecked") + private static Try> tryToLoadKotlinMetadataClass() { + return tryToLoadClass("kotlin.Metadata") // + .andThenTry(it -> (Class) it); + } + + public static boolean isKotlinSuspendingFunction(Method method) { + if (kotlinCoroutineContinuation != null && isKotlinType(method.getDeclaringClass())) { + int parameterCount = method.getParameterCount(); + return parameterCount > 0 // + && method.getParameterTypes()[parameterCount - 1] == kotlinCoroutineContinuation; + } + return false; + } + + private static boolean isKotlinType(Class clazz) { + return kotlinMetadata != null // + && clazz.getDeclaredAnnotation(kotlinMetadata) != null; + } + + public static Class getKotlinSuspendingFunctionReturnType(Method method) { + requireKotlinReflect(method); + return KotlinReflectionUtilsKt.getReturnType(method); + } + + public static Type getKotlinSuspendingFunctionGenericReturnType(Method method) { + requireKotlinReflect(method); + return KotlinReflectionUtilsKt.getGenericReturnType(method); + } + + public static Parameter[] getKotlinSuspendingFunctionParameters(Method method) { + requireKotlinReflect(method); + return KotlinReflectionUtilsKt.getParameters(method); + } + + public static Class[] getKotlinSuspendingFunctionParameterTypes(Method method) { + requireKotlinReflect(method); + return KotlinReflectionUtilsKt.getParameterTypes(method); + } + + public static Object invokeKotlinSuspendingFunction(Method method, Object target, Object[] args) { + requireKotlinReflect(method); + requireKotlinxCoroutines(method); + return KotlinReflectionUtilsKt.invoke(method, target, args); + } + + private static void requireKotlinReflect(Method method) { + requireDependency(method, kotlinReflectPresent, "org.jetbrains.kotlin:kotlin-reflect"); + } + + private static void requireKotlinxCoroutines(Method method) { + requireDependency(method, kotlinxCoroutinesPresent, "org.jetbrains.kotlinx:kotlinx-coroutines-core"); + } + + private static void requireDependency(Method method, boolean condition, String dependencyNotation) { + Preconditions.condition(condition, + () -> ("Kotlin suspending function [%s] requires %s to be on the classpath or module path. " + + "Please add a corresponding dependency.").formatted(method.toGenericString(), + dependencyNotation)); + } + +} diff --git a/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt b/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt new file mode 100644 index 000000000000..4bd3fe0d53ce --- /dev/null +++ b/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt @@ -0,0 +1,59 @@ +/* + * 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 + */ +@file:JvmName("KotlinReflectionUtilsKt") + +package org.junit.platform.commons.util + +import kotlinx.coroutines.runBlocking +import java.lang.reflect.InvocationTargetException +import java.lang.reflect.Method +import kotlin.reflect.full.callSuspend +import kotlin.reflect.full.valueParameters +import kotlin.reflect.jvm.javaType +import kotlin.reflect.jvm.jvmErasure +import kotlin.reflect.jvm.kotlinFunction + +internal fun getReturnType(method: Method): Class = + with(method.kotlinFunction!!.returnType.jvmErasure) { + if (this == Unit::class) { + Void.TYPE + } else { + java + } + } + +internal fun getGenericReturnType(method: Method) = method.kotlinFunction!!.returnType.javaType + +internal fun getParameterTypes(method: Method) = + method.kotlinFunction!! + .parameters + .map { it.type.jvmErasure.java } + .toTypedArray() + +internal fun getParameters(method: Method) = + method.kotlinFunction!!.valueParameters.size.let { + if (it > 0) { + method.parameters.copyOf(it) + } else { + emptyArray() + } + } + +internal fun invoke( + method: Method, + target: Any?, + vararg args: Any? +) = runBlocking { + try { + method.kotlinFunction!!.callSuspend(target, *args) + } catch (e: InvocationTargetException) { + throw e.targetException + } +} diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index 65d6c003fde8..4bdc51103c64 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -59,6 +59,7 @@ tasks { Import-Package: \ $importAPIGuardian,\ kotlin.*;resolution:="optional",\ + kotlinx.*;resolution:="optional",\ * # Disable the APIGuardian plugin since everything was already # processed, again because this is an aggregate jar diff --git a/jupiter-tests/jupiter-tests.gradle.kts b/jupiter-tests/jupiter-tests.gradle.kts index 061920f4d96d..dadeecfea33b 100644 --- a/jupiter-tests/jupiter-tests.gradle.kts +++ b/jupiter-tests/jupiter-tests.gradle.kts @@ -25,6 +25,8 @@ dependencies { testImplementation(testFixtures(projects.junitJupiterEngine)) testImplementation(testFixtures(projects.junitPlatformLauncher)) testImplementation(testFixtures(projects.junitPlatformReporting)) + + testRuntimeOnly(kotlin("reflect")) } tasks { 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 35a2e8941a73..d28bd80b4b27 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 kotlin.jvm.JvmClassMappingKt.getJavaClass; 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; @@ -29,6 +30,8 @@ import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; +import kotlin.reflect.KClass; + /** * Abstract base class for tests involving the {@link JupiterTestEngine}. * @@ -38,6 +41,10 @@ public abstract class AbstractJupiterTestEngineTests { private final JupiterTestEngine engine = new JupiterTestEngine(); + protected EngineExecutionResults executeTestsForClass(KClass testClass) { + return executeTestsForClass(getJavaClass(testClass)); + } + protected EngineExecutionResults executeTestsForClass(Class testClass) { return executeTests(selectClass(testClass)); } diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinSuspendFunctionsTests.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinSuspendFunctionsTests.kt new file mode 100644 index 000000000000..c5b0c742c186 --- /dev/null +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinSuspendFunctionsTests.kt @@ -0,0 +1,190 @@ +/* + * 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 + +import kotlinx.coroutines.runBlocking +import org.assertj.core.api.Assertions.assertThat +import org.junit.jupiter.api.DynamicTest.dynamicTest +import org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS +import org.junit.jupiter.engine.AbstractJupiterTestEngineTests +import org.junit.jupiter.params.AfterParameterizedClassInvocation +import org.junit.jupiter.params.BeforeParameterizedClassInvocation +import org.junit.jupiter.params.Parameter +import org.junit.jupiter.params.ParameterizedClass +import org.junit.jupiter.params.ParameterizedTest +import org.junit.jupiter.params.provider.ValueSource +import org.junit.platform.engine.reporting.ReportEntry +import org.junit.platform.testkit.engine.EngineExecutionResults +import java.util.stream.Stream + +class KotlinSuspendFunctionsTests : AbstractJupiterTestEngineTests() { + @Test + fun suspendingTestMethodsAreSupported() { + val results = executeTestsForClass(TestMethodTestCase::class) + assertAllTestsPassed(results, 1) + assertThat(getPublishedEvents(results)).containsExactly("test") + } + + @Test + fun suspendingTestTemplateMethodsAreSupported() { + val results = executeTestsForClass(TestTemplateTestCase::class) + assertAllTestsPassed(results, 2) + assertThat(getPublishedEvents(results)).containsExactly("foo", "bar") + } + + @Test + fun suspendingTestFactoryMethodsAreSupported() { + val results = executeTestsForClass(TestFactoryTestCase::class) + assertAllTestsPassed(results, 2) + assertThat(getPublishedEvents(results)).containsExactly("test", "foo", "bar") + } + + @Test + fun suspendingLifecycleMethodsAreSupported() { + val results = executeTestsForClass(LifecycleMethodsTestCase::class) + assertAllTestsPassed(results, 1) + assertThat(getPublishedEvents(results)).containsExactly("beforeAll", "beforeEach", "test", "afterEach", "afterAll") + } + + @Test + fun suspendingParameterizedLifecycleMethodsAreSupported() { + val results = executeTestsForClass(ParameterizedLifecycleMethodsTestCase::class) + assertAllTestsPassed(results, 2) + assertThat( + getPublishedEvents(results) + ).containsExactly("beforeInvocation[1]", "test[1]", "afterInvocation[1]", "beforeInvocation[2]", "test[2]", "afterInvocation[2]") + } + + private fun assertAllTestsPassed( + results: EngineExecutionResults, + numTests: Long + ) { + results.testEvents().assertStatistics { + it.started(numTests).succeeded(numTests) + } + } + + private fun getPublishedEvents(results: EngineExecutionResults) = + results + .allEvents() + .reportingEntryPublished() // + .map { it.getRequiredPayload(ReportEntry::class.java) } // + .map(ReportEntry::getKeyValuePairs) + .map { it["value"] } + + @Suppress("JUnitMalformedDeclaration") + class TestMethodTestCase { + @Test + suspend fun test(reporter: TestReporter) { + suspendingPublish(reporter, "test") + } + } + + @Suppress("JUnitMalformedDeclaration") + class TestTemplateTestCase { + @ParameterizedTest + @ValueSource(strings = ["foo", "bar"]) + suspend fun test( + message: String, + reporter: TestReporter + ) { + suspendingPublish(reporter, message) + } + } + + class TestFactoryTestCase { + @TestFactory + suspend fun test(reporter: TestReporter): Stream { + suspendingPublish(reporter, "test") + return Stream.of("foo", "bar").map { + dynamicTest(it) { + runBlocking { + suspendingPublish(reporter, it) + } + } + } + } + } + + @Suppress("JUnitMalformedDeclaration") + @TestInstance(PER_CLASS) + class LifecycleMethodsTestCase { + @BeforeAll + suspend fun beforeAll(reporter: TestReporter) { + suspendingPublish(reporter, "beforeAll") + } + + @BeforeEach + suspend fun beforeEach(reporter: TestReporter) { + suspendingPublish(reporter, "beforeEach") + } + + @Test + suspend fun test(reporter: TestReporter) { + suspendingPublish(reporter, "test") + } + + @AfterEach + suspend fun afterEach(reporter: TestReporter) { + suspendingPublish(reporter, "afterEach") + } + + @AfterAll + suspend fun afterAll(reporter: TestReporter) { + suspendingPublish(reporter, "afterAll") + } + } + + @Suppress("JUnitMalformedDeclaration", "RedundantSuspendModifier") + @ParameterizedClass + @ValueSource(ints = [1, 2]) + @TestInstance(PER_CLASS) + class ParameterizedLifecycleMethodsTestCase { + @BeforeParameterizedClassInvocation + suspend fun beforeInvocation() {} + + @BeforeParameterizedClassInvocation + suspend fun beforeInvocation( + parameter: Int, + reporter: TestReporter + ) { + suspendingPublish(reporter, "beforeInvocation[$parameter]") + } + + @AfterParameterizedClassInvocation + suspend fun afterInvocation() {} + + @AfterParameterizedClassInvocation + suspend fun afterInvocation( + parameter: Int, + reporter: TestReporter + ) { + suspendingPublish(reporter, "afterInvocation[$parameter]") + } + + @Parameter + var parameter: Int = 0 + + @Test + suspend fun test(reporter: TestReporter) { + suspendingPublish(reporter, "test[$parameter]") + } + } + + @Suppress("RedundantSuspendModifier") + companion object { + suspend fun suspendingPublish( + reporter: TestReporter, + message: String + ) { + reporter.publishEntry(message) + } + } +} diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt index 040ca4b3525e..0022a3df70bc 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt @@ -8,6 +8,9 @@ exports org.junit.platform.commons.support.scanning requires java.base mandated requires java.logging requires java.management +requires kotlin.reflect static +requires kotlin.stdlib static +requires kotlinx.coroutines.core static requires org.apiguardian.api static transitive uses org.junit.platform.commons.support.scanning.ClasspathScanner qualified exports org.junit.platform.commons.logging to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.suite.api org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts new file mode 100644 index 000000000000..602d9fadc900 --- /dev/null +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts @@ -0,0 +1,37 @@ +plugins { + kotlin("jvm") version "2.1.20" +} + +val junitVersion: String by project + +repositories { + maven { url = uri(file(System.getProperty("maven.repo"))) } + mavenCentral() +} + +dependencies { + testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + if (!project.hasProperty("withoutKotlinReflect")) { + testImplementation(kotlin("reflect")) + } + + if (!project.hasProperty("withoutKotlinxCoroutines")) { + testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.2") + } +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } +} + +tasks.test { + useJUnitPlatform() + testLogging { + exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL + } + systemProperty("junit.platform.stacktrace.pruning.enabled", "false") +} diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts new file mode 100644 index 000000000000..2e3f2dee51af --- /dev/null +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts @@ -0,0 +1,5 @@ +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" +} + +rootProject.name = "kotlin-coroutines" diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/src/test/kotlin/com/example/project/SuspendFunctionTests.kt b/platform-tooling-support-tests/projects/kotlin-coroutines/src/test/kotlin/com/example/project/SuspendFunctionTests.kt new file mode 100644 index 000000000000..6c0e8a9b9149 --- /dev/null +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/src/test/kotlin/com/example/project/SuspendFunctionTests.kt @@ -0,0 +1,20 @@ +/* + * 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 com.example.project + +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.fail + +class SuspendFunctionTests { + @Test + suspend fun test() { + fail("expected") + } +} diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index abaaee787a29..c54641f46604 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -17,6 +17,7 @@ import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAnyPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleName; +import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleNameEndingWith; import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC; import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier; import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name; @@ -61,6 +62,8 @@ class ArchUnitTests { .and(TOP_LEVEL_CLASSES) // .and(not(ANONYMOUS_CLASSES)) // .and(not(describe("are Kotlin SAM type implementations", simpleName("")))) // + .and(not(describe("are Kotlin-generated classes that contain only top-level functions", + simpleNameEndingWith("Kt")))) // .and(not(describe("are shadowed", resideInAnyPackage("..shadow..")))) // .should().beAnnotatedWith(API.class); diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/KotlinCoroutinesTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/KotlinCoroutinesTests.java new file mode 100644 index 000000000000..94f95d669a3e --- /dev/null +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/KotlinCoroutinesTests.java @@ -0,0 +1,83 @@ +/* + * 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 platform.tooling.support.tests; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static platform.tooling.support.tests.Projects.copyToWorkspace; + +import java.io.IOException; +import java.nio.file.Path; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.junit.platform.tests.process.OutputFiles; +import org.junit.platform.tests.process.ProcessResult; +import org.opentest4j.TestAbortedException; + +import platform.tooling.support.Helper; +import platform.tooling.support.MavenRepo; +import platform.tooling.support.ProcessStarters; + +/** + * @since 6.0 + */ +class KotlinCoroutinesTests { + + @Test + void failsExpectedlyWhenAllOptionalDependenciesArePresent(@TempDir Path workspace, + @FilePrefix("gradle") OutputFiles outputFiles) throws Exception { + var result = runBuild(workspace, outputFiles); + + assertEquals(1, result.exitCode(), "result=" + result); + assertThat(result.stdOut()).contains("AssertionFailedError: expected"); + assertThat(result.stdErr()).contains("BUILD FAILED"); + } + + @Test + void failsWithHelpfulErrorMessageWhenKotlinxCoroutinesIsMissing(@TempDir Path workspace, + @FilePrefix("gradle") OutputFiles outputFiles) throws Exception { + var result = runBuild(workspace, outputFiles, "-PwithoutKotlinxCoroutines"); + + assertEquals(1, result.exitCode(), "result=" + result); + assertThat(result.stdOut()).contains("PreconditionViolationException: Kotlin suspending function " + + "[public final java.lang.Object com.example.project.SuspendFunctionTests.test(kotlin.coroutines.Continuation)] " + + "requires org.jetbrains.kotlinx:kotlinx-coroutines-core to be on the classpath or module path. " + + "Please add a corresponding dependency."); + assertThat(result.stdErr()).contains("BUILD FAILED"); + } + + @Test + void failsWithHelpfulErrorMessageWhenKotlinReflectIsMissing(@TempDir Path workspace, + @FilePrefix("gradle") OutputFiles outputFiles) throws Exception { + var result = runBuild(workspace, outputFiles, "-PwithoutKotlinReflect"); + + assertEquals(1, result.exitCode(), "result=" + result); + assertThat(result.stdOut()).contains("PreconditionViolationException: Kotlin suspending function " + + "[public final java.lang.Object com.example.project.SuspendFunctionTests.test(kotlin.coroutines.Continuation)] " + + "requires org.jetbrains.kotlin:kotlin-reflect to be on the classpath or module path. " + + "Please add a corresponding dependency."); + assertThat(result.stdErr()).contains("BUILD FAILED"); + } + + private static ProcessResult runBuild(Path workspace, OutputFiles outputFiles, String... extraArgs) + throws InterruptedException, IOException { + + return ProcessStarters.gradlew() // + .workingDir(copyToWorkspace(Projects.KOTLIN_COROUTINES, workspace)) // + .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // + .addArguments("build", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail") // + .addArguments(extraArgs).putEnvironment("JDK17", + Helper.getJavaHome(17).orElseThrow(TestAbortedException::new).toString()) // + .redirectOutput(outputFiles) // + .startAndWait(); + } +} diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java index b3edd252e4fa..63b4588d2650 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/Projects.java @@ -22,6 +22,7 @@ public class Projects { public static final String GRADLE_MISSING_ENGINE = "gradle-missing-engine"; public static final String JAR_DESCRIBE_MODULE = "jar-describe-module"; public static final String JUPITER_STARTER = "jupiter-starter"; + public static final String KOTLIN_COROUTINES = "kotlin-coroutines"; public static final String MAVEN_SUREFIRE_COMPATIBILITY = "maven-surefire-compatibility"; public static final String MULTI_RELEASE_JAR = "multi-release-jar"; public static final String REFLECTION_TESTS = "reflection-tests"; From 0b6f60ae73f8db8d100e738441df8aa5e0cfa8f5 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 16 May 2025 15:46:36 +0200 Subject: [PATCH 052/521] Deprecate pre-17 `JRE` enum constants and remove unnecessary reflection * Remove unnecessary reflection in `JRE` enum * Deprecate `JRE.JAVA_8`...`JAVA_16` * Remove obsolete references to `JRE.UNDEFINED` --- .../release-notes/release-notes-6.0.0-M1.adoc | 7 ++ .../example/ConditionalTestExecutionDemo.java | 33 +++--- .../generator/GenerateJreRelatedSourceCode.kt | 8 +- .../condition/AbstractJreRangeCondition.java | 9 +- .../api/condition/DisabledForJreRange.java | 2 +- .../api/condition/EnabledForJreRange.java | 2 +- .../junit/jupiter/api/condition/JRE.java.jte | 101 ++++++------------ .../condition/JavaVersionPredicates.java.jte | 6 +- .../DisabledOnJreConditionTests.java.jte | 10 +- .../DisabledOnJreIntegrationTests.java.jte | 33 +++--- .../EnabledOnJreConditionTests.java.jte | 10 +- .../EnabledOnJreIntegrationTests.java.jte | 33 +++--- .../DisabledForJreRangeConditionTests.java | 29 ++--- .../DisabledForJreRangeIntegrationTests.java | 38 +++---- .../EnabledForJreRangeConditionTests.java | 38 +++---- .../EnabledForJreRangeIntegrationTests.java | 46 +++----- 16 files changed, 165 insertions(+), 240 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index cae381374e60..fb2d3e95dc31 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -92,6 +92,13 @@ repository on GitHub. - `InvocationInterceptor.interceptDynamicTest(Invocation, ExtensionContext)` method * The deprecated `junit.jupiter.tempdir.scope` configuration parameter is no longer supported. +* The `JRE` enum constants for `JAVA_8` to `JAVA_16` have been deprecated because they can + no longer be used at runtime since `JAVA_17` is the new baseline. Please also check for + values less than 17 used with the `minVersion` and `maxVersion` attributes of + `@EnabledForJreRange` nad `@DisabledForJreRange` or the `versions` attribute of + `@EnabledOnJre` and `@DisabledOnJre`. +* `@EnabledForJreRange` and `@DisabledForJreRange` now use `JAVA_17` as their default + `min` value. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/test/java/example/ConditionalTestExecutionDemo.java b/documentation/src/test/java/example/ConditionalTestExecutionDemo.java index ef18bb5ddff6..0bd278ddc9c1 100644 --- a/documentation/src/test/java/example/ConditionalTestExecutionDemo.java +++ b/documentation/src/test/java/example/ConditionalTestExecutionDemo.java @@ -10,10 +10,11 @@ package example; -import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_17; +import static org.junit.jupiter.api.condition.JRE.JAVA_18; +import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_21; -import static org.junit.jupiter.api.condition.JRE.JAVA_9; +import static org.junit.jupiter.api.condition.JRE.JAVA_25; import static org.junit.jupiter.api.condition.OS.LINUX; import static org.junit.jupiter.api.condition.OS.MAC; import static org.junit.jupiter.api.condition.OS.WINDOWS; @@ -113,44 +114,44 @@ void onJava17And21() { } @Test - @EnabledForJreRange(min = JAVA_9, max = JAVA_11) - void fromJava9To11() { + @EnabledForJreRange(min = JAVA_21, max = JAVA_25) + void fromJava21To25() { // ... } @Test - @EnabledForJreRange(min = JAVA_9) - void onJava9AndHigher() { + @EnabledForJreRange(min = JAVA_21) + void onJava21ndHigher() { // ... } @Test - @EnabledForJreRange(max = JAVA_11) - void fromJava8To11() { + @EnabledForJreRange(max = JAVA_18) + void fromJava17To18() { // ... } @Test - @DisabledOnJre(JAVA_9) - void notOnJava9() { + @DisabledOnJre(JAVA_19) + void notOnJava19() { // ... } @Test - @DisabledForJreRange(min = JAVA_9, max = JAVA_11) - void notFromJava9To11() { + @DisabledForJreRange(min = JAVA_17, max = JAVA_17) + void notFromJava17To19() { // ... } @Test - @DisabledForJreRange(min = JAVA_9) - void notOnJava9AndHigher() { + @DisabledForJreRange(min = JAVA_19) + void notOnJava19AndHigher() { // ... } @Test - @DisabledForJreRange(max = JAVA_11) - void notFromJava8To11() { + @DisabledForJreRange(max = JAVA_18) + void notFromJava17To18() { // ... } // end::user_guide_jre[] diff --git a/gradle/plugins/code-generator/src/main/kotlin/junitbuild/generator/GenerateJreRelatedSourceCode.kt b/gradle/plugins/code-generator/src/main/kotlin/junitbuild/generator/GenerateJreRelatedSourceCode.kt index b76ad39345d6..70f51a6d5f9f 100644 --- a/gradle/plugins/code-generator/src/main/kotlin/junitbuild/generator/GenerateJreRelatedSourceCode.kt +++ b/gradle/plugins/code-generator/src/main/kotlin/junitbuild/generator/GenerateJreRelatedSourceCode.kt @@ -57,9 +57,13 @@ abstract class GenerateJreRelatedSourceCode : DefaultTask() { mapper.registerModule(KotlinModule.Builder().build()) mapper.readValue(input, object : TypeReference>() {}) } + val minRuntimeVersion = 17 + val supportedJres = jres.filter { it.version >= minRuntimeVersion } val params = mapOf( - "jres" to jres, - "jresSortedByStringValue" to jres.sortedBy { it.version.toString() }, + "minRuntimeVersion" to minRuntimeVersion, + "allJres" to jres, + "supportedJres" to supportedJres, + "supportedJresSortedByStringValue" to supportedJres.sortedBy { it.version.toString() }, "licenseHeader" to licenseHeaderFile.asFile.get().readText() ) templates.forEach { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java index 7bc7d8a0b117..df6675e8485f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java @@ -26,6 +26,9 @@ */ abstract class AbstractJreRangeCondition extends BooleanExecutionCondition { + private static final JRE DEFAULT_MINIMUM_JRE = JRE.JAVA_17; + private static final JRE DEFAULT_MAXIMUM_JRE = JRE.OTHER; + private final String annotationName; AbstractJreRangeCondition(Class annotationType, Function customDisabledReason) { @@ -58,17 +61,17 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int // Now that we have checked the basic preconditions, we need to ensure that we are // using valid JRE enum constants. if (!minJreSet) { - minJre = JRE.JAVA_8; + minJre = DEFAULT_MINIMUM_JRE; } if (!maxJreSet) { - maxJre = JRE.OTHER; + maxJre = DEFAULT_MAXIMUM_JRE; } int min = (minVersionSet ? minVersion : minJre.version()); int max = (maxVersionSet ? maxVersion : maxJre.version()); // Finally, we need to validate the effective minimum and maximum values. - Preconditions.condition((min != JRE.MINIMUM_VERSION || max != Integer.MAX_VALUE), + Preconditions.condition((min != DEFAULT_MINIMUM_JRE.version() || max != DEFAULT_MAXIMUM_JRE.version()), () -> "You must declare a non-default value for the minimum or maximum value in @" + this.annotationName); Preconditions.condition(min <= max, () -> String.format("@%s's minimum value [%d] must be less than or equal to its maximum value [%d]", 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..a20d2d49db49 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 @@ -96,7 +96,7 @@ * {@link #minVersion() minVersion} instead. * *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted - * as {@link JRE#JAVA_8 JAVA_8} if the {@link #minVersion() minVersion} is + * as {@link JRE#JAVA_17 JAVA_17} if the {@link #minVersion() minVersion} is * not set. * * @see JRE 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..b1f3d4cfd7e0 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 @@ -96,7 +96,7 @@ * {@link #minVersion() minVersion} instead. * *

Defaults to {@link JRE#UNDEFINED UNDEFINED}, which will be interpreted - * as {@link JRE#JAVA_8 JAVA_8} if the {@link #minVersion() minVersion} is + * as {@link JRE#JAVA_17 JAVA_17} if the {@link #minVersion() minVersion} is * not set. * * @see JRE 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..005f728acf0e 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 @@ -2,7 +2,8 @@ @import gg.jte.support.ForSupport @import junitbuild.generator.model.JRE -@param List jres +@param int minRuntimeVersion +@param List allJres @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; @@ -11,26 +12,17 @@ import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; -import java.lang.reflect.Method; - import org.apiguardian.api.API; -import org.junit.platform.commons.logging.Logger; -import org.junit.platform.commons.logging.LoggerFactory; -import org.junit.platform.commons.support.ReflectionSupport; -import org.junit.platform.commons.util.StringUtils; /** * Enumeration of Java Runtime Environment (JRE) versions. * *

If the current JRE version can be detected but is not one of the predefined * constants in this enum, {@link #OTHER} will be considered to be the - * {@linkplain #isCurrentVersion current JRE version}. If the current JRE version - * cannot be detected — for example, if the {@code java.version} JVM system - * property is undefined — {@link #UNDEFINED} will be considered to be the - * current JRE version. + * {@linkplain #isCurrentVersion current JRE version}. * * @since 5.1 -@for(JRE jre : jres)<%-- +@for(JRE jre : allJres)<%-- --%> * @see #JAVA_${jre.getVersion()} @endfor<%-- --%> * @see #OTHER @@ -54,22 +46,30 @@ public enum JRE { */ @API(status = EXPERIMENTAL, since = "5.12") UNDEFINED(-1), -@for(var jre : jres) +@for(var jre : allJres) /** * Java ${jre.getVersion()}. - @if(jre.getSince() != null)<%-- + @if(jre.getSince() != null || jre.getVersion() < minRuntimeVersion)<%-- --%> * - * @since ${jre.getSince()} + @endif<%-- +--%>@if(jre.getSince() != null)<%-- +--%> * @since ${jre.getSince()} + @endif<%-- +--%>@if(jre.getVersion() < minRuntimeVersion)<%-- +--%> * @deprecated No longer supported at runtime; please use {@link #JAVA_17} or later @endif<%-- --%> */ - @if(jre.getSince() != null)<%-- + @if(jre.getVersion() < minRuntimeVersion)<%-- +--%>@API(status = DEPRECATED, since = "6.0") // + @Deprecated(since = "6.0", forRemoval = true) + @elseif(jre.getSince() != null)<%-- --%>@API(status = STABLE, since = "${jre.getSince()}") @endif<%-- --%>JAVA_${jre.getVersion()}(${jre.getVersion()}), @endfor /** * A JRE version other than <%-- ---%>@for(var jre : ForSupport.of(jres))<%-- +--%>@for(var jre : ForSupport.of(allJres))<%-- --%>@if(jre.isLast())or @endif<%-- --%>{@link #JAVA_${jre.get().getVersion()}}<%-- --%>@if(jre.isLast()).@else,@endif<%-- @@ -85,59 +85,13 @@ public enum JRE { static final int UNDEFINED_VERSION = -1; - static final int MINIMUM_VERSION = 8; - - private static final Logger logger = LoggerFactory.getLogger(JRE.class); - - private static final int CURRENT_VERSION = determineCurrentVersion(); - - private static final JRE CURRENT_JRE = determineCurrentJre(CURRENT_VERSION); - - private static int determineCurrentVersion() { - String javaVersion = System.getProperty("java.version"); - boolean javaVersionIsBlank = StringUtils.isBlank(javaVersion); + static final int MINIMUM_VERSION = ${allJres.getFirst().getVersion()}; - if (javaVersionIsBlank) { - logger.debug( - () -> "JVM system property 'java.version' is undefined. It is therefore not possible to detect Java 8."); - } - - if (!javaVersionIsBlank && javaVersion.startsWith("1.8")) { - return 8; - } - - try { - // java.lang.Runtime.version() is a static method available on Java 9+ - // that returns an instance of java.lang.Runtime.Version which has the - // following method: public int major() - Method versionMethod = Runtime.class.getMethod("version"); - Object version = ReflectionSupport.invokeMethod(versionMethod, null); - Method majorMethod = version.getClass().getMethod("major"); - return (int) ReflectionSupport.invokeMethod(majorMethod, version); - } - catch (Exception ex) { - logger.debug(ex, () -> "Failed to determine the current JRE version via java.lang.Runtime.Version."); - } - - return UNDEFINED_VERSION; - } - - private static JRE determineCurrentJre(int currentVersion) { - switch (currentVersion) { - case UNDEFINED_VERSION: - return UNDEFINED;<%-- - --%>@for(var jre : jres) - case ${jre.getVersion()}: - return JAVA_${jre.getVersion()};<%-- - --%>@endfor - default: - return OTHER; - } - } + private static final int CURRENT_VERSION = Runtime.version().feature(); private final int version; - private JRE(int version) { + JRE(int version) { this.version = version; } @@ -161,18 +115,18 @@ public enum JRE { /** * @return {@code true} if this {@code JRE} is known to be the * Java Runtime Environment version for the currently executing JVM or if - * the version is {@link #OTHER} or {@link #UNDEFINED} + * the version is {@link #OTHER} * * @see #currentJre() * @see #currentVersionNumber() */ public boolean isCurrentVersion() { - return this == CURRENT_JRE; + return this == currentJre(); } /** * @return the {@link JRE} for the currently executing JVM, potentially - * {@link #OTHER} or {@link #UNDEFINED} + * {@link #OTHER} * * @since 5.7 * @see #currentVersionNumber() @@ -186,14 +140,19 @@ public enum JRE { /** * @return the {@link JRE} for the currently executing JVM, potentially - * {@link #OTHER} or {@link #UNDEFINED} + * {@link #OTHER} * * @since 5.12 * @see #currentVersionNumber() */ @API(status = STABLE, since = "5.12") public static JRE currentJre() { - return CURRENT_JRE; + return switch (CURRENT_VERSION) {<%-- + --%>@for(var jre : allJres) + case ${jre.getVersion()} -> JAVA_${jre.getVersion()};<%-- + --%>@endfor + default -> OTHER; + }; } /** diff --git a/junit-jupiter-api/src/templates/resources/testFixtures/org/junit/jupiter/api/condition/JavaVersionPredicates.java.jte b/junit-jupiter-api/src/templates/resources/testFixtures/org/junit/jupiter/api/condition/JavaVersionPredicates.java.jte index 41db82bc794e..bf4929f61752 100644 --- a/junit-jupiter-api/src/templates/resources/testFixtures/org/junit/jupiter/api/condition/JavaVersionPredicates.java.jte +++ b/junit-jupiter-api/src/templates/resources/testFixtures/org/junit/jupiter/api/condition/JavaVersionPredicates.java.jte @@ -2,7 +2,7 @@ @import gg.jte.support.ForSupport @import junitbuild.generator.model.JRE -@param List jres +@param List supportedJres @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; @@ -10,13 +10,13 @@ package org.junit.jupiter.api.condition; public class JavaVersionPredicates { private static final int JAVA_VERSION = Runtime.version().feature(); -@for(JRE jre : jres) +@for(JRE jre : supportedJres) static boolean onJava${jre.getVersion()}() { return JAVA_VERSION == ${jre.getVersion()}; } @endfor static boolean onKnownVersion() { - return @for(var jre : ForSupport.of(jres))onJava${jre.get().getVersion()}()@if(!jre.isLast()) // + return @for(var jre : ForSupport.of(supportedJres))onJava${jre.get().getVersion()}()@if(!jre.isLast()) // || @endif@endfor; } } diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte index b6ce05e15fa6..67d8d3978950 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreConditionTests.java.jte @@ -1,14 +1,14 @@ @import java.util.List @import junitbuild.generator.model.JRE -@param List jres -@param List jresSortedByStringValue +@param List supportedJres +@param List supportedJresSortedByStringValue @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -@for(var jre : jresSortedByStringValue)<%-- +@for(var jre : supportedJresSortedByStringValue)<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava${jre.getVersion()}; @endfor<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -89,7 +89,7 @@ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { assertDisabledOnCurrentJreIf(true); assertCustomDisabledReasonIs("Disabled on every JRE"); } -@for(var jre : jres) +@for(var jre : supportedJres) /** * @see DisabledOnJreIntegrationTests#jre${jre.getVersion()}() */ @@ -99,7 +99,7 @@ class DisabledOnJreConditionTests extends AbstractExecutionConditionTests { assertDisabledOnCurrentJreIf(onJava${jre.getVersion()}()); } @endfor<%-- ---%>@for(var jre : jres) +--%>@for(var jre : supportedJres) /** * @see DisabledOnJreIntegrationTests#version${jre.getVersion()}() */ diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte index 509b5d47fa48..429d9d3f90ef 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/DisabledOnJreIntegrationTests.java.jte @@ -1,8 +1,9 @@ @import java.util.List @import junitbuild.generator.model.JRE -@param List jres -@param List jresSortedByStringValue +@param List allJres +@param List supportedJres +@param List supportedJresSortedByStringValue @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; @@ -10,12 +11,7 @@ package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -@for(var jre : jresSortedByStringValue)<%-- ---%>import static org.junit.jupiter.api.condition.JRE.JAVA_${jre.getVersion()}; -@endfor<%-- ---%>import static org.junit.jupiter.api.condition.JRE.OTHER; -import static org.junit.jupiter.api.condition.JRE.UNDEFINED; -@for(var jre : jresSortedByStringValue)<%-- +@for(var jre : supportedJresSortedByStringValue)<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava${jre.getVersion()}; @endfor<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -38,40 +34,41 @@ class DisabledOnJreIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") - @DisabledOnJre({}) + @DisabledOnJre void missingVersionDeclaration() { } @Test @Disabled("Only used in a unit test via reflection") - @DisabledOnJre(UNDEFINED) + @DisabledOnJre(JRE.UNDEFINED) void jreUndefined() { } @Test @Disabled("Only used in a unit test via reflection") - @DisabledOnJre(value = JAVA_17, versions = { 21, 7 }) + @DisabledOnJre(value = JRE.JAVA_17, versions = { 21, 7 }) void version7() { } + @SuppressWarnings("removal") @Test @DisabledOnJre(disabledReason = "Disabled on every JRE", value = { // -@for(var jre : jres)<%-- ---%> JAVA_${jre.getVersion()}, // +@for(var jre : allJres)<%-- +--%> JRE.JAVA_${jre.getVersion()}, // @endfor<%-- ---%> OTHER // +--%> JRE.OTHER // }) void disabledOnAllJavaVersions() { fail("should be disabled"); } -@for(var jre : jres) +@for(var jre : supportedJres) @Test - @DisabledOnJre(JAVA_${jre.getVersion()}) + @DisabledOnJre(JRE.JAVA_${jre.getVersion()}) void jre${jre.getVersion()}() { assertFalse(onJava${jre.getVersion()}()); } @endfor<%-- ---%>@for(var jre : jres) +--%>@for(var jre : supportedJres) @Test @DisabledOnJre(versions = ${jre.getVersion()}) void version${jre.getVersion()}() { @@ -79,7 +76,7 @@ class DisabledOnJreIntegrationTests { } @endfor @Test - @DisabledOnJre(OTHER) + @DisabledOnJre(JRE.OTHER) void other() { assertTrue(onKnownVersion()); } diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte index 9d6a1ee02021..7319b74ce364 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreConditionTests.java.jte @@ -1,14 +1,14 @@ @import java.util.List @import junitbuild.generator.model.JRE -@param List jres -@param List jresSortedByStringValue +@param List supportedJres +@param List supportedJresSortedByStringValue @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -@for(var jre : jresSortedByStringValue)<%-- +@for(var jre : supportedJresSortedByStringValue)<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava${jre.getVersion()}; @endfor<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -88,7 +88,7 @@ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { evaluateCondition(); assertEnabledOnCurrentJreIf(true); } -@for(var jre : jres) +@for(var jre : supportedJres) /** * @see EnabledOnJreIntegrationTests#jre${jre.getVersion()}() */ @@ -98,7 +98,7 @@ class EnabledOnJreConditionTests extends AbstractExecutionConditionTests { assertEnabledOnCurrentJreIf(onJava${jre.getVersion()}()); } @endfor<%-- ---%>@for(var jre : jres) +--%>@for(var jre : supportedJres) /** * @see EnabledOnJreIntegrationTests#version${jre.getVersion()}() */ diff --git a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte index 651345ea02b3..a1217d687b71 100644 --- a/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte +++ b/jupiter-tests/src/templates/resources/test/org/junit/jupiter/api/condition/EnabledOnJreIntegrationTests.java.jte @@ -1,20 +1,16 @@ @import java.util.List @import junitbuild.generator.model.JRE -@param List jres -@param List jresSortedByStringValue +@param List allJres +@param List supportedJres +@param List supportedJresSortedByStringValue @param String licenseHeader ${licenseHeader} package org.junit.jupiter.api.condition; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -@for(var jre : jresSortedByStringValue)<%-- ---%>import static org.junit.jupiter.api.condition.JRE.JAVA_${jre.getVersion()}; -@endfor<%-- ---%>import static org.junit.jupiter.api.condition.JRE.OTHER; -import static org.junit.jupiter.api.condition.JRE.UNDEFINED; -@for(var jre : jresSortedByStringValue)<%-- +@for(var jre : supportedJresSortedByStringValue)<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava${jre.getVersion()}; @endfor<%-- --%>import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; @@ -37,39 +33,40 @@ class EnabledOnJreIntegrationTests { @Test @Disabled("Only used in a unit test via reflection") - @EnabledOnJre({}) + @EnabledOnJre void missingVersionDeclaration() { } @Test @Disabled("Only used in a unit test via reflection") - @EnabledOnJre(UNDEFINED) + @EnabledOnJre(JRE.UNDEFINED) void jreUndefined() { } @Test @Disabled("Only used in a unit test via reflection") - @EnabledOnJre(value = JAVA_17, versions = { 21, 7 }) + @EnabledOnJre(value = JRE.JAVA_17, versions = { 21, 7 }) void version7() { } + @SuppressWarnings("removal") @Test @EnabledOnJre({ // -@for(var jre : jres)<%-- ---%> JAVA_${jre.getVersion()}, // +@for(var jre : allJres)<%-- +--%> JRE.JAVA_${jre.getVersion()}, // @endfor<%-- ---%> OTHER // +--%> JRE.OTHER // }) void enabledOnAllJavaVersions() { } -@for(var jre : jres) +@for(var jre : supportedJres) @Test - @EnabledOnJre(JAVA_${jre.getVersion()}) + @EnabledOnJre(JRE.JAVA_${jre.getVersion()}) void jre${jre.getVersion()}() { assertTrue(onJava${jre.getVersion()}()); } @endfor<%-- ---%>@for(var jre : jres) +--%>@for(var jre : supportedJres) @Test @EnabledOnJre(versions = ${jre.getVersion()}) void version${jre.getVersion()}() { @@ -77,7 +74,7 @@ class EnabledOnJreIntegrationTests { } @endfor @Test - @EnabledOnJre(value = OTHER, disabledReason = "Disabled on almost every JRE") + @EnabledOnJre(value = JRE.OTHER, disabledReason = "Disabled on almost every JRE") void other() { assertFalse(onKnownVersion()); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java index 8703958019ed..db7a64095fd8 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeConditionTests.java @@ -11,18 +11,9 @@ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava10; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava11; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava12; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava13; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava14; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava15; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava16; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; import org.junit.jupiter.api.Test; @@ -89,18 +80,18 @@ void effectiveVersionDefaultValues() { } /** - * @see DisabledForJreRangeIntegrationTests#min8() + * @see DisabledForJreRangeIntegrationTests#min17() */ @Test - void min8() { + void min17() { defaultValues(); } /** - * @see DisabledForJreRangeIntegrationTests#minVersion8() + * @see DisabledForJreRangeIntegrationTests#minVersion17() */ @Test - void minVersion8() { + void minVersion17() { defaultValues(); } @@ -131,13 +122,14 @@ void minVersion7() { } /** - * @see DisabledForJreRangeIntegrationTests#maxVersion7() + * @see DisabledForJreRangeIntegrationTests#maxVersion16() */ @Test - void maxVersion7() { + void maxVersion16() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// - .withMessage("@DisabledForJreRange's maxVersion [7] must be greater than or equal to 8"); + .withMessage( + "@DisabledForJreRange's minimum value [17] must be less than or equal to its maximum value [16]"); } /** @@ -170,7 +162,7 @@ void minGreaterThanMax() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// .withMessage( - "@DisabledForJreRange's minimum value [21] must be less than or equal to its maximum value [11]"); + "@DisabledForJreRange's minimum value [21] must be less than or equal to its maximum value [17]"); } /** @@ -220,8 +212,7 @@ void minVersion18() { @Test void max18() { evaluateCondition(); - assertDisabledOnCurrentJreIf(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() - || onJava14() || onJava15() || onJava16() || onJava17() || onJava18()); + assertDisabledOnCurrentJreIf(onJava17() || onJava18()); } /** diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeIntegrationTests.java index 7d043196079f..73e974b600a8 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledForJreRangeIntegrationTests.java @@ -13,25 +13,14 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_19; import static org.junit.jupiter.api.condition.JRE.JAVA_21; -import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.OTHER; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava10; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava11; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava12; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava13; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava14; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava15; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava16; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; import org.junit.jupiter.api.Disabled; @@ -57,29 +46,29 @@ void defaultValues() { @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(min = JAVA_8, max = OTHER) + @DisabledForJreRange(min = JAVA_17, max = OTHER) void effectiveJreDefaultValues() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(minVersion = 8, maxVersion = Integer.MAX_VALUE) + @DisabledForJreRange(minVersion = 17, maxVersion = Integer.MAX_VALUE) void effectiveVersionDefaultValues() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(min = JAVA_8) - void min8() { + @DisabledForJreRange(min = JAVA_17) + void min17() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(minVersion = 8) - void minVersion8() { + @DisabledForJreRange(minVersion = 17) + void minVersion17() { fail("should result in a configuration exception"); } @@ -106,8 +95,8 @@ void minVersion7() { @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(maxVersion = 7) - void maxVersion7() { + @DisabledForJreRange(maxVersion = 16) + void maxVersion16() { fail("should result in a configuration exception"); } @@ -127,28 +116,28 @@ void maxAndMaxVersion() { @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(min = JAVA_21, max = JAVA_11) + @DisabledForJreRange(min = JAVA_21, max = JAVA_17) void minGreaterThanMax() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(min = JAVA_21, maxVersion = 11) + @DisabledForJreRange(min = JAVA_21, maxVersion = 17) void minGreaterThanMaxVersion() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(minVersion = 21, maxVersion = 11) + @DisabledForJreRange(minVersion = 21, maxVersion = 17) void minVersionGreaterThanMaxVersion() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @DisabledForJreRange(minVersion = 21, max = JAVA_11) + @DisabledForJreRange(minVersion = 21, max = JAVA_17) void minVersionGreaterThanMax() { fail("should result in a configuration exception"); } @@ -169,8 +158,7 @@ void minVersion18() { @Test @DisabledForJreRange(max = JAVA_18) void max18() { - assertFalse(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() - || onJava15() || onJava16() || onJava17() || onJava18()); + assertFalse(onJava17() || onJava18()); } @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java index 886af0b8e309..3b7afb076d8a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java @@ -11,13 +11,6 @@ package org.junit.jupiter.api.condition; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava10; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava11; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava12; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava13; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava14; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava15; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava16; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; @@ -27,8 +20,6 @@ import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava23; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava24; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava25; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; import org.junit.jupiter.api.Test; @@ -95,18 +86,18 @@ void effectiveVersionDefaultValues() { } /** - * @see EnabledForJreRangeIntegrationTests#min8() + * @see EnabledForJreRangeIntegrationTests#min17() */ @Test - void min8() { + void min17() { defaultValues(); } /** - * @see EnabledForJreRangeIntegrationTests#minVersion8() + * @see EnabledForJreRangeIntegrationTests#minVersion17() */ @Test - void minVersion8() { + void minVersion17() { defaultValues(); } @@ -137,13 +128,14 @@ void minVersion7() { } /** - * @see EnabledForJreRangeIntegrationTests#maxVersion7() + * @see EnabledForJreRangeIntegrationTests#maxVersion16() */ @Test - void maxVersion7() { + void maxVersion16() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// - .withMessage("@EnabledForJreRange's maxVersion [7] must be greater than or equal to 8"); + .withMessage( + "@EnabledForJreRange's minimum value [17] must be less than or equal to its maximum value [16]"); } /** @@ -176,7 +168,7 @@ void minGreaterThanMax() { assertThatExceptionOfType(PreconditionViolationException.class)// .isThrownBy(this::evaluateCondition)// .withMessage( - "@EnabledForJreRange's minimum value [21] must be less than or equal to its maximum value [11]"); + "@EnabledForJreRange's minimum value [21] must be less than or equal to its maximum value [17]"); } /** @@ -226,9 +218,7 @@ void minVersion20() { @Test void max21() { evaluateCondition(); - assertEnabledOnCurrentJreIf( - onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() || onJava15() - || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); + assertEnabledOnCurrentJreIf(onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); } /** @@ -240,10 +230,10 @@ void maxVersion21() { } /** - * @see EnabledForJreRangeIntegrationTests#min8Max21() + * @see EnabledForJreRangeIntegrationTests#min17Max21() */ @Test - void min8Max21() { + void min17Max21() { max21(); } @@ -314,10 +304,10 @@ void minVersion20MaxVersion21() { } /** - * @see EnabledForJreRangeIntegrationTests#minVersion17MaxVersionMaxInteger() + * @see EnabledForJreRangeIntegrationTests#minVersion21MaxVersionMaxInteger() */ @Test - void minVersion17MaxVersionMaxInteger() { + void minVersion21MaxVersionMaxInteger() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22() || onJava23() || onJava24() || onJava25()); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java index 03d33d1e2632..d1c26b36507f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java @@ -13,20 +13,11 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import static org.junit.jupiter.api.condition.JRE.JAVA_11; import static org.junit.jupiter.api.condition.JRE.JAVA_17; import static org.junit.jupiter.api.condition.JRE.JAVA_18; import static org.junit.jupiter.api.condition.JRE.JAVA_20; import static org.junit.jupiter.api.condition.JRE.JAVA_21; -import static org.junit.jupiter.api.condition.JRE.JAVA_8; import static org.junit.jupiter.api.condition.JRE.OTHER; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava10; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava11; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava12; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava13; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava14; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava15; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava16; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava17; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava18; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava19; @@ -34,8 +25,6 @@ import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava21; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava22; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava23; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava8; -import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava9; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; import org.junit.jupiter.api.Disabled; @@ -64,29 +53,29 @@ void defaultValues() { @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(min = JAVA_8, max = OTHER) + @EnabledForJreRange(min = JAVA_17, max = OTHER) void effectiveJreDefaultValues() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(minVersion = 8, maxVersion = Integer.MAX_VALUE) + @EnabledForJreRange(minVersion = 17, maxVersion = Integer.MAX_VALUE) void effectiveVersionDefaultValues() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(min = JAVA_8) - void min8() { + @EnabledForJreRange(min = JAVA_17) + void min17() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(minVersion = 8) - void minVersion8() { + @EnabledForJreRange(minVersion = 17) + void minVersion17() { fail("should result in a configuration exception"); } @@ -113,8 +102,8 @@ void minVersion7() { @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(maxVersion = 7) - void maxVersion7() { + @EnabledForJreRange(maxVersion = 16) + void maxVersion16() { fail("should result in a configuration exception"); } @@ -134,28 +123,28 @@ void maxAndMaxVersion() { @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(min = JAVA_21, max = JAVA_11) + @EnabledForJreRange(min = JAVA_21, max = JAVA_17) void minGreaterThanMax() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(min = JAVA_21, maxVersion = 11) + @EnabledForJreRange(min = JAVA_21, maxVersion = 17) void minGreaterThanMaxVersion() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(minVersion = 21, maxVersion = 11) + @EnabledForJreRange(minVersion = 21, maxVersion = 17) void minVersionGreaterThanMaxVersion() { fail("should result in a configuration exception"); } @Test @Disabled("Only used in a unit test via reflection") - @EnabledForJreRange(minVersion = 21, max = JAVA_11) + @EnabledForJreRange(minVersion = 21, max = JAVA_17) void minVersionGreaterThanMax() { fail("should result in a configuration exception"); } @@ -184,8 +173,7 @@ void max21() { assertTrue(CURRENT_JRE.compareTo(JAVA_21) <= 0); assertTrue(CURRENT_JRE.version() <= 21); - assertTrue(onJava8() || onJava9() || onJava10() || onJava11() || onJava12() || onJava13() || onJava14() - || onJava15() || onJava16() || onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); + assertTrue(onJava17() || onJava18() || onJava19() || onJava20() || onJava21()); assertFalse(onJava22()); } @@ -196,8 +184,8 @@ void maxVersion21() { } @Test - @EnabledForJreRange(min = JAVA_8, max = JAVA_21) - void min8Max21() { + @EnabledForJreRange(min = JAVA_17, max = JAVA_21) + void min17Max21() { max21(); } @@ -251,8 +239,8 @@ void minVersion20MaxVersion21() { } @Test - @EnabledForJreRange(minVersion = 17, maxVersion = Integer.MAX_VALUE) - void minVersion17MaxVersionMaxInteger() { + @EnabledForJreRange(minVersion = 21, maxVersion = Integer.MAX_VALUE) + void minVersion21MaxVersionMaxInteger() { assertTrue(onKnownVersion()); assertTrue(JRE.currentVersionNumber() >= 17); } From bfc1e11c3f63b8aef4de929dfa41512c06775faa Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 16 May 2025 12:24:02 +0000 Subject: [PATCH 053/521] Update plugin org.jetbrains.kotlin.jvm to v2.1.21 --- .../projects/kotlin-coroutines/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts index 602d9fadc900..2639b23567a5 100644 --- a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.1.20" + kotlin("jvm") version "2.1.21" } val junitVersion: String by project From 68987952ddf0b28c88f7844d69ceb2502d933283 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sun, 18 May 2025 11:15:37 +0200 Subject: [PATCH 054/521] Prune release notes for 6.0 --- .../docs/asciidoc/release-notes/index.adoc | 6 --- .../release-notes/release-notes-5.12.0.adoc | 24 ------------ .../release-notes/release-notes-5.12.1.adoc | 38 ------------------- .../release-notes/release-notes-5.12.2.adoc | 33 ---------------- 4 files changed, 101 deletions(-) delete mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0.adoc delete mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc delete mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.12.2.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index f7e6ba99c99d..921e3dac46df 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -20,9 +20,3 @@ include::{includedir}/link-attributes.adoc[] include::{basedir}/release-notes-6.0.0-M1.adoc[] include::{basedir}/release-notes-5.13.0.adoc[] - -include::{basedir}/release-notes-5.12.2.adoc[] - -include::{basedir}/release-notes-5.12.1.adoc[] - -include::{basedir}/release-notes-5.12.0.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0.adoc deleted file mode 100644 index 75ff54748e5f..000000000000 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.0.adoc +++ /dev/null @@ -1,24 +0,0 @@ -[[release-notes-5.12.0]] -== 5.12.0 - -*Date of Release:* February 21, 2025 - -*Scope:* - -* Output file attachments for tests and containers -* Improvements to the Open Test Reporting XML output -* Resource lock definition improvements -* Thread dumps on test timeouts -* Parameterized test validation improvements -* Filtering support for auto-registered extensions -* Kotlin contracts for assertions -* Configurable Jupiter extension context scope -* Enhancements to the `ConsoleLauncher` -* Better support for GraalVM native image usage -* Improved discovery support for file-based test engines -* Customizable classpath scanning -* Parallel execution support in JUnit Vintage engine -* Numerous bug fixes and other enhancements - -For complete details consult the -https://junit.org/junit5/docs/5.12.0/release-notes/index.html[5.12.0 Release Notes] online. diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc deleted file mode 100644 index f41490897fb5..000000000000 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.1.adoc +++ /dev/null @@ -1,38 +0,0 @@ -[[release-notes-5.12.1]] -== 5.12.1 - -*Date of Release:* March 14, 2025 - -*Scope:* Bug fixes and enhancements since 5.12.0 - -For a complete list of all _closed_ issues and pull requests for this release, consult the -link:{junit5-repo}+/milestone/91?closed=1+[5.12.1] milestone page in the JUnit repository -on GitHub. - - -[[release-notes-5.12.1-junit-platform]] -=== JUnit Platform - -[[release-notes-5.12.1-junit-platform-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* Set stable module name `org.junit.platform.console.standalone` for the - `junit-platform-console-standalone` artifact, superseding the unstable name generated - from the name of the JAR file when putting the artifact on the module path. - - -[[release-notes-5.12.1-junit-jupiter]] -=== JUnit Jupiter - -[[release-notes-5.12.1-junit-jupiter-new-features-and-improvements]] -==== New Features and Improvements - -* New `ExtensionContext.getEnclosingTestClasses()` method to help with migration away from - `AnnotationSupport.findAnnotation(Class, Class, SearchOption)` (deprecated since 1.12.0) - to `AnnotationSupport.findAnnotation(Class, Class, List)`. - - -[[release-notes-5.12.1-junit-vintage]] -=== JUnit Vintage - -No changes. diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.2.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.2.adoc deleted file mode 100644 index 224078ba645e..000000000000 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.12.2.adoc +++ /dev/null @@ -1,33 +0,0 @@ -[[release-notes-5.12.2]] -== 5.12.2 - -*Date of Release:* April 11, 2025 - -*Scope:* Bug fixes and enhancements since 5.12.1 - -For a complete list of all _closed_ issues and pull requests for this release, consult the -link:{junit5-repo}+/milestone/95?closed=1+[5.12.2] milestone page in the JUnit repository -on GitHub. - - -[[release-notes-5.12.2-junit-platform]] -=== JUnit Platform - -No changes. - - -[[release-notes-5.12.2-junit-jupiter]] -=== JUnit Jupiter - -[[release-notes-5.12.2-junit-jupiter-bug-fixes]] -==== Bug Fixes - -* Fix handling of `CleanupMode.ON_SUCCESS` with `@TempDir` that caused no temporary - directories (using that mode) to be deleted after the first failure even if the - corresponding tests passed. - - -[[release-notes-5.12.2-junit-vintage]] -=== JUnit Vintage - -No changes. From a63facc379cec3c763395d9af87f80df9d814c28 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 11:36:02 +0200 Subject: [PATCH 055/521] Revert "Run Renovate also on `develop/.*` branches" This reverts commit ac3687a78369dcafc5d5cc7af5cc8e0fd8584d68. --- .github/renovate.json5 | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/renovate.json5 b/.github/renovate.json5 index d256a62d0f55..ea024d3d17e6 100644 --- a/.github/renovate.json5 +++ b/.github/renovate.json5 @@ -3,7 +3,6 @@ extends: [ 'github>junit-team/renovate-config', ], - baseBranches: ["main", "/^develop\\/.*/"], packageRules: [ { matchCurrentValue: '/^2\\./', From a15bf99181cdc1dcd8e7befc8fa9eb58db644c11 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 11:36:03 +0200 Subject: [PATCH 056/521] Revert "Run builds and publish snapshots for commits on `develop/**` branches" This reverts commit e0ce7cc0c8d0ba44b2453a74e0190a9eae19f65b. --- .github/workflows/codeql-analysis.yml | 2 -- .github/workflows/cross-version.yml | 1 - .github/workflows/main.yml | 3 +-- .github/workflows/reproducible-build.yml | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 0f273446d0de..7a3567c7e3ec 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,13 +5,11 @@ on: branches: - main - 'releases/**' - - 'develop/**' pull_request: # The branches below must be a subset of the branches above branches: - main - 'releases/**' - - 'develop/**' schedule: - cron: '0 19 * * 3' diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index ad6f8b246011..7c51412feaaf 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -7,7 +7,6 @@ on: branches: - main - 'releases/**' - - 'develop/**' pull_request: branches: - '**' diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index eb512b82c647..aadc10b78069 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -5,7 +5,6 @@ on: branches: - main - 'releases/**' - - 'develop/**' tags-ignore: - '**' pull_request: @@ -77,7 +76,7 @@ jobs: permissions: attestations: write # required for build provenance attestation id-token: write # required for build provenance attestation - if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || startsWith(github.ref, 'refs/heads/develop/') || github.ref == 'refs/heads/main') + if: github.event_name == 'push' && github.repository == 'junit-team/junit5' && (startsWith(github.ref, 'refs/heads/releases/') || github.ref == 'refs/heads/main') steps: - name: Check out repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 diff --git a/.github/workflows/reproducible-build.yml b/.github/workflows/reproducible-build.yml index e717a7a71d5c..546ff5b9cd18 100644 --- a/.github/workflows/reproducible-build.yml +++ b/.github/workflows/reproducible-build.yml @@ -5,7 +5,6 @@ on: branches: - main - 'releases/**' - - 'develop/**' pull_request: branches: - '**' From 145af95116dbf13f4ed223ef63b05f80b7a94c88 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 12:32:04 +0200 Subject: [PATCH 057/521] Relax Kotlin contracts for `Executable` passed to `assertTimeout` (#4551) Since `Executable` is allowed/expected to throw exceptions, the semantics of being called `EXACTLY_ONCE` are blurry because it might not be executed entirely when throwing an exception. Since the Kotlin 2.1 compiler emits a warning for these parameters, we're relaxing their contracts to be called `AT_MOST_ONCE` instead. Resolves #4371. --- .../release-notes/release-notes-6.0.0-M1.adoc | 3 ++ .../junit-jupiter-api.gradle.kts | 4 -- .../junit/jupiter/api/AssertDoesNotThrow.java | 5 ++- .../org/junit/jupiter/api/Assertions.kt | 38 ++++++++----------- .../api/KotlinAssertTimeoutAssertionsTests.kt | 17 +++++---- 5 files changed, 31 insertions(+), 36 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index fb2d3e95dc31..c90775899d35 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -99,6 +99,9 @@ repository on GitHub. `@EnabledOnJre` and `@DisabledOnJre`. * `@EnabledForJreRange` and `@DisabledForJreRange` now use `JAVA_17` as their default `min` value. +* The contracts for the `Executable` parameter of Kotlin-specific `assertTimeout` + functions was changed from `callsInPlace(executable, EXACTLY_ONCE)` to + `callsInPlace(executable, AT_MOST_ONCE)` which might result in compile errors. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/junit-jupiter-api/junit-jupiter-api.gradle.kts b/junit-jupiter-api/junit-jupiter-api.gradle.kts index 7932c998c884..402b5323eb57 100644 --- a/junit-jupiter-api/junit-jupiter-api.gradle.kts +++ b/junit-jupiter-api/junit-jupiter-api.gradle.kts @@ -22,10 +22,6 @@ dependencies { } tasks { - compileKotlin { - // https://github.com/junit-team/junit5/issues/4371 - compilerOptions.allWarningsAsErrors = false - } jar { bundle { val version = project.version diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java index e2b9135dbd88..439e9795d780 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java @@ -10,10 +10,12 @@ package org.junit.jupiter.api; +import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import java.util.function.Supplier; +import org.apiguardian.api.API; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.util.StringUtils; @@ -76,7 +78,8 @@ private static T assertDoesNotThrow(ThrowingSupplier supplier, Object mes } } - private static AssertionFailedError createAssertionFailedError(Object messageOrSupplier, Throwable t) { + @API(status = INTERNAL, since = "6.0") + public static AssertionFailedError createAssertionFailedError(Object messageOrSupplier, Throwable t) { return assertionFailure() // .message(messageOrSupplier) // .reason("Unexpected exception thrown: " + t.getClass().getName() + buildSuffix(t.getMessage())) // 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 44c13138a03d..db491e780f26 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 @@ -15,7 +15,7 @@ import org.apiguardian.api.API import org.apiguardian.api.API.Status.EXPERIMENTAL import org.apiguardian.api.API.Status.STABLE import org.junit.jupiter.api.function.Executable -import org.junit.jupiter.api.function.ThrowingSupplier +import org.junit.platform.commons.util.UnrecoverableExceptions.rethrowIfUnrecoverable import java.time.Duration import java.util.stream.Stream import kotlin.contracts.ExperimentalContracts @@ -354,7 +354,12 @@ inline fun assertDoesNotThrow(executable: () -> R): R { callsInPlace(executable, EXACTLY_ONCE) } - return Assertions.assertDoesNotThrow(evaluateAndWrap(executable)) + try { + return executable() + } catch (t: Throwable) { + rethrowIfUnrecoverable(t) + throw AssertDoesNotThrow.createAssertionFailedError(null, t) + } } /** @@ -401,24 +406,11 @@ inline fun assertDoesNotThrow( callsInPlace(message, AT_MOST_ONCE) } - return Assertions.assertDoesNotThrow( - evaluateAndWrap(executable), - message - ) -} - -@OptIn(ExperimentalContracts::class) -@PublishedApi -internal inline fun evaluateAndWrap(executable: () -> R): ThrowingSupplier { - contract { - callsInPlace(executable, EXACTLY_ONCE) - } - - return try { - val result = executable() - ThrowingSupplier { result } - } catch (throwable: Throwable) { - ThrowingSupplier { throw throwable } + try { + return executable() + } catch (t: Throwable) { + rethrowIfUnrecoverable(t) + throw AssertDoesNotThrow.createAssertionFailedError(message(), t) } } @@ -439,7 +431,7 @@ fun assertTimeout( executable: () -> R ): R { contract { - callsInPlace(executable, EXACTLY_ONCE) + callsInPlace(executable, AT_MOST_ONCE) } return Assertions.assertTimeout(timeout, executable) @@ -463,7 +455,7 @@ fun assertTimeout( executable: () -> R ): R { contract { - callsInPlace(executable, EXACTLY_ONCE) + callsInPlace(executable, AT_MOST_ONCE) } return Assertions.assertTimeout(timeout, executable, message) @@ -487,7 +479,7 @@ fun assertTimeout( executable: () -> R ): R { contract { - callsInPlace(executable, EXACTLY_ONCE) + callsInPlace(executable, AT_MOST_ONCE) callsInPlace(message, AT_MOST_ONCE) } diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinAssertTimeoutAssertionsTests.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinAssertTimeoutAssertionsTests.kt index a10d58420c8d..54b01a0ec3a4 100644 --- a/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinAssertTimeoutAssertionsTests.kt +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinAssertTimeoutAssertionsTests.kt @@ -156,17 +156,18 @@ internal class KotlinAssertTimeoutAssertionsTests { } @Test - fun `assertTimeout with value initialization in lambda`() { + fun `assertTimeout with value assignment in lambda`() { val value: Int - assertTimeout(ofMillis(500)) { value = 10 } - - assertEquals(10, value) + assertTimeout(ofMillis(500)) { + value = 10 // Val can be assigned in the message supplier lambda. + assertEquals(10, value) + } } @Test - fun `assertTimeout with message and value initialization in lambda`() { - val value: Int + fun `assertTimeout with message and value assignment in lambda`() { + var value = 0 assertTimeout(ofMillis(500), "message") { value = 10 } @@ -174,8 +175,8 @@ internal class KotlinAssertTimeoutAssertionsTests { } @Test - fun `assertTimeout with message supplier and value initialization in lambda`() { - val value: Int + fun `assertTimeout with message supplier and value assignment in lambda`() { + var value = 0 @Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE") val valueInMessageSupplier: Int From 4b94ce490f0415aecb74582a5ede60d05b39e54c Mon Sep 17 00:00:00 2001 From: Kim Gi Uk <2897robo@gmail.com> Date: Mon, 19 May 2025 19:44:54 +0900 Subject: [PATCH 058/521] Add example for using `@Execution` annotation to User Guide (#4525) Resolves #2669. --------- Co-authored-by: Marc Philipp --- .../asciidoc/user-guide/writing-tests.adoc | 11 +++++++ .../example/ExplicitExecutionModeDemo.java | 30 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 documentation/src/test/java/example/ExplicitExecutionModeDemo.java diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index da1a690b3f16..d20da177fbef 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -3207,6 +3207,17 @@ execution order. Thus, in both cases, test methods in such test classes are only concurrently if the `@Execution(CONCURRENT)` annotation is present on the test class or method. +You can use the `@Execution` annotation to explicitly configure the execution mode for a +test class or method: + +[source,java] +---- +include::{testDir}/example/ExplicitExecutionModeDemo.java[] +---- + +This allows test classes or methods to opt in or out of concurrent execution regardless of +the globally configured default. + When parallel execution is enabled and a default `{ClassOrderer}` is registered (see <> for details), top-level test classes will initially be sorted accordingly and scheduled in that order. However, they are not diff --git a/documentation/src/test/java/example/ExplicitExecutionModeDemo.java b/documentation/src/test/java/example/ExplicitExecutionModeDemo.java new file mode 100644 index 000000000000..83735b7b8419 --- /dev/null +++ b/documentation/src/test/java/example/ExplicitExecutionModeDemo.java @@ -0,0 +1,30 @@ +/* + * 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 example; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; + +@Execution(ExecutionMode.CONCURRENT) +class ExplicitExecutionModeDemo { + + @Test + void testA() { + // concurrent + } + + @Test + @Execution(ExecutionMode.SAME_THREAD) + void testB() { + // overrides to same_thread + } +} From 5b3dfad389b0f31bc434e0eb68804d7fcb146fdc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 17:01:35 +0000 Subject: [PATCH 059/521] Update dependency com.pinterest.ktlint:ktlint-cli to v1.6.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a346f651c6ae..809abe54a57c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -12,7 +12,7 @@ jacoco = "0.8.13" jmh = "1.37" junit4 = "4.13.2" junit4Min = "4.12" -ktlint = "1.5.0" +ktlint = "1.6.0" log4j = "2.24.3" logback = "1.5.18" opentest4j = "1.3.0" From b0333b233426374c4bcab5a1e0f0ea8c94d838a4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:04:58 +0000 Subject: [PATCH 060/521] Update plugin foojayResolver to v1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 809abe54a57c..3a01d019847f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -96,7 +96,7 @@ buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" } commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" } develocity = { id = "com.gradle.develocity", version = "4.0.1" } extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" } -foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "0.10.0" } +foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "1.0.0" } gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } From 298eb5ebe5fc9327799ef01acac0da3f25af469c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 19:05:03 +0000 Subject: [PATCH 061/521] Update plugin org.gradle.toolchains.foojay-resolver-convention to v1 --- .../projects/graalvm-starter/settings.gradle.kts | 2 +- .../projects/gradle-kotlin-extensions/settings.gradle.kts | 2 +- .../projects/gradle-missing-engine/settings.gradle.kts | 2 +- .../projects/jupiter-starter/settings.gradle.kts | 2 +- .../projects/kotlin-coroutines/settings.gradle.kts | 2 +- .../projects/reflection-tests/settings.gradle.kts | 2 +- .../projects/vintage/settings.gradle.kts | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts index a53a82439ab6..0b5bc3f36576 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts @@ -10,7 +10,7 @@ pluginManagement { } plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "graalvm-starter" diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/settings.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/settings.gradle.kts index 963ac745898a..f8ef92d0510a 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "gradle-kotlin-extensions" diff --git a/platform-tooling-support-tests/projects/gradle-missing-engine/settings.gradle.kts b/platform-tooling-support-tests/projects/gradle-missing-engine/settings.gradle.kts index 4e05cf034d46..27afc44c06b2 100644 --- a/platform-tooling-support-tests/projects/gradle-missing-engine/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-missing-engine/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "gradle-missing-engine" diff --git a/platform-tooling-support-tests/projects/jupiter-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/jupiter-starter/settings.gradle.kts index 2301fb77b192..f6b40adf9c41 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/jupiter-starter/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "gradle-starter" diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts index 2e3f2dee51af..1d23e10e72b6 100644 --- a/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "kotlin-coroutines" diff --git a/platform-tooling-support-tests/projects/reflection-tests/settings.gradle.kts b/platform-tooling-support-tests/projects/reflection-tests/settings.gradle.kts index dc695374e2d9..222e53054a3d 100644 --- a/platform-tooling-support-tests/projects/reflection-tests/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/reflection-tests/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "reflection-tests" diff --git a/platform-tooling-support-tests/projects/vintage/settings.gradle.kts b/platform-tooling-support-tests/projects/vintage/settings.gradle.kts index 00a3ba7dcdba..871f35f417a1 100644 --- a/platform-tooling-support-tests/projects/vintage/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/vintage/settings.gradle.kts @@ -1,5 +1,5 @@ plugins { - id("org.gradle.toolchains.foojay-resolver-convention") version "0.10.0" + id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } rootProject.name = "vintage" From e9048da486cbbd9f4ebc14d78e0b4b51b49f43d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 23:02:44 +0000 Subject: [PATCH 062/521] Update plugin openrewrite to v7.6.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3a01d019847f..c2122ae9025e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -102,7 +102,7 @@ jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } -openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.1" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "7.0.3" } From 1fc5958a092d1be11872f04e850ed9760dcf6953 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:32:25 +0200 Subject: [PATCH 063/521] Use `String.formatted` instead of `String.format` --- .../src/test/java/example/HttpServerDemo.java | 2 +- .../test/java/example/RepeatedTestsDemo.java | 2 +- .../testinterface/TestLifecycleLogger.java | 4 +-- .../java/example/timing/TimingExtension.java | 2 +- .../java21/example/DynamicTestsNamedDemo.java | 2 +- .../api/tools/AbstractApiReportWriter.java | 4 +-- .../junit/jupiter/api/AssertLinesMatch.java | 5 ++- .../org/junit/jupiter/api/AssertThrows.java | 3 +- .../jupiter/api/AssertThrowsExactly.java | 3 +- .../jupiter/api/AssertionFailureBuilder.java | 4 +-- .../jupiter/api/DisplayNameGenerator.java | 4 +-- .../junit/jupiter/api/RandomOrdererUtils.java | 2 +- .../api/condition/AbstractJreCondition.java | 2 +- .../condition/AbstractJreRangeCondition.java | 22 ++++++------- .../AbstractOsBasedExecutionCondition.java | 4 +-- ...AbstractRepeatableAnnotationCondition.java | 3 +- .../condition/BooleanExecutionCondition.java | 2 +- ...isabledIfEnvironmentVariableCondition.java | 9 +++-- .../DisabledIfSystemPropertyCondition.java | 9 +++-- ...EnabledIfEnvironmentVariableCondition.java | 9 +++-- .../EnabledIfSystemPropertyCondition.java | 10 +++--- .../api/condition/MethodBasedCondition.java | 11 +++---- .../extension/ConditionEvaluationResult.java | 2 +- .../EnumConfigurationParameterConverter.java | 4 +-- ...iatingConfigurationParameterConverter.java | 2 +- .../descriptor/ClassBasedTestDescriptor.java | 12 +++---- .../ClassTemplateTestDescriptor.java | 2 +- .../engine/descriptor/DisplayNameUtils.java | 2 +- .../engine/descriptor/ExtensionUtils.java | 8 ++--- .../descriptor/JupiterTestDescriptor.java | 5 ++- .../descriptor/LifecycleMethodUtils.java | 17 ++++------ .../descriptor/MethodBasedTestDescriptor.java | 8 ++--- .../descriptor/TestFactoryTestDescriptor.java | 2 +- .../TestTemplateTestDescriptor.java | 2 +- .../descriptor/UniqueIdPrefixTransformer.java | 2 +- .../discovery/ClassOrderingVisitor.java | 11 +++---- .../discovery/ClassSelectorResolver.java | 3 +- .../engine/discovery/MethodFinder.java | 2 +- .../discovery/MethodOrderingVisitor.java | 9 ++--- .../discovery/MethodSelectorResolver.java | 2 +- .../predicates/IsTestFactoryMethod.java | 3 +- .../predicates/IsTestableMethod.java | 2 +- .../predicates/TestClassPredicates.java | 2 +- .../engine/execution/ConditionEvaluator.java | 5 ++- .../execution/ParameterResolutionUtils.java | 16 ++++----- .../engine/extension/AutoCloseExtension.java | 8 ++--- .../extension/MutableExtensionRegistry.java | 13 ++++---- .../extension/RepeatedTestExtension.java | 10 +++--- .../engine/extension/TempDirectory.java | 4 +-- .../extension/TimeoutConfiguration.java | 12 +++---- .../extension/TimeoutExceptionFactory.java | 2 +- .../engine/extension/TimeoutExtension.java | 2 +- .../adapter/AbstractTestRuleAdapter.java | 2 +- .../params/ArgumentCountValidator.java | 18 +++++----- .../jupiter/params/EvaluatedArgumentSet.java | 2 +- ...arameterizedInvocationContextProvider.java | 5 ++- .../ParameterizedInvocationNameFormatter.java | 14 ++++---- .../ParameterizedTestSpiInstantiator.java | 2 +- .../junit/jupiter/params/ResolverFacade.java | 33 +++++++++---------- .../aggregator/DefaultArgumentsAccessor.java | 6 ++-- .../converter/DefaultArgumentConverter.java | 5 ++- .../converter/TypedArgumentConverter.java | 5 ++- .../params/provider/CsvArgumentsProvider.java | 3 +- .../provider/EmptyArgumentsProvider.java | 4 +-- .../provider/EnumArgumentsProvider.java | 3 +- .../provider/FieldArgumentsProvider.java | 14 ++++---- .../provider/MethodArgumentsProvider.java | 15 ++++----- .../provider/NullArgumentsProvider.java | 2 +- .../support/conversion/ConversionSupport.java | 2 +- .../scanning/DefaultClasspathScanner.java | 8 ++--- .../commons/util/AnnotationUtils.java | 7 ++-- .../commons/util/ClasspathScannerLoader.java | 6 ++-- .../commons/util/CollectionUtils.java | 4 +-- .../options/ListTestEnginesCommand.java | 2 +- .../options/ManifestVersionProvider.java | 3 +- .../options/TestDiscoveryOptionsMixin.java | 2 +- .../platform/console/tasks/ColorPalette.java | 2 +- .../console/tasks/FlatPrintingListener.java | 2 +- .../tasks/TestFeedPrintingListener.java | 2 +- .../platform/engine/CompositeFilter.java | 3 +- .../engine/ConfigurationParameters.java | 4 +-- .../engine/DiscoverySelectorIdentifier.java | 2 +- .../org/junit/platform/engine/TestTag.java | 2 +- .../junit/platform/engine/UniqueIdFormat.java | 6 ++-- .../discovery/ClasspathResourceSelector.java | 2 +- .../DiscoverySelectorIdentifierParsers.java | 2 +- .../engine/discovery/DiscoverySelectors.java | 4 +-- .../discovery/ExcludeClassNameFilter.java | 6 ++-- .../discovery/ExcludePackageNameFilter.java | 7 ++-- .../engine/discovery/FileSelector.java | 2 +- .../discovery/IncludeClassNameFilter.java | 7 ++-- .../discovery/IncludePackageNameFilter.java | 7 ++-- .../engine/discovery/IterationSelector.java | 2 +- .../engine/discovery/MethodSelector.java | 8 ++--- .../support/descriptor/MethodSource.java | 8 ++--- .../engine/support/descriptor/UriSource.java | 5 +-- ...arallelExecutionConfigurationStrategy.java | 11 +++---- .../support/hierarchical/NodeTestTask.java | 4 +-- .../store/NamespacedHierarchicalStore.java | 2 +- .../junit/platform/launcher/EngineFilter.java | 11 +++---- .../launcher/ExcludeMethodFilter.java | 7 ++-- .../launcher/IncludeMethodFilter.java | 7 ++-- .../junit/platform/launcher/TagFilter.java | 9 +++-- .../core/ClasspathAlignmentChecker.java | 2 +- .../CompositeEngineExecutionListener.java | 5 ++- .../core/CompositeTestExecutionListener.java | 2 +- .../core/EngineDiscoveryOrchestrator.java | 16 ++++----- .../core/EngineDiscoveryResultValidator.java | 2 +- .../core/EngineExecutionOrchestrator.java | 2 +- .../launcher/core/EngineIdValidator.java | 14 ++++---- .../core/LauncherConfigurationParameters.java | 11 +++---- .../core/LauncherDiscoveryRequestBuilder.java | 2 +- .../platform/launcher/core/LauncherPhase.java | 2 +- .../launcher/core/ServiceLoaderRegistry.java | 4 +-- .../launcher/core/TestEngineFormatter.java | 2 +- .../launcher/listeners/LoggingListener.java | 2 +- .../launcher/listeners/OutputDir.java | 2 +- .../SuiteLauncherDiscoveryRequestBuilder.java | 4 +-- .../suite/engine/ClassSelectorResolver.java | 3 +- .../platform/suite/engine/IsSuiteClass.java | 3 +- .../suite/engine/LifecycleMethodUtils.java | 10 +++--- .../engine/NoTestsDiscoveredException.java | 2 +- .../suite/engine/SuiteTestDescriptor.java | 4 +-- .../platform/testkit/engine/Assertions.java | 2 +- .../testkit/engine/EngineTestKit.java | 2 +- .../discovery/MethodSelectorResolver.java | 2 +- .../engine/support/UniqueIdReader.java | 3 +- .../api/AssertInstanceOfAssertionsTests.java | 2 +- .../condition/DisabledOnOsConditionTests.java | 14 ++++---- .../condition/EnabledOnOsConditionTests.java | 12 +++---- .../ExtensionComposabilityTests.java | 2 +- .../TypeBasedParameterResolverTests.java | 2 +- .../engine/NestedTestClassesTests.java | 3 +- .../engine/extension/AutoCloseTests.java | 13 +++----- ...gistrationViaParametersAndFieldsTests.java | 2 +- .../engine/extension/OrderedMethodTests.java | 2 +- .../extension/ParameterResolverTests.java | 2 +- .../sub/SystemPropertyCondition.java | 2 +- .../ParameterizedTestExtensionTests.java | 6 ++-- .../ParameterizedTestIntegrationTests.java | 20 +++++------ .../provider/EnumArgumentsProviderTests.java | 4 +-- .../commons/util/ReflectionUtilsTests.java | 4 +-- .../commons/util/StringUtilsTests.java | 17 +++++----- .../platform/console/ConsoleDetailsTests.java | 3 +- .../ConsoleLauncherIntegrationTests.java | 4 +-- .../junit/platform/engine/TestTagTests.java | 4 +-- .../discovery/DiscoverySelectorsTests.java | 6 ++-- .../descriptor/DemoMethodTestDescriptor.java | 2 +- .../platform/launcher/MethodFilterTests.java | 32 +++++++++--------- .../tooling/support/tests/ManifestTests.java | 2 +- 150 files changed, 402 insertions(+), 454 deletions(-) diff --git a/documentation/src/test/java/example/HttpServerDemo.java b/documentation/src/test/java/example/HttpServerDemo.java index 6411ec5d19c4..7ef0055af765 100644 --- a/documentation/src/test/java/example/HttpServerDemo.java +++ b/documentation/src/test/java/example/HttpServerDemo.java @@ -37,7 +37,7 @@ public class HttpServerDemo { void httpCall(HttpServer server) throws Exception { String hostName = server.getAddress().getHostName(); int port = server.getAddress().getPort(); - String rawUrl = String.format("http://%s:%d/example", hostName, port); + String rawUrl = "http://%s:%d/example".formatted(hostName, port); URL requestUrl = URI.create(rawUrl).toURL(); String responseBody = sendRequest(requestUrl); diff --git a/documentation/src/test/java/example/RepeatedTestsDemo.java b/documentation/src/test/java/example/RepeatedTestsDemo.java index dd23f1f39158..6f05dc3603c6 100644 --- a/documentation/src/test/java/example/RepeatedTestsDemo.java +++ b/documentation/src/test/java/example/RepeatedTestsDemo.java @@ -38,7 +38,7 @@ void beforeEach(TestInfo testInfo, RepetitionInfo repetitionInfo) { int currentRepetition = repetitionInfo.getCurrentRepetition(); int totalRepetitions = repetitionInfo.getTotalRepetitions(); String methodName = testInfo.getTestMethod().get().getName(); - logger.info(String.format("About to execute repetition %d of %d for %s", // + logger.info("About to execute repetition %d of %d for %s".formatted( // currentRepetition, totalRepetitions, methodName)); } diff --git a/documentation/src/test/java/example/testinterface/TestLifecycleLogger.java b/documentation/src/test/java/example/testinterface/TestLifecycleLogger.java index ae54cd61c3cf..0906b8674e6c 100644 --- a/documentation/src/test/java/example/testinterface/TestLifecycleLogger.java +++ b/documentation/src/test/java/example/testinterface/TestLifecycleLogger.java @@ -39,13 +39,13 @@ default void afterAllTests() { @BeforeEach default void beforeEachTest(TestInfo testInfo) { - logger.info(() -> String.format("About to execute [%s]", + logger.info(() -> "About to execute [%s]".formatted( testInfo.getDisplayName())); } @AfterEach default void afterEachTest(TestInfo testInfo) { - logger.info(() -> String.format("Finished executing [%s]", + logger.info(() -> "Finished executing [%s]".formatted( testInfo.getDisplayName())); } diff --git a/documentation/src/test/java/example/timing/TimingExtension.java b/documentation/src/test/java/example/timing/TimingExtension.java index 4d12db567543..1426e42629f1 100644 --- a/documentation/src/test/java/example/timing/TimingExtension.java +++ b/documentation/src/test/java/example/timing/TimingExtension.java @@ -47,7 +47,7 @@ public void afterTestExecution(ExtensionContext context) throws Exception { long duration = System.currentTimeMillis() - startTime; logger.info(() -> - String.format("Method [%s] took %s ms.", testMethod.getName(), duration)); + "Method [%s] took %s ms.".formatted(testMethod.getName(), duration)); } private Store getStore(ExtensionContext context) { diff --git a/documentation/src/test/java21/example/DynamicTestsNamedDemo.java b/documentation/src/test/java21/example/DynamicTestsNamedDemo.java index 0d515a8b49bc..97dfd35f5bee 100644 --- a/documentation/src/test/java21/example/DynamicTestsNamedDemo.java +++ b/documentation/src/test/java21/example/DynamicTestsNamedDemo.java @@ -64,7 +64,7 @@ record PalindromeNamedExecutable(String text) implements NamedExecutable { @Override public String getName() { - return String.format("'%s' is a palindrome", text); + return "'%s' is a palindrome".formatted(text); } @Override 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..b60a4aedaa45 100644 --- a/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java +++ b/documentation/src/tools/java/org/junit/api/tools/AbstractApiReportWriter.java @@ -39,7 +39,7 @@ public void printReportHeader(PrintWriter out) { out.println(h1("@API Declarations")); out.println(); out.println(paragraph( - format("Discovered %d types with %s declarations.", this.apiReport.types().size(), code("@API")))); + "Discovered %d types with %s declarations.".formatted(this.apiReport.types().size(), code("@API")))); out.println(); } @@ -76,7 +76,7 @@ protected void printDeclarationSectionHeader(Set statuses, Status status // omit section header when only a single status is printed return; } - out.println(h2(format("@API(%s)", status))); + out.println(h2("@API(%s)".formatted(status))); out.println(); out.println( paragraph(format("Discovered %d " + code("@API(%s)") + " declarations.", declarations.size(), status))); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java index 7596aed881f0..65a99466ac69 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api; -import static java.lang.String.format; import static java.lang.String.join; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.Preconditions.condition; @@ -196,7 +195,7 @@ void fail(String format, Object... args) { String newLine = System.lineSeparator(); assertionFailure() // .message(messageOrSupplier) // - .reason(format(format, args)) // + .reason(format.formatted(args)) // .expected(join(newLine, expectedLines)) // .actual(join(newLine, actualLines)) // .includeValuesInMessage(false) // @@ -214,7 +213,7 @@ static int parseFastForwardLimit(String fastForwardLine) { String text = fastForwardLine.substring(2, fastForwardLine.length() - 2).trim(); try { int limit = Integer.parseInt(text); - condition(limit > 0, () -> format("fast-forward(%d) limit must be greater than zero", limit)); + condition(limit > 0, () -> "fast-forward(%d) limit must be greater than zero".formatted(limit)); return limit; } catch (NumberFormatException e) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java index 70ee8b02fe4f..f8921615aabb 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api; -import static java.lang.String.format; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; @@ -69,7 +68,7 @@ private static T assertThrows(Class expectedType, Execu } throw assertionFailure() // .message(messageOrSupplier) // - .reason(format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType))) // + .reason("Expected %s to be thrown, but nothing was thrown.".formatted(getCanonicalName(expectedType))) // .build(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java index 4fa017318589..0eebe693c380 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api; -import static java.lang.String.format; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.jupiter.api.AssertionUtils.getCanonicalName; @@ -70,7 +69,7 @@ private static T assertThrowsExactly(Class expectedType throw assertionFailure() // .message(messageOrSupplier) // - .reason(format("Expected %s to be thrown, but nothing was thrown.", getCanonicalName(expectedType))) // + .reason("Expected %s to be thrown, but nothing was thrown.".formatted(getCanonicalName(expectedType))) // .build(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java index 9e98fb06f3a9..f03d4c281a39 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -171,10 +171,10 @@ private static String formatValues(Object expected, Object actual) { String expectedString = toString(expected); String actualString = toString(actual); if (expectedString.equals(actualString)) { - return String.format("expected: %s but was: %s", formatClassAndValue(expected, expectedString), + return "expected: %s but was: %s".formatted(formatClassAndValue(expected, expectedString), formatClassAndValue(actual, actualString)); } - return String.format("expected: <%s> but was: <%s>", expectedString, actualString); + return "expected: <%s> but was: <%s>".formatted(expectedString, actualString); } private static String formatClassAndValue(Object value, String valueString) { 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 1ff2974c06d1..99c4ce49b939 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 @@ -505,8 +505,8 @@ private static String getSentenceFragment(AnnotatedElement element) { return findAnnotation(element, SentenceFragment.class) // .map(SentenceFragment::value) // .map(sentenceFragment -> { - Preconditions.notBlank(sentenceFragment, String.format( - "@SentenceFragment on [%s] must be declared with a non-blank value.", element)); + Preconditions.notBlank(sentenceFragment, + "@SentenceFragment on [%s] must be declared with a non-blank value.".formatted(element)); return sentenceFragment.trim(); }) // .orElse(null); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RandomOrdererUtils.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RandomOrdererUtils.java index de221d3d5d61..16ca5250e539 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RandomOrdererUtils.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/RandomOrdererUtils.java @@ -36,7 +36,7 @@ private static Optional getCustomSeed(Function> c Logger logger) { return configurationParameterLookup.apply(RANDOM_SEED_PROPERTY_NAME).map(configurationParameter -> { try { - logger.config(() -> String.format("Using custom seed for configuration parameter [%s] with value [%s].", + logger.config(() -> "Using custom seed for configuration parameter [%s] with value [%s].".formatted( RANDOM_SEED_PROPERTY_NAME, configurationParameter)); return Long.valueOf(configurationParameter); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java index 1eb301b2d894..877635633656 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java @@ -47,7 +47,7 @@ protected final IntStream validatedVersions(JRE[] jres, int[] versions) { Preconditions.condition(Arrays.stream(jres).noneMatch(isEqual(JRE.UNDEFINED)), () -> "JRE.UNDEFINED is not supported in @" + this.annotationName); Arrays.stream(versions).min().ifPresent(version -> Preconditions.condition(version >= JRE.MINIMUM_VERSION, - () -> String.format("Version [%d] in @%s must be greater than or equal to %d", version, this.annotationName, + () -> "Version [%d] in @%s must be greater than or equal to %d".formatted(version, this.annotationName, JRE.MINIMUM_VERSION))); return IntStream.concat(// diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java index df6675e8485f..c33d8e4a4ccd 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java @@ -43,20 +43,20 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int boolean maxVersionSet = maxVersion != JRE.UNDEFINED_VERSION; // Users must choose between JRE enum constants and version numbers. - Preconditions.condition(!minJreSet || !minVersionSet, () -> String.format( - "@%s's minimum value must be configured with either a JRE enum constant or numeric version, but not both", - this.annotationName)); - Preconditions.condition(!maxJreSet || !maxVersionSet, () -> String.format( - "@%s's maximum value must be configured with either a JRE enum constant or numeric version, but not both", - this.annotationName)); + Preconditions.condition(!minJreSet || !minVersionSet, + () -> "@%s's minimum value must be configured with either a JRE enum constant or numeric version, but not both".formatted( + this.annotationName)); + Preconditions.condition(!maxJreSet || !maxVersionSet, + () -> "@%s's maximum value must be configured with either a JRE enum constant or numeric version, but not both".formatted( + this.annotationName)); // Users must supply valid values for minVersion and maxVersion. Preconditions.condition(!minVersionSet || (minVersion >= JRE.MINIMUM_VERSION), - () -> String.format("@%s's minVersion [%d] must be greater than or equal to %d", this.annotationName, - minVersion, JRE.MINIMUM_VERSION)); + () -> "@%s's minVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, minVersion, + JRE.MINIMUM_VERSION)); Preconditions.condition(!maxVersionSet || (maxVersion >= JRE.MINIMUM_VERSION), - () -> String.format("@%s's maxVersion [%d] must be greater than or equal to %d", this.annotationName, - maxVersion, JRE.MINIMUM_VERSION)); + () -> "@%s's maxVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, maxVersion, + JRE.MINIMUM_VERSION)); // Now that we have checked the basic preconditions, we need to ensure that we are // using valid JRE enum constants. @@ -74,7 +74,7 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int Preconditions.condition((min != DEFAULT_MINIMUM_JRE.version() || max != DEFAULT_MAXIMUM_JRE.version()), () -> "You must declare a non-default value for the minimum or maximum value in @" + this.annotationName); Preconditions.condition(min <= max, - () -> String.format("@%s's minimum value [%d] must be less than or equal to its maximum value [%d]", + () -> "@%s's minimum value [%d] must be less than or equal to its maximum value [%d]".formatted( this.annotationName, min, max)); return JRE.isCurrentVersionWithinRange(min, max); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractOsBasedExecutionCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractOsBasedExecutionCondition.java index c4ae691aee63..f581052c56ff 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractOsBasedExecutionCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractOsBasedExecutionCondition.java @@ -50,7 +50,7 @@ String createReason(boolean enabled, boolean osSpecified, boolean archSpecified) .append(osSpecified ? " on operating system: " : " on architecture: "); if (osSpecified && archSpecified) { - reason.append(String.format("%s (%s)", CURRENT_OS, CURRENT_ARCHITECTURE)); + reason.append("%s (%s)".formatted(CURRENT_OS, CURRENT_ARCHITECTURE)); } else if (osSpecified) { reason.append(CURRENT_OS); @@ -63,7 +63,7 @@ else if (osSpecified) { } private ConditionEvaluationResult enabledByDefault() { - String reason = String.format("@%s is not present", this.annotationType.getSimpleName()); + String reason = "@%s is not present".formatted(this.annotationType.getSimpleName()); return enabled(reason); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractRepeatableAnnotationCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractRepeatableAnnotationCondition.java index 66cc3d2e61c6..feb94e25f4b6 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractRepeatableAnnotationCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractRepeatableAnnotationCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.platform.commons.support.AnnotationSupport.findRepeatableAnnotations; import java.lang.annotation.Annotation; @@ -66,7 +65,7 @@ public final ConditionEvaluationResult evaluateExecutionCondition(ExtensionConte protected abstract ConditionEvaluationResult getNoDisabledConditionsEncounteredResult(); private void logResult(A annotation, AnnotatedElement annotatedElement, ConditionEvaluationResult result) { - logger.trace(() -> format("Evaluation of %s on [%s] resulted in: %s", annotation, annotatedElement, result)); + logger.trace(() -> "Evaluation of %s on [%s] resulted in: %s".formatted(annotation, annotatedElement, result)); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/BooleanExecutionCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/BooleanExecutionCondition.java index 0bc4281b9618..ffb9a9d03636 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/BooleanExecutionCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/BooleanExecutionCondition.java @@ -48,7 +48,7 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con abstract boolean isEnabled(A annotation); private ConditionEvaluationResult enabledByDefault() { - String reason = String.format("@%s is not present", this.annotationType.getSimpleName()); + String reason = "@%s is not present".formatted(this.annotationType.getSimpleName()); return enabled(reason); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java index cac8fe5300c4..571ab2067d43 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; @@ -49,16 +48,16 @@ protected ConditionEvaluationResult evaluate(DisabledIfEnvironmentVariable annot // Nothing to match against? if (actual == null) { - return enabled(format("Environment variable [%s] does not exist", name)); + return enabled("Environment variable [%s] does not exist".formatted(name)); } if (actual.matches(regex)) { - return disabled(format("Environment variable [%s] with value [%s] matches regular expression [%s]", name, + return disabled("Environment variable [%s] with value [%s] matches regular expression [%s]".formatted(name, actual, regex), annotation.disabledReason()); } // else - return enabled(format("Environment variable [%s] with value [%s] does not match regular expression [%s]", name, - actual, regex)); + return enabled("Environment variable [%s] with value [%s] does not match regular expression [%s]".formatted( + name, actual, regex)); } /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemPropertyCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemPropertyCondition.java index 45abb83f8cea..3c260a47c778 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemPropertyCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfSystemPropertyCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; @@ -48,17 +47,17 @@ protected ConditionEvaluationResult evaluate(DisabledIfSystemProperty annotation // Nothing to match against? if (actual == null) { - return enabled(format("System property [%s] does not exist", name)); + return enabled("System property [%s] does not exist".formatted(name)); } if (actual.matches(regex)) { return disabled( - format("System property [%s] with value [%s] matches regular expression [%s]", name, actual, regex), + "System property [%s] with value [%s] matches regular expression [%s]".formatted(name, actual, regex), annotation.disabledReason()); } // else - return enabled( - format("System property [%s] with value [%s] does not match regular expression [%s]", name, actual, regex)); + return enabled("System property [%s] with value [%s] does not match regular expression [%s]".formatted(name, + actual, regex)); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java index 050206f5559f..53dab802e793 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; @@ -50,14 +49,14 @@ protected ConditionEvaluationResult evaluate(EnabledIfEnvironmentVariable annota // Nothing to match against? if (actual == null) { - return disabled(format("Environment variable [%s] does not exist", name), annotation.disabledReason()); + return disabled("Environment variable [%s] does not exist".formatted(name), annotation.disabledReason()); } if (actual.matches(regex)) { - return enabled(format("Environment variable [%s] with value [%s] matches regular expression [%s]", name, + return enabled("Environment variable [%s] with value [%s] matches regular expression [%s]".formatted(name, actual, regex)); } - return disabled(format("Environment variable [%s] with value [%s] does not match regular expression [%s]", name, - actual, regex), annotation.disabledReason()); + return disabled("Environment variable [%s] with value [%s] does not match regular expression [%s]".formatted( + name, actual, regex), annotation.disabledReason()); } /** diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemPropertyCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemPropertyCondition.java index 00ce9a4c4c1f..c3baab3768f5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemPropertyCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfSystemPropertyCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; @@ -49,15 +48,14 @@ protected ConditionEvaluationResult evaluate(EnabledIfSystemProperty annotation) // Nothing to match against? if (actual == null) { - return disabled(format("System property [%s] does not exist", name), annotation.disabledReason()); + return disabled("System property [%s] does not exist".formatted(name), annotation.disabledReason()); } if (actual.matches(regex)) { return enabled( - format("System property [%s] with value [%s] matches regular expression [%s]", name, actual, regex)); + "System property [%s] with value [%s] matches regular expression [%s]".formatted(name, actual, regex)); } - return disabled( - format("System property [%s] with value [%s] does not match regular expression [%s]", name, actual, regex), - annotation.disabledReason()); + return disabled("System property [%s] with value [%s] does not match regular expression [%s]".formatted(name, + actual, regex), annotation.disabledReason()); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java index 48088225cf01..16a468daf4fd 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java @@ -10,7 +10,6 @@ package org.junit.jupiter.api.condition; -import static java.lang.String.format; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; @@ -69,7 +68,7 @@ Method getConditionMethod(String fullyQualifiedMethodName, ExtensionContext cont String methodName = methodParts[1]; ClassLoader classLoader = ClassLoaderUtils.getClassLoader(testClass); Class clazz = ReflectionSupport.tryToLoadClass(className, classLoader).getOrThrow( - cause -> new JUnitException(format("Could not load class [%s]", className), cause)); + cause -> new JUnitException("Could not load class [%s]".formatted(className), cause)); return findMethod(clazz, methodName); } @@ -80,9 +79,9 @@ private Method findMethod(Class clazz, String methodName) { private boolean invokeConditionMethod(Method method, ExtensionContext context) { Preconditions.condition(method.getReturnType() == boolean.class, - () -> format("Method [%s] must return a boolean", method)); + () -> "Method [%s] must return a boolean".formatted(method)); Preconditions.condition(acceptsExtensionContextOrNoArguments(method), - () -> format("Method [%s] must accept either an ExtensionContext or no arguments", method)); + () -> "Method [%s] must accept either an ExtensionContext or no arguments".formatted(method)); Object testInstance = context.getTestInstance().orElse(null); if (method.getParameterCount() == 0) { @@ -97,7 +96,7 @@ private boolean acceptsExtensionContextOrNoArguments(Method method) { } private ConditionEvaluationResult buildConditionEvaluationResult(boolean methodResult, A annotation) { - Supplier defaultReason = () -> format("@%s(\"%s\") evaluated to %s", + Supplier defaultReason = () -> "@%s(\"%s\") evaluated to %s".formatted( this.annotationType.getSimpleName(), this.methodName.apply(annotation), methodResult); if (isEnabled(methodResult)) { return enabled(defaultReason.get()); @@ -109,7 +108,7 @@ private ConditionEvaluationResult buildConditionEvaluationResult(boolean methodR protected abstract boolean isEnabled(boolean methodResult); private ConditionEvaluationResult enabledByDefault() { - return enabled(format("@%s is not present", this.annotationType.getSimpleName())); + return enabled("@%s is not present".formatted(this.annotationType.getSimpleName())); } } 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..5b683e43f32b 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 @@ -60,7 +60,7 @@ public static ConditionEvaluationResult disabled(String reason, String customRea if (StringUtils.isBlank(customReason)) { return disabled(reason); } - return disabled(String.format("%s ==> %s", reason, customReason)); + return disabled("%s ==> %s".formatted(reason, customReason)); } private final boolean enabled; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/EnumConfigurationParameterConverter.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/EnumConfigurationParameterConverter.java index 19c8222c76ad..d0a470aed8ec 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/EnumConfigurationParameterConverter.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/EnumConfigurationParameterConverter.java @@ -53,8 +53,8 @@ public E get(String key, Function> lookup, E defaultVal try { constantName = value.get().trim().toUpperCase(Locale.ROOT); E result = Enum.valueOf(enumType, constantName); - logger.config(() -> String.format("Using %s '%s' set via the '%s' configuration parameter.", - enumDisplayName, result, key)); + logger.config(() -> "Using %s '%s' set via the '%s' configuration parameter.".formatted(enumDisplayName, + result, key)); return result; } catch (Exception ex) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/InstantiatingConfigurationParameterConverter.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/InstantiatingConfigurationParameterConverter.java index c0df1064f0c3..5f2eaf34745b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/InstantiatingConfigurationParameterConverter.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/InstantiatingConfigurationParameterConverter.java @@ -67,7 +67,7 @@ private void logFailureMessage(String className, String key, Exception cause) { } private void logSuccessMessage(String className, String key) { - logger.config(() -> String.format("Using default %s '%s' set via the '%s' configuration parameter.", this.name, + logger.config(() -> "Using default %s '%s' set via the '%s' configuration parameter.".formatted(this.name, className, key)); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index d6837494403e..a78de2138afd 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -142,7 +142,7 @@ public final void validate(DiscoveryIssueReporter reporter) { private void validateDisplayNameAnnotation(DiscoveryIssueReporter reporter) { DisplayNameUtils.validateAnnotation(getTestClass(), // - () -> String.format("class '%s'", getTestClass().getName()), // + () -> "class '%s'".formatted(getTestClass().getName()), // () -> getSource().orElse(null), // reporter); } @@ -300,8 +300,7 @@ private TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registr .map(factory -> factory.getClass().getName())// .collect(joining(", ")); - String errorMessage = String.format( - "The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s", + String errorMessage = "The following TestInstanceFactory extensions were registered for test class [%s], but only one is permitted: %s".formatted( getTestClass().getName(), factoryNames); throw new ExtensionConfigurationException(errorMessage); @@ -370,7 +369,7 @@ private Object invokeTestInstanceFactory(Optional outerInstance, throw (TestInstantiationException) throwable; } - String message = String.format("TestInstanceFactory [%s] failed to instantiate test class [%s]", + String message = "TestInstanceFactory [%s] failed to instantiate test class [%s]".formatted( this.testInstanceFactory.getClass().getName(), getTestClass().getName()); if (StringUtils.isNotBlank(throwable.getMessage())) { message += ": " + throwable.getMessage(); @@ -390,8 +389,7 @@ private Object invokeTestInstanceFactory(Optional outerInstance, testClassName += "@" + Integer.toHexString(System.identityHashCode(getTestClass())); instanceClassName += "@" + Integer.toHexString(System.identityHashCode(instanceClass)); } - String message = String.format( - "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].", + String message = "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].".formatted( this.testInstanceFactory.getClass().getName(), testClassName, instanceClassName); throw new TestInstantiationException(message); @@ -561,7 +559,7 @@ protected static class ClassInfo { ClassInfo(Class testClass, JupiterConfiguration configuration) { this.testClass = testClass; this.tags = getTags(testClass, // - () -> String.format("class '%s'", testClass.getName()), // + () -> "class '%s'".formatted(testClass.getName()), // () -> ClassSource.from(testClass), // discoveryIssues::add); this.lifecycle = getTestInstanceLifecycle(testClass, configuration); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java index 77b540c6e2bb..e88153f502cd 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java @@ -221,7 +221,7 @@ boolean supports(ClassTemplateInvocationContextProvider provider, ExtensionConte @Override protected String getNoRegisteredProviderErrorMessage() { - return String.format("You must register at least one %s that supports @%s class [%s]", + return "You must register at least one %s that supports @%s class [%s]".formatted( ClassTemplateInvocationContextProvider.class.getSimpleName(), ClassTemplate.class.getSimpleName(), getTestClass().getName()); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java index 619bbf81a60c..a25d2e16b6ee 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java @@ -87,7 +87,7 @@ static void validateAnnotation(AnnotatedElement element, Supplier elemen .map(DisplayName::value) // .filter(StringUtils::isBlank) // .ifPresent(__ -> { - String message = String.format("@DisplayName on %s must be declared with a non-blank value.", + String message = "@DisplayName on %s must be declared with a non-blank value.".formatted( elementDescription.get()); reporter.reportIssue( DiscoveryIssue.builder(Severity.WARNING, message).source(sourceProvider.get()).build()); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java index 976e7df23790..65845e8ecca6 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java @@ -142,11 +142,11 @@ private static Extension readAndValidateExtensionFromField(Field field, Object i List> declarativeExtensionTypes) { Object value = tryToReadFieldValue(field, instance) // .getOrThrow(e -> new PreconditionViolationException( - String.format("Failed to read @RegisterExtension field [%s]", field), e)); + "Failed to read @RegisterExtension field [%s]".formatted(field), e)); - Preconditions.condition(value instanceof Extension, () -> String.format( - "Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.", - field, (value != null ? value.getClass().getName() : null), Extension.class.getName())); + Preconditions.condition(value instanceof Extension, + () -> "Failed to register extension via @RegisterExtension field [%s]: field value's type [%s] must implement an [%s] API.".formatted( + field, (value != null ? value.getClass().getName() : null), Extension.class.getName())); declarativeExtensionTypes.forEach(extensionType -> { Class valueType = value.getClass(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index b9e737463d32..c4052d38ec27 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -85,9 +85,8 @@ static Set getTags(AnnotatedElement element, Supplier elementDe .filter(tag -> { boolean isValid = TestTag.isValid(tag); if (!isValid) { - String message = String.format( - "Invalid tag syntax in @Tag(\"%s\") declaration on %s. Tag will be ignored.", tag, - elementDescription.get()); + String message = "Invalid tag syntax in @Tag(\"%s\") declaration on %s. Tag will be ignored.".formatted( + tag, elementDescription.get()); if (source.get() == null) { source.set(sourceProvider.get()); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java index 1d897c3c27c4..5c633980985c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java @@ -76,8 +76,7 @@ static void validateNoClassTemplateInvocationLifecycleMethodsAreDeclared(Class findClassTemplateInvocationLifecycleMethodAnnotation(method) // .ifPresent(annotation -> { - String message = String.format( - "@%s method '%s' must not be declared in test class '%s' because it is not annotated with @%s.", + String message = "@%s method '%s' must not be declared in test class '%s' because it is not annotated with @%s.".formatted( annotation.lifecycleMethodAnnotation().getSimpleName(), method.toGenericString(), testClass.getName(), annotation.classTemplateAnnotation().getSimpleName()); issueReporter.reportIssue(createIssue(Severity.ERROR, message, method)); @@ -141,8 +140,7 @@ private static List findMethodsAndCheckVoidReturnType(Class testClass private static Condition isStatic(DiscoveryIssueReporter issueReporter, Function annotationNameProvider) { return issueReporter.createReportingCondition(ModifierSupport::isStatic, method -> { - String message = String.format( - "@%s method '%s' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).", + String message = "@%s method '%s' must be static unless the test class is annotated with @TestInstance(Lifecycle.PER_CLASS).".formatted( annotationNameProvider.apply(method), method.toGenericString()); return createIssue(Severity.ERROR, message, method); }); @@ -151,7 +149,7 @@ private static Condition isStatic(DiscoveryIssueReporter issueReporter, private static Condition isNotStatic(DiscoveryIssueReporter issueReporter, Function annotationNameProvider) { return issueReporter.createReportingCondition(ModifierSupport::isNotStatic, method -> { - String message = String.format("@%s method '%s' must not be static.", annotationNameProvider.apply(method), + String message = "@%s method '%s' must not be static.".formatted(annotationNameProvider.apply(method), method.toGenericString()); return createIssue(Severity.ERROR, message, method); }); @@ -159,7 +157,7 @@ private static Condition isNotStatic(DiscoveryIssueReporter issueReporte private static Condition isNotPrivateError(DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(ModifierSupport::isNotPrivate, method -> { - String message = String.format("@%s method '%s' must not be private.", + String message = "@%s method '%s' must not be private.".formatted( classTemplateInvocationLifecycleMethodAnnotationName(method), method.toGenericString()); return createIssue(Severity.ERROR, message, method); }); @@ -168,8 +166,7 @@ private static Condition isNotPrivateError(DiscoveryIssueReporter issueR private static Condition isNotPrivateWarning(DiscoveryIssueReporter issueReporter, Supplier annotationNameProvider) { return issueReporter.createReportingCondition(ModifierSupport::isNotPrivate, method -> { - String message = String.format( - "@%s method '%s' should not be private. This will be disallowed in a future release.", + String message = "@%s method '%s' should not be private. This will be disallowed in a future release.".formatted( annotationNameProvider.get(), method.toGenericString()); return createIssue(Severity.WARNING, message, method); }); @@ -178,8 +175,8 @@ private static Condition isNotPrivateWarning(DiscoveryIssueReporter issu private static Condition returnsPrimitiveVoid(DiscoveryIssueReporter issueReporter, Function annotationNameProvider) { return issueReporter.createReportingCondition(method -> getReturnType(method) == void.class, method -> { - String message = String.format("@%s method '%s' must not return a value.", - annotationNameProvider.apply(method), method.toGenericString()); + String message = "@%s method '%s' must not return a value.".formatted(annotationNameProvider.apply(method), + method.toGenericString()); return createIssue(Severity.ERROR, message, method); }); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java index 4af8de8080e7..c4d9af414bee 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java @@ -88,7 +88,7 @@ public final Set getTags() { @Override public String getLegacyReportingName() { - return String.format("%s(%s)", getTestMethod().getName(), + return "%s(%s)".formatted(getTestMethod().getName(), ClassUtils.nullSafeToString(Class::getSimpleName, getTestMethod().getParameterTypes())); } @@ -114,7 +114,7 @@ public List> getEnclosingTestClasses() { public void validate(DiscoveryIssueReporter reporter) { Validatable.reportAndClear(this.methodInfo.discoveryIssues, reporter); DisplayNameUtils.validateAnnotation(getTestMethod(), // - () -> String.format("method '%s'", getTestMethod().toGenericString()), // + () -> "method '%s'".formatted(getTestMethod().toGenericString()), // // Use _declaring_ class here because that's where the `@DisplayName` annotation is declared () -> MethodSource.from(getTestMethod()), // reporter); @@ -178,7 +178,7 @@ protected void invokeTestWatchers(JupiterEngineExecutionContext context, boolean UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); ExtensionContext extensionContext = context.getExtensionContext(); logger.warn(throwable, - () -> String.format("Failed to invoke TestWatcher [%s] for method [%s] with display name [%s]", + () -> "Failed to invoke TestWatcher [%s] for method [%s] with display name [%s]".formatted( watcher.getClass().getName(), ReflectionUtils.getFullyQualifiedMethodName(extensionContext.getRequiredTestClass(), extensionContext.getRequiredTestMethod()), @@ -209,7 +209,7 @@ private static class MethodInfo { this.testClass = Preconditions.notNull(testClass, "Class must not be null"); this.testMethod = testMethod; this.tags = getTags(testMethod, // - () -> String.format("method '%s'", testMethod.toGenericString()), // + () -> "method '%s'".formatted(testMethod.toGenericString()), // // Use _declaring_ class here because that's where the `@Tag` annotation is declared () -> MethodSource.from(testMethod.getDeclaringClass(), testMethod), // discoveryIssues::add); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java index 5b8183513ed1..0c6674299e42 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java @@ -141,7 +141,7 @@ private Stream toDynamicNodeStream(Object testFactoryMethodResult) } private JUnitException invalidReturnTypeException(Throwable cause) { - String message = String.format("Objects produced by @TestFactory method '%s' must be of type %s.", + String message = "Objects produced by @TestFactory method '%s' must be of type %s.".formatted( getTestMethod().toGenericString(), DynamicNode.class.getName()); return new JUnitException(message, cause); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateTestDescriptor.java index 90a0515e1e00..32cbbcc8a4a2 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateTestDescriptor.java @@ -127,7 +127,7 @@ boolean supports(TestTemplateInvocationContextProvider provider, ExtensionContex @Override protected String getNoRegisteredProviderErrorMessage() { - return String.format("You must register at least one %s that supports @%s method [%s]", + return "You must register at least one %s that supports @%s method [%s]".formatted( TestTemplateInvocationContextProvider.class.getSimpleName(), TestTemplate.class.getSimpleName(), getTestMethod()); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/UniqueIdPrefixTransformer.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/UniqueIdPrefixTransformer.java index 20a85ba1382b..7389c307b905 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/UniqueIdPrefixTransformer.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/UniqueIdPrefixTransformer.java @@ -34,7 +34,7 @@ class UniqueIdPrefixTransformer implements UnaryOperator { @Override public UniqueId apply(UniqueId uniqueId) { Preconditions.condition(uniqueId.hasPrefix(oldPrefix), - () -> String.format("Unique ID %s does not have the expected prefix %s", uniqueId, oldPrefix)); + () -> "Unique ID %s does not have the expected prefix %s".formatted(uniqueId, oldPrefix)); List oldSegments = uniqueId.getSegments(); List suffix = oldSegments.subList(oldPrefixLength, oldSegments.size()); UniqueId newValue = newPrefix; 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..abe7b7e64eb7 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 @@ -49,8 +49,7 @@ 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.", + String message = "Ineffective @Order annotation on class '%s'. It will not be applied because ClassOrderer.OrderAnnotation is not in use.".formatted( testDescriptor.getTestClass().getName()); return DiscoveryIssue.builder(Severity.INFO, message) // .source(ClassSource.from(testDescriptor.getTestClass())) // @@ -132,11 +131,9 @@ private DescriptorWrapperOrderer createDes Consumer> orderingAction = classDescriptors -> classOrderer.orderClasses( new DefaultClassOrdererContext(classDescriptors, this.configuration)); - MessageGenerator descriptorsAddedMessageGenerator = number -> String.format( - "ClassOrderer [%s] added %s ClassDescriptor(s) which will be ignored.", classOrderer.getClass().getName(), - number); - MessageGenerator descriptorsRemovedMessageGenerator = number -> String.format( - "ClassOrderer [%s] removed %s ClassDescriptor(s) which will be retained with arbitrary ordering.", + MessageGenerator descriptorsAddedMessageGenerator = number -> "ClassOrderer [%s] added %s ClassDescriptor(s) which will be ignored.".formatted( + classOrderer.getClass().getName(), number); + MessageGenerator descriptorsRemovedMessageGenerator = number -> "ClassOrderer [%s] removed %s ClassDescriptor(s) which will be retained with arbitrary ordering.".formatted( classOrderer.getClass().getName(), number); return new DescriptorWrapperOrderer<>(classOrderer, orderingAction, descriptorsAddedMessageGenerator, 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 19480129303e..4eeb93e4bb70 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 @@ -113,8 +113,7 @@ public Resolution resolve(NestedClassSelector selector, Context context) { } } else if (isInnerClass(nestedClass) && predicates.looksLikeIntendedTestClass(nestedClass)) { - String message = String.format( - "Inner class '%s' looks like it was intended to be a test class but will not be executed. It must be static or annotated with @Nested.", + String message = "Inner class '%s' looks like it was intended to be a test class but will not be executed. It must be static or annotated with @Nested.".formatted( nestedClass.getName()); issueReporter.reportIssue(DiscoveryIssue.builder(Severity.WARNING, message) // .source(ClassSource.from(nestedClass))); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodFinder.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodFinder.java index 59fc6e356012..10bb24ab5139 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodFinder.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodFinder.java @@ -30,7 +30,7 @@ Optional findMethod(String methodSpecPart, Class clazz) { Matcher matcher = METHOD_PATTERN.matcher(methodSpecPart); Preconditions.condition(matcher.matches(), - () -> String.format("Method [%s] does not match pattern [%s]", methodSpecPart, METHOD_PATTERN)); + () -> "Method [%s] does not match pattern [%s]".formatted(methodSpecPart, METHOD_PATTERN)); String methodName = matcher.group(1); String parameterTypeNames = matcher.group(2); 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 471b9ecf8368..b4b2352aeafe 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 @@ -45,8 +45,7 @@ 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.", + String message = "Ineffective @Order annotation on method '%s'. It will not be applied because MethodOrderer.OrderAnnotation is not in use.".formatted( testDescriptor.getTestMethod().toGenericString()); return DiscoveryIssue.builder(Severity.INFO, message) // .source(MethodSource.from(testDescriptor.getTestMethod())) // @@ -112,11 +111,9 @@ private DescriptorWrapperOrderer createDescriptorWra Consumer> orderingAction = methodDescriptors -> methodOrderer.orderMethods( new DefaultMethodOrdererContext(testClass, methodDescriptors, this.configuration)); - MessageGenerator descriptorsAddedMessageGenerator = number -> String.format( - "MethodOrderer [%s] added %s MethodDescriptor(s) for test class [%s] which will be ignored.", + MessageGenerator descriptorsAddedMessageGenerator = number -> "MethodOrderer [%s] added %s MethodDescriptor(s) for test class [%s] which will be ignored.".formatted( methodOrderer.getClass().getName(), number, testClass.getName()); - MessageGenerator descriptorsRemovedMessageGenerator = number -> String.format( - "MethodOrderer [%s] removed %s MethodDescriptor(s) for test class [%s] which will be retained with arbitrary ordering.", + MessageGenerator descriptorsRemovedMessageGenerator = number -> "MethodOrderer [%s] removed %s MethodDescriptor(s) for test class [%s] which will be retained with arbitrary ordering.".formatted( methodOrderer.getClass().getName(), number, testClass.getName()); return new DescriptorWrapperOrderer<>(methodOrderer, orderingAction, descriptorsAddedMessageGenerator, diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java index 09b021766f72..57d9a64ad198 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java @@ -236,7 +236,7 @@ private TestDescriptor createTestDescriptor(TestDescriptor parent, Class test } private UniqueId createUniqueId(Method method, TestDescriptor parent) { - String methodId = String.format("%s(%s)", method.getName(), + String methodId = "%s(%s)".formatted(method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); return parent.getUniqueId().append(segmentType, methodId); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java index 07fbcc51a80c..aa4b693d8443 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java @@ -40,8 +40,7 @@ @API(status = INTERNAL, since = "5.0") public class IsTestFactoryMethod extends IsTestableMethod { - private static final String EXPECTED_RETURN_TYPE_MESSAGE = String.format( - "must return a single %1$s or a Stream, Collection, Iterable, Iterator, Iterator provider, or array of %1$s", + private static final String EXPECTED_RETURN_TYPE_MESSAGE = "must return a single %1$s or a Stream, Collection, Iterable, Iterator, Iterator provider, or array of %1$s".formatted( DynamicNode.class.getName()); public IsTestFactoryMethod(DiscoveryIssueReporter issueReporter) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java index 089fef2e4bbc..2497598f3e96 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestableMethod.java @@ -77,7 +77,7 @@ protected static Condition hasVoidReturnType(Class protected static DiscoveryIssue createIssue(Class annotationType, Method method, String condition) { - String message = String.format("@%s method '%s' %s. It will not be executed.", annotationType.getSimpleName(), + String message = "@%s method '%s' %s. It will not be executed.".formatted(annotationType.getSimpleName(), method.toGenericString(), condition); return DiscoveryIssue.builder(Severity.WARNING, message) // .source(MethodSource.from(method)) // 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 6dceea4dfb98..5e48b659f46b 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 @@ -126,7 +126,7 @@ 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(), + String message = "%s class '%s' %s. It will not be executed.".formatted(prefix, testClass.getName(), detailMessage); return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message) // .source(ClassSource.from(testClass)) // diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluator.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluator.java index e51126bec2ef..c8c4ee3899c0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluator.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluator.java @@ -10,7 +10,6 @@ package org.junit.jupiter.engine.execution; -import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; @@ -71,14 +70,14 @@ private ConditionEvaluationResult evaluate(ExecutionCondition condition, Extensi } private void logResult(Class conditionType, ConditionEvaluationResult result, ExtensionContext context) { - logger.trace(() -> format("Evaluation of condition [%s] on [%s] resulted in: %s", conditionType.getName(), + logger.trace(() -> "Evaluation of condition [%s] on [%s] resulted in: %s".formatted(conditionType.getName(), context.getElement().orElse(null), result)); } private ConditionEvaluationException evaluationException(Class conditionType, Exception ex) { String cause = StringUtils.isNotBlank(ex.getMessage()) ? ": " + ex.getMessage() : ""; return new ConditionEvaluationException( - format("Failed to evaluate condition [%s]%s", conditionType.getName(), cause), ex); + "Failed to evaluate condition [%s]%s".formatted(conditionType.getName(), cause), ex); } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java index 92f9cd7c7bf7..efd12ab21592 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java @@ -135,7 +135,7 @@ private static Object resolveParameter(ParameterContext parameterContext, Execut if (matchingResolvers.isEmpty()) { throw new ParameterResolutionException( - String.format("No ParameterResolver registered for parameter [%s] in %s [%s].", + "No ParameterResolver registered for parameter [%s] in %s [%s].".formatted( parameterContext.getParameter(), asLabel(executable), executable.toGenericString())); } @@ -146,7 +146,7 @@ private static Object resolveParameter(ParameterContext parameterContext, Execut .collect(joining(", ")); // @formatter:on throw new ParameterResolutionException( - String.format("Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s", + "Discovered multiple competing ParameterResolvers for parameter [%s] in %s [%s]: %s".formatted( parameterContext.getParameter(), asLabel(executable), executable.toGenericString(), resolvers)); } @@ -154,10 +154,10 @@ private static Object resolveParameter(ParameterContext parameterContext, Execut Object value = resolver.resolveParameter(parameterContext, extensionContext.get(resolver)); validateResolvedType(parameterContext.getParameter(), value, executable, resolver); - logger.trace(() -> String.format( - "ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s].", - resolver.getClass().getName(), (value != null ? value.getClass().getName() : null), - parameterContext.getParameter(), asLabel(executable), executable.toGenericString())); + logger.trace( + () -> "ParameterResolver [%s] resolved a value of type [%s] for parameter [%s] in %s [%s].".formatted( + resolver.getClass().getName(), (value != null ? value.getClass().getName() : null), + parameterContext.getParameter(), asLabel(executable), executable.toGenericString())); return value; } @@ -167,8 +167,8 @@ private static Object resolveParameter(ParameterContext parameterContext, Execut catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); - String message = String.format("Failed to resolve parameter [%s] in %s [%s]", - parameterContext.getParameter(), asLabel(executable), executable.toGenericString()); + String message = "Failed to resolve parameter [%s] in %s [%s]".formatted(parameterContext.getParameter(), + asLabel(executable), executable.toGenericString()); if (StringUtils.isNotBlank(throwable.getMessage())) { message += ": " + throwable.getMessage(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java index 07f10d636e4b..d9f41da9e8f4 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java @@ -75,7 +75,7 @@ private static void closeField(Field field, Object testInstance) throws Exceptio Object fieldValue = ReflectionSupport.tryToReadFieldValue(field, testInstance).get(); if (fieldValue == null) { - logger.warn(() -> String.format("Cannot @AutoClose field %s because it is null.", getQualifiedName(field))); + logger.warn(() -> "Cannot @AutoClose field %s because it is null.".formatted(getQualifiedName(field))); } else { invokeCloseMethod(field, fieldValue, methodName.trim()); @@ -92,15 +92,15 @@ private static void invokeCloseMethod(Field field, Object target, String methodN Class targetType = target.getClass(); Method closeMethod = ReflectionSupport.findMethod(targetType, methodName).orElseThrow( () -> new ExtensionConfigurationException( - String.format("Cannot @AutoClose field %s because %s does not define method %s().", - getQualifiedName(field), targetType.getName(), methodName))); + "Cannot @AutoClose field %s because %s does not define method %s().".formatted(getQualifiedName(field), + targetType.getName(), methodName))); closeMethod = ReflectionUtils.getInterfaceMethodIfPossible(closeMethod, targetType); ReflectionSupport.invokeMethod(closeMethod, target); } private static void checkCondition(boolean condition, String messageFormat, Field field) { - Preconditions.condition(condition, () -> String.format(messageFormat, getQualifiedName(field))); + Preconditions.condition(condition, () -> messageFormat.formatted(getQualifiedName(field))); } private static String getQualifiedName(Field field) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index eac99fe980f7..43927d66d3c8 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -124,8 +124,8 @@ private static void logExcludedExtensions(List> exclu .map(Class::getName) .collect(Collectors.toList()); // @formatter:on - logger.config(() -> String.format( - "Excluded auto-detected extensions due to configured includes/excludes: %s", excludeExtensionNames)); + logger.config(() -> "Excluded auto-detected extensions due to configured includes/excludes: %s".formatted( + excludeExtensionNames)); } } @@ -218,8 +218,8 @@ public void registerUninitializedExtension(Class testClass, Field source, Preconditions.notNull(source, "source must not be null"); Preconditions.notNull(initializer, "initializer must not be null"); - logger.trace(() -> String.format("Registering local extension (late-init) for [%s]%s", - source.getType().getName(), buildSourceInfo(source))); + logger.trace(() -> "Registering local extension (late-init) for [%s]%s".formatted(source.getType().getName(), + buildSourceInfo(source))); LateInitEntry entry = getLateInitExtensions(testClass) // .add(new LateInitEntry(testClass, initializer)); @@ -261,8 +261,7 @@ private void registerExtension(String category, Extension extension, Object sour Preconditions.notBlank(category, "category must not be null or blank"); Preconditions.notNull(extension, "extension must not be null"); - logger.trace( - () -> String.format("Registering %s extension [%s]%s", category, extension, buildSourceInfo(source))); + logger.trace(() -> "Registering %s extension [%s]%s".formatted(category, extension, buildSourceInfo(source))); this.registeredExtensions.add(Entry.of(extension)); this.registeredExtensionTypes.add(extension.getClass()); @@ -275,7 +274,7 @@ private String buildSourceInfo(Object source) { if (source instanceof Member) { Member member = (Member) source; Object type = (member instanceof Method ? "method" : "field"); - source = String.format("%s %s.%s", type, member.getDeclaringClass().getName(), member.getName()); + source = "%s %s.%s".formatted(type, member.getDeclaringClass().getName(), member.getName()); } return " from source [" + source + "]"; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestExtension.java index efdcfdc8d679..46b91c5e8a77 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestExtension.java @@ -57,8 +57,9 @@ public Stream provideTestTemplateInvocationContex private int totalRepetitions(RepeatedTest repeatedTest, Method method) { int repetitions = repeatedTest.value(); - Preconditions.condition(repetitions > 0, () -> String.format( - "Configuration error: @RepeatedTest on method [%s] must be declared with a positive 'value'.", method)); + Preconditions.condition(repetitions > 0, + () -> "Configuration error: @RepeatedTest on method [%s] must be declared with a positive 'value'.".formatted( + method)); return repetitions; } @@ -76,8 +77,9 @@ private int failureThreshold(RepeatedTest repeatedTest, Method method) { private RepeatedTestDisplayNameFormatter displayNameFormatter(RepeatedTest repeatedTest, Method method, String displayName) { - String pattern = Preconditions.notBlank(repeatedTest.name().trim(), () -> String.format( - "Configuration error: @RepeatedTest on method [%s] must be declared with a non-empty name.", method)); + String pattern = Preconditions.notBlank(repeatedTest.name().trim(), + () -> "Configuration error: @RepeatedTest on method [%s] must be declared with a non-empty name.".formatted( + method)); return new RepeatedTestDisplayNameFormatter(pattern, displayName); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java index 900a98e10d85..45a97565d663 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java @@ -311,7 +311,7 @@ public void close() throws IOException { try { if (this.cleanupMode == NEVER || (this.cleanupMode == ON_SUCCESS && selfOrChildFailed(this.extensionContext))) { - LOGGER.info(() -> String.format("Skipping cleanup of temp dir %s for %s due to CleanupMode.%s.", + LOGGER.info(() -> "Skipping cleanup of temp dir %s for %s due to CleanupMode.%s.".formatted( this.dir, descriptionFor(this.annotatedElement), this.cleanupMode.name())); return; } @@ -364,7 +364,7 @@ private static String descriptionFor(Executable executable) { boolean isConstructor = executable instanceof Constructor; String type = isConstructor ? "constructor" : "method"; String name = isConstructor ? executable.getDeclaringClass().getSimpleName() : executable.getName(); - return String.format("%s %s(%s)", type, name, + return "%s %s(%s)".formatted(type, name, ClassUtils.nullSafeToString(Class::getSimpleName, executable.getParameterTypes())); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutConfiguration.java index 60a8734db382..42831f0e737d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutConfiguration.java @@ -105,7 +105,7 @@ private Optional parseTimeoutDuration(String propertyName) { } catch (Exception e) { logger.warn(e, - () -> String.format("Ignored invalid timeout '%s' set via the '%s' configuration parameter.", value, + () -> "Ignored invalid timeout '%s' set via the '%s' configuration parameter.".formatted(value, key)); return null; } @@ -128,17 +128,17 @@ private Optional parseTimeoutThreadModeConfiguration() { try { ThreadMode threadMode = ThreadMode.valueOf(value.toUpperCase()); if (threadMode == ThreadMode.INFERRED) { - logger.warn(() -> String.format( - "Invalid timeout thread mode '%s', only %s and %s can be used as configuration parameter for %s.", - value, SAME_THREAD, SEPARATE_THREAD, DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); + logger.warn( + () -> "Invalid timeout thread mode '%s', only %s and %s can be used as configuration parameter for %s.".formatted( + value, SAME_THREAD, SEPARATE_THREAD, DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); return null; } return threadMode; } catch (Exception e) { logger.warn(e, - () -> String.format("Invalid timeout thread mode '%s' set via the '%s' configuration parameter.", - value, DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); + () -> "Invalid timeout thread mode '%s' set via the '%s' configuration parameter.".formatted(value, + DEFAULT_TIMEOUT_THREAD_MODE_PROPERTY_NAME)); return null; } }); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java index 41174c609857..e911ac35ad74 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java @@ -23,7 +23,7 @@ private TimeoutExceptionFactory() { } static TimeoutException create(String methodSignature, TimeoutDuration timeoutDuration, Throwable failure) { - String message = String.format("%s timed out after %s", + String message = "%s timed out after %s".formatted( Preconditions.notNull(methodSignature, "method signature must not be null"), Preconditions.notNull(timeoutDuration, "timeout duration must not be null")); TimeoutException timeoutException = new TimeoutException(message); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java index f7fd783d077a..555fb053ad1b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java @@ -202,7 +202,7 @@ private String describe(ReflectiveInvocationContext invocationContext, E Method method = invocationContext.getExecutable(); Optional> testClass = extensionContext.getTestClass(); if (testClass.isPresent() && invocationContext.getTargetClass().equals(testClass.get())) { - return String.format("%s(%s)", method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); + return "%s(%s)".formatted(method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); } return ReflectionUtils.getFullyQualifiedMethodName(invocationContext.getTargetClass(), method); } diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java index 5c60dcf5df24..d54bdaf1fc52 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java @@ -43,7 +43,7 @@ protected Object executeMethod(String name) { protected Object executeMethod(String methodName, Class[] parameterTypes, Object... arguments) { Method method = findMethod(this.target.getClass(), methodName, parameterTypes).orElseThrow( - () -> new JUnitException(String.format("Failed to find method %s(%s) in class %s", methodName, + () -> new JUnitException("Failed to find method %s(%s) in class %s".formatted(methodName, ClassUtils.nullSafeToString(parameterTypes), this.target.getClass().getName()))); return invokeMethod(method, this.target, arguments); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java index 322aa34d557d..706f33971cb5 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java @@ -45,12 +45,12 @@ void validate(ExtensionContext extensionContext) { int consumedCount = this.declarationContext.getResolverFacade().determineConsumedArgumentCount( this.arguments); int totalCount = this.arguments.getTotalLength(); - Preconditions.condition(consumedCount == totalCount, () -> String.format( - "Configuration error: @%s consumes %s %s but there %s %s %s provided.%nNote: the provided arguments were %s", - this.declarationContext.getAnnotationName(), consumedCount, - pluralize(consumedCount, "parameter", "parameters"), pluralize(totalCount, "was", "were"), - totalCount, pluralize(totalCount, "argument", "arguments"), - Arrays.toString(this.arguments.getAllPayloads()))); + Preconditions.condition(consumedCount == totalCount, + () -> "Configuration error: @%s consumes %s %s but there %s %s %s provided.%nNote: the provided arguments were %s".formatted( + this.declarationContext.getAnnotationName(), consumedCount, + pluralize(consumedCount, "parameter", "parameters"), pluralize(totalCount, "was", "were"), + totalCount, pluralize(totalCount, "argument", "arguments"), + Arrays.toString(this.arguments.getAllPayloads()))); break; default: throw new ExtensionConfigurationException( @@ -80,9 +80,9 @@ private ArgumentCountValidationMode getArgumentCountValidationModeConfiguration( ArgumentCountValidationMode.values()).filter( mode -> mode.name().equalsIgnoreCase(configValue)).findFirst(); if (enumValue.isPresent()) { - logger.config(() -> String.format( - "Using ArgumentCountValidationMode '%s' set via the '%s' configuration parameter.", - enumValue.get().name(), key)); + logger.config( + () -> "Using ArgumentCountValidationMode '%s' set via the '%s' configuration parameter.".formatted( + enumValue.get().name(), key)); return enumValue.get(); } else { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java index 623f262ddc91..65202b04b828 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java @@ -86,7 +86,7 @@ Optional getName() { private static Object[] dropSurplus(Object[] arguments, int newLength) { Preconditions.condition(newLength <= arguments.length, - () -> String.format("New length %d must be less than or equal to the total length %d", newLength, + () -> "New length %d must be less than or equal to the total length %d".formatted(newLength, arguments.length)); return arguments.length > newLength ? Arrays.copyOf(arguments, newLength) : arguments; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContextProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContextProvider.java index 77e5a98059b7..bacf1504fded 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContextProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContextProvider.java @@ -55,8 +55,7 @@ protected Stream provideInvocationContexts(ExtensionContext extensionContext, private static void validateInvokedAtLeastOnce(long invocationCount, ParameterizedDeclarationContext declarationContext) { if (invocationCount == 0 && !declarationContext.isAllowingZeroInvocations()) { - String message = String.format( - "Configuration error: You must configure at least one set of arguments for this @%s", + String message = "Configuration error: You must configure at least one set of arguments for this @%s".formatted( declarationContext.getAnnotationName()); throw new TemplateInvocationValidationException(message); } @@ -67,7 +66,7 @@ private static List collectArgumentSources(ParameterizedDeclara ArgumentsSource.class); Preconditions.notEmpty(argumentsSources, - () -> String.format("Configuration error: You must configure at least one arguments source for this @%s", + () -> "Configuration error: You must configure at least one arguments source for this @%s".formatted( declarationContext.getAnnotationName())); return argumentsSources; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java index 1f1e9f103e65..ebaf50c536df 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java @@ -59,10 +59,10 @@ static ParameterizedInvocationNameFormatter create(ExtensionContext extensionCon ? extensionContext.getConfigurationParameter(DISPLAY_NAME_PATTERN_KEY) // .orElse(DEFAULT_DISPLAY_NAME_PATTERN) : name; - pattern = Preconditions.notBlank(pattern.trim(), () -> String.format( - "Configuration error: @%s on %s must be declared with a non-empty name.", - declarationContext.getAnnotationName(), - declarationContext.getResolverFacade().getIndexedParameterDeclarations().getSourceElementDescription())); + pattern = Preconditions.notBlank(pattern.trim(), + () -> "Configuration error: @%s on %s must be declared with a non-empty name.".formatted( + declarationContext.getAnnotationName(), + declarationContext.getResolverFacade().getIndexedParameterDeclarations().getSourceElementDescription())); int argumentMaxLength = extensionContext.getConfigurationParameter(ARGUMENT_MAX_LENGTH_KEY, Integer::parseInt) // .orElse(512); @@ -243,9 +243,9 @@ public void append(ArgumentsContext context, StringBuffer result) { result.append(context.argumentSetName.get()); return; } - throw new ExtensionConfigurationException(String.format( - "When the display name pattern for a @%s contains %s, the arguments must be supplied as an ArgumentSet.", - this.annotationName, ARGUMENT_SET_NAME_PLACEHOLDER)); + throw new ExtensionConfigurationException( + "When the display name pattern for a @%s contains %s, the arguments must be supplied as an ArgumentSet.".formatted( + this.annotationName, ARGUMENT_SET_NAME_PLACEHOLDER)); } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestSpiInstantiator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestSpiInstantiator.java index 1545d292a062..bed7e1b61a3b 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestSpiInstantiator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestSpiInstantiator.java @@ -49,7 +49,7 @@ private static Constructor findBestConstructor(Class spiInterface, Class implementationClass) { Preconditions.condition(!ReflectionUtils.isInnerClass(implementationClass), - () -> String.format("The %s [%s] must be either a top-level class or a static nested class", + () -> "The %s [%s] must be either a top-level class or a static nested class".formatted( spiInterface.getSimpleName(), implementationClass.getName())); Constructor[] constructors = implementationClass.getDeclaredConstructors(); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 2ca2590df654..6507d0096549 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -242,7 +242,7 @@ ArgumentSetLifecycleMethod.ParameterResolver createLifecycleMethodParameterResol () -> new DefaultArgumentSetLifecycleMethodParameterResolver(originalResolverFacade, lifecycleMethodResolverFacade, parameterDeclarationMapping))) // .getOrThrow(cause -> new ExtensionConfigurationException( - String.format("Invalid @%s lifecycle method declaration: %s", + "Invalid @%s lifecycle method declaration: %s".formatted( annotation.annotationType().getSimpleName(), method.toGenericString()), cause)); } @@ -347,13 +347,13 @@ private static List validateLifecycleMethodParameters(Method method, Ann break; } if (!actualDeclaration.getParameterType().equals(originalDeclaration.getParameterType())) { - errors.add(String.format( - "parameter%s with index %d is incompatible with the parameter declared on the parameterized class: expected type '%s' but found '%s'", - parameterName(actualDeclaration), parameterIndex, originalDeclaration.getParameterType(), - actualDeclaration.getParameterType())); + errors.add( + "parameter%s with index %d is incompatible with the parameter declared on the parameterized class: expected type '%s' but found '%s'".formatted( + parameterName(actualDeclaration), parameterIndex, originalDeclaration.getParameterType(), + actualDeclaration.getParameterType())); } else if (findAnnotation(actualDeclaration.getAnnotatedElement(), ConvertWith.class).isPresent()) { - errors.add(String.format("parameter%s with index %d must not be annotated with @ConvertWith", + errors.add("parameter%s with index %d must not be annotated with @ConvertWith".formatted( parameterName(actualDeclaration), parameterIndex)); } else if (errors.isEmpty()) { @@ -375,7 +375,7 @@ else if (errors.size() == 1) { throw new PreconditionViolationException("Configuration error: " + errors.get(0) + "."); } else { - throw new PreconditionViolationException(String.format("%d configuration errors:%n%s", errors.size(), + throw new PreconditionViolationException("%d configuration errors:%n%s".formatted(errors.size(), errors.stream().collect(joining(lineSeparator() + "- ", "- ", "")))); } } @@ -392,7 +392,7 @@ private static void validateIndexedParameters( for (int index = 0; index <= indexedParameters.lastKey(); index++) { if (!indexedParameters.containsKey(index)) { - errors.add(String.format("no field annotated with @Parameter(%d) declared", index)); + errors.add("no field annotated with @Parameter(%d) declared".formatted(index)); } } } @@ -402,18 +402,17 @@ private static void validateIndexedParameterDeclarations(int index, List fields = declarations.stream().map(FieldParameterDeclaration::getField).collect(toList()); if (index < 0) { declarations.stream() // - .map(declaration -> String.format( - "index must be greater than or equal to zero in @Parameter(%d) annotation on field [%s]", index, - declaration.getField())) // + .map( + declaration -> "index must be greater than or equal to zero in @Parameter(%d) annotation on field [%s]".formatted( + index, declaration.getField())) // .forEach(errors::add); } else if (declarations.size() > 1) { - errors.add( - String.format("duplicate index declared in @Parameter(%d) annotation on fields %s", index, fields)); + errors.add("duplicate index declared in @Parameter(%d) annotation on fields %s".formatted(index, fields)); } fields.stream() // .filter(ModifierSupport::isFinal) // - .map(field -> String.format("@Parameter field [%s] must not be declared as final", field)) // + .map(field -> "@Parameter field [%s] must not be declared as final".formatted(field)) // .forEach(errors::add); } @@ -421,9 +420,9 @@ private static void validateAggregatorParameters(Set List errors) { aggregatorParameters.stream() // .filter(declaration -> declaration.getParameterIndex() != Parameter.UNSET_INDEX) // - .map(declaration -> String.format( - "no index may be declared in @Parameter(%d) annotation on aggregator field [%s]", - declaration.getParameterIndex(), declaration.getField())) // + .map( + declaration -> "no index may be declared in @Parameter(%d) annotation on aggregator field [%s]".formatted( + declaration.getParameterIndex(), declaration.getField())) // .forEach(errors::add); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java index 40bf7213e1c7..62750bbae9e8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java @@ -10,7 +10,6 @@ package org.junit.jupiter.params.aggregator; -import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; @@ -61,7 +60,7 @@ private DefaultArgumentsAccessor(BiFunction, Object> converter, @Override public Object get(int index) { Preconditions.condition(index >= 0 && index < this.arguments.length, - () -> format("index must be >= 0 and < %d", this.arguments.length)); + () -> "index must be >= 0 and < %d".formatted(this.arguments.length)); return this.arguments[index]; } @@ -74,8 +73,7 @@ public T get(int index, Class requiredType) { return requiredType.cast(convertedValue); } catch (Exception ex) { - String message = format( - "Argument at index [%d] with value [%s] and type [%s] could not be converted or cast to type [%s].", + String message = "Argument at index [%d] with value [%s] and type [%s] could not be converted or cast to type [%s].".formatted( index, value, ClassUtils.nullSafeToString(value == null ? null : value.getClass()), requiredType.getName()); throw new ArgumentAccessException(message, ex); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java index eea0e734508a..3ac11b1c4a82 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java @@ -119,9 +119,8 @@ public final Object convert(Object source, Class targetType, ClassLoader clas } } - throw new ArgumentConversionException( - String.format("No built-in converter for source type %s and target type %s", - source.getClass().getTypeName(), targetType.getTypeName())); + throw new ArgumentConversionException("No built-in converter for source type %s and target type %s".formatted( + source.getClass().getTypeName(), targetType.getTypeName())); } private LocaleConversionFormat getLocaleConversionFormat() { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java index 949cba18590c..79b7a42d1549 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java @@ -62,13 +62,12 @@ private T convert(Object source, Class actualTargetType) { return convert(null); } if (!this.sourceType.isInstance(source)) { - String message = String.format( - "%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.", + String message = "%s cannot convert objects of type [%s]. Only source objects of type [%s] are supported.".formatted( getClass().getSimpleName(), source.getClass().getName(), this.sourceType.getName()); throw new ArgumentConversionException(message); } if (!ReflectionUtils.isAssignableTo(this.targetType, actualTargetType)) { - String message = String.format("%s cannot convert to type [%s]. Only target type [%s] is supported.", + String message = "%s cannot convert to type [%s]. Only target type [%s] is supported.".formatted( getClass().getSimpleName(), actualTargetType.getName(), this.targetType.getName()); throw new ArgumentConversionException(message); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index f5d25363c379..2b40f6cae7ac 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -125,8 +125,7 @@ static Arguments processCsvRecord(Object[] csvRecord, Set nullValues, bo } Preconditions.condition(!useHeadersInDisplayName || (csvRecord.length <= headers.length), - () -> String.format( - "The number of columns (%d) exceeds the number of supplied headers (%d) in CSV record: %s", + () -> "The number of columns (%d) exceeds the number of supplied headers (%d) in CSV record: %s".formatted( csvRecord.length, headers.length, Arrays.toString(csvRecord))); Object[] arguments = new Object[csvRecord.length]; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java index 65657724932e..9c9b4f5a8173 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EmptyArgumentsProvider.java @@ -45,7 +45,7 @@ public Stream provideArguments(ParameterDeclarations parame Optional firstParameter = parameters.getFirst(); Preconditions.condition(firstParameter.isPresent(), - () -> String.format("@EmptySource cannot provide an empty argument to %s: no formal parameters declared.", + () -> "@EmptySource cannot provide an empty argument to %s: no formal parameters declared.".formatted( parameters.getSourceElementDescription())); Class parameterType = firstParameter.get().getParameterType(); @@ -89,7 +89,7 @@ public Stream provideArguments(ParameterDeclarations parame } // else throw new PreconditionViolationException( - String.format("@EmptySource cannot provide an empty argument to %s: [%s] is not a supported type.", + "@EmptySource cannot provide an empty argument to %s: [%s] is not a supported type.".formatted( parameters.getSourceElementDescription(), parameterType.getName())); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java index e234e3a7f722..ce657e281418 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java @@ -56,8 +56,7 @@ private > Set getEnumConstants(ParameterDeclarati E from = enumSource.from().isEmpty() ? constants[0] : Enum.valueOf(enumClass, enumSource.from()); E to = enumSource.to().isEmpty() ? constants[constants.length - 1] : Enum.valueOf(enumClass, enumSource.to()); Preconditions.condition(from.compareTo(to) <= 0, - () -> String.format( - "Invalid enum range: 'from' (%s) must come before 'to' (%s) in the natural order of enum constants.", + () -> "Invalid enum range: 'from' (%s) must come before 'to' (%s) in the natural order of enum constants.".formatted( from, to)); return EnumSet.range(from, to); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java index 944419c351a6..ea8b439e4f48 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java @@ -90,8 +90,8 @@ static Field findField(Class testClass, String fieldName) { .findFirst()// .orElse(null); - Preconditions.notNull(field, - () -> format("Could not find field named [%s] in class [%s]", resolvedFieldName, resolvedClass.getName())); + Preconditions.notNull(field, () -> "Could not find field named [%s] in class [%s]".formatted(resolvedFieldName, + resolvedClass.getName())); return field; } @@ -106,22 +106,22 @@ private static Field validateField(Field field, Object testInstance) { private static Object readField(Field field, Object testInstance) { Object value = ReflectionSupport.tryToReadFieldValue(field, testInstance).getOrThrow( - cause -> new JUnitException(format("Could not read field [%s]", field.getName()), cause)); + cause -> new JUnitException("Could not read field [%s]".formatted(field.getName()), cause)); String fieldName = field.getName(); String declaringClass = field.getDeclaringClass().getName(); Preconditions.notNull(value, - () -> format("The value of field [%s] in class [%s] must not be null", fieldName, declaringClass)); + () -> "The value of field [%s] in class [%s] must not be null".formatted(fieldName, declaringClass)); Preconditions.condition(!(value instanceof BaseStream), - () -> format("The value of field [%s] in class [%s] must not be a stream", fieldName, declaringClass)); + () -> "The value of field [%s] in class [%s] must not be a stream".formatted(fieldName, declaringClass)); Preconditions.condition(!(value instanceof Iterator), - () -> format("The value of field [%s] in class [%s] must not be an Iterator", fieldName, declaringClass)); + () -> "The value of field [%s] in class [%s] must not be an Iterator".formatted(fieldName, declaringClass)); Preconditions.condition(isConvertibleToStream(field, value), - () -> format("The value of field [%s] in class [%s] must be convertible to a Stream", fieldName, + () -> "The value of field [%s] in class [%s] must be convertible to a Stream".formatted(fieldName, declaringClass)); return value; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java index 4a67985cac84..0c112eab5a66 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java @@ -80,9 +80,9 @@ private static Method findFactoryMethod(Class testClass, Optional tes Method factoryMethod = findFactoryMethodByFullyQualifiedName(testClass, testMethod, factoryMethodName); // Ensure factory method has a valid return type and is not a test method. - Preconditions.condition(isFactoryMethod.test(factoryMethod), () -> format( - "Could not find valid factory method [%s] for test class [%s] but found the following invalid candidate: %s", - originalFactoryMethodName, testClass.getName(), factoryMethod)); + Preconditions.condition(isFactoryMethod.test(factoryMethod), + () -> "Could not find valid factory method [%s] for test class [%s] but found the following invalid candidate: %s".formatted( + originalFactoryMethodName, testClass.getName(), factoryMethod)); return factoryMethod; } @@ -129,7 +129,7 @@ static Method findFactoryMethodByFullyQualifiedName(Class testClass, Optional // If we didn't find an exact match but an explicit parameter list was specified, // that's a user configuration error. Preconditions.condition(!explicitParameterListSpecified, - () -> format("Could not find factory method [%s(%s)] in class [%s]", methodName, methodParameters, + () -> "Could not find factory method [%s(%s)] in class [%s]".formatted(methodName, methodParameters, className)); // Otherwise, fall back to the same lenient search semantics that are used @@ -158,17 +158,16 @@ private static Method findFactoryMethodBySimpleName(Class clazz, Optional { if (candidates.isEmpty()) { // Report that we didn't find anything. - return format("Could not find factory method [%s] in class [%s]", factoryMethodName, clazz.getName()); + return "Could not find factory method [%s] in class [%s]".formatted(factoryMethodName, clazz.getName()); } // If we didn't find the factory method using the isFactoryMethod Predicate, perhaps // the specified factory method has an invalid return type or is a test method. // In that case, we report the invalid candidates that were found. - return format( - "Could not find valid factory method [%s] in class [%s] but found the following invalid candidates: %s", + return "Could not find valid factory method [%s] in class [%s] but found the following invalid candidates: %s".formatted( factoryMethodName, clazz.getName(), candidates); }); Preconditions.condition(factoryMethods.size() == 1, - () -> format("%d factory methods named [%s] were found in class [%s]: %s", factoryMethods.size(), + () -> "%d factory methods named [%s] were found in class [%s]: %s".formatted(factoryMethods.size(), factoryMethodName, clazz.getName(), factoryMethods)); return factoryMethods.get(0); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java index 8cafbb51e3cf..e6fb99f84074 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java @@ -29,7 +29,7 @@ class NullArgumentsProvider implements ArgumentsProvider { @Override public Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) { Preconditions.condition(parameters.getFirst().isPresent(), - () -> String.format("@NullSource cannot provide a null argument to %s: no formal parameters declared.", + () -> "@NullSource cannot provide a null argument to %s: no formal parameters declared.".formatted( parameters.getSourceElementDescription())); return Stream.of(nullArguments); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java index fa95826f5ddd..6d60ccbe8d61 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java @@ -128,7 +128,7 @@ public static T convert(String source, Class targetType, ClassLoader clas } // else throw new ConversionException( - String.format("Failed to convert String \"%s\" to type %s", source, targetType.getTypeName()), ex); + "Failed to convert String \"%s\" to type %s".formatted(source, targetType.getTypeName()), ex); } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java index f4ff533b000c..0e9bb167a491 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java @@ -10,7 +10,6 @@ package org.junit.platform.commons.support.scanning; -import static java.lang.String.format; import static java.util.Collections.emptyList; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; @@ -297,8 +296,9 @@ private void handleThrowable(Path classFile, Throwable throwable) { private void logMalformedClassName(Path classFile, String fullyQualifiedClassName, InternalError ex) { try { - logger.debug(ex, () -> format("The java.lang.Class loaded from path [%s] has a malformed class name [%s].", - classFile.toAbsolutePath(), fullyQualifiedClassName)); + logger.debug(ex, + () -> "The java.lang.Class loaded from path [%s] has a malformed class name [%s].".formatted( + classFile.toAbsolutePath(), fullyQualifiedClassName)); } catch (Throwable t) { UnrecoverableExceptions.rethrowIfUnrecoverable(t); @@ -309,7 +309,7 @@ private void logMalformedClassName(Path classFile, String fullyQualifiedClassNam private void logGenericFileProcessingException(Path classpathFile, Throwable throwable) { logger.debug(throwable, - () -> format("Failed to load [%s] during classpath scanning.", classpathFile.toAbsolutePath())); + () -> "Failed to load [%s] during classpath scanning.".formatted(classpathFile.toAbsolutePath())); } private ClassLoader getClassLoader() { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index 15d47bb253ce..bea632eb79f7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -342,9 +342,10 @@ else if (candidateAnnotationType.equals(containerType)) { // a 'value' attribute that returns an array of the contained annotation type. // See https://docs.oracle.com/javase/specs/jls/se8/html/jls-9.html#jls-9.6.3 Method method = ReflectionUtils.tryToGetMethod(containerType, "value").getOrThrow( - cause -> new JUnitException(String.format( - "Container annotation type '%s' must declare a 'value' attribute of type %s[].", - containerType, annotationType), cause)); + cause -> new JUnitException( + "Container annotation type '%s' must declare a 'value' attribute of type %s[].".formatted( + containerType, annotationType), + cause)); Annotation[] containedAnnotations = (Annotation[]) ReflectionUtils.invokeMethod(method, candidate); found.addAll((Collection) asList(containedAnnotations)); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java index 67c919d930b2..0560ad7e8a5f 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java @@ -36,9 +36,9 @@ static ClasspathScanner getInstance() { } if (classpathScanners.size() > 1) { - throw new JUnitException(String.format( - "There should not be more than one ClasspathScanner implementation present on the classpath but there were %d: %s", - classpathScanners.size(), classpathScanners)); + throw new JUnitException( + "There should not be more than one ClasspathScanner implementation present on the classpath but there were %d: %s".formatted( + classpathScanners.size(), classpathScanners)); } return new DefaultClasspathScanner(ClassLoaderUtils::getDefaultClassLoader, ReflectionUtils::tryToLoadClass); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index c50a4b178518..9c6bf10b88e7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -238,8 +238,8 @@ private static Stream tryConvertToStreamByReflection(Object object) { .map(method -> (Iterator) invokeMethod(method, object)) // .map(iterator -> spliteratorUnknownSize(iterator, ORDERED)) // .map(spliterator -> stream(spliterator, false)) // - .orElseThrow(() -> new PreconditionViolationException(String.format( - "Cannot convert instance of %s into a Stream: %s", object.getClass().getName(), object))); + .orElseThrow(() -> new PreconditionViolationException( + "Cannot convert instance of %s into a Stream: %s".formatted(object.getClass().getName(), object))); } private static Optional findIteratorMethod(Class type) { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ListTestEnginesCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ListTestEnginesCommand.java index a83ac4530e7c..6e17282662b8 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ListTestEnginesCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ListTestEnginesCommand.java @@ -46,7 +46,7 @@ private void displayEngine(PrintWriter out, TestEngine engine) { engine.getGroupId().ifPresent(details::add); engine.getArtifactId().ifPresent(details::add); engine.getVersion().ifPresent(details::add); - out.println(getColorScheme().string(String.format("@|bold %s|@%s", engine.getId(), details))); + out.println(getColorScheme().string("@|bold %s|@%s".formatted(engine.getId(), details))); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ManifestVersionProvider.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ManifestVersionProvider.java index 8f41f9f8c894..45a0c1bdb070 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ManifestVersionProvider.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ManifestVersionProvider.java @@ -25,8 +25,7 @@ public static Optional getImplementationVersion() { @Override public String[] getVersion() { return new String[] { // - String.format("@|bold JUnit Platform Console Launcher %s|@", - getImplementationVersion().orElse("")), // + "@|bold JUnit Platform Console Launcher %s|@".formatted(getImplementationVersion().orElse("")), // "JVM: ${java.version} (${java.vendor} ${java.vm.name} ${java.vm.version})", // "OS: ${os.name} ${os.version} ${os.arch}" // }; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java index 82f07dae6665..0c59318a95a8 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java @@ -240,7 +240,7 @@ private void validateUnique(String key, String newValue) { String existing = configurationParameters.get(key); if (existing != null && !existing.equals(newValue)) { throw new CommandLine.ParameterException(spec.commandLine(), - String.format("Duplicate key '%s' for values '%s' and '%s'.", key, existing, newValue)); + "Duplicate key '%s' for values '%s' and '%s'.".formatted(key, existing, newValue)); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ColorPalette.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ColorPalette.java index 7ff8e3f6809b..120f2de48a6f 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ColorPalette.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ColorPalette.java @@ -122,7 +122,7 @@ public String paint(Style style, String text) { } private String getAnsiFormatter(Style style) { - return String.format("\u001B[%sm", this.colorsToAnsiSequences.get(style)); + return "\u001B[%sm".formatted(this.colorsToAnsiSequences.get(style)); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/FlatPrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/FlatPrintingListener.java index f1b0e755b2a2..abdb07208f7a 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/FlatPrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/FlatPrintingListener.java @@ -93,7 +93,7 @@ private void printlnMessage(Style style, String message, String detail) { } private void println(Style style, String format, Object... args) { - this.out.println(colorPalette.paint(style, String.format(format, args))); + this.out.println(colorPalette.paint(style, format.formatted(args))); } /** diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java index f0be524edaab..e44b4bec561e 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java @@ -50,7 +50,7 @@ public void testPlanExecutionFinished(TestPlan testPlan) { public void executionSkipped(TestIdentifier testIdentifier, String reason) { if (shouldPrint(testIdentifier)) { String msg = formatTestIdentifier(testIdentifier); - String indentedReason = indented(String.format("Reason: %s", reason)); + String indentedReason = indented("Reason: %s".formatted(reason)); println(Style.SKIPPED, String.format("%s" + STATUS_SEPARATOR + "SKIPPED%n" + INDENTATION + "%s", msg, indentedReason)); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java index 6a29af05e7bf..2083d4d2800f 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java @@ -10,7 +10,6 @@ package org.junit.platform.engine; -import static java.lang.String.format; import static java.util.stream.Collectors.joining; import static org.junit.platform.engine.FilterResult.included; @@ -82,7 +81,7 @@ public String toString() { // @formatter:off return filters.stream() .map(Object::toString) - .map(value -> format("(%s)", value)) + .map(value -> "(%s)".formatted(value)) .collect(joining(" and ")); // @formatter:on } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java index 53968332bfea..b447c70f642b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java @@ -123,8 +123,8 @@ default Optional get(String key, Function transformer) { return transformer.apply(input); } catch (Exception ex) { - String message = String.format( - "Failed to transform configuration parameter with key '%s' and initial value '%s'", key, input); + String message = "Failed to transform configuration parameter with key '%s' and initial value '%s'".formatted( + key, input); throw new JUnitException(message, ex); } }); 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..5feabcc7b131 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 @@ -108,7 +108,7 @@ public int hashCode() { */ @Override public String toString() { - return String.format("%s:%s", this.prefix, this.value); + return "%s:%s".formatted(this.prefix, this.value); } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index ba0834df4dfa..30cf051a2bdc 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -118,7 +118,7 @@ public static TestTag create(String name) throws PreconditionViolationException private TestTag(String name) { Preconditions.condition(TestTag.isValid(name), - () -> String.format("Tag name [%s] must be syntactically valid", name)); + () -> "Tag name [%s] must be syntactically valid".formatted(name)); this.name = name.trim(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java index 2aaebf38eb18..734031b27cd1 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java @@ -70,7 +70,7 @@ private static String encode(char c) { this.closeSegment = closeSegment; this.segmentDelimiter = segmentDelimiter; this.segmentPattern = Pattern.compile( - String.format("%s(.+)%s(.+)%s", quote(openSegment), quote(typeValueSeparator), quote(closeSegment)), + "%s(.+)%s(.+)%s".formatted(quote(openSegment), quote(typeValueSeparator), quote(closeSegment)), Pattern.DOTALL); // Compute "forbidden" character encoding map. @@ -99,7 +99,7 @@ UniqueId parse(String source) throws JUnitException { private Segment createSegment(String segmentString) throws JUnitException { Matcher segmentMatcher = this.segmentPattern.matcher(segmentString); if (!segmentMatcher.matches()) { - throw new JUnitException(String.format("'%s' is not a well-formed UniqueId segment", segmentString)); + throw new JUnitException("'%s' is not a well-formed UniqueId segment".formatted(segmentString)); } String type = decode(checkAllowed(segmentMatcher.group(1))); String value = decode(checkAllowed(segmentMatcher.group(2))); @@ -116,7 +116,7 @@ private String checkAllowed(String typeOrValue) { private void checkDoesNotContain(String typeOrValue, char forbiddenCharacter) { Preconditions.condition(typeOrValue.indexOf(forbiddenCharacter) < 0, - () -> String.format("type or value '%s' must not contain '%s'", typeOrValue, forbiddenCharacter)); + () -> "type or value '%s' must not contain '%s'".formatted(typeOrValue, forbiddenCharacter)); } /** 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..052462be8e93 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 @@ -159,7 +159,7 @@ public Optional toIdentifier() { } else { return Optional.of(DiscoverySelectorIdentifier.create(IdentifierParser.PREFIX, - String.format("%s?%s", this.classpathResourceName, this.position.toQueryPart()))); + "%s?%s".formatted(this.classpathResourceName, this.position.toQueryPart()))); } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java index 0f2d195eeb8d..8407dabb182f 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java @@ -75,7 +75,7 @@ private enum Singleton { for (DiscoverySelectorIdentifierParser parser : loadedParsers) { DiscoverySelectorIdentifierParser previous = parsersByPrefix.put(parser.getPrefix(), parser); Preconditions.condition(previous == null, - () -> String.format("Duplicate parser for prefix: [%s]; candidate a: [%s]; candidate b: [%s]", + () -> "Duplicate parser for prefix: [%s]; candidate a: [%s]; candidate b: [%s]".formatted( parser.getPrefix(), requireNonNull(previous).getClass().getName(), parser.getClass().getName())); } 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..5b0edccb7c3f 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 @@ -177,7 +177,7 @@ public static FileSelector selectFile(String path, FilePosition position) { public static FileSelector selectFile(File file, FilePosition position) { Preconditions.notNull(file, "File must not be null"); Preconditions.condition(file.isFile(), - () -> String.format("The supplied java.io.File [%s] must represent an existing file", file)); + () -> "The supplied java.io.File [%s] must represent an existing file".formatted(file)); try { return new FileSelector(file.getCanonicalPath(), position); } @@ -219,7 +219,7 @@ public static DirectorySelector selectDirectory(String path) { public static DirectorySelector selectDirectory(File directory) { Preconditions.notNull(directory, "Directory must not be null"); Preconditions.condition(directory.isDirectory(), - () -> String.format("The supplied java.io.File [%s] must represent an existing directory", directory)); + () -> "The supplied java.io.File [%s] must represent an existing directory".formatted(directory)); try { return new DirectorySelector(directory.getCanonicalPath()); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java index 3a1733d00775..152ec5f04cb1 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java @@ -41,11 +41,11 @@ public FilterResult apply(String className) { } private String formatInclusionReason(String className) { - return String.format("Class name [%s] does not match any excluded pattern: %s", className, patternDescription); + return "Class name [%s] does not match any excluded pattern: %s".formatted(className, patternDescription); } private String formatExclusionReason(String className, Pattern pattern) { - return String.format("Class name [%s] matches excluded pattern: '%s'", className, pattern); + return "Class name [%s] matches excluded pattern: '%s'".formatted(className, pattern); } @Override @@ -55,7 +55,7 @@ public Predicate toPredicate() { @Override public String toString() { - return String.format("%s that excludes class names that match one of the following regular expressions: %s", + return "%s that excludes class names that match one of the following regular expressions: %s".formatted( getClass().getSimpleName(), this.patternDescription); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java index eb649b634c3f..8f5f80504267 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java @@ -51,12 +51,12 @@ public FilterResult apply(String packageName) { } private String formatInclusionReason(String packageName) { - return String.format("Package name [%s] does not match any excluded names: %s", packageName, + return "Package name [%s] does not match any excluded names: %s".formatted(packageName, this.patternDescription); } private String formatExclusionReason(String packageName, String matchedName) { - return String.format("Package name [%s] matches excluded name: '%s'", packageName, matchedName); + return "Package name [%s] matches excluded name: '%s'".formatted(packageName, matchedName); } @Override @@ -71,8 +71,7 @@ private Optional findMatchingName(String packageName) { @Override public String toString() { - return String.format( - "%s that excludes packages whose names are either equal to or start with one of the following: %s", + return "%s that excludes packages whose names are either equal to or start with one of the following: %s".formatted( getClass().getSimpleName(), this.patternDescription); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java index 80333c12af9d..2bc66d4e7787 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java @@ -127,7 +127,7 @@ public Optional toIdentifier() { } else { return Optional.of(DiscoverySelectorIdentifier.create(IdentifierParser.PREFIX, - String.format("%s?%s", this.path, this.position.toQueryPart()))); + "%s?%s".formatted(this.path, this.position.toQueryPart()))); } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludeClassNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludeClassNameFilter.java index 8e233bb002fd..6c44a92ad0e5 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludeClassNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludeClassNameFilter.java @@ -41,12 +41,11 @@ public FilterResult apply(String className) { } private String formatInclusionReason(String className, Pattern pattern) { - return String.format("Class name [%s] matches included pattern: '%s'", className, pattern); + return "Class name [%s] matches included pattern: '%s'".formatted(className, pattern); } private String formatExclusionReason(String className) { - return String.format("Class name [%s] does not match any included pattern: %s", className, - this.patternDescription); + return "Class name [%s] does not match any included pattern: %s".formatted(className, this.patternDescription); } @Override @@ -56,7 +55,7 @@ public Predicate toPredicate() { @Override public String toString() { - return String.format("%s that includes class names that match one of the following regular expressions: %s", + return "%s that includes class names that match one of the following regular expressions: %s".formatted( getClass().getSimpleName(), this.patternDescription); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludePackageNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludePackageNameFilter.java index 322f840ae94d..4317b42f3e5b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludePackageNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/IncludePackageNameFilter.java @@ -51,11 +51,11 @@ public FilterResult apply(String packageName) { } private String formatInclusionReason(String packageName, String matchedName) { - return String.format("Package name [%s] matches included name: '%s'", packageName, matchedName); + return "Package name [%s] matches included name: '%s'".formatted(packageName, matchedName); } private String formatExclusionReason(String packageName) { - return String.format("Package name [%s] does not match any included names: %s", packageName, + return "Package name [%s] does not match any included names: %s".formatted(packageName, this.patternDescription); } @@ -71,8 +71,7 @@ private Optional findMatchingName(String packageName) { @Override public String toString() { - return String.format( - "%s that includes packages whose names are either equal to or start with one of the following: %s", + return "%s that includes packages whose names are either equal to or start with one of the following: %s".formatted( getClass().getSimpleName(), this.patternDescription); } 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..13389cfac23f 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 @@ -106,7 +106,7 @@ public String toString() { public Optional toIdentifier() { return this.parentSelector.toIdentifier().map(parentSelectorString -> DiscoverySelectorIdentifier.create( // IdentifierParser.PREFIX, // - String.format("%s[%s]", parentSelectorString, formatIterationIndicesAsRanges())) // + "%s[%s]".formatted(parentSelectorString, formatIterationIndicesAsRanges())) // ); } 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 d5df4bdd99ea..7817c0d1f6fe 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 @@ -234,14 +234,14 @@ private void lazyLoadJavaMethod() { if (this.parameterTypes.length > 0) { this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName, this.parameterTypes).orElseThrow( - () -> new PreconditionViolationException(String.format( - "Could not find method with name [%s] and parameter types [%s] in class [%s].", - this.methodName, this.parameterTypeNames, this.javaClass.getName()))); + () -> new PreconditionViolationException( + "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( + this.methodName, this.parameterTypeNames, this.javaClass.getName()))); } else { this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( - String.format("Could not find method with name [%s] in class [%s].", this.methodName, + "Could not find method with name [%s] in class [%s].".formatted(this.methodName, this.javaClass.getName()))); } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java index 3f2f876a49ba..5b7bfd00101b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java @@ -208,14 +208,14 @@ private void lazyLoadJavaMethod() { if (StringUtils.isNotBlank(this.methodParameterTypes)) { this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName, this.methodParameterTypes).orElseThrow( - () -> new PreconditionViolationException(String.format( - "Could not find method with name [%s] and parameter types [%s] in class [%s].", - this.methodName, this.methodParameterTypes, this.javaClass.getName()))); + () -> new PreconditionViolationException( + "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( + this.methodName, this.methodParameterTypes, this.javaClass.getName()))); } else { this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( - String.format("Could not find method with name [%s] in class [%s].", this.methodName, + "Could not find method with name [%s] in class [%s].".formatted(this.methodName, this.javaClass.getName()))); } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java index 58efdba0a566..4e5c3bb090c3 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java @@ -68,8 +68,9 @@ static UriSource from(URI uri) { } } catch (RuntimeException ex) { - LoggerFactory.getLogger(UriSource.class).debug(ex, () -> String.format( - "The supplied URI [%s] is not path-based. Falling back to default UriSource implementation.", uri)); + LoggerFactory.getLogger(UriSource.class).debug(ex, + () -> "The supplied URI [%s] is not path-based. Falling back to default UriSource implementation.".formatted( + uri)); } // Store supplied URI as-is 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..7bf7c9581f95 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 @@ -40,8 +40,8 @@ public enum DefaultParallelExecutionConfigurationStrategy implements ParallelExe public ParallelExecutionConfiguration createConfiguration(ConfigurationParameters configurationParameters) { int parallelism = configurationParameters.get(CONFIG_FIXED_PARALLELISM_PROPERTY_NAME, Integer::valueOf).orElseThrow( - () -> new JUnitException(String.format("Configuration parameter '%s' must be set", - CONFIG_FIXED_PARALLELISM_PROPERTY_NAME))); + () -> new JUnitException( + "Configuration parameter '%s' must be set".formatted(CONFIG_FIXED_PARALLELISM_PROPERTY_NAME))); int maxPoolSize = configurationParameters.get(CONFIG_FIXED_MAX_POOL_SIZE_PROPERTY_NAME, Integer::valueOf).orElse(parallelism + 256); @@ -66,8 +66,8 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter BigDecimal::new).orElse(BigDecimal.ONE); Preconditions.condition(factor.compareTo(BigDecimal.ZERO) > 0, - () -> String.format("Factor '%s' specified via configuration parameter '%s' must be greater than 0", - factor, CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME)); + () -> "Factor '%s' specified via configuration parameter '%s' must be greater than 0".formatted(factor, + CONFIG_DYNAMIC_FACTOR_PROPERTY_NAME)); int parallelism = Math.max(1, factor.multiply(BigDecimal.valueOf(Runtime.getRuntime().availableProcessors())).intValue()); @@ -75,8 +75,7 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter int maxPoolSize = configurationParameters.get(CONFIG_DYNAMIC_MAX_POOL_SIZE_FACTOR_PROPERTY_NAME, BigDecimal::new).map(maxPoolSizeFactor -> { Preconditions.condition(maxPoolSizeFactor.compareTo(BigDecimal.ONE) >= 0, - () -> String.format( - "Factor '%s' specified via configuration parameter '%s' must be greater than or equal to 1", + () -> "Factor '%s' specified via configuration parameter '%s' must be greater than or equal to 1".formatted( factor, CONFIG_DYNAMIC_MAX_POOL_SIZE_FACTOR_PROPERTY_NAME)); return maxPoolSizeFactor.multiply(BigDecimal.valueOf(parallelism)).intValue(); }).orElseGet(() -> 256 + parallelism); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java index 928b6d21e55a..4bdbcbbcdd26 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java @@ -181,7 +181,7 @@ private void reportCompletion() { catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.debug(throwable, - () -> String.format("Failed to invoke nodeSkipped() on Node %s", testDescriptor.getUniqueId())); + () -> "Failed to invoke nodeSkipped() on Node %s".formatted(testDescriptor.getUniqueId())); } taskContext.getListener().executionSkipped(testDescriptor, skipResult.getReason().orElse("")); return; @@ -196,7 +196,7 @@ private void reportCompletion() { catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); logger.debug(throwable, - () -> String.format("Failed to invoke nodeFinished() on Node %s", testDescriptor.getUniqueId())); + () -> "Failed to invoke nodeFinished() on Node %s".formatted(testDescriptor.getUniqueId())); } taskContext.getListener().executionFinished(testDescriptor, throwableCollector.toTestExecutionResult()); throwableCollector = null; 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..eee38ecb4b80 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 @@ -308,7 +308,7 @@ private T castToRequiredType(Object key, Object value, Class requiredType } // else throw new NamespacedHierarchicalStoreException( - String.format("Object stored under key [%s] is not of required type [%s], but was [%s]: %s", key, + "Object stored under key [%s] is not of required type [%s], but was [%s]: %s".formatted(key, requiredType.getName(), value.getClass().getName(), value)); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java index 8dd34af794aa..bd3f183d6652 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java @@ -128,20 +128,19 @@ public FilterResult apply(TestEngine testEngine) { if (this.type == Type.INCLUDE) { return includedIf(this.engineIds.stream().anyMatch(engineId::equals), // - () -> String.format("Engine ID [%s] is in included list [%s]", engineId, this.engineIds), // - () -> String.format("Engine ID [%s] is not in included list [%s]", engineId, this.engineIds)); + () -> "Engine ID [%s] is in included list [%s]".formatted(engineId, this.engineIds), // + () -> "Engine ID [%s] is not in included list [%s]".formatted(engineId, this.engineIds)); } else { return includedIf(this.engineIds.stream().noneMatch(engineId::equals), // - () -> String.format("Engine ID [%s] is not in excluded list [%s]", engineId, this.engineIds), // - () -> String.format("Engine ID [%s] is in excluded list [%s]", engineId, this.engineIds)); + () -> "Engine ID [%s] is not in excluded list [%s]".formatted(engineId, this.engineIds), // + () -> "Engine ID [%s] is in excluded list [%s]".formatted(engineId, this.engineIds)); } } @Override public String toString() { - return String.format("%s that %s engines with IDs %s", getClass().getSimpleName(), this.type.verb, - this.engineIds); + return "%s that %s engines with IDs %s".formatted(getClass().getSimpleName(), this.type.verb, this.engineIds); } private static List validateAndTrim(List engineIds) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java index b9b46d764a2e..4b17bfb54453 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java @@ -42,17 +42,16 @@ public FilterResult apply(TestDescriptor descriptor) { } private String formatInclusionReason(String methodName) { - return String.format("Method name [%s] does not match any excluded pattern: %s", methodName, - patternDescription); + return "Method name [%s] does not match any excluded pattern: %s".formatted(methodName, patternDescription); } private String formatExclusionReason(String methodName, Pattern pattern) { - return String.format("Method name [%s] matches excluded pattern: '%s'", methodName, pattern); + return "Method name [%s] matches excluded pattern: '%s'".formatted(methodName, pattern); } @Override public String toString() { - return String.format("%s that excludes method names that match one of the following regular expressions: %s", + return "%s that excludes method names that match one of the following regular expressions: %s".formatted( getClass().getSimpleName(), patternDescription); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java index 30d943bfcf94..26a467f9552c 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java @@ -42,17 +42,16 @@ public FilterResult apply(TestDescriptor descriptor) { } private String formatInclusionReason(String methodName, Pattern pattern) { - return String.format("Method name [%s] matches included pattern: '%s'", methodName, pattern); + return "Method name [%s] matches included pattern: '%s'".formatted(methodName, pattern); } private String formatExclusionReason(String methodName) { - return String.format("Method name [%s] does not match any included pattern: %s", methodName, - patternDescription); + return "Method name [%s] does not match any included pattern: %s".formatted(methodName, patternDescription); } @Override public String toString() { - return String.format("%s that includes method names that match one of the following regular expressions: %s", + return "%s that includes method names that match one of the following regular expressions: %s".formatted( getClass().getSimpleName(), patternDescription); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java index ff8c8a828742..406b28d3d613 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java @@ -140,12 +140,11 @@ private static PostDiscoveryFilter includeMatching(List tagExpressions) } private static String inclusionReasonExpressionSatisfy(List tagExpressions) { - return String.format("included because tags match expression(s): [%s]", formatToString(tagExpressions)); + return "included because tags match expression(s): [%s]".formatted(formatToString(tagExpressions)); } private static String exclusionReasonExpressionNotSatisfy(List tagExpressions) { - return String.format("excluded because tags do not match tag expression(s): [%s]", - formatToString(tagExpressions)); + return "excluded because tags do not match tag expression(s): [%s]".formatted(formatToString(tagExpressions)); } private static PostDiscoveryFilter excludeMatching(List tagExpressions) { @@ -161,11 +160,11 @@ private static PostDiscoveryFilter excludeMatching(List tagExpressions) } private static String inclusionReasonExpressionNotSatisfy(List tagExpressions) { - return String.format("included because tags do not match expression(s): [%s]", formatToString(tagExpressions)); + return "included because tags do not match expression(s): [%s]".formatted(formatToString(tagExpressions)); } private static String exclusionReasonExpressionSatisfy(List tagExpressions) { - return String.format("excluded because tags match tag expression(s): [%s]", formatToString(tagExpressions)); + return "excluded because tags match tag expression(s): [%s]".formatted(formatToString(tagExpressions)); } private static String formatToString(List tagExpressions) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 70113dbd9fe7..09a436d7507c 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -86,7 +86,7 @@ static Optional check(LinkageError error, Function String.format("- %s: %s%n", pkg.getName(), pkg.getImplementationVersion())) // + .map(pkg -> "- %s: %s%n".formatted(pkg.getName(), pkg.getImplementationVersion())) // .forEach(message::append); return Optional.of(new JUnitException(message.toString(), error)); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeEngineExecutionListener.java index dac24275f15f..142f1f6a1ea3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeEngineExecutionListener.java @@ -83,9 +83,8 @@ private static void notifyEach(List liste } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); - logger.warn(throwable, - () -> String.format("EngineExecutionListener [%s] threw exception for method: %s", - listener.getClass().getName(), description.get())); + logger.warn(throwable, () -> "EngineExecutionListener [%s] threw exception for method: %s".formatted( + listener.getClass().getName(), description.get())); } }); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java index e9e823fed1a7..c47461c561b0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java @@ -111,7 +111,7 @@ private static void notifyEach(List listene } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); - logger.warn(throwable, () -> String.format("TestExecutionListener [%s] threw exception for method: %s", + logger.warn(throwable, () -> "TestExecutionListener [%s] threw exception for method: %s".formatted( listener.getClass().getName(), description.get())); } }); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java index 5c989b32d79a..13d8ee7deafa 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java @@ -163,13 +163,13 @@ private Map discoverSafely(LauncherDiscoveryReques boolean engineIsExcluded = engineFilterer.isExcluded(testEngine); if (engineIsExcluded) { - logger.debug(() -> String.format("Test discovery for engine '%s' was skipped due to an EngineFilter%s.", - testEngine.getId(), phase.map(it -> String.format(" in %s phase", it)).orElse(""))); + logger.debug(() -> "Test discovery for engine '%s' was skipped due to an EngineFilter%s.".formatted( + testEngine.getId(), phase.map(it -> " in %s phase".formatted(it)).orElse(""))); continue; } - logger.debug(() -> String.format("Discovering tests%s in engine '%s'.", - phase.map(it -> String.format(" during Launcher %s phase", it)).orElse(""), testEngine.getId())); + logger.debug(() -> "Discovering tests%s in engine '%s'.".formatted( + phase.map(it -> " during Launcher %s phase".formatted(it)).orElse(""), testEngine.getId())); EngineResultInfo engineResult = discoverEngineRoot(testEngine, request, issueCollector, uniqueIdCreator); testEngineDescriptors.put(testEngine, engineResult); @@ -204,7 +204,7 @@ private EngineResultInfo discoverEngineRoot(TestEngine testEngine, LauncherDisco cause = ClasspathAlignmentChecker.check((LinkageError) throwable).orElse(null); } if (cause == null) { - String message = String.format("TestEngine with ID '%s' failed to discover tests", testEngine.getId()); + String message = "TestEngine with ID '%s' failed to discover tests".formatted(testEngine.getId()); cause = new JUnitException(message, throwable); } listener.engineDiscoveryFinished(uniqueEngineId, EngineDiscoveryResult.failed(cause)); @@ -247,10 +247,10 @@ private void logTestDescriptorExclusionReasons(Map> String displayNames = testDescriptors.stream().map(TestDescriptor::getDisplayName).collect(joining(", ")); long containerCount = testDescriptors.stream().filter(TestDescriptor::isContainer).count(); long methodCount = testDescriptors.stream().filter(TestDescriptor::isTest).count(); - logger.config(() -> String.format("%d containers and %d tests were %s", containerCount, methodCount, - exclusionReason)); + logger.config( + () -> "%d containers and %d tests were %s".formatted(containerCount, methodCount, exclusionReason)); logger.debug( - () -> String.format("The following containers and tests were %s: %s", exclusionReason, displayNames)); + () -> "The following containers and tests were %s: %s".formatted(exclusionReason, displayNames)); }); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java index 61b57a24b67b..d2c20ce6b1b5 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java @@ -69,7 +69,7 @@ private Optional getCyclicGraphInfo(TestDescriptor root) { List path2 = findPath(visited, parent.getUniqueId()); path2.add(uid); - return Optional.of(String.format("%s exists in at least two paths:\n(1) %s\n(2) %s", uid, + return Optional.of("%s exists in at least two paths:\n(1) %s\n(2) %s".formatted(uid, formatted(path1), formatted(path2))); } else { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java index 1cf63758f3aa..4f809967798a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java @@ -239,7 +239,7 @@ private void executeEngine(TestDescriptor engineDescriptor, EngineExecutionListe cause = ClasspathAlignmentChecker.check((LinkageError) throwable).orElse(null); } if (cause == null) { - String message = String.format("TestEngine with ID '%s' failed to execute tests", testEngine.getId()); + String message = "TestEngine with ID '%s' failed to execute tests".formatted(testEngine.getId()); cause = new JUnitException(message, throwable); } delayingListener.reportEngineStartIfNecessary(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java index 878df7d3c207..80df2561c5e5 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java @@ -32,15 +32,15 @@ static Iterable validate(Iterable testEngines) { for (TestEngine testEngine : testEngines) { // check usage of reserved ID prefix if (!validateReservedIds(testEngine)) { - getLogger().warn(() -> String.format( - "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '%s'", - testEngine.getId())); + getLogger().warn( + () -> "Third-party TestEngine implementations are forbidden to use the reserved 'junit-' prefix for their ID: '%s'".formatted( + testEngine.getId())); } // check uniqueness if (!ids.add(testEngine.getId())) { - throw new JUnitException(String.format( - "Cannot create Launcher for multiple engines with the same ID '%s'.", testEngine.getId())); + throw new JUnitException( + "Cannot create Launcher for multiple engines with the same ID '%s'.".formatted(testEngine.getId())); } } return testEngines; @@ -54,7 +54,7 @@ private static Logger getLogger() { // https://github.com/junit-team/junit5/issues/1557 private static boolean validateReservedIds(TestEngine testEngine) { String engineId = Preconditions.notBlank(testEngine.getId(), - () -> String.format("ID for TestEngine [%s] must not be null or blank", testEngine.getClass().getName())); + () -> "ID for TestEngine [%s] must not be null or blank".formatted(testEngine.getClass().getName())); if (!engineId.startsWith("junit-")) { return true; } @@ -82,7 +82,7 @@ private static void validateWellKnownClassName(TestEngine testEngine, String exp return; } throw new JUnitException( - String.format("Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.", + "Third-party TestEngine '%s' is forbidden to use the reserved '%s' TestEngine ID.".formatted( actualClassName, testEngine.getId())); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java index 9d1adea4f511..9523a05e9b75 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java @@ -270,14 +270,14 @@ private static Properties loadClasspathResource(String configFileName) { Stream.of(configFileUrl + " (*)"), // resources.stream().skip(1).map(URL::toString) // ).collect(joining("\n- ", "\n- ", "")); - return String.format( - "Discovered %d '%s' configuration files on the classpath (see below); only the first (*) will be used.%s", + return "Discovered %d '%s' configuration files on the classpath (see below); only the first (*) will be used.%s".formatted( resources.size(), configFileName, formattedResourceList); }); } - logger.config(() -> String.format( - "Loading JUnit Platform configuration parameters from classpath resource [%s].", configFileUrl)); + logger.config( + () -> "Loading JUnit Platform configuration parameters from classpath resource [%s].".formatted( + configFileUrl)); URLConnection urlConnection = configFileUrl.openConnection(); urlConnection.setUseCaches(false); try (InputStream inputStream = urlConnection.getInputStream()) { @@ -287,8 +287,7 @@ private static Properties loadClasspathResource(String configFileName) { } catch (Exception ex) { logger.warn(ex, - () -> String.format( - "Failed to load JUnit Platform configuration parameters from classpath resource [%s].", + () -> "Failed to load JUnit Platform configuration parameters from classpath resource [%s].".formatted( configFileName)); } 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 4c237b54bbd9..58a0e8178b5c 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 @@ -315,7 +315,7 @@ else if (filter instanceof DiscoveryFilter) { } else { throw new PreconditionViolationException( - String.format("Filter [%s] must implement %s, %s, or %s.", filter, EngineFilter.class.getSimpleName(), + "Filter [%s] must implement %s, %s, or %s.".formatted(filter, EngineFilter.class.getSimpleName(), PostDiscoveryFilter.class.getSimpleName(), DiscoveryFilter.class.getSimpleName())); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java index 107bcf971c94..5536e8c7227d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java @@ -37,7 +37,7 @@ static Optional getDiscoveryIssueFailurePhase(ConfigurationParame } catch (Exception e) { logger.warn( - () -> String.format("Ignoring invalid LauncherPhase '%s' set via the '%s' configuration parameter.", + () -> "Ignoring invalid LauncherPhase '%s' set via the '%s' configuration parameter.".formatted( value, DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME)); return null; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java index f06339619841..ebab21e42302 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java @@ -48,9 +48,9 @@ static Iterable load(@SuppressWarnings("SameParameterValue") Class typ private static String logLoadedInstances(Class type, List instances, List exclusions) { String typeName = type.getSimpleName(); if (exclusions == null) { - return String.format("Loaded %s instances: %s", typeName, instances); + return "Loaded %s instances: %s".formatted(typeName, instances); } - return String.format("Loaded %s instances: %s (excluded classes: %s)", typeName, instances, exclusions); + return "Loaded %s instances: %s (excluded classes: %s)".formatted(typeName, instances, exclusions); } private static List load(Class type, Predicate classNameFilter, diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/TestEngineFormatter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/TestEngineFormatter.java index 558e6824fbe0..3ebd9f109783 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/TestEngineFormatter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/TestEngineFormatter.java @@ -33,7 +33,7 @@ static String format(String title, Iterable testEngines) { private static String format(String title, Stream testEngines) { String details = testEngines // - .map(engine -> String.format("- %s (%s)", engine.getId(), join(", ", computeAttributes(engine)))) // + .map(engine -> "- %s (%s)".formatted(engine.getId(), join(", ", computeAttributes(engine)))) // .collect(joining("\n")); return title + ":" + (details.isEmpty() ? " " : "\n" + details); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java index 3b6e37907565..eb0fd73cdd74 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java @@ -124,7 +124,7 @@ private void log(String message, Object... args) { } private void logWithThrowable(String message, Throwable t, Object... args) { - this.logger.accept(t, () -> String.format(message, args)); + this.logger.accept(t, () -> message.formatted(args)); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java index acff49f57a9d..ee5297b2d359 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java @@ -98,7 +98,7 @@ public Path toPath() { } public Path createFile(String prefix, String extension) throws UncheckedIOException { - String filename = String.format("%s-%d.%s", prefix, Math.abs(random.nextLong()), extension); + String filename = "%s-%d.%s".formatted(prefix, Math.abs(random.nextLong()), extension); Path outputFile = path.resolve(filename); try { diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java index 5d5b0cdfe25d..292a2aea605e 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java @@ -463,7 +463,7 @@ private List selectClasses(Class suiteClass, SelectClasses ann private static Stream toClassSelectors(Class suiteClass, SelectClasses annotation) { Preconditions.condition(annotation.value().length > 0 || annotation.names().length > 0, - () -> String.format("@SelectClasses on class [%s] must declare at least one class reference or name", + () -> "@SelectClasses on class [%s] must declare at least one class reference or name".formatted( suiteClass.getName())); return Stream.concat(// AdditionalDiscoverySelectors.selectClasses(annotation.value()), // @@ -535,7 +535,7 @@ private static MethodSelector toMethodSelector(Class suiteClass, Class typ } private static String prefixErrorMessageForInvalidSelectMethodUsage(Class suiteClass, String detailMessage) { - return String.format("@SelectMethod on class [%s]: %s", suiteClass.getName(), detailMessage); + return "@SelectMethod on class [%s]: %s".formatted(suiteClass.getName(), detailMessage); } private ClassNameFilter createIncludeClassNameFilter(String... patterns) { diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/ClassSelectorResolver.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/ClassSelectorResolver.java index 9694f15c9860..764841e4b052 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/ClassSelectorResolver.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/ClassSelectorResolver.java @@ -133,8 +133,7 @@ private static boolean containsCycle(UniqueId id) { } private static String createConfigContainsCycleMessage(Class suiteClass, UniqueId suiteId) { - return String.format( - "The suite configuration of [%s] resulted in a cycle [%s] and will not be discovered a second time.", + return "The suite configuration of [%s] resulted in a cycle [%s] and will not be discovered a second time.".formatted( suiteClass.getName(), suiteId); } diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/IsSuiteClass.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/IsSuiteClass.java index 6d9fcbe98ffa..277ac34edcd7 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/IsSuiteClass.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/IsSuiteClass.java @@ -65,8 +65,7 @@ private static Condition> isNotInner(DiscoveryIssueReporter issueReport } private static DiscoveryIssue createIssue(Class testClass, String detailMessage) { - String message = String.format("@Suite class '%s' %s It will not be executed.", testClass.getName(), - detailMessage); + String message = "@Suite class '%s' %s It will not be executed.".formatted(testClass.getName(), detailMessage); return DiscoveryIssue.builder(DiscoveryIssue.Severity.WARNING, message) // .source(ClassSource.from(testClass)) // .build(); diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java index df8d894c3444..2509ff0e4e87 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java @@ -65,7 +65,7 @@ private static List findMethodsAndCheckStaticAndNonPrivate(Class test private static DiscoveryIssueReporter.Condition isStatic(Class annotationType, DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(ModifierSupport::isStatic, method -> { - String message = String.format("@%s method '%s' must be static.", annotationType.getSimpleName(), + String message = "@%s method '%s' must be static.".formatted(annotationType.getSimpleName(), method.toGenericString()); return createError(message, method); }); @@ -74,7 +74,7 @@ private static DiscoveryIssueReporter.Condition isStatic(Class isNotPrivate(Class annotationType, DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(ModifierSupport::isNotPrivate, method -> { - String message = String.format("@%s method '%s' must not be private.", annotationType.getSimpleName(), + String message = "@%s method '%s' must not be private.".formatted(annotationType.getSimpleName(), method.toGenericString()); return createError(message, method); }); @@ -83,7 +83,7 @@ private static DiscoveryIssueReporter.Condition isNotPrivate(Class returnsPrimitiveVoid( Class annotationType, DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(ReflectionUtils::returnsPrimitiveVoid, method -> { - String message = String.format("@%s method '%s' must not return a value.", annotationType.getSimpleName(), + String message = "@%s method '%s' must not return a value.".formatted(annotationType.getSimpleName(), method.toGenericString()); return createError(message, method); }); @@ -92,8 +92,8 @@ private static DiscoveryIssueReporter.Condition returnsPrimitiveVoid( private static DiscoveryIssueReporter.Condition hasNoParameters(Class annotationType, DiscoveryIssueReporter issueReporter) { return issueReporter.createReportingCondition(method -> method.getParameterCount() == 0, method -> { - String message = String.format("@%s method '%s' must not accept parameters.", - annotationType.getSimpleName(), method.toGenericString()); + String message = "@%s method '%s' must not accept parameters.".formatted(annotationType.getSimpleName(), + method.toGenericString()); return createError(message, method); }); } diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java index e0f22d8fa257..c0c5eaa92f7c 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java @@ -17,7 +17,7 @@ class NoTestsDiscoveredException extends JUnitException { private static final long serialVersionUID = 1L; NoTestsDiscoveredException(Class suiteClass) { - super(String.format("Suite [%s] did not discover any tests", suiteClass.getName())); + super("Suite [%s] did not discover any tests".formatted(suiteClass.getName())); } } diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index d9837a6a2319..0ab81c9e3836 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -90,7 +90,7 @@ private static Boolean getFailIfNoTests(Class suiteClass) { // @formatter:off return findAnnotation(suiteClass, Suite.class) .map(Suite::failIfNoTests) - .orElseThrow(() -> new JUnitException(String.format("Suite [%s] was not annotated with @Suite", suiteClass.getName()))); + .orElseThrow(() -> new JUnitException("Suite [%s] was not annotated with @Suite".formatted(suiteClass.getName()))); // @formatter:on } @@ -246,7 +246,7 @@ static DiscoveryIssueForwardingListener create(UniqueId id, EngineDiscoveryListe if (message.endsWith(".")) { message = message.substring(0, message.length() - 1); } - return String.format("[%s] %s (via @Suite %s).", engineId, message, suitePath); + return "[%s] %s (via @Suite %s).".formatted(engineId, message, suitePath); })); } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java index 3e01ed7a9f0d..3a2a471980fc 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java @@ -82,7 +82,7 @@ private static String buildPrefix(String message) { } private static String formatValues(long expected, long actual) { - return String.format("expected: <%d> but was: <%d>", expected, actual); + return "expected: <%d> but was: <%d>".formatted(expected, actual); } } 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 57539cfc533c..9732fda836c1 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 @@ -293,7 +293,7 @@ private static TestEngine loadTestEngine(String engineId) { .filter((TestEngine engine) -> engineId.equals(engine.getId()))// .findFirst()// .orElseThrow(() -> new PreconditionViolationException( - String.format("Failed to load TestEngine with ID [%s]", engineId))); + "Failed to load TestEngine with ID [%s]".formatted(engineId))); } private EngineTestKit() { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java index 6511fe8c5af8..6bafcee2efab 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java @@ -113,7 +113,7 @@ private boolean isParameterizedMethod(Description description) { @Override public String describe() { - return String.format("Method %s", desiredDescription.getDisplayName()); + return "Method %s".formatted(desiredDescription.getDisplayName()); } }; } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/UniqueIdReader.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/UniqueIdReader.java index d9cae90a119a..3973c1c6b1bd 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/UniqueIdReader.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/UniqueIdReader.java @@ -10,7 +10,6 @@ package org.junit.vintage.engine.support; -import static java.lang.String.format; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.ReflectionUtils.tryToReadFieldValue; @@ -47,7 +46,7 @@ public Serializable apply(Description description) { return tryToReadFieldValue(Description.class, fieldName, description) .andThenTry(Serializable.class::cast) .ifFailure(cause -> logger.warn(cause, () -> - format("Could not read unique ID for Description; using display name instead: %s", description))) + "Could not read unique ID for Description; using display name instead: %s".formatted(description))) .toOptional() .orElseGet(description::getDisplayName); // @formatter:on diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java index b5bfd62438eb..ff666a7ef0f5 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java @@ -93,7 +93,7 @@ private void assertInstanceOfSucceeds(Class expectedType, Object actualVa private void assertInstanceOfFails(Class expectedType, Object actualValue, String unexpectedSort) { String valueType = actualValue == null ? "null" : actualValue.getClass().getCanonicalName(); - String expectedMessage = String.format("Unexpected %s, expected: <%s> but was: <%s>", unexpectedSort, + String expectedMessage = "Unexpected %s, expected: <%s> but was: <%s>".formatted(unexpectedSort, expectedType.getCanonicalName(), valueType); assertThrowsWithMessage(expectedMessage, () -> assertInstanceOf(expectedType, actualValue)); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledOnOsConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledOnOsConditionTests.java index 8a098c8a7e04..2f16d47e4d77 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledOnOsConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledOnOsConditionTests.java @@ -74,7 +74,7 @@ void missingOsAndArchitectureDeclaration() { void disabledOnEveryOs() { evaluateCondition(); assertDisabled(); - assertReasonContains(String.format("Disabled on operating system: %s ==> Disabled on every OS", OS_NAME)); + assertReasonContains("Disabled on operating system: %s ==> Disabled on every OS".formatted(OS_NAME)); } /** @@ -234,33 +234,33 @@ void aarch64WithLinux() { private void assertDisabledOnCurrentOsIf(boolean condition) { if (condition) { assertDisabled(); - assertReasonContains(String.format("Disabled on operating system: %s", OS_NAME)); + assertReasonContains("Disabled on operating system: %s".formatted(OS_NAME)); } else { assertEnabled(); - assertReasonContains(String.format("Enabled on operating system: %s", OS_NAME)); + assertReasonContains("Enabled on operating system: %s".formatted(OS_NAME)); } } private void assertDisabledOnCurrentArchitectureIf(boolean condition) { if (condition) { assertDisabled(); - assertReasonContains(String.format("Disabled on architecture: %s", ARCH)); + assertReasonContains("Disabled on architecture: %s".formatted(ARCH)); } else { assertEnabled(); - assertReasonContains(String.format("Enabled on architecture: %s", ARCH)); + assertReasonContains("Enabled on architecture: %s".formatted(ARCH)); } } private void assertDisabledOnCurrentOsAndArchitectureIf(boolean condition) { if (condition) { assertDisabled(); - assertReasonContains(String.format("Disabled on operating system: %s (%s)", OS_NAME, ARCH)); + assertReasonContains("Disabled on operating system: %s (%s)".formatted(OS_NAME, ARCH)); } else { assertEnabled(); - assertReasonContains(String.format("Enabled on operating system: %s (%s)", OS_NAME, ARCH)); + assertReasonContains("Enabled on operating system: %s (%s)".formatted(OS_NAME, ARCH)); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledOnOsConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledOnOsConditionTests.java index 56c3f0431a37..57ca8a41b69a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledOnOsConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledOnOsConditionTests.java @@ -234,33 +234,33 @@ void aarch64WithLinux() { private void assertEnabledOnCurrentOsIf(boolean condition) { if (condition) { assertEnabled(); - assertReasonContains(String.format("Enabled on operating system: %s", OS_NAME)); + assertReasonContains("Enabled on operating system: %s".formatted(OS_NAME)); } else { assertDisabled(); - assertReasonContains(String.format("Disabled on operating system: %s", OS_NAME)); + assertReasonContains("Disabled on operating system: %s".formatted(OS_NAME)); } } private void assertEnabledOnCurrentArchitectureIf(boolean condition) { if (condition) { assertEnabled(); - assertReasonContains(String.format("Enabled on architecture: %s", ARCH)); + assertReasonContains("Enabled on architecture: %s".formatted(ARCH)); } else { assertDisabled(); - assertReasonContains(String.format("Disabled on architecture: %s", ARCH)); + assertReasonContains("Disabled on architecture: %s".formatted(ARCH)); } } private void assertEnabledOnCurrentOsAndArchitectureIf(boolean condition) { if (condition) { assertEnabled(); - assertReasonContains(String.format("Enabled on operating system: %s (%s)", OS_NAME, ARCH)); + assertReasonContains("Enabled on operating system: %s (%s)".formatted(OS_NAME, ARCH)); } else { assertDisabled(); - assertReasonContains(String.format("Disabled on operating system: %s (%s)", OS_NAME, ARCH)); + assertReasonContains("Disabled on operating system: %s (%s)".formatted(OS_NAME, ARCH)); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/ExtensionComposabilityTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/ExtensionComposabilityTests.java index 9fb7a9efa9dd..8d8c7c7e9339 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/ExtensionComposabilityTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/ExtensionComposabilityTests.java @@ -150,7 +150,7 @@ private boolean isExtensionApi(Class candidate) { } private String methodSignature(Method method) { - return String.format("%s(%s)", method.getName(), + return "%s(%s)".formatted(method.getName(), ClassUtils.nullSafeToString(Class::getSimpleName, method.getParameterTypes())); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java index eec416474611..fb8c6b0ed0b2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java @@ -119,7 +119,7 @@ static class BasicTypeBasedParameterResolver extends TypeBasedParameterResolver< public String resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { Class parameterAnnotation = parameterContext.getParameter().getAnnotations()[0].annotationType(); - return String.format("%s %s", extensionContext.getDisplayName(), parameterAnnotation.getSimpleName()); + return "%s %s".formatted(extensionContext.getDisplayName(), parameterAnnotation.getSimpleName()); } } 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 2fe8352f41b8..60eea16c0028 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 @@ -208,8 +208,7 @@ void individualMethodsWithinRecursiveNestedTestClassHierarchiesAreExecuted() { private void assertNestedCycle(Class start, Class from, Class to) { var results = executeTestsForClass(start); - var expectedMessage = String.format( - "Cause: org.junit.platform.commons.JUnitException: Detected cycle in inner class hierarchy between %s and %s", + var expectedMessage = "Cause: org.junit.platform.commons.JUnitException: Detected cycle in inner class hierarchy between %s and %s".formatted( from.getName(), to.getName()); results.containerEvents().assertThatEvents() // .haveExactly(1, finishedWithFailure(message(it -> it.contains(expectedMessage)))); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java index c1fc0ed4cfa1..53b754d8b99b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java @@ -61,8 +61,7 @@ void resetTracking() { @Test void blankCloseMethodName() { Class testClass = BlankCloseMethodNameTestCase.class; - String msg = String.format("@AutoClose on field %s.field must specify a method name.", - testClass.getCanonicalName()); + String msg = "@AutoClose on field %s.field must specify a method name.".formatted(testClass.getCanonicalName()); Events tests = executeTestsForClass(testClass).testEvents(); assertFailingWithMessage(tests, msg); } @@ -70,8 +69,7 @@ void blankCloseMethodName() { @Test void primitiveTypeCannotBeClosed() { Class testClass = PrimitiveFieldTestCase.class; - String msg = String.format("@AutoClose is not supported on primitive field %s.x.", - testClass.getCanonicalName()); + String msg = "@AutoClose is not supported on primitive field %s.x.".formatted(testClass.getCanonicalName()); Events tests = executeTestsForClass(testClass).testEvents(); assertFailingWithMessage(tests, msg); } @@ -79,7 +77,7 @@ void primitiveTypeCannotBeClosed() { @Test void arrayCannotBeClosed() { Class testClass = ArrayFieldTestCase.class; - String msg = String.format("@AutoClose is not supported on array field %s.x.", testClass.getCanonicalName()); + String msg = "@AutoClose is not supported on array field %s.x.".formatted(testClass.getCanonicalName()); Events tests = executeTestsForClass(testClass).testEvents(); assertFailingWithMessage(tests, msg); } @@ -87,8 +85,7 @@ void arrayCannotBeClosed() { @Test void nullCannotBeClosed(@TrackLogRecords LogRecordListener listener) { Class testClass = NullCloseableFieldTestCase.class; - String msg = String.format("Cannot @AutoClose field %s.field because it is null.", - testClass.getCanonicalName()); + String msg = "Cannot @AutoClose field %s.field because it is null.".formatted(testClass.getCanonicalName()); Events tests = executeTestsForClass(testClass).testEvents(); tests.assertStatistics(stats -> stats.succeeded(1).failed(0)); assertThat(listener.stream(Level.WARNING)).map(LogRecord::getMessage).anyMatch(msg::equals); @@ -394,7 +391,7 @@ private static void assertFailingWithMessage(Events testEvents, String msg) { } private void assertMissingCloseMethod(Class testClass, String methodName) { - String msg = String.format("Cannot @AutoClose field %s.field because %s does not define method %s().", + String msg = "Cannot @AutoClose field %s.field because %s does not define method %s().".formatted( testClass.getCanonicalName(), String.class.getName(), methodName); Events tests = executeTestsForClass(testClass).testEvents(); assertFailingWithMessage(tests, msg); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java index c70238d7473e..0a72e2dd4212 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java @@ -853,7 +853,7 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte String name = declaringExecutable instanceof Constructor ? declaringExecutable.getDeclaringClass().getSimpleName() : declaringExecutable.getName(); - return String.format("%s-%d-%s", name, parameterContext.getIndex(), text); + return "%s-%d-%s".formatted(name, parameterContext.getIndex(), text); } } } 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 daebaab379d5..3085d59cb66c 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 @@ -402,7 +402,7 @@ static class AMethodNameTestCase extends BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { var method = testInfo.getTestMethod().orElseThrow(AssertionError::new); - var signature = String.format("%s(%s)", method.getName(), + var signature = "%s(%s)".formatted(method.getName(), ClassUtils.nullSafeToString(method.getParameterTypes())); callSequence.add(signature); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ParameterResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ParameterResolverTests.java index 500a1fcbd1f3..4ba0ef82ebb7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ParameterResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ParameterResolverTests.java @@ -227,7 +227,7 @@ void executeTestsForTypeBasedParameterResolverTestCaseSelectingByFullyQualifiedM void executeTestsForParameterizedTypesSelectingByFullyQualifiedMethodNameContainingGenericInfo() throws Exception { Method method = ParameterizedTypeTestCase.class.getDeclaredMethod("testMapOfStrings", Map.class); String genericParameterTypeName = method.getGenericParameterTypes()[0].getTypeName(); - String fqmn = String.format("%s#%s(%s)", ParameterizedTypeTestCase.class.getName(), "testMapOfStrings", + String fqmn = "%s#%s(%s)".formatted(ParameterizedTypeTestCase.class.getName(), "testMapOfStrings", genericParameterTypeName); assertEventsForParameterizedTypes(executeTests(selectMethod(fqmn))); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/sub/SystemPropertyCondition.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/sub/SystemPropertyCondition.java index bb50d774a31c..fca7809b51ab 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/sub/SystemPropertyCondition.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/sub/SystemPropertyCondition.java @@ -56,7 +56,7 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con if (!Objects.equals(expected, actual)) { return ConditionEvaluationResult.disabled( - String.format("System property [%s] has a value of [%s] instead of [%s]", key, actual, expected)); + "System property [%s] has a value of [%s] instead of [%s]".formatted(key, actual, expected)); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java index 9eb006afbbc9..741a392c4caf 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java @@ -182,9 +182,9 @@ void throwsExceptionWhenArgumentsProviderIsNotStatic() { var exception = assertThrows(JUnitException.class, stream::toArray); assertThat(exception) // - .hasMessage(String.format( - "The ArgumentsProvider [%s] must be either a top-level class or a static nested class", - NonStaticArgumentsProvider.class.getName())); + .hasMessage( + "The ArgumentsProvider [%s] must be either a top-level class or a static nested class".formatted( + NonStaticArgumentsProvider.class.getName())); } @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index be726c17fba1..515f7eb87d6f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -1175,8 +1175,8 @@ void failsWithArgumentsSourceProvidingUnusedArguments() { var results = execute(ArgumentCountValidationMode.STRICT, UnusedArgumentsTestCase.class, "testWithTwoUnusedStringArgumentsProvider", String.class); results.allEvents().assertThatEvents() // - .haveExactly(1, event(finishedWithFailure(message(String.format( - "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]"))))); + .haveExactly(1, event(finishedWithFailure(message( + "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]".formatted())))); } @Test @@ -1184,8 +1184,8 @@ void failsWithMethodSourceProvidingUnusedArguments() { var results = execute(ArgumentCountValidationMode.STRICT, UnusedArgumentsTestCase.class, "testWithMethodSourceProvidingUnusedArguments", String.class); results.allEvents().assertThatEvents() // - .haveExactly(1, event(finishedWithFailure(message(String.format( - "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]"))))); + .haveExactly(1, event(finishedWithFailure(message( + "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]".formatted())))); } @Test @@ -1193,8 +1193,8 @@ void failsWithCsvSourceUnusedArgumentsAndStrictArgumentCountValidationAnnotation var results = execute(ArgumentCountValidationMode.NONE, UnusedArgumentsTestCase.class, "testWithStrictArgumentCountValidation", String.class); results.allEvents().assertThatEvents() // - .haveExactly(1, event(finishedWithFailure(message(String.format( - "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]"))))); + .haveExactly(1, event(finishedWithFailure(message( + "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]".formatted())))); } @Test @@ -1202,8 +1202,8 @@ void failsWithCsvSourceUnusedArgumentsButExecutesRemainingArgumentsWhereThereIsN var results = execute(ArgumentCountValidationMode.STRICT, UnusedArgumentsTestCase.class, "testWithCsvSourceContainingDifferentNumbersOfArguments", String.class); results.allEvents().assertThatEvents() // - .haveExactly(1, event(finishedWithFailure(message(String.format( - "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]"))))) // + .haveExactly(1, event(finishedWithFailure(message( + "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused1]".formatted())))) // .haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))); } @@ -1231,8 +1231,8 @@ void evaluatesArgumentsAtMostOnce() { var results = execute(ArgumentCountValidationMode.STRICT, UnusedArgumentsTestCase.class, "testWithEvaluationReportingArgumentsProvider", String.class); results.allEvents().assertThatEvents() // - .haveExactly(1, event(finishedWithFailure(message(String.format( - "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused]"))))); + .haveExactly(1, event(finishedWithFailure(message( + "Configuration error: @ParameterizedTest consumes 1 parameter but there were 2 arguments provided.%nNote: the provided arguments were [foo, unused]".formatted())))); results.allEvents().reportingEntryPublished().assertThatEvents() // .haveExactly(1, event(EventConditions.reportEntry(Map.of("evaluated", "true")))); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java index e15bc98e7308..02ba3d442a7b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java @@ -212,8 +212,8 @@ private > Stream provideArguments(Class enumClass when(annotation.mode()).thenReturn(mode); when(annotation.names()).thenReturn(names); when(annotation.toString()).thenReturn( - String.format("@EnumSource(value=%s.class, from=%s, to=%s, mode=%s, names=%s)", enumClass.getSimpleName(), - from, to, mode, Arrays.toString(names))); + "@EnumSource(value=%s.class, from=%s, to=%s, mode=%s, names=%s)".formatted(enumClass.getSimpleName(), from, + to, mode, Arrays.toString(names))); var provider = new EnumArgumentsProvider(); provider.accept(annotation); 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 86fea83374b3..1c391226562b 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 @@ -1135,7 +1135,7 @@ private void assertNestedCycle(Class start, Class from, Class to) { assertThatExceptionOfType(JUnitException.class)// .as("expected cycle from %s to %s", from.getSimpleName(), to.getSimpleName())// .isThrownBy(() -> findNestedClasses(start))// - .withMessageMatching(String.format("Detected cycle in inner class hierarchy between .+%s and .+%s", + .withMessageMatching("Detected cycle in inner class hierarchy between .+%s and .+%s".formatted( from.getSimpleName(), to.getSimpleName())); } @@ -1785,7 +1785,7 @@ void findMethodsDoesNotReturnOverriddenDefaultMethods() { private static List signaturesOf(List methods) { // @formatter:off return methods.stream() - .map(m -> String.format("%s(%s)", m.getName(), ClassUtils.nullSafeToString(m.getParameterTypes()))) + .map(m -> "%s(%s)".formatted(m.getName(), ClassUtils.nullSafeToString(m.getParameterTypes()))) .toList(); // @formatter:on } diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java index ca66fe79c766..4707b9d91a95 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java @@ -150,27 +150,26 @@ void nullSafeToStringForObjectWhoseToStringImplementationThrowsAnException() { } private void shouldContainWhitespace(String str) { - assertTrue(containsWhitespace(str), () -> String.format("'%s' should contain whitespace", str)); - assertFalse(doesNotContainWhitespace(str), () -> String.format("'%s' should contain whitespace", str)); + assertTrue(containsWhitespace(str), () -> "'%s' should contain whitespace".formatted(str)); + assertFalse(doesNotContainWhitespace(str), () -> "'%s' should contain whitespace".formatted(str)); } private void shouldNotContainWhitespace(String str) { - assertTrue(doesNotContainWhitespace(str), () -> String.format("'%s' should not contain whitespace", str)); - assertFalse(containsWhitespace(str), () -> String.format("'%s' should not contain whitespace", str)); + assertTrue(doesNotContainWhitespace(str), () -> "'%s' should not contain whitespace".formatted(str)); + assertFalse(containsWhitespace(str), () -> "'%s' should not contain whitespace".formatted(str)); } private void shouldContainIsoControlCharacter(String str) { - assertTrue(containsIsoControlCharacter(str), - () -> String.format("'%s' should contain ISO control character", str)); + assertTrue(containsIsoControlCharacter(str), () -> "'%s' should contain ISO control character".formatted(str)); assertFalse(doesNotContainIsoControlCharacter(str), - () -> String.format("'%s' should contain ISO control character", str)); + () -> "'%s' should contain ISO control character".formatted(str)); } private void shouldNotContainIsoControlCharacter(String str) { assertTrue(doesNotContainIsoControlCharacter(str), - () -> String.format("'%s' should not contain ISO control character", str)); + () -> "'%s' should not contain ISO control character".formatted(str)); assertFalse(containsIsoControlCharacter(str), - () -> String.format("'%s' should not contain ISO control character", str)); + () -> "'%s' should not contain ISO control character".formatted(str)); } private static class ToStringReturnsNull { diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java index 2071549d8981..f56e5cf0e182 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java @@ -10,7 +10,6 @@ package org.junit.platform.console; -import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; import static org.junit.jupiter.api.Assertions.assertLinesMatch; import static org.junit.jupiter.api.Assertions.fail; @@ -214,7 +213,7 @@ public void execute() throws Throwable { Files.createDirectories(temp); var path = Files.writeString(temp.resolve(outName), result.out); throw new TestAbortedException( - format("resource `%s` not found\nwrote console stdout to: %s/%s", dirName, outName, path)); + "resource `%s` not found\nwrote console stdout to: %s/%s".formatted(dirName, outName, path)); } fail("could not load resource named `" + dirName + "/" + outName + "`"); } diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java index 79e707fd94d4..6fe058ff2493 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherIntegrationTests.java @@ -97,7 +97,7 @@ void executeWithRedirectedStdStream(String redirectedStream, int outputFileSize, throws IOException { var outputFile = tempDir.resolve("output.txt"); - var line = String.format("execute -e junit-jupiter --select-class %s %s %s", StdStreamTestCase.class.getName(), + var line = "execute -e junit-jupiter --select-class %s %s %s".formatted(StdStreamTestCase.class.getName(), redirectedStream, outputFile); var args = line.split(" "); new ConsoleLauncherWrapper().execute(args); @@ -113,7 +113,7 @@ void executeWithRedirectedStdStream(String redirectedStream, int outputFileSize, @Test void executeWithRedirectedStdStreamsToSameFile(@TempDir Path tempDir) throws IOException { var outputFile = tempDir.resolve("output.txt"); - var line = String.format("execute -e junit-jupiter --select-class %s --redirect-stdout %s --redirect-stderr %s", + var line = "execute -e junit-jupiter --select-class %s --redirect-stdout %s --redirect-stderr %s".formatted( StdStreamTestCase.class.getName(), outputFile, outputFile); var args = line.split(" "); new ConsoleLauncherWrapper().execute(args); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java b/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java index 63adfe5e51a5..1152290acd19 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java @@ -89,11 +89,11 @@ void toStringPrintsName() { } private static void yep(String tag) { - assertTrue(TestTag.isValid(tag), () -> String.format("'%s' should be a valid tag", tag)); + assertTrue(TestTag.isValid(tag), () -> "'%s' should be a valid tag".formatted(tag)); } private static void nope(String tag) { - assertFalse(TestTag.isValid(tag), () -> String.format("'%s' should not be a valid tag", tag)); + assertFalse(TestTag.isValid(tag), () -> "'%s' should not be a valid tag".formatted(tag)); } private void assertSyntaxViolation(String tag) { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index c384a90434d2..43fd5b2f2321 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -824,7 +824,7 @@ void selectMethodByFullyQualifiedNameContainingHashtagsAndWithParameterList() { var className = "org.example.CalculatorSpec"; var methodName = "#a plus #b equals #c"; var methodParameters = "int, int, int"; - var fqmn = String.format("%s#%s(%s)", className, methodName, methodParameters); + var fqmn = "%s#%s(%s)".formatted(className, methodName, methodParameters); var selector = selectMethod(fqmn); assertEquals(className, selector.getClassName()); @@ -875,7 +875,7 @@ void selectMethodByFullyQualifiedNameEndingWithParenthesesAndWithParameterList() var className = "org.example.KotlinTestCase"; var methodName = "test name ends with parentheses()"; var methodParameters = "int, int, int"; - var fqmn = String.format("%s#%s(%s)", className, methodName, methodParameters); + var fqmn = "%s#%s(%s)".formatted(className, methodName, methodParameters); var selector = selectMethod(fqmn); @@ -1440,7 +1440,7 @@ private static String fqmn(Class clazz, String methodName, Class... params } private static String fqmnWithParamNames(String... params) { - return String.format("%s#%s(%s)", DiscoverySelectorsTests.class.getName(), "myTest", join(", ", params)); + return "%s#%s(%s)".formatted(DiscoverySelectorsTests.class.getName(), "myTest", join(", ", params)); } interface TestInterface { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DemoMethodTestDescriptor.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DemoMethodTestDescriptor.java index 2c4dcb8b7402..9b90b9f63ca7 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DemoMethodTestDescriptor.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DemoMethodTestDescriptor.java @@ -32,7 +32,7 @@ public class DemoMethodTestDescriptor extends AbstractTestDescriptor { public DemoMethodTestDescriptor(UniqueId uniqueId, Method testMethod) { super(uniqueId, - String.format("%s(%s)", Preconditions.notNull(testMethod, "Method must not be null").getName(), + "%s(%s)".formatted(Preconditions.notNull(testMethod, "Method must not be null").getName(), ClassUtils.nullSafeToString(Class::getSimpleName, testMethod.getParameterTypes())), MethodSource.from(testMethod)); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java index b868986c1d31..57f716bb0e5e 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java @@ -58,14 +58,14 @@ void includeSingleMethodNamePattern() { var filter = includeMethodNamePatterns(regex); assertIncluded(filter.apply(CLASS1_TEST1), - String.format("Method name [%s] matches included pattern: '%s'", CLASS1_TEST1_NAME, regex)); + "Method name [%s] matches included pattern: '%s'".formatted(CLASS1_TEST1_NAME, regex)); assertIncluded(filter.apply(CLASS1_TEST2), - String.format("Method name [%s] matches included pattern: '%s'", CLASS1_TEST2_NAME, regex)); + "Method name [%s] matches included pattern: '%s'".formatted(CLASS1_TEST2_NAME, regex)); assertExcluded(filter.apply(CLASS2_TEST1), - String.format("Method name [%s] does not match any included pattern: '%s'", CLASS2_TEST1_NAME, regex)); + "Method name [%s] does not match any included pattern: '%s'".formatted(CLASS2_TEST1_NAME, regex)); assertExcluded(filter.apply(CLASS2_TEST2), - String.format("Method name [%s] does not match any included pattern: '%s'", CLASS2_TEST2_NAME, regex)); + "Method name [%s] does not match any included pattern: '%s'".formatted(CLASS2_TEST2_NAME, regex)); } @Test @@ -75,14 +75,14 @@ void includeMultipleMethodNamePatterns() { var filter = includeMethodNamePatterns(firstRegex, secondRegex); assertIncluded(filter.apply(CLASS1_TEST1), - String.format("Method name [%s] matches included pattern: '%s'", CLASS1_TEST1_NAME, firstRegex)); + "Method name [%s] matches included pattern: '%s'".formatted(CLASS1_TEST1_NAME, firstRegex)); assertIncluded(filter.apply(CLASS1_TEST2), - String.format("Method name [%s] matches included pattern: '%s'", CLASS1_TEST2_NAME, firstRegex)); + "Method name [%s] matches included pattern: '%s'".formatted(CLASS1_TEST2_NAME, firstRegex)); assertIncluded(filter.apply(CLASS2_TEST1), - String.format("Method name [%s] matches included pattern: '%s'", CLASS2_TEST1_NAME, secondRegex)); + "Method name [%s] matches included pattern: '%s'".formatted(CLASS2_TEST1_NAME, secondRegex)); assertExcluded(filter.apply(CLASS2_TEST2), - String.format("Method name [%s] does not match any included pattern: '%s' OR '%s'", CLASS2_TEST2_NAME, + "Method name [%s] does not match any included pattern: '%s' OR '%s'".formatted(CLASS2_TEST2_NAME, firstRegex, secondRegex)); } @@ -105,14 +105,14 @@ void excludeSingleMethodNamePattern() { var filter = excludeMethodNamePatterns(regex); assertExcluded(filter.apply(CLASS1_TEST1), - String.format("Method name [%s] matches excluded pattern: '%s'", CLASS1_TEST1_NAME, regex)); + "Method name [%s] matches excluded pattern: '%s'".formatted(CLASS1_TEST1_NAME, regex)); assertExcluded(filter.apply(CLASS1_TEST2), - String.format("Method name [%s] matches excluded pattern: '%s'", CLASS1_TEST2_NAME, regex)); + "Method name [%s] matches excluded pattern: '%s'".formatted(CLASS1_TEST2_NAME, regex)); assertIncluded(filter.apply(CLASS2_TEST1), - String.format("Method name [%s] does not match any excluded pattern: '%s'", CLASS2_TEST1_NAME, regex)); + "Method name [%s] does not match any excluded pattern: '%s'".formatted(CLASS2_TEST1_NAME, regex)); assertIncluded(filter.apply(CLASS2_TEST2), - String.format("Method name [%s] does not match any excluded pattern: '%s'", CLASS2_TEST2_NAME, regex)); + "Method name [%s] does not match any excluded pattern: '%s'".formatted(CLASS2_TEST2_NAME, regex)); } @Test @@ -122,14 +122,14 @@ void excludeMultipleMethodNamePatterns() { var filter = excludeMethodNamePatterns(firstRegex, secondRegex); assertExcluded(filter.apply(CLASS1_TEST1), - String.format("Method name [%s] matches excluded pattern: '%s'", CLASS1_TEST1_NAME, firstRegex)); + "Method name [%s] matches excluded pattern: '%s'".formatted(CLASS1_TEST1_NAME, firstRegex)); assertExcluded(filter.apply(CLASS1_TEST2), - String.format("Method name [%s] matches excluded pattern: '%s'", CLASS1_TEST2_NAME, firstRegex)); + "Method name [%s] matches excluded pattern: '%s'".formatted(CLASS1_TEST2_NAME, firstRegex)); assertExcluded(filter.apply(CLASS2_TEST1), - String.format("Method name [%s] matches excluded pattern: '%s'", CLASS2_TEST1_NAME, secondRegex)); + "Method name [%s] matches excluded pattern: '%s'".formatted(CLASS2_TEST1_NAME, secondRegex)); assertIncluded(filter.apply(CLASS2_TEST2), - String.format("Method name [%s] does not match any excluded pattern: '%s' OR '%s'", CLASS2_TEST2_NAME, + "Method name [%s] does not match any excluded pattern: '%s' OR '%s'".formatted(CLASS2_TEST2_NAME, firstRegex, secondRegex)); } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java index ac1ee44b6139..f71b3f14eb12 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ManifestTests.java @@ -86,6 +86,6 @@ private static String specificationVersion(String version) { private static void assertValue(Attributes attributes, String name, String expected) { var actual = attributes.getValue(name); assertEquals(expected, actual, - String.format("Manifest attribute %s expected to be %s, but is: %s", name, expected, actual)); + "Manifest attribute %s expected to be %s, but is: %s".formatted(name, expected, actual)); } } From 800c4bee7b8a4e390d36425e583acd0b358f1cbf Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:32:41 +0200 Subject: [PATCH 064/521] Use `@Serial` annotation --- .../api/extension/ExtensionConfigurationException.java | 3 +++ .../jupiter/api/extension/ExtensionContextException.java | 3 +++ .../jupiter/api/extension/ParameterResolutionException.java | 3 +++ .../extension/TemplateInvocationValidationException.java | 3 +++ .../jupiter/api/extension/TestInstantiationException.java | 3 +++ .../engine/execution/ConditionEvaluationException.java | 3 +++ .../jupiter/params/aggregator/ArgumentAccessException.java | 3 +++ .../params/aggregator/ArgumentsAggregationException.java | 3 +++ .../params/converter/ArgumentConversionException.java | 3 +++ .../junit/jupiter/params/provider/CsvParsingException.java | 3 +++ .../java/org/junit/platform/commons/JUnitException.java | 3 +++ .../platform/commons/PreconditionViolationException.java | 3 +++ .../commons/support/conversion/ConversionException.java | 3 +++ .../main/java/org/junit/platform/commons/util/LruCache.java | 2 ++ .../src/main/java/org/junit/platform/engine/TestTag.java | 2 ++ .../src/main/java/org/junit/platform/engine/UniqueId.java | 3 +++ .../main/java/org/junit/platform/engine/UniqueIdFormat.java | 2 ++ .../org/junit/platform/engine/discovery/FilePosition.java | 2 ++ .../platform/engine/support/descriptor/ClassSource.java | 2 ++ .../engine/support/descriptor/ClasspathResourceSource.java | 2 ++ .../engine/support/descriptor/CompositeTestSource.java | 2 ++ .../engine/support/descriptor/DefaultUriSource.java | 2 ++ .../platform/engine/support/descriptor/DirectorySource.java | 2 ++ .../platform/engine/support/descriptor/FilePosition.java | 2 ++ .../platform/engine/support/descriptor/FileSource.java | 2 ++ .../platform/engine/support/descriptor/MethodSource.java | 2 ++ .../platform/engine/support/descriptor/PackageSource.java | 2 ++ .../support/store/NamespacedHierarchicalStoreException.java | 3 +++ .../java/org/junit/platform/launcher/TestIdentifier.java | 6 ++++++ .../platform/launcher/core/DiscoveryIssueException.java | 3 +++ .../platform/suite/engine/NoTestsDiscoveredException.java | 3 +++ 31 files changed, 83 insertions(+) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java index 91e5c7ee997d..fd915b661156 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -24,6 +26,7 @@ @API(status = STABLE, since = "5.0") public class ExtensionConfigurationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ExtensionConfigurationException(String message) { 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..eb9ad1138504 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 @@ -13,6 +13,8 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.platform.commons.JUnitException; @@ -26,6 +28,7 @@ @API(status = STABLE, since = "5.0") public class ExtensionContextException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; @SuppressWarnings("unused") diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolutionException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolutionException.java index 31c9730b6222..3c5d87458904 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolutionException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolutionException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -25,6 +27,7 @@ @API(status = STABLE, since = "5.0") public class ParameterResolutionException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ParameterResolutionException(String message) { 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..25b7b3645628 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 @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -27,6 +29,7 @@ @API(status = EXPERIMENTAL, since = "5.13") public class TemplateInvocationValidationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public TemplateInvocationValidationException(String message) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationException.java index 66884bdba9db..4ec882a2ea5d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestInstantiationException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -24,6 +26,7 @@ @API(status = STABLE, since = "5.10") public class TestInstantiationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public TestInstantiationException(String message) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluationException.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluationException.java index 7b9a948205c2..35f7b29f79dd 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluationException.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConditionEvaluationException.java @@ -10,6 +10,8 @@ package org.junit.jupiter.engine.execution; +import java.io.Serial; + import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.JUnitException; @@ -22,6 +24,7 @@ */ class ConditionEvaluationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ConditionEvaluationException(String message, Throwable cause) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentAccessException.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentAccessException.java index dbdad3cf0d7f..3a52c9812a4b 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentAccessException.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentAccessException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -26,6 +28,7 @@ @API(status = STABLE, since = "5.7") public class ArgumentAccessException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ArgumentAccessException(String message) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregationException.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregationException.java index f2c80d0910b7..af251259e560 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregationException.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAggregationException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -26,6 +28,7 @@ @API(status = STABLE, since = "5.7") public class ArgumentsAggregationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ArgumentsAggregationException(String message) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java index 358d6e122c74..08a6228bd127 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -26,6 +28,7 @@ @API(status = STABLE, since = "5.7") public class ArgumentConversionException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ArgumentConversionException(String message) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvParsingException.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvParsingException.java index b0db31d48b2f..3528e62ee819 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvParsingException.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvParsingException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -25,6 +27,7 @@ @API(status = STABLE, since = "5.7") public class CsvParsingException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public CsvParsingException(String message) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java index 2dbc032984fd..7498b502c9c9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java @@ -13,6 +13,8 @@ import static org.apiguardian.api.API.Status.MAINTAINED; import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; /** @@ -24,6 +26,7 @@ @API(status = STABLE, since = "1.5") public class JUnitException extends RuntimeException { + @Serial private static final long serialVersionUID = 1L; public JUnitException(String message) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java index 025b00ff8e0f..0771766bc2de 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; + import org.apiguardian.api.API; /** @@ -22,6 +24,7 @@ @API(status = STABLE, since = "1.5") public class PreconditionViolationException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public PreconditionViolationException(String message) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionException.java index 1e3474d27c6c..008421ceb06a 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionException.java @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -24,6 +26,7 @@ @API(status = EXPERIMENTAL, since = "1.11") public class ConversionException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public ConversionException(String message) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/LruCache.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/LruCache.java index 83a56c172608..b4fd94c246db 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/LruCache.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/LruCache.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.INTERNAL; +import java.io.Serial; import java.util.LinkedHashMap; import java.util.Map; @@ -29,6 +30,7 @@ @API(status = INTERNAL, since = "1.6") public class LruCache extends LinkedHashMap { + @Serial private static final long serialVersionUID = 1L; private final int maxSize; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index 30cf051a2bdc..2edf2fea3584 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.io.Serializable; import java.util.Arrays; import java.util.Collections; @@ -35,6 +36,7 @@ @API(status = STABLE, since = "1.0") public final class TestTag implements Serializable { + @Serial private static final long serialVersionUID = 1L; private final String name; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java index acd4fe3d4d2c..49d15a8bbb19 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java @@ -14,6 +14,7 @@ import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.io.Serializable; import java.lang.ref.SoftReference; import java.util.ArrayList; @@ -37,6 +38,7 @@ @API(status = STABLE, since = "1.0") public class UniqueId implements Cloneable, Serializable { + @Serial private static final long serialVersionUID = 1L; private static final String ENGINE_SEGMENT_TYPE = "engine"; @@ -296,6 +298,7 @@ public String toString() { @API(status = STABLE, since = "1.0") public static class Segment implements Serializable { + @Serial private static final long serialVersionUID = 1L; private final String type; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java index 734031b27cd1..5a96a33a6846 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java @@ -13,6 +13,7 @@ import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; +import java.io.Serial; import java.io.Serializable; import java.io.UnsupportedEncodingException; import java.net.URLDecoder; @@ -36,6 +37,7 @@ */ class UniqueIdFormat implements Serializable { + @Serial private static final long serialVersionUID = 1L; private static final UniqueIdFormat defaultFormat = new UniqueIdFormat('[', ':', ']', '/'); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java index 48cb72eb7e73..0383e03179fb 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.io.Serializable; import java.util.Objects; import java.util.Optional; @@ -37,6 +38,7 @@ @API(status = STABLE, since = "1.7") public class FilePosition implements Serializable { + @Serial private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(FilePosition.class); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java index 186cf149b07d..ce76cc6549db 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.net.URI; import java.util.Objects; import java.util.Optional; @@ -43,6 +44,7 @@ @API(status = STABLE, since = "1.0") public class ClassSource implements TestSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java index a49f65ed040b..303bdc5bc5c4 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.net.URI; import java.util.Objects; import java.util.Optional; @@ -33,6 +34,7 @@ @API(status = STABLE, since = "1.0") public class ClasspathResourceSource implements TestSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java index 43a396a221b5..cfff2d02cc4a 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java @@ -13,6 +13,7 @@ import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -32,6 +33,7 @@ @API(status = STABLE, since = "1.0") public class CompositeTestSource implements TestSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java index 54ae69de460a..334c1d6f4e93 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java @@ -10,6 +10,7 @@ package org.junit.platform.engine.support.descriptor; +import java.io.Serial; import java.net.URI; import java.util.Objects; @@ -23,6 +24,7 @@ */ class DefaultUriSource implements UriSource { + @Serial private static final long serialVersionUID = 1L; private final URI uri; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java index 04cc46369d5f..a2b3645bd203 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DirectorySource.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; +import java.io.Serial; import java.net.URI; import org.apiguardian.api.API; @@ -30,6 +31,7 @@ @API(status = STABLE, since = "1.0") public class DirectorySource implements FileSystemSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java index 859006090008..28d4246a8cdd 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.io.Serializable; import java.util.Objects; import java.util.Optional; @@ -32,6 +33,7 @@ @API(status = STABLE, since = "1.0") public class FilePosition implements Serializable { + @Serial private static final long serialVersionUID = 1L; private static final Logger logger = LoggerFactory.getLogger(FilePosition.class); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java index 0e6e42acba94..b07fddbe7b65 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java @@ -14,6 +14,7 @@ import java.io.File; import java.io.IOException; +import java.io.Serial; import java.net.URI; import java.util.Objects; import java.util.Optional; @@ -33,6 +34,7 @@ @API(status = STABLE, since = "1.0") public class FileSource implements FileSystemSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java index 5b7bfd00101b..c00af72f9b45 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.ClassUtils.nullSafeToString; +import java.io.Serial; import java.lang.reflect.Method; import java.util.Objects; @@ -36,6 +37,7 @@ @API(status = STABLE, since = "1.0") public class MethodSource implements TestSource { + @Serial private static final long serialVersionUID = 1L; /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/PackageSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/PackageSource.java index c6bca4e9c0ff..d3c46953a3f9 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/PackageSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/PackageSource.java @@ -12,6 +12,7 @@ import static org.apiguardian.api.API.Status.STABLE; +import java.io.Serial; import java.util.Objects; import org.apiguardian.api.API; @@ -31,6 +32,7 @@ @API(status = STABLE, since = "1.0") public class PackageSource implements TestSource { + @Serial private static final long serialVersionUID = 1L; /** 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..60734fbbc81c 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 @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -23,6 +25,7 @@ @API(status = EXPERIMENTAL, since = "1.10") public class NamespacedHierarchicalStoreException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; public NamespacedHierarchicalStoreException(String message) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index 80e7cd3b76ec..7e880f395ad5 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -22,6 +22,7 @@ import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.ObjectStreamField; +import java.io.Serial; import java.io.Serializable; import java.util.LinkedHashSet; import java.util.Objects; @@ -47,7 +48,9 @@ @API(status = STABLE, since = "1.0") public final class TestIdentifier implements Serializable { + @Serial private static final long serialVersionUID = 1L; + @Serial private static final ObjectStreamField[] serialPersistentFields = ObjectStreamClass.lookup( SerializedForm.class).getFields(); @@ -272,11 +275,13 @@ public String toString() { // @formatter:on } + @Serial private void writeObject(ObjectOutputStream s) throws IOException { SerializedForm serializedForm = new SerializedForm(this); serializedForm.serialize(s); } + @Serial private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { SerializedForm serializedForm = SerializedForm.deserialize(s); uniqueId = UniqueId.parse(serializedForm.uniqueId); @@ -295,6 +300,7 @@ private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOEx */ private static class SerializedForm implements Serializable { + @Serial private static final long serialVersionUID = 1L; private final String uniqueId; 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..86da544837b0 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 @@ -12,6 +12,8 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; +import java.io.Serial; + import org.apiguardian.api.API; import org.junit.platform.commons.JUnitException; @@ -24,6 +26,7 @@ @API(status = EXPERIMENTAL, since = "1.13") public class DiscoveryIssueException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; DiscoveryIssueException(String message) { diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java index c0c5eaa92f7c..6283e63c27aa 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/NoTestsDiscoveredException.java @@ -10,10 +10,13 @@ package org.junit.platform.suite.engine; +import java.io.Serial; + import org.junit.platform.commons.JUnitException; class NoTestsDiscoveredException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; NoTestsDiscoveredException(Class suiteClass) { From fa22a75e19e2a2fe8381b68a6082a941b2f91e91 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:33:01 +0200 Subject: [PATCH 065/521] Use `Path.of` instead of `Paths.get` --- .../java/example/UsingTheLauncherDemo.java | 3 +- .../engine/extension/TempDirectory.java | 3 +- .../provider/CsvFileArgumentsProvider.java | 4 +-- .../support/scanning/CloseablePath.java | 3 +- .../discovery/ClasspathRootSelector.java | 3 +- .../engine/discovery/DirectorySelector.java | 3 +- .../engine/discovery/FileSelector.java | 3 +- .../engine/support/descriptor/UriSource.java | 3 +- .../HierarchicalOutputDirectoryProvider.java | 3 +- .../launcher/listeners/OutputDir.java | 3 +- .../listeners/UniqueIdTrackingListener.java | 2 +- .../LegacyXmlReportGeneratingListener.java | 3 +- .../xml/OpenTestReportGeneratingListener.java | 3 +- .../VintageTestEngineDiscoveryTests.java | 5 ++- .../DiscoverySelectorResolverTests.java | 5 ++- .../TempDirectoryPreconditionTests.java | 5 ++- .../conversion/ConversionSupportTests.java | 7 ++--- .../DefaultClasspathScannerTests.java | 3 +- .../platform/console/ConsoleDetailsTests.java | 6 ++-- .../CommandLineOptionsParsingTests.java | 13 ++++---- .../options/ExecuteTestsCommandTests.java | 4 +-- .../tasks/ConsoleTestExecutorTests.java | 4 +-- .../tasks/DiscoveryRequestCreatorTests.java | 6 ++-- .../discovery/DiscoverySelectorsTests.java | 31 +++++++++---------- ...eLauncherDiscoveryRequestBuilderTests.java | 6 ++-- .../java/platform/tooling/support/Helper.java | 3 +- 26 files changed, 59 insertions(+), 78 deletions(-) diff --git a/documentation/src/test/java/example/UsingTheLauncherDemo.java b/documentation/src/test/java/example/UsingTheLauncherDemo.java index 6b0a2d508237..ee5ff525c565 100644 --- a/documentation/src/test/java/example/UsingTheLauncherDemo.java +++ b/documentation/src/test/java/example/UsingTheLauncherDemo.java @@ -17,7 +17,6 @@ import java.io.PrintWriter; import java.nio.file.Path; -import java.nio.file.Paths; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; @@ -111,7 +110,7 @@ void execution() { @org.junit.jupiter.api.Test void launcherConfig() { - Path reportsDir = Paths.get("target", "xml-reports"); + Path reportsDir = Path.of("target", "xml-reports"); PrintWriter out = new PrintWriter(System.out); // @formatter:off // tag::launcherConfig[] diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java index 45a97565d663..2223ad4142c0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java @@ -36,7 +36,6 @@ import java.nio.file.LinkOption; import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.DosFileAttributeView; @@ -514,7 +513,7 @@ private static void tryToResetPermissions(Path path) { } private IOException createIOExceptionWithAttachedFailures(SortedMap failures) { - Path emptyPath = Paths.get(""); + Path emptyPath = Path.of(""); String joinedPaths = failures.keySet().stream() // .map(this::tryToDeleteOnExit) // .map(this::relativizeSafely) // diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index f514bb74bed7..09635ced0b26 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -23,7 +23,7 @@ import java.io.InputStream; import java.nio.charset.Charset; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -201,7 +201,7 @@ public InputStream openClasspathResource(Class baseClass, String path) { public InputStream openFile(String path) { Preconditions.notBlank(path, () -> "File [" + path + "] must not be null or blank"); try { - return Files.newInputStream(Paths.get(path)); + return Files.newInputStream(Path.of(path)); } catch (IOException e) { throw new JUnitException("File [" + path + "] could not be read", e); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java index 0cb4977d9477..48aecf9b4896 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java @@ -20,7 +20,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicBoolean; @@ -65,7 +64,7 @@ static CloseablePath create(URI uri, FileSystemProvider fileSystemProvider) thro return createForJarFileSystem(new URI(JAR_URI_SCHEME + ':' + uri), fileSystem -> fileSystem.getRootDirectories().iterator().next(), fileSystemProvider); } - return new CloseablePath(Paths.get(uri), NULL_CLOSEABLE); + return new CloseablePath(Path.of(uri), NULL_CLOSEABLE); } private static CloseablePath createForJarFileSystem(URI jarUri, Function pathProvider, diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathRootSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathRootSelector.java index 133572b909ff..27708e10f8f2 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathRootSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ClasspathRootSelector.java @@ -17,7 +17,6 @@ import java.net.URI; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Objects; import java.util.Optional; @@ -114,7 +113,7 @@ public String getPrefix() { @Override public Optional parse(DiscoverySelectorIdentifier identifier, Context context) { - Path path = Paths.get(URI.create(identifier.getValue())); + Path path = Path.of(URI.create(identifier.getValue())); return getFirstElement(DiscoverySelectors.selectClasspathRoots(singleton(path))); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DirectorySelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DirectorySelector.java index fe74b2a1fdc8..577b97bc93a1 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DirectorySelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DirectorySelector.java @@ -17,7 +17,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Objects; import java.util.Optional; @@ -67,7 +66,7 @@ public File getDirectory() { * @see #getRawPath() */ public Path getPath() { - return Paths.get(this.path); + return Path.of(this.path); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java index 2bc66d4e7787..cd59c69e7fbf 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java @@ -17,7 +17,6 @@ import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Objects; import java.util.Optional; @@ -70,7 +69,7 @@ public File getFile() { * @see #getRawPath() */ public Path getPath() { - return Paths.get(this.path); + return Path.of(this.path); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java index 4e5c3bb090c3..d27d8dd8f1e3 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/UriSource.java @@ -15,7 +15,6 @@ import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import org.apiguardian.api.API; import org.junit.platform.commons.logging.LoggerFactory; @@ -59,7 +58,7 @@ static UriSource from(URI uri) { try { URI uriWithoutQuery = ResourceUtils.stripQueryComponent(uri); - Path path = Paths.get(uriWithoutQuery); + Path path = Path.of(uriWithoutQuery); if (Files.isRegularFile(path)) { return FileSource.from(path.toFile(), FilePosition.fromQuery(uri.getQuery()).orElse(null)); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java index b85d3176668a..c5a9772d67a0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java @@ -13,7 +13,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.function.Supplier; import java.util.regex.Pattern; @@ -62,7 +61,7 @@ public synchronized Path getRootDirectory() { } private static Path toSanitizedPath(Segment segment) { - return Paths.get(sanitizeName(segment.getValue())); + return Path.of(sanitizeName(segment.getValue())); } private static String sanitizeName(String value) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java index ee5297b2d359..34be95e19c12 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/OutputDir.java @@ -17,7 +17,6 @@ import java.io.UncheckedIOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.security.SecureRandom; import java.util.Optional; @@ -36,7 +35,7 @@ public class OutputDir { Pattern.quote(OUTPUT_DIR_UNIQUE_NUMBER_PLACEHOLDER)); public static OutputDir create(Optional customDir) { - return create(customDir, () -> Paths.get(".")); + return create(customDir, () -> Path.of(".")); } static OutputDir create(Optional customDir, Supplier currentWorkingDir) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java index 8b8b8d51f274..e25e4319da31 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java @@ -206,7 +206,7 @@ private Path createOutputFile(ConfigurationParameters configurationParameters) { String prefix = configurationParameters.get(OUTPUT_FILE_PREFIX_PROPERTY_NAME) // .orElse(DEFAULT_OUTPUT_FILE_PREFIX); Supplier workingDirSupplier = () -> configurationParameters.get(WORKING_DIR_PROPERTY_NAME).map( - Paths::get).orElseGet(() -> Paths.get(".")); + Paths::get).orElseGet(() -> Path.of(".")); return OutputDir.create(configurationParameters.get(OUTPUT_DIR_PROPERTY_NAME), workingDirSupplier) // .createFile(prefix, "txt"); } diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java index 06bd0ecfc7a0..33288eaa7062 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java @@ -17,7 +17,6 @@ import java.io.Writer; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Clock; import javax.xml.stream.XMLStreamException; @@ -57,7 +56,7 @@ public LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out) { // For tests only LegacyXmlReportGeneratingListener(String reportsDir, PrintWriter out, Clock clock) { - this(Paths.get(reportsDir), out, clock); + this(Path.of(reportsDir), out, clock); } private LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out, Clock clock) { 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 954cdc334fc5..e0f34a7356f3 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 @@ -61,7 +61,6 @@ import java.net.UnknownHostException; import java.nio.charset.Charset; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Instant; import java.time.LocalDateTime; import java.util.Map; @@ -119,7 +118,7 @@ public class OpenTestReportGeneratingListener implements TestExecutionListener { @SuppressWarnings("unused") // Used via ServiceLoader public OpenTestReportGeneratingListener() { - this(Paths.get(".").toAbsolutePath()); + this(Path.of(".").toAbsolutePath()); } OpenTestReportGeneratingListener(Path workingDir) { diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java index 8947aeae6212..5ae829c9b873 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java @@ -33,7 +33,6 @@ import java.net.URLClassLoader; import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Base64; import java.util.List; @@ -271,7 +270,7 @@ void resolvesClasspathSelector() throws Exception { @Test void resolvesClasspathSelectorForJarFile() throws Exception { var jarUrl = getClass().getResource("/vintage-testjar.jar"); - var jarFile = Paths.get(jarUrl.toURI()); + var jarFile = Path.of(jarUrl.toURI()); var originalClassLoader = Thread.currentThread().getContextClassLoader(); try (var classLoader = new URLClassLoader(new URL[] { jarUrl })) { @@ -721,7 +720,7 @@ private TestDescriptor discoverTests(LauncherDiscoveryRequest discoveryRequest) private Path getClasspathRoot(Class testClass) throws Exception { var location = testClass.getProtectionDomain().getCodeSource().getLocation(); - return Paths.get(location.toURI()); + return Path.of(location.toURI()); } private void assertYieldsNoDescriptors(Class testClass) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java index f607f28e15b9..9833fa18cb43 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java @@ -49,7 +49,6 @@ import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Predicate; @@ -522,7 +521,7 @@ void packageResolutionUsingDefaultPackage() throws Exception { @Test void classpathResolution() throws Exception { - Path classpath = Paths.get( + Path classpath = Path.of( DiscoverySelectorResolverTests.class.getProtectionDomain().getCodeSource().getLocation().toURI()); List selectors = selectClasspathRoots(singleton(classpath)); @@ -549,7 +548,7 @@ void classpathResolution() throws Exception { @Test void classpathResolutionForJarFiles() throws Exception { URL jarUrl = requireNonNull(getClass().getResource("/jupiter-testjar.jar")); - Path path = Paths.get(jarUrl.toURI()); + Path path = Path.of(jarUrl.toURI()); List selectors = selectClasspathRoots(singleton(path)); ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPreconditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPreconditionTests.java index fc3f84f3a146..1312ce42b1b0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPreconditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryPreconditionTests.java @@ -20,7 +20,6 @@ import java.io.File; import java.nio.file.Path; -import java.nio.file.Paths; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -102,7 +101,7 @@ void invalidTempDirType(@TempDir String text) { @SuppressWarnings("JUnitMalformedDeclaration") static class FinalStaticFieldTestCase { - static final @TempDir Path path = Paths.get("."); + static final @TempDir Path path = Path.of("."); @Test void test() { @@ -112,7 +111,7 @@ void test() { @SuppressWarnings("JUnitMalformedDeclaration") static class FinalInstanceFieldTestCase { - final @TempDir Path path = Paths.get("."); + final @TempDir Path path = Path.of("."); @Test void test() { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java index 3a57fbe3b5a3..626fbe117939 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java @@ -22,7 +22,6 @@ import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.nio.file.Path; -import java.nio.file.Paths; import java.time.Duration; import java.time.Instant; import java.time.LocalDate; @@ -202,9 +201,9 @@ void convertsStringToFile() { @Test void convertsStringToPath() { - assertConverts("path", Path.class, Paths.get("path")); - assertConverts("/path", Path.class, Paths.get("/path")); - assertConverts("/some/path", Path.class, Paths.get("/some/path")); + assertConverts("path", Path.class, Path.of("path")); + assertConverts("/path", Path.class, Path.of("/path")); + assertConverts("/some/path", Path.class, Path.of("/some/path")); } // --- java.lang ----------------------------------------------------------- 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..26a2fa53ad98 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 @@ -31,7 +31,6 @@ import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -558,7 +557,7 @@ void findAllClassesInClasspathRootForNullRoot() { @Test void findAllClassesInClasspathRootForNonExistingRoot() { assertThrows(PreconditionViolationException.class, - () -> classpathScanner.scanForClassesInClasspathRoot(Paths.get("does_not_exist").toUri(), allClasses)); + () -> classpathScanner.scanForClassesInClasspathRoot(Path.of("does_not_exist").toUri(), allClasses)); } @Test diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java index f56e5cf0e182..3c69d48b2dbf 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleDetailsTests.java @@ -24,7 +24,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.file.Files; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumMap; import java.util.LinkedHashMap; @@ -209,7 +209,7 @@ public void execute() throws Throwable { if (optionalUri.isEmpty()) { if (Boolean.getBoolean("org.junit.platform.console.ConsoleDetailsTests.writeResultOut")) { // do not use Files.createTempDirectory(prefix) as we want one folder for one container - var temp = Paths.get(System.getProperty("java.io.tmpdir"), dirName.replace('/', '-')); + var temp = Path.of(System.getProperty("java.io.tmpdir"), dirName.replace('/', '-')); Files.createDirectories(temp); var path = Files.writeString(temp.resolve(outName), result.out); throw new TestAbortedException( @@ -218,7 +218,7 @@ public void execute() throws Throwable { fail("could not load resource named `" + dirName + "/" + outName + "`"); } - var path = Paths.get(optionalUri.get()); + var path = Path.of(optionalUri.get()); assumeTrue(Files.exists(path), "path does not exist: " + path); assumeTrue(Files.isReadable(path), "can not read: " + path); diff --git a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java index 5fe516ef78f1..f6852850705b 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java @@ -34,7 +34,6 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -318,7 +317,7 @@ void parseInvalidExcludedEngines() { @ParameterizedTest @EnumSource void parseValidAdditionalClasspathEntries(ArgsType type) { - var dir = Paths.get("."); + var dir = Path.of("."); // @formatter:off assertAll( () -> assertEquals(List.of(dir), type.parseArgLine("-cp .").discovery.getAdditionalClasspathEntries()), @@ -553,7 +552,7 @@ void parseInvalidUniqueIdSelectors() { @ParameterizedTest @EnumSource void parseClasspathScanningEntries(ArgsType type) { - var dir = Paths.get("."); + var dir = Path.of("."); // @formatter:off assertAll( () -> assertTrue(type.parseArgLine("--scan-class-path").discovery.isScanClasspath()), @@ -563,8 +562,8 @@ void parseClasspathScanningEntries(ArgsType type) { () -> assertTrue(type.parseArgLine("--scan-class-path .").discovery.isScanClasspath()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path .").discovery.getSelectedClasspathEntries()), () -> assertEquals(List.of(dir), type.parseArgLine("--scan-class-path=.").discovery.getSelectedClasspathEntries()), - () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path . --scan-class-path src/test/java").discovery.getSelectedClasspathEntries()), - () -> assertEquals(List.of(dir, Paths.get("src/test/java")), type.parseArgLine("--scan-class-path ." + File.pathSeparator + "src/test/java").discovery.getSelectedClasspathEntries()) + () -> assertEquals(List.of(dir, Path.of("src/test/java")), type.parseArgLine("--scan-class-path . --scan-class-path src/test/java").discovery.getSelectedClasspathEntries()), + () -> assertEquals(List.of(dir, Path.of("src/test/java")), type.parseArgLine("--scan-class-path ." + File.pathSeparator + "src/test/java").discovery.getSelectedClasspathEntries()) ); // @formatter:on } @@ -605,7 +604,7 @@ void parseInvalidConfigurationParameters() { @ParameterizedTest @EnumSource void parseValidStdoutRedirectionFile(ArgsType type) { - var file = Paths.get("foo.txt"); + var file = Path.of("foo.txt"); // @formatter:off assertAll( () -> assertNull(type.parseArgLine("").output.getStdoutPath()), @@ -619,7 +618,7 @@ void parseValidStdoutRedirectionFile(ArgsType type) { @ParameterizedTest @EnumSource void parseValidStderrRedirectionFile(ArgsType type) { - var file = Paths.get("foo.txt"); + var file = Path.of("foo.txt"); // @formatter:off assertAll( () -> assertNull(type.parseArgLine("").output.getStderrPath()), diff --git a/platform-tests/src/test/java/org/junit/platform/console/options/ExecuteTestsCommandTests.java b/platform-tests/src/test/java/org/junit/platform/console/options/ExecuteTestsCommandTests.java index d7186357b51c..f259409c39a6 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/options/ExecuteTestsCommandTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/options/ExecuteTestsCommandTests.java @@ -17,7 +17,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -96,7 +96,7 @@ void hasStatusCode0ForNoTestsAndNotFailIfNoTestsFound() { @Test void parseValidXmlReportsDirs() { - var dir = Paths.get("build", "test-results"); + var dir = Path.of("build", "test-results"); // @formatter:off assertAll( () -> assertEquals(Optional.empty(), parseArgs().getReportsDir()), diff --git a/platform-tests/src/test/java/org/junit/platform/console/tasks/ConsoleTestExecutorTests.java b/platform-tests/src/test/java/org/junit/platform/console/tasks/ConsoleTestExecutorTests.java index f3c99037a180..76da53bcc218 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/tasks/ConsoleTestExecutorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/tasks/ConsoleTestExecutorTests.java @@ -19,7 +19,7 @@ import java.io.PrintWriter; import java.io.StringWriter; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.List; import java.util.Optional; @@ -98,7 +98,7 @@ void printsFailuresEvenIfDetailsAreHidden() { @Test void usesCustomClassLoaderIfAdditionalClassPathEntriesArePresent() { - discoveryOptions.setAdditionalClasspathEntries(List.of(Paths.get("."))); + discoveryOptions.setAdditionalClasspathEntries(List.of(Path.of("."))); var oldClassLoader = getDefaultClassLoader(); dummyTestEngine.addTest("failingTest", diff --git a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java index 4b29e747cc76..2c238614bce1 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java @@ -26,7 +26,7 @@ import java.io.File; import java.net.URI; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -73,7 +73,7 @@ void convertsScanClasspathOptionWithoutExplicitRootDirectories() { @Test void convertsScanClasspathOptionWithExplicitRootDirectories() { options.setScanClasspath(true); - options.setSelectedClasspathEntries(List.of(Paths.get("."), Paths.get(".."))); + options.setSelectedClasspathEntries(List.of(Path.of("."), Path.of(".."))); var request = convert(); @@ -87,7 +87,7 @@ void convertsScanClasspathOptionWithExplicitRootDirectories() { @Test void convertsScanClasspathOptionWithAdditionalClasspathEntries() { options.setScanClasspath(true); - options.setAdditionalClasspathEntries(List.of(Paths.get("."), Paths.get(".."))); + options.setAdditionalClasspathEntries(List.of(Path.of("."), Path.of(".."))); var request = convert(); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index 43fd5b2f2321..7d649513deaf 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -37,7 +37,6 @@ import java.lang.reflect.Method; import java.net.URI; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -118,7 +117,7 @@ void selectFileByName() { var selector = selectFile(path); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getFile()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); } @Test @@ -132,7 +131,7 @@ void selectFileByNameAndPosition() { var selector = selectFile(path, filePosition); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getFile()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); assertEquals(filePosition, selector.getPosition().orElseThrow()); } @@ -149,7 +148,7 @@ void selectFileByFileReference() throws Exception { var selector = selectFile(file); assertEquals(path, selector.getRawPath()); assertEquals(file.getCanonicalFile(), selector.getFile()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); } @Test @@ -166,7 +165,7 @@ void selectFileByFileReferenceAndPosition() throws Exception { var selector = selectFile(file, filePosition); assertEquals(path, selector.getRawPath()); assertEquals(file.getCanonicalFile(), selector.getFile()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); assertEquals(FilePosition.from(12, 34), selector.getPosition().orElseThrow()); } @@ -184,7 +183,7 @@ void parseFileSelectorWithRelativePath() { .asInstanceOf(type(FileSelector.class)) // .extracting(FileSelector::getRawPath, FileSelector::getFile, FileSelector::getPath, FileSelector::getPosition) // - .containsExactly(path, new File(path), Paths.get(path), Optional.empty()); + .containsExactly(path, new File(path), Path.of(path), Optional.empty()); } @Test @@ -197,7 +196,7 @@ void parseFileSelectorWithAbsolutePath() { .asInstanceOf(type(FileSelector.class)) // .extracting(FileSelector::getRawPath, FileSelector::getFile, FileSelector::getPath, FileSelector::getPosition) // - .containsExactly(absolutePath, new File(absolutePath), Paths.get(absolutePath), Optional.empty()); + .containsExactly(absolutePath, new File(absolutePath), Path.of(absolutePath), Optional.empty()); } @Test @@ -210,7 +209,7 @@ void parseFileSelectorWithRelativePathAndFilePosition() { .asInstanceOf(type(FileSelector.class)) // .extracting(FileSelector::getRawPath, FileSelector::getFile, FileSelector::getPath, FileSelector::getPosition) // - .containsExactly(path, new File(path), Paths.get(path), Optional.of(filePosition)); + .containsExactly(path, new File(path), Path.of(path), Optional.of(filePosition)); } @Test @@ -224,7 +223,7 @@ void parseFileSelectorWithAbsolutePathAndFilePosition() { .asInstanceOf(type(FileSelector.class)) // .extracting(FileSelector::getRawPath, FileSelector::getFile, FileSelector::getPath, FileSelector::getPosition) // - .containsExactly(absolutePath, new File(absolutePath), Paths.get(absolutePath), + .containsExactly(absolutePath, new File(absolutePath), Path.of(absolutePath), Optional.of(filePosition)); } @@ -238,7 +237,7 @@ void selectDirectoryByName() { var selector = selectDirectory(path); assertEquals(path, selector.getRawPath()); assertEquals(new File(path), selector.getDirectory()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); } @Test @@ -254,7 +253,7 @@ void selectDirectoryByFileReference() throws Exception { var selector = selectDirectory(directory); assertEquals(path, selector.getRawPath()); assertEquals(directory.getCanonicalFile(), selector.getDirectory()); - assertEquals(Paths.get(path), selector.getPath()); + assertEquals(Path.of(path), selector.getPath()); } } @@ -272,7 +271,7 @@ void parseDirectorySelectorWithRelativePath() { .asInstanceOf(type(DirectorySelector.class)) // .extracting(DirectorySelector::getRawPath, DirectorySelector::getDirectory, DirectorySelector::getPath) // - .containsExactly(path, new File(path), Paths.get(path)); + .containsExactly(path, new File(path), Path.of(path)); } @Test @@ -285,7 +284,7 @@ void parseDirectorySelectorWithAbsolutePath() { .asInstanceOf(type(DirectorySelector.class)) // .extracting(DirectorySelector::getRawPath, DirectorySelector::getDirectory, DirectorySelector::getPath) // - .containsExactly(path, new File(path), Paths.get(path)); + .containsExactly(path, new File(path), Path.of(path)); } @Test @@ -468,14 +467,14 @@ class SelectClasspathRootsTests { @Test void selectClasspathRootsWithNonExistingDirectory() { - var selectors = selectClasspathRoots(Set.of(Paths.get("some", "local", "path"))); + var selectors = selectClasspathRoots(Set.of(Path.of("some", "local", "path"))); assertThat(selectors).isEmpty(); } @Test void selectClasspathRootsWithNonExistingJarFile() { - var selectors = selectClasspathRoots(Set.of(Paths.get("some.jar"))); + var selectors = selectClasspathRoots(Set.of(Path.of("some.jar"))); assertThat(selectors).isEmpty(); } @@ -490,7 +489,7 @@ void selectClasspathRootsWithExistingDirectory(@TempDir Path tempDir) { @Test void selectClasspathRootsWithExistingJarFile() throws Exception { var jarUri = requireNonNull(getClass().getResource("/jartest.jar")).toURI(); - var jarFile = Paths.get(jarUri); + var jarFile = Path.of(jarUri); var selectors = selectClasspathRoots(Set.of(jarFile)); diff --git a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java index 60d244895eea..125a8c2a8e81 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.net.URI; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.Collections; import java.util.List; import java.util.Map; @@ -487,7 +487,7 @@ class Suite { LauncherDiscoveryRequest request = builder.applySelectorsAndFiltersFromSuite(Suite.class).build(); List selectors = request.getSelectorsByType(DirectorySelector.class); - assertEquals(Paths.get("path/to/root"), exactlyOne(selectors).getPath()); + assertEquals(Path.of("path/to/root"), exactlyOne(selectors).getPath()); } @Test @@ -508,7 +508,7 @@ class Suite { LauncherDiscoveryRequest request = builder.applySelectorsAndFiltersFromSuite(Suite.class).build(); List selectors = request.getSelectorsByType(FileSelector.class); - assertEquals(Paths.get("path/to/root"), exactlyOne(selectors).getPath()); + assertEquals(Path.of("path/to/root"), exactlyOne(selectors).getPath()); } @Test diff --git a/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java b/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java index e6df0bafa2fa..0df95dd15ca8 100644 --- a/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java +++ b/platform-tooling-support-tests/src/main/java/platform/tooling/support/Helper.java @@ -12,7 +12,6 @@ import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -26,7 +25,7 @@ */ public class Helper { - private static final Path ROOT = Paths.get(".."); + private static final Path ROOT = Path.of(".."); private static final Path GRADLE_PROPERTIES = ROOT.resolve("gradle.properties"); private static final Path SETTINGS_GRADLE = ROOT.resolve("settings.gradle.kts"); From 16c145981ae3aebca480107f5fbdefef4d71a3b1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:33:10 +0200 Subject: [PATCH 066/521] Use `Optional.stream` --- .../engine/descriptor/DynamicContainerTestDescriptor.java | 3 +-- .../jupiter/engine/discovery/ClassSelectorResolver.java | 3 +-- .../jupiter/engine/discovery/MethodSelectorResolver.java | 6 ++---- .../discovery/DiscoverySelectorIdentifierParsers.java | 6 ++---- .../core/StackTracePruningEngineExecutionListener.java | 3 +-- 5 files changed, 7 insertions(+), 14 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicContainerTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicContainerTestDescriptor.java index 8f157b9f8726..c5ade66011e3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicContainerTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicContainerTestDescriptor.java @@ -69,8 +69,7 @@ public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext conte Preconditions.notNull(child, "individual dynamic node must not be null"); return toDynamicDescriptor(index.getAndIncrement(), child); }) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(Optional::stream) .forEachOrdered(dynamicTestExecutor::execute); // @formatter:on } 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 4eeb93e4bb70..1c48d3f607a9 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 @@ -172,8 +172,7 @@ private Resolution resolveIterations(IterationSelector selector, Context context .map(index -> context.addToParent(() -> parentSelector, parent -> Optional.of(newDummyClassTemplateInvocationTestDescriptor(parent, index + 1)))) // .map(this::toInvocationMatch) // - .filter(Optional::isPresent) // - .map(Optional::get) // + .flatMap(Optional::stream) // .collect(toSet()); return matches.isEmpty() ? unresolved() : Resolution.matches(matches); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java index 57d9a64ad198..ec75bcc3734c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java @@ -95,8 +95,7 @@ private Resolution resolve(Context context, List> enclosingClasses, Cla // @formatter:off Set matches = methodTypes.stream() .map(methodType -> methodType.resolve(enclosingClasses, testClass, method, context, configuration)) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(Optional::stream) .map(testDescriptor -> matchFactory.apply(testDescriptor, expansionCallback(testDescriptor))) .collect(toSet()); // @formatter:on @@ -119,8 +118,7 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { // @formatter:off return methodTypes.stream() .map(methodType -> methodType.resolveUniqueIdIntoTestDescriptor(uniqueId, context, configuration)) - .filter(Optional::isPresent) - .map(Optional::get) + .flatMap(Optional::stream) .map(testDescriptor -> { boolean exactMatch = uniqueId.equals(testDescriptor.getUniqueId()); if (testDescriptor instanceof Filterable) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java index 8407dabb182f..63aacfb900f0 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java @@ -37,16 +37,14 @@ static Stream parseAll(String... identifiers) { Preconditions.notNull(identifiers, "identifiers must not be null"); return Stream.of(identifiers) // .map(DiscoverySelectorIdentifierParsers::parse) // - .filter(Optional::isPresent) // - .map(Optional::get); + .flatMap(Optional::stream); } static Stream parseAll(Collection identifiers) { Preconditions.notNull(identifiers, "identifiers must not be null"); return identifiers.stream() // .map(DiscoverySelectorIdentifierParsers::parse) // - .filter(Optional::isPresent) // - .map(Optional::get); + .flatMap(Optional::stream); } static Optional parse(String identifier) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java index 6a6193337d89..2e5d5b66ac1d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java @@ -50,8 +50,7 @@ private static List getTestClassNames(TestDescriptor testDescriptor) { return testDescriptor.getAncestors() // .stream() // .map(TestDescriptor::getSource) // - .filter(Optional::isPresent) // - .map(Optional::get) // + .flatMap(Optional::stream) // .map(source -> { if (source instanceof ClassSource) { return ((ClassSource) source).getClassName(); From e69892178d5f648ae9a14c67cd675f99284b506a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:33:32 +0200 Subject: [PATCH 067/521] Use `Optional.isEmpty()` instead of `!Optional.isPresent()` --- .../jupiter/engine/extension/MutableExtensionRegistry.java | 4 ++-- .../junit/jupiter/params/ParameterizedClassExtension.java | 2 +- .../junit/jupiter/params/ParameterizedTestExtension.java | 2 +- .../main/java/org/junit/jupiter/params/ResolverFacade.java | 2 +- .../junit/platform/commons/support/AnnotationSupport.java | 2 +- .../org/junit/platform/commons/util/AnnotationUtils.java | 4 ++-- .../java/org/junit/platform/commons/util/RuntimeUtils.java | 2 +- .../java/org/junit/platform/console/tasks/TreePrinter.java | 4 ++-- .../java/org/junit/platform/engine/TestDescriptor.java | 4 ++-- .../platform/engine/discovery/ExcludeClassNameFilter.java | 2 +- .../engine/discovery/ExcludePackageNameFilter.java | 2 +- .../main/java/org/junit/platform/launcher/TestPlan.java | 2 +- .../launcher/core/EngineDiscoveryResultValidator.java | 7 +++---- .../core/StreamInterceptingTestExecutionListener.java | 2 +- .../legacy/xml/LegacyXmlReportGeneratingListener.java | 2 +- .../java/org/junit/platform/testkit/engine/Events.java | 2 +- .../junit/vintage/engine/execution/RunListenerAdapter.java | 2 +- .../java/org/junit/vintage/engine/execution/TestRun.java | 2 +- 18 files changed, 24 insertions(+), 25 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index 43927d66d3c8..1ad9dd1eeb39 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -312,12 +312,12 @@ public Class getTestClass() { } void initialize(Object testInstance) { - Preconditions.condition(!extension.isPresent(), "Extension already initialized"); + Preconditions.condition(extension.isEmpty(), "Extension already initialized"); extension = Optional.of(initializer.apply(testInstance)); } LateInitEntry copy() { - Preconditions.condition(!extension.isPresent(), "Extension already initialized"); + Preconditions.condition(extension.isEmpty(), "Extension already initialized"); return new LateInitEntry(testClass, initializer); } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java index db56de4f8f78..2f45b6d7f606 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java @@ -97,7 +97,7 @@ private boolean validateAndStoreClassContext(ExtensionContext extensionContext) Optional annotation = findAnnotation(extensionContext.getTestClass(), ParameterizedClass.class); - if (!annotation.isPresent()) { + if (annotation.isEmpty()) { return false; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java index 5097d9f02322..1b4393d4f3a3 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java @@ -31,7 +31,7 @@ class ParameterizedTestExtension extends ParameterizedInvocationContextProvider< @Override public boolean supportsTestTemplate(ExtensionContext context) { Optional annotation = findAnnotation(context.getTestMethod(), ParameterizedTest.class); - if (!annotation.isPresent()) { + if (annotation.isEmpty()) { return false; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 6507d0096549..f47fcf872575 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -710,7 +710,7 @@ public Object resolve(Resolver resolver, ExtensionContext extensionContext, Eval private ParameterContext toParameterContext(ExtensionContext extensionContext, Optional originalParameterContext) { Optional target = originalParameterContext.flatMap(ParameterContext::getTarget); - if (!target.isPresent()) { + if (target.isEmpty()) { target = extensionContext.getTestInstance(); } return toParameterContext(target); 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..2da05b6e2ccf 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 @@ -220,7 +220,7 @@ public static Optional findAnnotation(Class clazz, Preconditions.notNull(enclosingInstanceTypes, "enclosingInstanceTypes must not be null"); Optional annotation = findAnnotation(clazz, annotationType); - if (!annotation.isPresent()) { + if (annotation.isEmpty()) { ListIterator> iterator = enclosingInstanceTypes.listIterator(enclosingInstanceTypes.size()); while (iterator.hasPrevious()) { annotation = findAnnotation(iterator.previous(), annotationType); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index bea632eb79f7..cc10f439054b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -111,7 +111,7 @@ public static boolean isAnnotated(AnnotatedElement element, Class Optional findAnnotation(Optional element, Class annotationType) { - if (element == null || !element.isPresent()) { + if (element == null || element.isEmpty()) { return Optional.empty(); } @@ -251,7 +251,7 @@ public static Optional findAnnotation(Class clazz, public static List findRepeatableAnnotations(Optional element, Class annotationType) { - if (element == null || !element.isPresent()) { + if (element == null || element.isEmpty()) { return Collections.emptyList(); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java index e738aea49d8c..490d5c741c89 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java @@ -52,7 +52,7 @@ public static boolean isDebugMode() { static Optional> getInputArguments() { Optional> managementFactoryClass = ReflectionUtils.tryToLoadClass( "java.lang.management.ManagementFactory").toOptional(); - if (!managementFactoryClass.isPresent()) { + if (managementFactoryClass.isEmpty()) { return Optional.empty(); } // Can't use "java.lang.management.ManagementFactory.getRuntimeMXBean().getInputArguments()" diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java index c1997f52d342..6e6201031ca0 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java @@ -80,7 +80,7 @@ private void printVisible(TreeNode node, String indent, boolean continuous) { out.print(" "); out.print(duration); } - boolean nodeIsBeingListed = node.duration == 0 && !node.result().isPresent() && !node.reason().isPresent(); + boolean nodeIsBeingListed = node.duration == 0 && node.result().isEmpty() && node.reason().isEmpty(); if (!nodeIsBeingListed) { out.print(" "); out.print(icon); @@ -120,7 +120,7 @@ private String colorCaption(TreeNode node) { } private void printThrowable(String indent, TestExecutionResult result) { - if (!result.getThrowable().isPresent()) { + if (result.getThrowable().isEmpty()) { return; } Throwable throwable = result.getThrowable().get(); 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..f3113a41be5a 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 @@ -120,7 +120,7 @@ default String getLegacyReportingName() { */ @API(status = STABLE, since = "1.10") default Set getAncestors() { - if (!getParent().isPresent()) { + if (getParent().isEmpty()) { return Collections.emptySet(); } TestDescriptor parent = getParent().get(); @@ -215,7 +215,7 @@ default void orderChildren(UnaryOperator> orderer) { *

A root descriptor is a descriptor without a parent. */ default boolean isRoot() { - return !getParent().isPresent(); + return getParent().isEmpty(); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java index 152ec5f04cb1..f98d90de6966 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludeClassNameFilter.java @@ -50,7 +50,7 @@ private String formatExclusionReason(String className, Pattern pattern) { @Override public Predicate toPredicate() { - return className -> !findMatchingPattern(className).isPresent(); + return className -> findMatchingPattern(className).isEmpty(); } @Override diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java index 8f5f80504267..49986e06fd92 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/ExcludePackageNameFilter.java @@ -61,7 +61,7 @@ private String formatExclusionReason(String packageName, String matchedName) { @Override public Predicate toPredicate() { - return packageName -> !findMatchingName(packageName).isPresent(); + return packageName -> findMatchingName(packageName).isEmpty(); } private Optional findMatchingName(String packageName) { 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 646f2bd01274..56900c46844e 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 @@ -110,7 +110,7 @@ public void addInternal(TestIdentifier testIdentifier) { allIdentifiers.put(testIdentifier.getUniqueIdObject(), testIdentifier); // Root identifiers. Typically, a test engine. - if (!testIdentifier.getParentIdObject().isPresent()) { + if (testIdentifier.getParentIdObject().isEmpty()) { roots.add(testIdentifier); return; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java index d2c20ce6b1b5..85d417df85e0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryResultValidator.java @@ -39,12 +39,11 @@ class EngineDiscoveryResultValidator { */ void validate(TestEngine testEngine, TestDescriptor root) { Preconditions.notNull(root, - () -> String.format( - "The discover() method for TestEngine with ID '%s' must return a non-null root TestDescriptor.", + () -> "The discover() method for TestEngine with ID '%s' must return a non-null root TestDescriptor.".formatted( testEngine.getId())); Optional cyclicGraphInfo = getCyclicGraphInfo(root); - Preconditions.condition(!cyclicGraphInfo.isPresent(), - () -> String.format("The discover() method for TestEngine with ID '%s' returned a cyclic graph; %s", + Preconditions.condition(cyclicGraphInfo.isEmpty(), + () -> "The discover() method for TestEngine with ID '%s' returned a cyclic graph; %s".formatted( testEngine.getId(), cyclicGraphInfo.get())); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptingTestExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptingTestExecutionListener.java index 65a5f8ba453c..1a337082620e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptingTestExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptingTestExecutionListener.java @@ -55,7 +55,7 @@ static Optional create(ConfigurationPar Optional stderrInterceptor = captureStderr ? StreamInterceptor.registerStderr(maxSize) : Optional.empty(); - if ((!stdoutInterceptor.isPresent() && captureStdout) || (!stderrInterceptor.isPresent() && captureStderr)) { + if ((stdoutInterceptor.isEmpty() && captureStdout) || (stderrInterceptor.isEmpty() && captureStderr)) { stdoutInterceptor.ifPresent(StreamInterceptor::unregister); stderrInterceptor.ifPresent(StreamInterceptor::unregister); return Optional.empty(); diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java index 33288eaa7062..4d885ee80c2d 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java @@ -121,7 +121,7 @@ private void writeXmlReportSafely(TestIdentifier testIdentifier, String rootName } private boolean isRoot(TestIdentifier testIdentifier) { - return !testIdentifier.getParentIdObject().isPresent(); + return testIdentifier.getParentIdObject().isEmpty(); } private void printException(String message, Exception exception) { 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..9e61e64dbc6f 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 @@ -476,7 +476,7 @@ private static Event findEvent(List events, SoftAssertions softly, Condit .findFirst(); // @formatter:on - if (!matchedEvent.isPresent()) { + if (matchedEvent.isEmpty()) { softly.fail("Condition did not match any event: " + condition); } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java index ae0aab651df9..8aec956c3af3 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java @@ -216,7 +216,7 @@ private void fireExecutionFinishedForInProgressNonAncestorTestDescriptorsWithSyn private boolean isAncestor(TestDescriptor candidate, TestDescriptor testDescriptor) { Optional parent = testDescriptor.getParent(); - if (!parent.isPresent()) { + if (parent.isEmpty()) { return false; } if (parent.get().equals(candidate)) { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java index 0e1a4e0ec2e7..5f5fd53311d6 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java @@ -114,7 +114,7 @@ private Optional lookupUnambiguouslyOrApplyFallback(Descr VintageDescriptors vintageDescriptors = descriptionToDescriptors.getOrDefault(description, VintageDescriptors.NONE); Optional result = vintageDescriptors.getUnambiguously(description); - if (!result.isPresent()) { + if (result.isEmpty()) { result = fallback.apply(vintageDescriptors); } return result; From 89c8ddf4671f0483e9e07e04062e877e8ed59b7e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 17:33:43 +0200 Subject: [PATCH 068/521] Use `instanceof` pattern matching --- .../java/example/ParameterizedTestDemo.java | 4 +- .../junit/jupiter/api/AssertArrayEquals.java | 36 ++++++------- .../jupiter/api/AssertIterableEquals.java | 5 +- .../jupiter/api/AssertionFailureBuilder.java | 10 ++-- .../support/TypeBasedParameterResolver.java | 6 +-- .../descriptor/AbstractExtensionContext.java | 8 +-- .../descriptor/ClassBasedTestDescriptor.java | 4 +- .../ClassTemplateTestDescriptor.java | 8 +-- .../descriptor/JupiterTestDescriptor.java | 4 +- .../descriptor/NestedClassTestDescriptor.java | 3 +- .../descriptor/TestFactoryTestDescriptor.java | 7 ++- .../discovery/ClassOrderingVisitor.java | 3 +- .../discovery/ClassSelectorResolver.java | 11 ++-- .../discovery/DiscoverySelectorResolver.java | 4 +- .../discovery/MethodSelectorResolver.java | 9 ++-- .../predicates/IsTestFactoryMethod.java | 15 +++--- .../JupiterEngineExecutionContext.java | 4 +- .../engine/extension/AutoCloseExtension.java | 4 +- .../extension/MutableExtensionRegistry.java | 6 +-- .../engine/extension/TempDirectory.java | 6 +-- .../jupiter/params/EvaluatedArgumentSet.java | 6 +-- .../junit/jupiter/params/ResolverFacade.java | 12 ++--- .../converter/DefaultArgumentConverter.java | 6 +-- .../params/provider/ArgumentsUtils.java | 8 +-- .../params/provider/CsvArgumentsProvider.java | 4 +- .../provider/FieldArgumentsProvider.java | 17 +++--- .../AnnotationConsumerInitializer.java | 5 +- .../support/conversion/ConversionSupport.java | 4 +- .../commons/util/AnnotationUtils.java | 6 +-- .../commons/util/CollectionUtils.java | 44 ++++++++-------- .../platform/commons/util/StringUtils.java | 32 ++++++------ .../tasks/CustomClassLoaderCloseStrategy.java | 4 +- .../tasks/DiscoveryRequestCreator.java | 12 ++--- .../org/junit/platform/engine/TestTag.java | 3 +- .../EngineDiscoveryRequestResolution.java | 52 +++++++++---------- .../store/NamespacedHierarchicalStore.java | 8 +-- .../platform/launcher/TestIdentifier.java | 3 +- .../core/DiscoveryIssueCollector.java | 29 +++++------ .../launcher/core/DiscoveryIssueNotifier.java | 6 +-- .../core/EngineDiscoveryOrchestrator.java | 4 +- .../core/EngineExecutionOrchestrator.java | 4 +- .../core/LauncherDiscoveryRequestBuilder.java | 12 ++--- ...ckTracePruningEngineExecutionListener.java | 8 +-- .../LoggingLauncherDiscoveryListener.java | 4 +- .../xml/OpenTestReportGeneratingListener.java | 28 +++++----- .../descriptor/RunnerTestDescriptor.java | 10 ++-- .../discovery/MethodSelectorResolver.java | 3 +- .../vintage/engine/execution/TestRun.java | 9 ++-- .../sample/LongParameterResolver.java | 4 +- .../engine/extension/TempDirectoryTests.java | 2 +- .../TestInstancePostProcessorTests.java | 4 +- .../TestInstancePreDestroyCallbackTests.java | 4 +- .../ParallelExecutionIntegrationTests.java | 4 +- .../hierarchical/ResourceLockSupport.java | 4 +- .../tooling/support/tests/XmlAssertions.java | 4 +- 55 files changed, 246 insertions(+), 280 deletions(-) diff --git a/documentation/src/test/java/example/ParameterizedTestDemo.java b/documentation/src/test/java/example/ParameterizedTestDemo.java index 50bf1ff882fa..b76647dc6861 100644 --- a/documentation/src/test/java/example/ParameterizedTestDemo.java +++ b/documentation/src/test/java/example/ParameterizedTestDemo.java @@ -465,8 +465,8 @@ public class ToStringArgumentConverter extends SimpleArgumentConverter { @Override protected Object convert(Object source, Class targetType) { assertEquals(String.class, targetType, "Can only convert to String"); - if (source instanceof Enum) { - return ((Enum) source).name(); + if (source instanceof Enum constant) { + return constant.name(); } return String.valueOf(source); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java index 06be401319d6..883b7bd841cf 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java @@ -351,32 +351,32 @@ private static void assertArrayEquals(Object[] expected, Object[] actual, Deque< private static void assertArrayElementsEqual(Object expected, Object actual, Deque indexes, Object messageOrSupplier) { - if (expected instanceof Object[] && actual instanceof Object[]) { - assertArrayEquals((Object[]) expected, (Object[]) actual, indexes, messageOrSupplier); + if (expected instanceof Object[] expectedArray && actual instanceof Object[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof byte[] && actual instanceof byte[]) { - assertArrayEquals((byte[]) expected, (byte[]) actual, indexes, messageOrSupplier); + else if (expected instanceof byte[] expectedArray && actual instanceof byte[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof short[] && actual instanceof short[]) { - assertArrayEquals((short[]) expected, (short[]) actual, indexes, messageOrSupplier); + else if (expected instanceof short[] expectedArray && actual instanceof short[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof int[] && actual instanceof int[]) { - assertArrayEquals((int[]) expected, (int[]) actual, indexes, messageOrSupplier); + else if (expected instanceof int[] expectedArray && actual instanceof int[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof long[] && actual instanceof long[]) { - assertArrayEquals((long[]) expected, (long[]) actual, indexes, messageOrSupplier); + else if (expected instanceof long[] expectedArray && actual instanceof long[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof char[] && actual instanceof char[]) { - assertArrayEquals((char[]) expected, (char[]) actual, indexes, messageOrSupplier); + else if (expected instanceof char[] expectedArray && actual instanceof char[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof float[] && actual instanceof float[]) { - assertArrayEquals((float[]) expected, (float[]) actual, indexes, messageOrSupplier); + else if (expected instanceof float[] expectedArray && actual instanceof float[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof double[] && actual instanceof double[]) { - assertArrayEquals((double[]) expected, (double[]) actual, indexes, messageOrSupplier); + else if (expected instanceof double[] expectedArray && actual instanceof double[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } - else if (expected instanceof boolean[] && actual instanceof boolean[]) { - assertArrayEquals((boolean[]) expected, (boolean[]) actual, indexes, messageOrSupplier); + else if (expected instanceof boolean[] expectedArray && actual instanceof boolean[] actualArray) { + assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); } else if (!Objects.equals(expected, actual)) { if (expected == null && isArray(actual)) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java index c0dcf1dd5875..effc99618785 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java @@ -88,7 +88,7 @@ private static void assertIterableElementsEqual(Object expected, Object actual, } // If both are iterables, we need to check whether they contain the same elements. - if (expected instanceof Iterable && actual instanceof Iterable) { + if (expected instanceof Iterable expectedIterable && actual instanceof Iterable actualIterable) { Pair pair = new Pair(expected, actual); @@ -109,8 +109,7 @@ private static void assertIterableElementsEqual(Object expected, Object actual, // Otherwise, we put the pair under investigation and recurse. investigatedElements.put(pair, Status.UNDER_INVESTIGATION); - assertIterableEquals((Iterable) expected, (Iterable) actual, indexes, messageOrSupplier, - investigatedElements); + assertIterableEquals(expectedIterable, actualIterable, indexes, messageOrSupplier, investigatedElements); // If we reach this point, we've checked that the two iterables contain the same elements so we store this information // in case we come across the same pair again. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java index f03d4c281a39..2af178c2ee46 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -156,8 +156,8 @@ private static String nullSafeGet(Object messageOrSupplier) { if (messageOrSupplier == null) { return null; } - if (messageOrSupplier instanceof Supplier) { - Object message = ((Supplier) messageOrSupplier).get(); + if (messageOrSupplier instanceof Supplier supplier) { + Object message = supplier.get(); return StringUtils.nullSafeToString(message); } return StringUtils.nullSafeToString(messageOrSupplier); @@ -188,8 +188,8 @@ private static String formatClassAndValue(Object value, String valueString) { } private static String toString(Object obj) { - if (obj instanceof Class) { - return getCanonicalName((Class) obj); + if (obj instanceof Class clazz) { + return getCanonicalName(clazz); } return StringUtils.nullSafeToString(obj); } @@ -200,7 +200,7 @@ private static String toHash(Object obj) { private static String getClassName(Object obj) { return (obj == null ? "null" - : obj instanceof Class ? getCanonicalName((Class) obj) : obj.getClass().getName()); + : obj instanceof Class clazz ? getCanonicalName(clazz) : obj.getClass().getName()); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java index 25608a4a1ae8..f2bcf2f73a50 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java @@ -69,10 +69,10 @@ private ParameterizedType findTypeBasedParameterResolverSuperclass(Class claz } Type genericSuperclass = clazz.getGenericSuperclass(); - if (genericSuperclass instanceof ParameterizedType) { - Type rawType = ((ParameterizedType) genericSuperclass).getRawType(); + if (genericSuperclass instanceof ParameterizedType type) { + Type rawType = type.getRawType(); if (rawType == TypeBasedParameterResolver.class) { - return (ParameterizedType) genericSuperclass; + return type; } } return findTypeBasedParameterResolverSuperclass(superclass); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index 219acbb474c7..7adb978fea33 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -93,17 +93,17 @@ private NamespacedHierarchicalStore.CloseAction { boolean isAutoCloseEnabled = this.configuration.isClosingStoredAutoCloseablesEnabled(); - if (value instanceof AutoCloseable && isAutoCloseEnabled) { - ((AutoCloseable) value).close(); + if (value instanceof AutoCloseable closeable && isAutoCloseEnabled) { + closeable.close(); return; } - if (value instanceof Store.CloseableResource) { + if (value instanceof Store.CloseableResource resource) { if (isAutoCloseEnabled) { LOGGER.warn( () -> "Type implements CloseableResource but not AutoCloseable: " + value.getClass().getName()); } - ((Store.CloseableResource) value).close(); + resource.close(); } }; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index a78de2138afd..09b0dd981361 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -365,8 +365,8 @@ private Object invokeTestInstanceFactory(Optional outerInstance, catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); - if (throwable instanceof TestInstantiationException) { - throw (TestInstantiationException) throwable; + if (throwable instanceof TestInstantiationException exception) { + throw exception; } String message = "TestInstanceFactory [%s] failed to instantiate test class [%s]".formatted( diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java index e88153f502cd..35360b0b33ab 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java @@ -134,8 +134,8 @@ public void prune() { new LinkedHashSet<>(this.children).forEach(child -> child.accept(TestDescriptor::prune)); // Second iteration to avoid processing children that were pruned in the first iteration this.children.forEach(child -> { - if (child instanceof ClassTemplateInvocationTestDescriptor) { - int index = ((ClassTemplateInvocationTestDescriptor) child).getIndex(); + if (child instanceof ClassTemplateInvocationTestDescriptor descriptor) { + int index = descriptor.getIndex(); this.dynamicDescendantFilter.allowIndex(index - 1); this.childrenPrototypesByIndex.put(index, child.getChildren()); } @@ -180,8 +180,8 @@ public Function> getResou public Set getExclusiveResources() { Set result = determineExclusiveResources().collect(toCollection(HashSet::new)); Visitor visitor = testDescriptor -> { - if (testDescriptor instanceof Node) { - result.addAll(((Node) testDescriptor).getExclusiveResources()); + if (testDescriptor instanceof Node node) { + result.addAll(node.getExclusiveResources()); } }; this.childrenPrototypes.forEach(child -> child.accept(visitor)); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index c4052d38ec27..fe5547cafd84 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -181,8 +181,8 @@ public static ExecutionMode toExecutionMode(org.junit.jupiter.api.parallel.Execu @Override public Set getExclusiveResources() { - if (this instanceof ResourceLockAware) { - return ((ResourceLockAware) this).determineExclusiveResources().collect(toSet()); + if (this instanceof ResourceLockAware aware) { + return aware.determineExclusiveResources().collect(toSet()); } return emptySet(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java index deb609ef8814..e6ffaa3d9144 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java @@ -88,8 +88,7 @@ public List> getEnclosingTestClasses() { @API(status = INTERNAL, since = "5.12") public static List> getEnclosingTestClasses(TestDescriptor parent) { - if (parent instanceof TestClassAware) { - TestClassAware parentClassDescriptor = (TestClassAware) parent; + if (parent instanceof TestClassAware parentClassDescriptor) { List> result = new ArrayList<>(parentClassDescriptor.getEnclosingTestClasses()); result.add(parentClassDescriptor.getTestClass()); return result; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java index 0c6674299e42..a2d782bad1fa 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java @@ -134,8 +134,8 @@ protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTe @SuppressWarnings("unchecked") private Stream toDynamicNodeStream(Object testFactoryMethodResult) { - if (testFactoryMethodResult instanceof DynamicNode) { - return Stream.of((DynamicNode) testFactoryMethodResult); + if (testFactoryMethodResult instanceof DynamicNode node) { + return Stream.of(node); } return (Stream) CollectionUtils.toStream(testFactoryMethodResult); } @@ -155,8 +155,7 @@ static Optional createDynamicDescriptor(JupiterTestDescri Optional customTestSource = node.getTestSourceUri().map(TestFactoryTestDescriptor::fromUri); TestSource source = customTestSource.orElse(defaultTestSource); - if (node instanceof DynamicTest) { - DynamicTest test = (DynamicTest) node; + if (node instanceof DynamicTest test) { uniqueId = parent.getUniqueId().append(DYNAMIC_TEST_SEGMENT_TYPE, "#" + index); descriptorCreator = () -> new DynamicTestTestDescriptor(uniqueId, index, test, source, configuration); } 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 abe7b7e64eb7..2d6502f6c898 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 @@ -116,8 +116,7 @@ private DescriptorWrapperOrderer createCla .map(this::createDescriptorWrapperOrderer)// .orElseGet(() -> { Object parent = classBasedTestDescriptor.getParent().orElse(null); - if (parent instanceof ClassBasedTestDescriptor) { - ClassBasedTestDescriptor parentClassTestDescriptor = (ClassBasedTestDescriptor) parent; + if (parent instanceof ClassBasedTestDescriptor parentClassTestDescriptor) { DescriptorWrapperOrderer cacheEntry = ordererCache.get( parentClassTestDescriptor); return cacheEntry != null ? cacheEntry : createClassLevelOrderer(parentClassTestDescriptor); 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 1c48d3f607a9..b47e8434c009 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 @@ -155,12 +155,12 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { @Override public Resolution resolve(IterationSelector selector, Context context) { DiscoverySelector parentSelector = selector.getParentSelector(); - if (parentSelector instanceof ClassSelector - && this.predicates.isAnnotatedWithClassTemplate.test(((ClassSelector) parentSelector).getJavaClass())) { + if (parentSelector instanceof ClassSelector classSelector + && this.predicates.isAnnotatedWithClassTemplate.test(classSelector.getJavaClass())) { return resolveIterations(selector, context); } - if (parentSelector instanceof NestedClassSelector && this.predicates.isAnnotatedWithClassTemplate.test( - ((NestedClassSelector) parentSelector).getNestedClass())) { + if (parentSelector instanceof NestedClassSelector nestedClassSelector + && this.predicates.isAnnotatedWithClassTemplate.test(nestedClassSelector.getNestedClass())) { return resolveIterations(selector, context); } return unresolved(); @@ -283,8 +283,7 @@ private static List> getTestClasses(TestClassAware testDescriptor) { private Supplier> expansionCallback(TestDescriptor testDescriptor, Supplier>> testClassesSupplier) { return () -> { - if (testDescriptor instanceof Filterable) { - Filterable filterable = (Filterable) testDescriptor; + if (testDescriptor instanceof Filterable filterable) { filterable.getDynamicDescendantFilter().allowAll(); } List> testClasses = testClassesSupplier.get(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java index 4cb16f9170fa..dbe6c9a92a2b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolver.java @@ -47,8 +47,8 @@ public class DiscoverySelectorResolver { new ClassOrderingVisitor(getConfiguration(ctx), ctx.getIssueReporter()), // new MethodOrderingVisitor(getConfiguration(ctx), ctx.getIssueReporter()), // descriptor -> { - if (descriptor instanceof Validatable) { - ((Validatable) descriptor).validate(ctx.getIssueReporter()); + if (descriptor instanceof Validatable validatable) { + validatable.validate(ctx.getIssueReporter()); } })) // .build(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java index ec75bcc3734c..ee187caf066f 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java @@ -121,8 +121,7 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { .flatMap(Optional::stream) .map(testDescriptor -> { boolean exactMatch = uniqueId.equals(testDescriptor.getUniqueId()); - if (testDescriptor instanceof Filterable) { - Filterable filterable = (Filterable) testDescriptor; + if (testDescriptor instanceof Filterable filterable) { if (exactMatch) { filterable.getDynamicDescendantFilter().allowAll(); } @@ -143,8 +142,7 @@ public Resolution resolve(IterationSelector selector, Context context) { MethodSelector methodSelector = (MethodSelector) selector.getParentSelector(); return resolve(context, emptyList(), methodSelector.getJavaClass(), methodSelector::getJavaMethod, (testDescriptor, childSelectorsSupplier) -> { - if (testDescriptor instanceof Filterable) { - Filterable filterable = (Filterable) testDescriptor; + if (testDescriptor instanceof Filterable filterable) { filterable.getDynamicDescendantFilter().allowIndex(selector.getIterationIndices()); } return Match.partial(testDescriptor, childSelectorsSupplier); @@ -155,8 +153,7 @@ public Resolution resolve(IterationSelector selector, Context context) { private Supplier> expansionCallback(TestDescriptor testDescriptor) { return () -> { - if (testDescriptor instanceof Filterable) { - Filterable filterable = (Filterable) testDescriptor; + if (testDescriptor instanceof Filterable filterable) { filterable.getDynamicDescendantFilter().allowAll(); } return emptySet(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java index aa4b693d8443..7b3e27d6abc7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/IsTestFactoryMethod.java @@ -69,20 +69,19 @@ private static boolean isCompatible(Method method, DiscoveryIssueReporter issueR private static boolean isCompatibleContainerType(Method method, DiscoveryIssueReporter issueReporter) { Type genericReturnType = getGenericReturnType(method); - if (genericReturnType instanceof ParameterizedType) { - Type[] typeArguments = ((ParameterizedType) genericReturnType).getActualTypeArguments(); + if (genericReturnType instanceof ParameterizedType type) { + Type[] typeArguments = type.getActualTypeArguments(); if (typeArguments.length == 1) { Type typeArgument = typeArguments[0]; - if (typeArgument instanceof Class) { + if (typeArgument instanceof Class clazz) { // Stream etc. - return DynamicNode.class.isAssignableFrom((Class) typeArgument); + return DynamicNode.class.isAssignableFrom(clazz); } - if (typeArgument instanceof WildcardType) { - WildcardType wildcardType = (WildcardType) typeArgument; + if (typeArgument instanceof WildcardType wildcardType) { Type[] upperBounds = wildcardType.getUpperBounds(); Type[] lowerBounds = wildcardType.getLowerBounds(); - if (upperBounds.length == 1 && lowerBounds.length == 0 && upperBounds[0] instanceof Class) { - Class upperBound = (Class) upperBounds[0]; + if (upperBounds.length == 1 && lowerBounds.length == 0 + && upperBounds[0] instanceof Class upperBound) { if (Object.class.equals(upperBound)) { // Stream etc. issueReporter.reportIssue(createTooGenericReturnTypeIssue(method)); return true; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java index fab10b76024e..f62338b9b272 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java @@ -45,9 +45,9 @@ private JupiterEngineExecutionContext(State state) { public void close() throws Exception { ExtensionContext extensionContext = getExtensionContext(); - if (extensionContext instanceof AutoCloseable) { + if (extensionContext instanceof AutoCloseable closeable) { try { - ((AutoCloseable) extensionContext).close(); + closeable.close(); } catch (Exception e) { throw new JUnitException("Failed to close extension context", e); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java index d9f41da9e8f4..b4d4261d772e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java @@ -84,8 +84,8 @@ private static void closeField(Field field, Object testInstance) throws Exceptio private static void invokeCloseMethod(Field field, Object target, String methodName) throws Exception { // Avoid reflection if we can directly invoke close() via AutoCloseable. - if (target instanceof AutoCloseable && "close".equals(methodName)) { - ((AutoCloseable) target).close(); + if (target instanceof AutoCloseable closeable && "close".equals(methodName)) { + closeable.close(); return; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index 1ad9dd1eeb39..4dd3f44ff778 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -167,8 +167,7 @@ private MutableExtensionRegistry(Set> registeredExten this.lateInitExtensions = new LinkedHashMap<>(); registeredExtensions.forEach(entry -> { Entry newEntry = entry; - if (entry instanceof LateInitEntry) { - LateInitEntry lateInitEntry = (LateInitEntry) entry; + if (entry instanceof LateInitEntry lateInitEntry) { newEntry = lateInitEntry.getExtension() // .map(Entry::of) // .orElseGet(() -> getLateInitExtensions(lateInitEntry.getTestClass()).add(lateInitEntry.copy())); @@ -271,8 +270,7 @@ private String buildSourceInfo(Object source) { if (source == null) { return ""; } - if (source instanceof Member) { - Member member = (Member) source; + if (source instanceof Member member) { Object type = (member instanceof Method ? "method" : "field"); source = "%s %s.%s".formatted(type, member.getDeclaringClass().getName(), member.getName()); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java index 2223ad4142c0..5252b18f4f03 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java @@ -344,12 +344,10 @@ public void close() throws IOException { * @since 5.12 */ private static String descriptionFor(AnnotatedElement annotatedElement) { - if (annotatedElement instanceof Field) { - Field field = (Field) annotatedElement; + if (annotatedElement instanceof Field field) { return "field " + field.getDeclaringClass().getSimpleName() + "." + field.getName(); } - if (annotatedElement instanceof Parameter) { - Parameter parameter = (Parameter) annotatedElement; + if (annotatedElement instanceof Parameter parameter) { Executable executable = parameter.getDeclaringExecutable(); return "parameter '" + parameter.getName() + "' in " + descriptionFor(executable); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java index 65202b04b828..99c609d8969c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java @@ -92,8 +92,8 @@ private static Object[] dropSurplus(Object[] arguments, int newLength) { } private static Optional determineName(Arguments arguments) { - if (arguments instanceof ArgumentSet) { - return Optional.of(((ArgumentSet) arguments).getName()); + if (arguments instanceof ArgumentSet set) { + return Optional.of(set.getName()); } return Optional.empty(); } @@ -105,7 +105,7 @@ private static Object[] extractFromNamed(Object[] arguments, Function, } private static Object extractFromNamed(Object argument, Function, Object> mapper) { - return argument instanceof Named ? mapper.apply((Named) argument) : argument; + return argument instanceof Named named ? mapper.apply(named) : argument; } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index f47fcf872575..54dc04b767f4 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -592,14 +592,14 @@ public String getSourceElementDescription() { } static String describe(AnnotatedElement sourceElement) { - if (sourceElement instanceof Method) { - return String.format("method [%s]", ((Method) sourceElement).toGenericString()); + if (sourceElement instanceof Method method) { + return "method [%s]".formatted(method.toGenericString()); } - if (sourceElement instanceof Constructor) { - return String.format("constructor [%s]", ((Constructor) sourceElement).toGenericString()); + if (sourceElement instanceof Constructor constructor) { + return "constructor [%s]".formatted(constructor.toGenericString()); } - if (sourceElement instanceof Class) { - return String.format("class [%s]", ((Class) sourceElement).getName()); + if (sourceElement instanceof Class clazz) { + return "class [%s]".formatted(clazz.getName()); } return sourceElement.toString(); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java index 3ac11b1c4a82..81e0bf1bc95d 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java @@ -106,13 +106,13 @@ public final Object convert(Object source, Class targetType, ClassLoader clas return source; } - if (source instanceof String) { + if (source instanceof String string) { if (targetType == Locale.class && getLocaleConversionFormat() == LocaleConversionFormat.BCP_47) { - return Locale.forLanguageTag((String) source); + return Locale.forLanguageTag(string); } try { - return convert((String) source, targetType, classLoader); + return convert(string, targetType, classLoader); } catch (ConversionException ex) { throw new ArgumentConversionException(ex.getMessage(), ex); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsUtils.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsUtils.java index 105d85354079..e688909889eb 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsUtils.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsUtils.java @@ -30,8 +30,8 @@ private ArgumentsUtils() { */ static Arguments toArguments(Object item) { // Nothing to do except cast. - if (item instanceof Arguments) { - return (Arguments) item; + if (item instanceof Arguments arguments) { + return arguments; } // Pass all multidimensional arrays "as is", in contrast to Object[]. @@ -42,8 +42,8 @@ static Arguments toArguments(Object item) { // Special treatment for one-dimensional reference arrays. // See https://github.com/junit-team/junit5/issues/1665 - if (item instanceof Object[]) { - return arguments((Object[]) item); + if (item instanceof Object[] objects) { + return arguments(objects); } // Pass everything else "as is". diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index 2b40f6cae7ac..86329b967638 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -149,8 +149,8 @@ static Arguments processCsvRecord(Object[] csvRecord, Set nullValues, bo */ static RuntimeException handleCsvException(Throwable throwable, Annotation annotation) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); - if (throwable instanceof PreconditionViolationException) { - throw (PreconditionViolationException) throwable; + if (throwable instanceof PreconditionViolationException exception) { + throw exception; } throw new CsvParsingException("Failed to parse CSV input configured via " + annotation, throwable); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java index ea8b439e4f48..a0a4b137f4d7 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java @@ -60,8 +60,8 @@ protected Stream provideArguments(ParameterDeclarations par .map(field -> validateField(field, testInstance)) .map(field -> readField(field, testInstance)) .flatMap(fieldValue -> { - if (fieldValue instanceof Supplier) { - fieldValue = ((Supplier) fieldValue).get(); + if (fieldValue instanceof Supplier supplier) { + fieldValue = supplier.get(); } return CollectionUtils.toStream(fieldValue); }) @@ -141,21 +141,18 @@ private static boolean isConvertibleToStream(Field field, Object value) { // Check declared type T of Supplier. if (Supplier.class.isAssignableFrom(field.getType())) { Type genericType = field.getGenericType(); - if (genericType instanceof ParameterizedType) { - ParameterizedType parameterizedType = (ParameterizedType) genericType; + if (genericType instanceof ParameterizedType parameterizedType) { Type[] typeArguments = parameterizedType.getActualTypeArguments(); if (typeArguments.length == 1) { Type type = typeArguments[0]; // Handle cases such as Supplier - if (type instanceof Class) { - Class clazz = (Class) type; + if (type instanceof Class clazz) { return CollectionUtils.isConvertibleToStream(clazz); } // Handle cases such as Supplier> - if (type instanceof ParameterizedType) { - Type rawType = ((ParameterizedType) type).getRawType(); - if (rawType instanceof Class) { - Class clazz = (Class) rawType; + if (type instanceof ParameterizedType innerParameterizedType) { + Type rawType = innerParameterizedType.getRawType(); + if (rawType instanceof Class clazz) { return CollectionUtils.isConvertibleToStream(clazz); } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index 785c9e571fc4..5c80776b3be4 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -49,7 +49,7 @@ private AnnotationConsumerInitializer() { @SuppressWarnings({ "unchecked", "rawtypes" }) public static T initialize(AnnotatedElement annotatedElement, T annotationConsumerInstance) { - if (annotationConsumerInstance instanceof AnnotationConsumer) { + if (annotationConsumerInstance instanceof AnnotationConsumer consumer) { Class annotationType = findConsumedAnnotationType(annotationConsumerInstance); List annotations = findAnnotations(annotatedElement, annotationType); @@ -58,8 +58,7 @@ public static T initialize(AnnotatedElement annotatedElement, T annotationCo + " must be used with an annotation of type " + annotationType.getName()); } - annotations.forEach(annotation -> initializeAnnotationConsumer( - (AnnotationConsumer) annotationConsumerInstance, annotation)); + annotations.forEach(annotation -> initializeAnnotationConsumer(consumer, annotation)); } return annotationConsumerInstance; } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java index 6d60ccbe8d61..e56570ca41c7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java @@ -122,9 +122,9 @@ public static T convert(String source, Class targetType, ClassLoader clas return (T) converter.get().convert(source, targetTypeToUse, classLoaderToUse); } catch (Exception ex) { - if (ex instanceof ConversionException) { + if (ex instanceof ConversionException conversionException) { // simply rethrow it - throw (ConversionException) ex; + throw conversionException; } // else throw new ConversionException( diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index cc10f439054b..a1c16200f124 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -159,8 +159,7 @@ private static Optional findAnnotation(AnnotatedElemen return directMetaAnnotation; } - if (element instanceof Class) { - Class clazz = (Class) element; + if (element instanceof Class clazz) { // Search on interfaces for (Class ifc : clazz.getInterfaces()) { @@ -297,8 +296,7 @@ private static void findRepeatableAnnotations(AnnotatedEl Class annotationType, Class containerType, boolean inherited, Set found, Set visited) { - if (element instanceof Class) { - Class clazz = (Class) element; + if (element instanceof Class clazz) { // Recurse first in order to support top-down semantics for inherited, repeatable annotations. if (inherited) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index 9c6bf10b88e7..8e5a6f4d6621 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -194,38 +194,38 @@ public static boolean isConvertibleToStream(Class type) { */ public static Stream toStream(Object object) { Preconditions.notNull(object, "Object must not be null"); - if (object instanceof Stream) { - return (Stream) object; + if (object instanceof Stream stream) { + return stream; } - if (object instanceof DoubleStream) { - return ((DoubleStream) object).boxed(); + if (object instanceof DoubleStream stream) { + return stream.boxed(); } - if (object instanceof IntStream) { - return ((IntStream) object).boxed(); + if (object instanceof IntStream stream) { + return stream.boxed(); } - if (object instanceof LongStream) { - return ((LongStream) object).boxed(); + if (object instanceof LongStream stream) { + return stream.boxed(); } - if (object instanceof Collection) { - return ((Collection) object).stream(); + if (object instanceof Collection collection) { + return collection.stream(); } - if (object instanceof Iterable) { - return stream(((Iterable) object).spliterator(), false); + if (object instanceof Iterable iterable) { + return stream(iterable.spliterator(), false); } - if (object instanceof Iterator) { - return stream(spliteratorUnknownSize((Iterator) object, ORDERED), false); + if (object instanceof Iterator iterator) { + return stream(spliteratorUnknownSize(iterator, ORDERED), false); } - if (object instanceof Object[]) { - return Arrays.stream((Object[]) object); + if (object instanceof Object[] array) { + return Arrays.stream(array); } - if (object instanceof double[]) { - return DoubleStream.of((double[]) object).boxed(); + if (object instanceof double[] array) { + return DoubleStream.of(array).boxed(); } - if (object instanceof int[]) { - return IntStream.of((int[]) object).boxed(); + if (object instanceof int[] array) { + return IntStream.of(array).boxed(); } - if (object instanceof long[]) { - return LongStream.of((long[]) object).boxed(); + if (object instanceof long[] array) { + return LongStream.of(array).boxed(); } if (object.getClass().isArray() && object.getClass().getComponentType().isPrimitive()) { return IntStream.range(0, Array.getLength(object)).mapToObj(i -> Array.get(object, i)); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java index 9989cb33a93b..18949e91eb9c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java @@ -165,29 +165,29 @@ public static String nullSafeToString(Object obj) { try { if (obj.getClass().isArray()) { if (obj.getClass().getComponentType().isPrimitive()) { - if (obj instanceof boolean[]) { - return Arrays.toString((boolean[]) obj); + if (obj instanceof boolean[] booleans) { + return Arrays.toString(booleans); } - if (obj instanceof char[]) { - return Arrays.toString((char[]) obj); + if (obj instanceof char[] chars) { + return Arrays.toString(chars); } - if (obj instanceof short[]) { - return Arrays.toString((short[]) obj); + if (obj instanceof short[] shorts) { + return Arrays.toString(shorts); } - if (obj instanceof byte[]) { - return Arrays.toString((byte[]) obj); + if (obj instanceof byte[] bytes) { + return Arrays.toString(bytes); } - if (obj instanceof int[]) { - return Arrays.toString((int[]) obj); + if (obj instanceof int[] ints) { + return Arrays.toString(ints); } - if (obj instanceof long[]) { - return Arrays.toString((long[]) obj); + if (obj instanceof long[] longs) { + return Arrays.toString(longs); } - if (obj instanceof float[]) { - return Arrays.toString((float[]) obj); + if (obj instanceof float[] floats) { + return Arrays.toString(floats); } - if (obj instanceof double[]) { - return Arrays.toString((double[]) obj); + if (obj instanceof double[] doubles) { + return Arrays.toString(doubles); } } return Arrays.deepToString((Object[]) obj); diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java index 8a4694ba2156..f859e2bb687a 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java @@ -31,8 +31,8 @@ public enum CustomClassLoaderCloseStrategy { @Override public void handle(ClassLoader customClassLoader) { - if (customClassLoader instanceof AutoCloseable) { - close((AutoCloseable) customClassLoader); + if (customClassLoader instanceof AutoCloseable closeable) { + close(closeable); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java index 75934df963ac..d85bed36ca35 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java @@ -137,15 +137,15 @@ private static ClassNameFilter includedClassNamePatterns(TestDiscoveryOptions op Stream patternStreams = Stream.concat( // options.getIncludedClassNamePatterns().stream(), // selectors.stream() // - .map(selector -> selector instanceof IterationSelector - ? ((IterationSelector) selector).getParentSelector() + .map(selector -> selector instanceof IterationSelector iterationSelector + ? iterationSelector.getParentSelector() : selector) // .map(selector -> { - if (selector instanceof ClassSelector) { - return ((ClassSelector) selector).getClassName(); + if (selector instanceof ClassSelector classSelector) { + return classSelector.getClassName(); } - if (selector instanceof MethodSelector) { - return ((MethodSelector) selector).getClassName(); + if (selector instanceof MethodSelector methodSelector) { + return methodSelector.getClassName(); } return null; }) // diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index 2edf2fea3584..70a04ce893dc 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -135,8 +135,7 @@ public String getName() { @Override public boolean equals(Object obj) { - if (obj instanceof TestTag) { - TestTag that = (TestTag) obj; + if (obj instanceof TestTag that) { return Objects.equals(this.name, that.name); } return false; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java index 36a939414a7d..2c4590fd11be 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java @@ -120,46 +120,46 @@ private Optional resolve(DiscoverySelector selector) { if (resolvedSelectors.containsKey(selector)) { return Optional.of(resolvedSelectors.get(selector)); } - if (selector instanceof UniqueIdSelector) { - return resolveUniqueId((UniqueIdSelector) selector); + if (selector instanceof UniqueIdSelector uniqueIdSelector) { + return resolveUniqueId(uniqueIdSelector); } return resolve(selector, resolver -> { Context context = getContext(selector); - if (selector instanceof ClasspathResourceSelector) { - return resolver.resolve((ClasspathResourceSelector) selector, context); + if (selector instanceof ClasspathResourceSelector classpathResourceSelector) { + return resolver.resolve(classpathResourceSelector, context); } - if (selector instanceof ClasspathRootSelector) { - return resolver.resolve((ClasspathRootSelector) selector, context); + if (selector instanceof ClasspathRootSelector classpathRootSelector) { + return resolver.resolve(classpathRootSelector, context); } - if (selector instanceof ClassSelector) { - return resolver.resolve((ClassSelector) selector, context); + if (selector instanceof ClassSelector classSelector) { + return resolver.resolve(classSelector, context); } - if (selector instanceof IterationSelector) { - return resolver.resolve((IterationSelector) selector, context); + if (selector instanceof IterationSelector iterationSelector) { + return resolver.resolve(iterationSelector, context); } - if (selector instanceof NestedClassSelector) { - return resolver.resolve((NestedClassSelector) selector, context); + if (selector instanceof NestedClassSelector nestedClassSelector) { + return resolver.resolve(nestedClassSelector, context); } - if (selector instanceof DirectorySelector) { - return resolver.resolve((DirectorySelector) selector, context); + if (selector instanceof DirectorySelector directorySelector) { + return resolver.resolve(directorySelector, context); } - if (selector instanceof FileSelector) { - return resolver.resolve((FileSelector) selector, context); + if (selector instanceof FileSelector fileSelector) { + return resolver.resolve(fileSelector, context); } - if (selector instanceof MethodSelector) { - return resolver.resolve((MethodSelector) selector, context); + if (selector instanceof MethodSelector methodSelector) { + return resolver.resolve(methodSelector, context); } - if (selector instanceof NestedMethodSelector) { - return resolver.resolve((NestedMethodSelector) selector, context); + if (selector instanceof NestedMethodSelector nestedMethodSelector) { + return resolver.resolve(nestedMethodSelector, context); } - if (selector instanceof ModuleSelector) { - return resolver.resolve((ModuleSelector) selector, context); + if (selector instanceof ModuleSelector moduleSelector) { + return resolver.resolve(moduleSelector, context); } - if (selector instanceof PackageSelector) { - return resolver.resolve((PackageSelector) selector, context); + if (selector instanceof PackageSelector packageSelector) { + return resolver.resolve(packageSelector, context); } - if (selector instanceof UriSelector) { - return resolver.resolve((UriSelector) selector, context); + if (selector instanceof UriSelector uriSelector) { + return resolver.resolve(uriSelector, context); } return resolver.resolve(selector, context); }); 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 eee38ecb4b80..916a87bcd97e 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 @@ -424,8 +424,8 @@ public Object get() { if (this.value == NO_VALUE_SET) { computeValue(); } - if (this.value instanceof Failure) { - throw ExceptionUtils.throwAsUncheckedException(((Failure) this.value).throwable); + if (this.value instanceof Failure failure) { + throw ExceptionUtils.throwAsUncheckedException(failure.throwable); } return this.value; } @@ -464,8 +464,8 @@ public interface CloseAction { @API(status = EXPERIMENTAL, since = "1.13") static CloseAction closeAutoCloseables() { return (__, ___, value) -> { - if (value instanceof AutoCloseable) { - ((AutoCloseable) value).close(); + if (value instanceof AutoCloseable closeable) { + closeable.close(); } }; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index 7e880f395ad5..1d4eca7a17e0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -248,8 +248,7 @@ public Set getTags() { @Override public boolean equals(Object obj) { - if (obj instanceof TestIdentifier) { - TestIdentifier that = (TestIdentifier) obj; + if (obj instanceof TestIdentifier that) { return Objects.equals(this.uniqueId, that.uniqueId); } return false; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java index 2b19b1e92f81..e78e720272dd 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java @@ -69,8 +69,8 @@ public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, Sel .source(toSource(selector)) // .build()); } - else if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelector) { - UniqueId uniqueId = ((UniqueIdSelector) selector).getUniqueId(); + else if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelector uniqueIdSelector) { + UniqueId uniqueId = uniqueIdSelector.getUniqueId(); if (uniqueId.hasPrefix(engineId)) { this.issues.add(DiscoveryIssue.create(Severity.ERROR, selector + " could not be resolved")); } @@ -78,37 +78,34 @@ else if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelecto } static TestSource toSource(DiscoverySelector selector) { - if (selector instanceof ClassSelector) { - return ClassSource.from(((ClassSelector) selector).getClassName()); + if (selector instanceof ClassSelector classSelector) { + return ClassSource.from(classSelector.getClassName()); } - if (selector instanceof MethodSelector) { - MethodSelector methodSelector = (MethodSelector) selector; + if (selector instanceof MethodSelector methodSelector) { return MethodSource.from(methodSelector.getClassName(), methodSelector.getMethodName(), methodSelector.getParameterTypeNames()); } - if (selector instanceof ClasspathResourceSelector) { - ClasspathResourceSelector resourceSelector = (ClasspathResourceSelector) selector; + if (selector instanceof ClasspathResourceSelector resourceSelector) { String resourceName = resourceSelector.getClasspathResourceName(); return resourceSelector.getPosition() // .map(DiscoveryIssueCollector::convert) // .map(position -> ClasspathResourceSource.from(resourceName, position)) // .orElseGet(() -> ClasspathResourceSource.from(resourceName)); } - if (selector instanceof PackageSelector) { - return PackageSource.from(((PackageSelector) selector).getPackageName()); + if (selector instanceof PackageSelector packageSelector) { + return PackageSource.from(packageSelector.getPackageName()); } - if (selector instanceof FileSelector) { - FileSelector fileSelector = (FileSelector) selector; + if (selector instanceof FileSelector fileSelector) { return fileSelector.getPosition() // .map(DiscoveryIssueCollector::convert) // .map(position -> FileSource.from(fileSelector.getFile(), position)) // .orElseGet(() -> FileSource.from(fileSelector.getFile())); } - if (selector instanceof DirectorySelector) { - return DirectorySource.from(((DirectorySelector) selector).getDirectory()); + if (selector instanceof DirectorySelector directorySelector) { + return DirectorySource.from(directorySelector.getDirectory()); } - if (selector instanceof UriSelector) { - return UriSource.from(((UriSelector) selector).getUri()); + if (selector instanceof UriSelector uriSelector) { + return UriSource.from(uriSelector.getUri()); } return null; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java index 592af7bd866b..f7b3abe14c22 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java @@ -123,12 +123,10 @@ private static String formatMessage(TestEngine testEngine, List issue.message()); issue.source().ifPresent(source -> { message.append("\n Source: ").append(source); - if (source instanceof MethodSource) { - MethodSource methodSource = (MethodSource) source; + if (source instanceof MethodSource methodSource) { appendIdeCompatibleLink(message, methodSource.getClassName(), methodSource.getMethodName()); } - else if (source instanceof ClassSource) { - ClassSource classSource = (ClassSource) source; + else if (source instanceof ClassSource classSource) { appendIdeCompatibleLink(message, classSource.getClassName(), ""); } }); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java index 13d8ee7deafa..026cefeeba9d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java @@ -200,8 +200,8 @@ private EngineResultInfo discoverEngineRoot(TestEngine testEngine, LauncherDisco catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); JUnitException cause = null; - if (throwable instanceof LinkageError) { - cause = ClasspathAlignmentChecker.check((LinkageError) throwable).orElse(null); + if (throwable instanceof LinkageError error) { + cause = ClasspathAlignmentChecker.check(error).orElse(null); } if (cause == null) { String message = "TestEngine with ID '%s' failed to discover tests".formatted(testEngine.getId()); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java index 4f809967798a..0536b5134736 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineExecutionOrchestrator.java @@ -235,8 +235,8 @@ private void executeEngine(TestDescriptor engineDescriptor, EngineExecutionListe catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); JUnitException cause = null; - if (throwable instanceof LinkageError) { - cause = ClasspathAlignmentChecker.check((LinkageError) throwable).orElse(null); + if (throwable instanceof LinkageError error) { + cause = ClasspathAlignmentChecker.check(error).orElse(null); } if (cause == null) { String message = "TestEngine with ID '%s' failed to execute tests".formatted(testEngine.getId()); 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 58a0e8178b5c..8154f4024d25 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 @@ -304,14 +304,14 @@ public LauncherDiscoveryRequestBuilder outputDirectoryProvider(OutputDirectoryPr } private void storeFilter(Filter filter) { - if (filter instanceof EngineFilter) { - this.engineFilters.add((EngineFilter) filter); + if (filter instanceof EngineFilter engineFilter) { + this.engineFilters.add(engineFilter); } - else if (filter instanceof PostDiscoveryFilter) { - this.postDiscoveryFilters.add((PostDiscoveryFilter) filter); + else if (filter instanceof PostDiscoveryFilter postDiscoveryFilter) { + this.postDiscoveryFilters.add(postDiscoveryFilter); } - else if (filter instanceof DiscoveryFilter) { - this.discoveryFilters.add((DiscoveryFilter) filter); + else if (filter instanceof DiscoveryFilter discoveryFilter) { + this.discoveryFilters.add(discoveryFilter); } else { throw new PreconditionViolationException( diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java index 2e5d5b66ac1d..4fa0a8023fdb 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java @@ -52,11 +52,11 @@ private static List getTestClassNames(TestDescriptor testDescriptor) { .map(TestDescriptor::getSource) // .flatMap(Optional::stream) // .map(source -> { - if (source instanceof ClassSource) { - return ((ClassSource) source).getClassName(); + if (source instanceof ClassSource classSource) { + return classSource.getClassName(); } - else if (source instanceof MethodSource) { - return ((MethodSource) source).getClassName(); + else if (source instanceof MethodSource methodSource) { + return methodSource.getClassName(); } else { return null; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java index b57289f8dab0..ed175537540d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java @@ -78,8 +78,8 @@ public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, Sel break; case UNRESOLVED: Consumer> loggingConsumer = logger::debug; - if (selector instanceof UniqueIdSelector) { - UniqueId uniqueId = ((UniqueIdSelector) selector).getUniqueId(); + if (selector instanceof UniqueIdSelector uniqueIdSelector) { + UniqueId uniqueId = uniqueIdSelector.getUniqueId(); if (uniqueId.hasPrefix(engineId)) { loggingConsumer = logger::warn; } 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 e0f34a7356f3..2fae334d983a 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 @@ -303,17 +303,15 @@ private void reportStarted(TestIdentifier testIdentifier, String id) { } private void addTestSource(TestSource source, Sources sources) { - if (source instanceof CompositeTestSource) { - ((CompositeTestSource) source).getSources().forEach(it -> addTestSource(it, sources)); + if (source instanceof CompositeTestSource compositeSource) { + compositeSource.getSources().forEach(it -> addTestSource(it, sources)); } - else if (source instanceof ClassSource) { - ClassSource classSource = (ClassSource) source; + else if (source instanceof ClassSource classSource) { sources.append(classSource(classSource.getClassName()), // element -> classSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } - else if (source instanceof MethodSource) { - MethodSource methodSource = (MethodSource) source; + else if (source instanceof MethodSource methodSource) { sources.append(methodSource(methodSource.getClassName(), methodSource.getMethodName()), element -> { String methodParameterTypes = methodSource.getMethodParameterTypes(); if (methodParameterTypes != null) { @@ -321,26 +319,24 @@ else if (source instanceof MethodSource) { } }); } - else if (source instanceof ClasspathResourceSource) { - ClasspathResourceSource classpathResourceSource = (ClasspathResourceSource) source; + else if (source instanceof ClasspathResourceSource classpathResourceSource) { sources.append(classpathResourceSource(classpathResourceSource.getClasspathResourceName()), // element -> classpathResourceSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } - else if (source instanceof PackageSource) { - sources.append(packageSource(((PackageSource) source).getPackageName())); + else if (source instanceof PackageSource packageSource) { + sources.append(packageSource(packageSource.getPackageName())); } - else if (source instanceof FileSource) { - FileSource fileSource = (FileSource) source; + else if (source instanceof FileSource fileSource) { sources.append(fileSource(fileSource.getFile()), // element -> fileSource.getPosition().ifPresent( filePosition -> element.addFilePosition(filePosition.getLine(), filePosition.getColumn()))); } - else if (source instanceof DirectorySource) { - sources.append(directorySource(((DirectorySource) source).getFile())); + else if (source instanceof DirectorySource directorySource) { + sources.append(directorySource(directorySource.getFile())); } - else if (source instanceof UriSource) { - sources.append(uriSource(((UriSource) source).getUri())); + else if (source instanceof UriSource uriSource) { + sources.append(uriSource(uriSource.getUri())); } } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java index 05eb8ebfb046..dfe014468d7f 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java @@ -85,10 +85,10 @@ protected boolean tryToExcludeFromRunner(Description description) { } private boolean tryToFilterRunner(Description description) { - if (runner instanceof Filterable) { + if (runner instanceof Filterable filterable) { ExcludeDescriptionFilter filter = new ExcludeDescriptionFilter(description); try { - ((Filterable) runner).filter(filter); + filterable.filter(filter); } catch (NoTestsRemainException ignore) { // it's safe to ignore this exception because childless TestDescriptors will get pruned @@ -163,7 +163,7 @@ public void applyFilters(Consumer childrenCreator) { } private Runner getRunnerToReport() { - return (runner instanceof RunnerDecorator) ? ((RunnerDecorator) runner).getDecoratedRunner() : runner; + return (runner instanceof RunnerDecorator decorator) ? decorator.getDecoratedRunner() : runner; } public boolean isIgnored() { @@ -172,8 +172,8 @@ public boolean isIgnored() { public void setExecutorService(ExecutorService executorService) { Runner runner = getRunnerToReport(); - if (runner instanceof ParentRunner) { - ((ParentRunner) runner).setScheduler(new RunnerScheduler() { + if (runner instanceof ParentRunner parentRunner) { + parentRunner.setScheduler(new RunnerScheduler() { private final List> futures = new CopyOnWriteArrayList<>(); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java index 6bafcee2efab..4f86e78b6579 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java @@ -59,8 +59,7 @@ private Resolution resolveParentAndAddFilter(Context context, DiscoverySelector private Optional addFilter(TestDescriptor parent, Function filterCreator) { - if (parent instanceof RunnerTestDescriptor) { - RunnerTestDescriptor runnerTestDescriptor = (RunnerTestDescriptor) parent; + if (parent instanceof RunnerTestDescriptor runnerTestDescriptor) { runnerTestDescriptor.getFilters().ifPresent( filters -> filters.add(filterCreator.apply(runnerTestDescriptor))); return Optional.of(runnerTestDescriptor); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java index 5f5fd53311d6..dd9ba6d31e21 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java @@ -122,8 +122,7 @@ private Optional lookupUnambiguouslyOrApplyFallback(Descr void markSkipped(TestDescriptor testDescriptor) { skippedDescriptors.add(testDescriptor); - if (testDescriptor instanceof VintageTestDescriptor) { - VintageTestDescriptor vintageDescriptor = (VintageTestDescriptor) testDescriptor; + if (testDescriptor instanceof VintageTestDescriptor vintageDescriptor) { descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); } } @@ -139,8 +138,7 @@ boolean isSkipped(TestDescriptor testDescriptor) { void markStarted(TestDescriptor testDescriptor, EventType eventType) { inProgressDescriptors.put(testDescriptor, eventType); startedDescriptors.add(testDescriptor); - if (testDescriptor instanceof VintageTestDescriptor) { - VintageTestDescriptor vintageDescriptor = (VintageTestDescriptor) testDescriptor; + if (testDescriptor instanceof VintageTestDescriptor vintageDescriptor) { inProgressDescriptorsByStartingThread.get().addLast(vintageDescriptor); descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); } @@ -153,8 +151,7 @@ boolean isNotStarted(TestDescriptor testDescriptor) { void markFinished(TestDescriptor testDescriptor) { inProgressDescriptors.remove(testDescriptor); finishedDescriptors.add(testDescriptor); - if (testDescriptor instanceof VintageTestDescriptor) { - VintageTestDescriptor descriptor = (VintageTestDescriptor) testDescriptor; + if (testDescriptor instanceof VintageTestDescriptor descriptor) { inProgressDescriptorsByStartingThread.get().removeLastOccurrence(descriptor); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/LongParameterResolver.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/LongParameterResolver.java index b668e8fc9609..661ee3178b49 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/LongParameterResolver.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/LongParameterResolver.java @@ -43,8 +43,8 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon for (TypeVariable typeVariable : parameterContext.getDeclaringExecutable().getDeclaringClass().getTypeParameters()) { boolean namesMatch = typeInMethod.getTypeName().equals(typeVariable.getName()); boolean typesAreCompatible = typeVariable.getBounds().length == 1 && // - typeVariable.getBounds()[0] instanceof Class && // - ((Class) typeVariable.getBounds()[0]).isAssignableFrom(Long.class); + typeVariable.getBounds()[0] instanceof Class clazz && // + clazz.isAssignableFrom(Long.class); if (namesMatch && typesAreCompatible) { return true; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java index bd7b5d3479b8..394f7005e298 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java @@ -1402,7 +1402,7 @@ public Path createTempDirectory(AnnotatedElementContext elementContext, Extensio } private static String getName(AnnotatedElement element) { - return element instanceof Field ? ((Field) element).getName() : ((Parameter) element).getName(); + return element instanceof Field field ? field.getName() : ((Parameter) element).getName(); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePostProcessorTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePostProcessorTests.java index 698c59068383..2036342affbe 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePostProcessorTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePostProcessorTests.java @@ -189,8 +189,8 @@ static abstract class AbstractInstancePostProcessor implements TestInstancePostP @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) { - if (testInstance instanceof Named) { - ((Named) testInstance).setName(name, context.getRequiredTestClass().getSimpleName()); + if (testInstance instanceof Named named) { + named.setName(name, context.getRequiredTestClass().getSimpleName()); } String instanceType = testInstance.getClass().getSimpleName(); callSequence.add(name + ":" + instanceType); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePreDestroyCallbackTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePreDestroyCallbackTests.java index f2d05a8dc002..bb1c51210ae1 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePreDestroyCallbackTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstancePreDestroyCallbackTests.java @@ -187,8 +187,8 @@ static abstract class AbstractTestInstancePreDestroyCallback implements TestInst public void preDestroyTestInstance(ExtensionContext context) { assertThat(context.getTestInstance()).isPresent(); Object testInstance = context.getTestInstance().get(); - if (testInstance instanceof Destroyable) { - ((Destroyable) testInstance).setDestroyed(); + if (testInstance instanceof Destroyable destroyable) { + destroyable.setDestroyed(); } callSequence.add(name + "PreDestroyCallbackTestInstance:" + testInstance.getClass().getSimpleName()); } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java index 2775585bb9da..b04794acdb78 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionIntegrationTests.java @@ -265,8 +265,8 @@ void runsIsolatedTestsLastToMaximizeParallelism() { List parallelTestMethodEvents = events.reportingEntryPublished() // .filter(e -> e.getTestDescriptor().getSource() // .filter(it -> // - it instanceof MethodSource - && SuccessfulParallelTestCase.class.equals(((MethodSource) it).getJavaClass()) // + it instanceof MethodSource methodSource + && SuccessfulParallelTestCase.class.equals(methodSource.getJavaClass()) // ).isPresent() // ) // .toList(); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ResourceLockSupport.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ResourceLockSupport.java index 8325fb7b30a9..6760d4726e8e 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ResourceLockSupport.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ResourceLockSupport.java @@ -19,8 +19,8 @@ static List getLocks(ResourceLock resourceLock) { if (resourceLock instanceof NopLock) { return List.of(); } - if (resourceLock instanceof SingleLock) { - return List.of(((SingleLock) resourceLock).getLock()); + if (resourceLock instanceof SingleLock lock) { + return List.of(lock.getLock()); } return ((CompositeLock) resourceLock).getLocks(); } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/XmlAssertions.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/XmlAssertions.java index f55c60c4d821..7aa7052999ce 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/XmlAssertions.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/XmlAssertions.java @@ -73,8 +73,8 @@ private static SnapshotSerializer obfuscatingSnapshotSerializer(SnapshotSerializ UnaryOperator obfuscator) { return testResult -> { Object obfuscatedTestResult = testResult; - if (testResult instanceof String) { - obfuscatedTestResult = obfuscator.apply((String) testResult); + if (testResult instanceof String string) { + obfuscatedTestResult = obfuscator.apply(string); } return delegate.serialize(obfuscatedTestResult); }; From 09cbba1d94ff1b4a35fd6e5389cae8f50843d421 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 20 May 2025 20:42:33 +0000 Subject: [PATCH 069/521] Update dependency org.mockito:mockito-bom to v5.18.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c2122ae9025e..87f28c059097 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -54,7 +54,7 @@ log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4 maven = { module = "org.apache.maven:apache-maven", version = "3.9.9" } mavenSurefirePlugin = { module = "org.apache.maven.plugins:maven-surefire-plugin", version.ref = "surefire" } memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.8.1" } -mockito-bom = { module = "org.mockito:mockito-bom", version = "5.17.0" } +mockito-bom = { module = "org.mockito:mockito-bom", version = "5.18.0" } mockito-core = { module = "org.mockito:mockito-core" } mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter" } nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version = "0.0.11" } From 4ce2d9c76aff9e2a9e6ce339f9aabd4e7e8e0dba Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 04:01:54 +0000 Subject: [PATCH 070/521] Update dependency com.puppycrawl.tools:checkstyle to v10.24.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 87f28c059097..ebc98dc48394 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.24.0" eclipse = "4.35.0" jackson = "2.19.0" jacoco = "0.8.13" From ac7f75aafe69f06aad78331a22edadc3af946abf Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 22 May 2025 14:36:09 +0000 Subject: [PATCH 071/521] Update dependency gradle to v8.14.1 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 247cf2a9f5ce..9128c7d428d8 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=61ad310d3c7d3e5da131b76bbf22b5a4c0786e9d892dae8c1658d4b484de3caa -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-bin.zip +distributionSha256Sum=845952a9d6afa783db70bb3b0effaae45ae5542ca2bb7929619e8af49cb634cf +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 74ea7618f39a4a0e7b44c6a1929dc82f0f7f252f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 17:29:39 +0200 Subject: [PATCH 072/521] Fix `SimpleArgumentsAggregator` for fields --- .../jupiter/params/aggregator/SimpleArgumentsAggregator.java | 2 +- .../jupiter/params/ParameterizedClassIntegrationTests.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) 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 25373b624f75..7537e5a64e46 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 @@ -40,7 +40,7 @@ public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext co @Override public Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) throws ArgumentsAggregationException { - return aggregateArguments(accessor, null, context, context.getParameterIndex()); + return aggregateArguments(accessor, context.getField().getType(), context, context.getParameterIndex()); } protected abstract Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java index 6e678900084e..7d7946553b5e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java @@ -1055,6 +1055,7 @@ private static class TimesTwoAggregator extends SimpleArgumentsAggregator { protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, AnnotatedElementContext context, int parameterIndex) throws ArgumentsAggregationException { + assertThat(targetType).isEqualTo(int.class); return accessor.getInteger(0) * 2; } } From c5618b41f328cfb6f48e16f89a4e06551f130f45 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 10:51:28 +0000 Subject: [PATCH 073/521] Update xmlunit to v2.10.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ebc98dc48394..2d8e0149dd0e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,7 +19,7 @@ opentest4j = "1.3.0" openTestReporting = "0.2.3" snapshotTests = "1.11.0" surefire = "3.5.3" -xmlunit = "2.10.1" +xmlunit = "2.10.2" [libraries] ant = { module = "org.apache.ant:ant", version.ref = "ant" } From 9f093e64fd622a55d1d648a556f833ab5e914996 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 23 May 2025 16:38:52 +0200 Subject: [PATCH 074/521] Polish Javadoc for Arguments --- .../org/junit/jupiter/params/provider/Arguments.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) 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..b6fb2e20943b 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 @@ -24,17 +24,16 @@ * typically be provided by an {@link ArgumentsProvider}. * * @apiNote

This interface is specifically designed as a simple holder of - * arguments of a parameterized test. Therefore, if you end up - * {@linkplain java.util.stream.Stream#map(java.util.function.Function) transforming} - * or + * arguments for a parameterized test. Therefore, if you end up + * {@linkplain java.util.stream.Stream#map(java.util.function.Function) transforming} or * {@linkplain java.util.stream.Stream#filter(java.util.function.Predicate) filtering} * the arguments, you should consider using one of the following in intermediate * steps: * *

From b50e28bf5105efa8af8aade6e96e1b03dd3086dd Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 23 May 2025 16:39:26 +0200 Subject: [PATCH 075/521] =?UTF-8?q?Make=20Arguments=20a=20@=E2=81=A0Functi?= =?UTF-8?q?onalInterface?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes gh-4568 --- .../src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 2 ++ .../main/java/org/junit/jupiter/params/provider/Arguments.java | 1 + 2 files changed, 3 insertions(+) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index c90775899d35..bded769be12b 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -107,6 +107,8 @@ repository on GitHub. ==== New Features and Improvements * Add support for using Kotlin's `suspend` modifier on test and lifecycle methods. +* The `Arguments` interface for parameterized tests is now officially a + `@FunctionalInterface`. [[release-notes-6.0.0-M1-junit-vintage]] 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 b6fb2e20943b..4a54fcbeb0a0 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 @@ -49,6 +49,7 @@ * @see org.junit.jupiter.params.provider.ArgumentsProvider * @see org.junit.jupiter.params.converter.ArgumentConverter */ +@FunctionalInterface @API(status = STABLE, since = "5.7") public interface Arguments { From 291970a44a1c564440a06595cdcb09810d819c51 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 23 May 2025 16:55:11 +0200 Subject: [PATCH 076/521] Polish release notes for 6.0 M1 --- .../release-notes/release-notes-6.0.0-M1.adoc | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index bded769be12b..f8a932f61913 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -45,9 +45,9 @@ repository on GitHub. subcommand. * Remove support for deprecated non-conventional `ConsoleLauncher` options such as `--h` (rather than `-h`) or `-help` (rather than `--help`). -* The `junit-platform-runner` module that provided the `JUnitPlatform` runner has been - discontinued. -* Support for Maven Surefire/Failsafe versions < 3.0.0 has been dropped. +* The `junit-platform-runner` module that provided the JUnit 4 based `JUnitPlatform` + runner has been discontinued. +* Support for Maven Surefire/Failsafe versions less than 3.0.0 has been dropped. * The following deprecated APIs have been removed: - `ReflectionSupport.loadClass(String)` method - `ReflectionUtils.readFieldValue(...)` methods @@ -93,20 +93,21 @@ repository on GitHub. * The deprecated `junit.jupiter.tempdir.scope` configuration parameter is no longer supported. * The `JRE` enum constants for `JAVA_8` to `JAVA_16` have been deprecated because they can - no longer be used at runtime since `JAVA_17` is the new baseline. Please also check for - values less than 17 used with the `minVersion` and `maxVersion` attributes of - `@EnabledForJreRange` nad `@DisabledForJreRange` or the `versions` attribute of - `@EnabledOnJre` and `@DisabledOnJre`. + no longer be used at runtime since `JAVA_17` is the new baseline. Please also manually + update any values used with the `minVersion` and `maxVersion` attributes in + `@EnabledForJreRange` and `@DisabledForJreRange` or the `versions` attributes in + `@EnabledOnJre` and `@DisabledOnJre` to ensure that you are no longer declaring version + values less than 17. * `@EnabledForJreRange` and `@DisabledForJreRange` now use `JAVA_17` as their default `min` value. -* The contracts for the `Executable` parameter of Kotlin-specific `assertTimeout` - functions was changed from `callsInPlace(executable, EXACTLY_ONCE)` to - `callsInPlace(executable, AT_MOST_ONCE)` which might result in compile errors. +* The contracts for the `Executable` parameters of Kotlin-specific `assertTimeout` + functions were changed from `callsInPlace(executable, EXACTLY_ONCE)` to + `callsInPlace(executable, AT_MOST_ONCE)` which might result in compilation errors. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements -* Add support for using Kotlin's `suspend` modifier on test and lifecycle methods. +* Kotlin's `suspend` modifier may now be applied to test and lifecycle methods. * The `Arguments` interface for parameterized tests is now officially a `@FunctionalInterface`. From ce1545b7d4e3741c888cd2a407702da450447ed1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 14:56:48 +0200 Subject: [PATCH 077/521] Create pre-compiled script plugin for NullAway and Error Prone --- gradle/libs.versions.toml | 5 ++++ gradle/plugins/common/build.gradle.kts | 2 ++ ...ld.java-nullability-conventions.gradle.kts | 24 +++++++++++++++++++ 3 files changed, 31 insertions(+) create mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2d8e0149dd0e..9a5e3e813cb8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,6 +35,7 @@ bndlib = { module = "biz.aQute.bnd:biz.aQute.bndlib", version.ref = "bnd" } checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checkstyle" } classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.179" } commons-io = { module = "commons-io:commons-io", version = "2.19.0" } +errorProne-core = { module = "com.google.errorprone:error_prone_core", version = "2.38.0" } groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.26" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.23" } hamcrest = { module = "org.hamcrest:hamcrest", version = "3.0" } @@ -46,6 +47,7 @@ jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" } jmh-core = { module = "org.openjdk.jmh:jmh-core", version.ref = "jmh" } jmh-generator-annprocess = { module = "org.openjdk.jmh:jmh-generator-annprocess", version.ref = "jmh" } joox = { module = "org.jooq:joox", version = "2.0.1" } +jspecify = { module = "org.jspecify:jspecify", version = "1.0.0" } jte = { module = "gg.jte:jte", version = "3.2.1" } junit4 = { module = "junit:junit", version = { require = "[4.12,)", prefer = "4.13.2" } } kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.10.2" } @@ -58,6 +60,7 @@ mockito-bom = { module = "org.mockito:mockito-bom", version = "5.18.0" } mockito-core = { module = "org.mockito:mockito-core" } mockito-junit-jupiter = { module = "org.mockito:mockito-junit-jupiter" } nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version = "0.0.11" } +nullaway = { module = "com.uber.nullaway:nullaway", version = "0.12.7" } opentest4j = { module = "org.opentest4j:opentest4j", version.ref = "opentest4j" } openTestReporting-cli = { module = "org.opentest4j.reporting:open-test-reporting-cli", version.ref = "openTestReporting" } openTestReporting-events = { module = "org.opentest4j.reporting:open-test-reporting-events", version.ref = "openTestReporting" } @@ -95,6 +98,7 @@ bnd = { id = "biz.aQute.bnd", version.ref = "bnd" } buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" } commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" } develocity = { id = "com.gradle.develocity", version = "4.0.1" } +errorProne = { id = "net.ltgt.errorprone", version = "4.2.0" } extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" } foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "1.0.0" } gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } @@ -102,6 +106,7 @@ jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } +nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 5f31236d8715..ded9ec6a99bb 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -11,9 +11,11 @@ dependencies { implementation(libs.plugins.bnd.markerCoordinates) implementation(libs.plugins.commonCustomUserData.markerCoordinates) implementation(libs.plugins.develocity.markerCoordinates) + implementation(libs.plugins.errorProne.markerCoordinates) implementation(libs.plugins.foojayResolver.markerCoordinates) implementation(libs.plugins.jmh.markerCoordinates) implementation(libs.plugins.jreleaser.markerCoordinates) + implementation(libs.plugins.nullaway.markerCoordinates) implementation(libs.plugins.openrewrite.markerCoordinates) implementation(libs.plugins.shadow.markerCoordinates) implementation(libs.plugins.spotless.markerCoordinates) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts new file mode 100644 index 000000000000..dbc7f58e2e8b --- /dev/null +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -0,0 +1,24 @@ +import junitbuild.extensions.dependencyFromLibs +import net.ltgt.gradle.errorprone.errorprone + +plugins { + `java-library` + id("net.ltgt.errorprone") + id("net.ltgt.nullaway") +} + +dependencies { + errorprone(dependencyFromLibs("errorProne-core")) + errorprone(dependencyFromLibs("nullaway")) +} + +nullaway { + onlyNullMarked = true +} + +tasks.withType().configureEach { + options.errorprone { + disableAllChecks = true + enable("NullAway") + } +} From 59c7f56f0a619c20bdeb7ea41ad6a5fda0e8dc26 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 11:40:18 +0200 Subject: [PATCH 078/521] Set up OSGi verification to ignore missing JSpecify --- .../main/kotlin/junitbuild.osgi-conventions.gradle.kts | 8 +++++--- junit-platform-commons/junit-platform-commons.gradle.kts | 2 ++ .../junit-platform-console-standalone.gradle.kts | 2 ++ 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts index 03514d7e967a..d5f47a50e2e8 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.osgi-conventions.gradle.kts @@ -5,8 +5,6 @@ plugins { `java-library` } -val importAPIGuardian = "org.apiguardian.*;resolution:=\"optional\"" - val projectDescription = objects.property().convention(provider { project.description }) // This task enhances `jar` and `shadowJar` tasks with the bnd @@ -15,7 +13,9 @@ val projectDescription = objects.property().convention(provider { projec tasks.withType().named { it == "jar" || it == "shadowJar" }.all { // configure tasks eagerly as workaround for https://github.com/bndtools/bnd/issues/5695 - extra["importAPIGuardian"] = importAPIGuardian + + val importAPIGuardian by extra { "org.apiguardian.*;resolution:=\"optional\"" } + val importJSpecify by extra { "org.jspecify.*;resolution:=\"optional\"" } extensions.create(BundleTaskExtension.NAME, this).apply { properties.set(projectDescription.map { @@ -37,6 +37,7 @@ tasks.withType().named { # These are the general rules for package imports. Import-Package: \ ${importAPIGuardian},\ + ${importJSpecify},\ org.junit.platform.commons.logging;status=INTERNAL,\ kotlin.*;resolution:="optional",\ * @@ -45,6 +46,7 @@ tasks.withType().named { # the kotlin and apiguardian packages, but enough modules do to make it a default. -fixupmessages.kotlin.import: "Unused Import-Package instructions: \\[kotlin.*\\]";is:=ignore -fixupmessages.apiguardian.import: "Unused Import-Package instructions: \\[org.apiguardian.*\\]";is:=ignore + -fixupmessages.jspecify.import: "Unused Import-Package instructions: \\[org.jspecify.*\\]";is:=ignore # This tells bnd to ignore classes it finds in `META-INF/versions/` # because bnd doesn't yet support multi-release jars. diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 3ba44841ada3..06db0ef37eac 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -29,9 +29,11 @@ tasks.compileJava { tasks.jar { bundle { val importAPIGuardian: String by extra + val importJSpecify: String by extra bnd(""" Import-Package: \ $importAPIGuardian,\ + $importJSpecify,\ kotlin.*;resolution:="optional",\ kotlinx.*;resolution:="optional",\ * diff --git a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts index 4bdc51103c64..1ef341f586ff 100644 --- a/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts +++ b/junit-platform-console-standalone/junit-platform-console-standalone.gradle.kts @@ -54,10 +54,12 @@ tasks { bundle { val importAPIGuardian: String by extra + val importJSpecify: String by extra bnd(""" # Customize the imports because this is an aggregate jar Import-Package: \ $importAPIGuardian,\ + $importJSpecify,\ kotlin.*;resolution:="optional",\ kotlinx.*;resolution:="optional",\ * From b2d249116dac26fd82cd980a8be3c3b74af1b74a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 14:57:16 +0200 Subject: [PATCH 079/521] Enable NullAway in junit-platform-commons --- junit-platform-commons/junit-platform-commons.gradle.kts | 2 ++ junit-platform-commons/src/main/java/module-info.java | 2 ++ .../jar-describe-module/junit-platform-commons.expected.txt | 1 + 3 files changed, 5 insertions(+) diff --git a/junit-platform-commons/junit-platform-commons.gradle.kts b/junit-platform-commons/junit-platform-commons.gradle.kts index 06db0ef37eac..36ebd5359aa9 100644 --- a/junit-platform-commons/junit-platform-commons.gradle.kts +++ b/junit-platform-commons/junit-platform-commons.gradle.kts @@ -1,6 +1,7 @@ import junitbuild.extensions.javaModuleName plugins { + id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") `java-test-fixtures` } @@ -11,6 +12,7 @@ dependencies { api(platform(projects.junitBom)) compileOnlyApi(libs.apiguardian) + compileOnlyApi(libs.jspecify) compileOnly(kotlin("stdlib")) compileOnly(kotlin("reflect")) diff --git a/junit-platform-commons/src/main/java/module-info.java b/junit-platform-commons/src/main/java/module-info.java index 2cb4016429a3..092c654cdd51 100644 --- a/junit-platform-commons/src/main/java/module-info.java +++ b/junit-platform-commons/src/main/java/module-info.java @@ -16,7 +16,9 @@ module org.junit.platform.commons { requires java.logging; requires java.management; // needed by RuntimeUtils to determine input arguments + requires static transitive org.apiguardian.api; + requires static transitive org.jspecify; requires static kotlin.stdlib; requires static kotlin.reflect; diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt index 0022a3df70bc..79178a9ec365 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-commons.expected.txt @@ -12,6 +12,7 @@ requires kotlin.reflect static requires kotlin.stdlib static requires kotlinx.coroutines.core static requires org.apiguardian.api static transitive +requires org.jspecify static transitive uses org.junit.platform.commons.support.scanning.ClasspathScanner qualified exports org.junit.platform.commons.logging to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.suite.api org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine qualified exports org.junit.platform.commons.util to org.junit.jupiter.api org.junit.jupiter.engine org.junit.jupiter.migrationsupport org.junit.jupiter.params org.junit.platform.console org.junit.platform.engine org.junit.platform.jfr org.junit.platform.launcher org.junit.platform.reporting org.junit.platform.suite.api org.junit.platform.suite.commons org.junit.platform.suite.engine org.junit.platform.testkit org.junit.vintage.engine From e3e7d1a2615cc3908132d0c24df1476e81c03a99 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 11:42:03 +0200 Subject: [PATCH 080/521] Fix `ModularUserGuideTests` --- .../platform-tooling-support-tests.gradle.kts | 1 + .../platform/tooling/support/tests/ModularUserGuideTests.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index b37a2a1318a9..176e862221e9 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -59,6 +59,7 @@ dependencies { thirdPartyJars(libs.assertj) thirdPartyJars(libs.apiguardian) thirdPartyJars(libs.hamcrest) + thirdPartyJars(libs.jspecify) thirdPartyJars(libs.opentest4j) thirdPartyJars(libs.openTestReporting.tooling.spi) thirdPartyJars(libs.jimfs) diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java index 6451f5e8d1fd..7882fc19847b 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ModularUserGuideTests.java @@ -89,6 +89,7 @@ private static List compile(Path temp, Writer out, Writer err) throws Ex ThirdPartyJars.copy(lib, "net.bytebuddy", "byte-buddy"); ThirdPartyJars.copy(lib, "org.apiguardian", "apiguardian-api"); ThirdPartyJars.copy(lib, "org.hamcrest", "hamcrest"); + ThirdPartyJars.copy(lib, "org.jspecify", "jspecify"); ThirdPartyJars.copy(lib, "org.opentest4j", "opentest4j"); ThirdPartyJars.copy(lib, "org.opentest4j.reporting", "open-test-reporting-tooling-spi"); ThirdPartyJars.copy(lib, "com.google.jimfs", "jimfs"); @@ -172,6 +173,7 @@ void runTestsFromUserGuideWithinModularBoundaries(@TempDir Path temp, "lib/guava-.+\\.jar", // "lib/hamcrest-.+\\.jar", // "lib/jimfs-.+\\.jar", // + "lib/jspecify-.+\\.jar", // "lib/junit-.+\\.jar", // ">> ALL JUNIT 5 JARS >>", // "lib/opentest4j-.+\\.jar", // From b7c0081553e44f5eaeefcee5471a7b0e22e27b7a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 08:36:31 +0200 Subject: [PATCH 081/521] Annotate nullability in `org.junit.platform.commons.logging` package --- .../commons/logging/LogRecordListener.java | 3 +++ .../platform/commons/logging/Logger.java | 13 ++++++------ .../commons/logging/LoggerFactory.java | 20 ++++++++++--------- .../commons/logging/package-info.java | 3 +++ 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LogRecordListener.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LogRecordListener.java index 22a53d59453b..e5ac90f9d8fb 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LogRecordListener.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LogRecordListener.java @@ -75,6 +75,7 @@ public Stream stream() { * @see #stream(Class) * @see #stream(Class, Level) */ + @SuppressWarnings("ConstantValue") public Stream stream(Level level) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. @@ -100,6 +101,7 @@ public Stream stream(Level level) { * @see #stream(Level) * @see #stream(Class, Level) */ + @SuppressWarnings("ConstantValue") public Stream stream(Class clazz) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. @@ -127,6 +129,7 @@ public Stream stream(Class clazz) { * @see #stream(Level) * @see #stream(Class) */ + @SuppressWarnings("ConstantValue") public Stream stream(Class clazz, Level level) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java index 09d4d3c93918..caa1dff66a17 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/Logger.java @@ -15,6 +15,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * The {@code Logger} API serves as a simple logging facade for @@ -38,7 +39,7 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#SEVERE} in JUL. */ - void error(Throwable throwable, Supplier messageSupplier); + void error(@Nullable Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at warning level. @@ -53,7 +54,7 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#WARNING} in JUL. */ - void warn(Throwable throwable, Supplier messageSupplier); + void warn(@Nullable Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at info level. @@ -68,7 +69,7 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#INFO} in JUL. */ - void info(Throwable throwable, Supplier messageSupplier); + void info(@Nullable Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at config level. @@ -83,7 +84,7 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#CONFIG} in JUL. */ - void config(Throwable throwable, Supplier messageSupplier); + void config(@Nullable Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at debug level. @@ -98,7 +99,7 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#FINE} in JUL. */ - void debug(Throwable throwable, Supplier messageSupplier); + void debug(@Nullable Throwable throwable, Supplier messageSupplier); /** * Log the message from the provided {@code messageSupplier} at trace level. @@ -113,6 +114,6 @@ public interface Logger { * *

Maps to {@link java.util.logging.Level#FINER} in JUL. */ - void trace(Throwable throwable, Supplier messageSupplier); + void trace(@Nullable Throwable throwable, Supplier messageSupplier); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java index c6b3ce3b44e4..ee37d83db1c9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java @@ -19,6 +19,7 @@ import java.util.logging.LogRecord; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; /** @@ -41,6 +42,7 @@ private LoggerFactory() { * @param clazz the class for which to get the logger; never {@code null} * @return the logger */ + @SuppressWarnings("ConstantValue") public static Logger getLogger(Class clazz) { // NOTE: we cannot use org.junit.platform.commons.util.Preconditions here // since that would introduce a package cycle. @@ -86,7 +88,7 @@ public void error(Supplier messageSupplier) { } @Override - public void error(Throwable throwable, Supplier messageSupplier) { + public void error(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.SEVERE, throwable, messageSupplier); } @@ -96,7 +98,7 @@ public void warn(Supplier messageSupplier) { } @Override - public void warn(Throwable throwable, Supplier messageSupplier) { + public void warn(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.WARNING, throwable, messageSupplier); } @@ -106,7 +108,7 @@ public void info(Supplier messageSupplier) { } @Override - public void info(Throwable throwable, Supplier messageSupplier) { + public void info(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.INFO, throwable, messageSupplier); } @@ -116,7 +118,7 @@ public void config(Supplier messageSupplier) { } @Override - public void config(Throwable throwable, Supplier messageSupplier) { + public void config(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.CONFIG, throwable, messageSupplier); } @@ -126,7 +128,7 @@ public void debug(Supplier messageSupplier) { } @Override - public void debug(Throwable throwable, Supplier messageSupplier) { + public void debug(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.FINE, throwable, messageSupplier); } @@ -136,11 +138,11 @@ public void trace(Supplier messageSupplier) { } @Override - public void trace(Throwable throwable, Supplier messageSupplier) { + public void trace(@Nullable Throwable throwable, Supplier messageSupplier) { log(Level.FINER, throwable, messageSupplier); } - private void log(Level level, Throwable throwable, Supplier messageSupplier) { + private void log(Level level, @Nullable Throwable throwable, Supplier messageSupplier) { boolean loggable = this.julLogger.isLoggable(level); if (loggable || !listeners.isEmpty()) { LogRecord logRecord = createLogRecord(level, throwable, nullSafeGet(messageSupplier)); @@ -151,7 +153,7 @@ private void log(Level level, Throwable throwable, Supplier messageSuppl } } - private LogRecord createLogRecord(Level level, Throwable throwable, String message) { + private LogRecord createLogRecord(Level level, @Nullable Throwable throwable, @Nullable String message) { String sourceClassName = null; String sourceMethodName = null; boolean found = false; @@ -178,7 +180,7 @@ else if (found) { return logRecord; } - private static String nullSafeGet(Supplier messageSupplier) { + private static @Nullable String nullSafeGet(@Nullable Supplier<@Nullable String> messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java index 75260c34a99a..9fe567592387 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java @@ -8,4 +8,7 @@ * Use at your own risk! */ +@NullMarked package org.junit.platform.commons.logging; + +import org.jspecify.annotations.NullMarked; From 7e65ff5dede057e3c0e2165cd3320355d03ab37c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 15:17:39 +0200 Subject: [PATCH 082/521] Annotate nullability in `org.junit.platform.commons.annotation` package --- .../org/junit/platform/commons/annotation/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java index f5f0eaf51493..1221aebb8f50 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java @@ -2,4 +2,7 @@ * Common annotations for the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.annotation; + +import org.jspecify.annotations.NullMarked; From edfac87d728249d62134f3eb9db8ca9aa832dd1d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 15:30:49 +0200 Subject: [PATCH 083/521] Annotate nullability in `org.junit.platform.commons.function` package --- .../org/junit/platform/commons/function/Try.java | 13 +++++++------ .../platform/commons/function/package-info.java | 3 +++ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java index 04403c18a34d..cab3a5a4b623 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java @@ -20,6 +20,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; /** @@ -39,7 +40,7 @@ * @since 1.4 */ @API(status = MAINTAINED, since = "1.4") -public abstract class Try { +public abstract class Try { /** * Call the supplied {@link Callable} and return a successful {@code Try} @@ -64,7 +65,7 @@ public static Try call(Callable action) { * @return a succeeded {@code Try} that contains the supplied value; never * {@code null} */ - public static Try success(V value) { + public static Try success(V value) { return new Success<>(value); } @@ -80,7 +81,7 @@ public static Try failure(Exception cause) { } // Cannot use Preconditions due to package cycle - private static T checkNotNull(T input, String title) { + private static T checkNotNull(@Nullable T input, String title) { if (input == null) { // Cannot use PreconditionViolationException due to package cycle throw new JUnitException(title + " must not be null"); @@ -198,7 +199,7 @@ private Try() { * except that a {@code Transformer} may throw an exception. */ @FunctionalInterface - public interface Transformer { + public interface Transformer { /** * Apply this transformer to the supplied value. @@ -209,7 +210,7 @@ public interface Transformer { } - private static class Success extends Try { + private static class Success extends Try { private final V value; @@ -287,7 +288,7 @@ public int hashCode() { } } - private static class Failure extends Try { + private static class Failure extends Try { private final Exception cause; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java index 8f031faf22e0..79d053801103 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java @@ -2,4 +2,7 @@ * Functional interfaces and support classes. */ +@NullMarked package org.junit.platform.commons.function; + +import org.jspecify.annotations.NullMarked; From e1b46deb9e72446ca314193cea9843c03a84c70e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 08:36:45 +0200 Subject: [PATCH 084/521] Annotate nullability in `org.junit.platform.commons.support.scanning` --- .../commons/support/scanning/ClasspathFileVisitor.java | 3 ++- .../junit/platform/commons/support/scanning/CloseablePath.java | 3 +++ .../junit/platform/commons/support/scanning/package-info.java | 3 +++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFileVisitor.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFileVisitor.java index 2bc01963da99..3387e121f6e7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFileVisitor.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/ClasspathFileVisitor.java @@ -20,6 +20,7 @@ import java.util.function.BiConsumer; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; @@ -55,7 +56,7 @@ public FileVisitResult visitFileFailed(Path file, IOException ex) { } @Override - public FileVisitResult postVisitDirectory(Path dir, IOException ex) { + public FileVisitResult postVisitDirectory(Path dir, @Nullable IOException ex) { if (ex != null) { logger.warn(ex, () -> "I/O error visiting directory: " + dir); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java index 48aecf9b4896..cbe5c17ec01d 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java @@ -26,6 +26,8 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import org.jspecify.annotations.Nullable; + /** * @since 1.0 */ @@ -113,6 +115,7 @@ private ManagedFileSystem retain() { return this; } + @Nullable private ManagedFileSystem release() { if (referenceCount.decrementAndGet() == 0) { close(); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java index 769733a65aef..2da61c5d8ce9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java @@ -2,4 +2,7 @@ * Classpath scanning APIs provided by the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.support.scanning; + +import org.jspecify.annotations.NullMarked; From 92f271dcf37ea5d7ee62a8d59e7971d156a2f115 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 08:36:39 +0200 Subject: [PATCH 085/521] Annotate nullability in `org.junit.platform.commons.support.conversion` --- .../commons/support/conversion/ConversionSupport.java | 4 +++- .../support/conversion/FallbackStringToObjectConverter.java | 3 +++ .../commons/support/conversion/StringToClassConverter.java | 2 ++ .../conversion/StringToCommonJavaTypesConverter.java | 6 +++++- .../support/conversion/StringToJavaTimeConverter.java | 6 +++++- .../commons/support/conversion/StringToNumberConverter.java | 6 +++++- .../commons/support/conversion/StringToObjectConverter.java | 4 ++++ .../platform/commons/support/conversion/package-info.java | 3 +++ 8 files changed, 30 insertions(+), 4 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java index e56570ca41c7..a9a09540997b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java @@ -19,6 +19,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ClassLoaderUtils; /** @@ -99,7 +100,8 @@ private ConversionSupport() { * @since 1.11 */ @SuppressWarnings("unchecked") - public static T convert(String source, Class targetType, ClassLoader classLoader) { + @Nullable + public static T convert(@Nullable String source, Class targetType, @Nullable ClassLoader classLoader) { if (source == null) { if (targetType.isPrimitive()) { throw new ConversionException( diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java index aeea2d9e119d..ef8191beae75 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java @@ -26,6 +26,7 @@ import java.util.function.Function; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -97,6 +98,7 @@ private static Function findFactoryExecutable(Class targetTyp }); } + @Nullable private static Method findFactoryMethod(Class targetType) { List factoryMethods = findMethods(targetType, new IsFactoryMethod(targetType), BOTTOM_UP); if (factoryMethods.size() == 1) { @@ -105,6 +107,7 @@ private static Method findFactoryMethod(Class targetType) { return null; } + @Nullable private static Constructor findFactoryConstructor(Class targetType) { List> constructors = findConstructors(targetType, new IsFactoryConstructor(targetType)); if (constructors.size() == 1) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java index ad16fb18edf3..1e1cd0e832b4 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java @@ -10,6 +10,7 @@ package org.junit.platform.commons.support.conversion; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.support.ReflectionSupport; class StringToClassConverter implements StringToObjectConverter { @@ -25,6 +26,7 @@ public Object convert(String source, Class targetType) throws Exception { } @Override + @Nullable public Object convert(String className, Class targetType, ClassLoader classLoader) throws Exception { // @formatter:off return ReflectionSupport.tryToLoadClass(className, classLoader) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java index 17aa357439ae..ceeca4d05e09 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java @@ -26,6 +26,8 @@ import java.util.UUID; import java.util.function.Function; +import org.junit.platform.commons.util.Preconditions; + class StringToCommonJavaTypesConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; @@ -55,7 +57,9 @@ public boolean canConvertTo(Class targetType) { @Override public Object convert(String source, Class targetType) throws Exception { - return CONVERTERS.get(targetType).apply(source); + Function converter = Preconditions.notNull(CONVERTERS.get(targetType), + () -> "No registered converter for %s".formatted(targetType.getName())); + return converter.apply(source); } private static URL toURL(String url) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java index 0e544f39a3a4..fb884a84fd4b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java @@ -30,6 +30,8 @@ import java.util.Map; import java.util.function.Function; +import org.junit.platform.commons.util.Preconditions; + class StringToJavaTimeConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; @@ -59,7 +61,9 @@ public boolean canConvertTo(Class targetType) { @Override public Object convert(String source, Class targetType) throws Exception { - return CONVERTERS.get(targetType).apply(source); + Function converter = Preconditions.notNull(CONVERTERS.get(targetType), + () -> "No registered converter for %s".formatted(targetType.getName())); + return converter.apply(source); } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java index 21a7a0fc2e62..972cd29b07e4 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java @@ -18,6 +18,8 @@ import java.util.Map; import java.util.function.Function; +import org.junit.platform.commons.util.Preconditions; + class StringToNumberConverter implements StringToObjectConverter { private static final Map, Function> CONVERTERS; @@ -44,7 +46,9 @@ public boolean canConvertTo(Class targetType) { @Override public Object convert(String source, Class targetType) { - return CONVERTERS.get(targetType).apply(source.replace("_", "")); + Function converter = Preconditions.notNull(CONVERTERS.get(targetType), + () -> "No registered converter for %s".formatted(targetType.getName())); + return converter.apply(source.replace("_", "")); } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java index ceb00e2e95d8..378a7bad5ed8 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java @@ -10,6 +10,8 @@ package org.junit.platform.commons.support.conversion; +import org.jspecify.annotations.Nullable; + /** * Internal API for converting arguments of type {@link String} to a specified * target type. @@ -31,6 +33,7 @@ interface StringToObjectConverter { *

This method will only be invoked in {@link #canConvertTo(Class)} * returned {@code true} for the same target type. */ + @Nullable Object convert(String source, Class targetType) throws Exception; /** @@ -45,6 +48,7 @@ interface StringToObjectConverter { * Can be overridden by concrete implementations of this interface that need * access to the supplied {@link ClassLoader}. */ + @Nullable default Object convert(String source, Class targetType, ClassLoader classLoader) throws Exception { return convert(source, targetType); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java index 18807d6a4e90..79ba440a7609 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java @@ -2,4 +2,7 @@ * Conversion APIs provided by the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.support.conversion; + +import org.jspecify.annotations.NullMarked; From ca28a8519412ba8fc0504587ece74afe21a377ca Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 15:42:55 +0200 Subject: [PATCH 086/521] Annotate nullability in `org.junit.platform.commons` package --- .../java/org/junit/platform/commons/JUnitException.java | 8 +++++--- .../platform/commons/PreconditionViolationException.java | 3 ++- .../java/org/junit/platform/commons/package-info.java | 3 +++ 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java index 7498b502c9c9..162514bec3fc 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/JUnitException.java @@ -16,6 +16,7 @@ import java.io.Serial; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Base class for all {@link RuntimeException RuntimeExceptions} thrown @@ -29,11 +30,11 @@ public class JUnitException extends RuntimeException { @Serial private static final long serialVersionUID = 1L; - public JUnitException(String message) { + public JUnitException(@Nullable String message) { super(message); } - public JUnitException(String message, Throwable cause) { + public JUnitException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } @@ -41,7 +42,8 @@ public JUnitException(String message, Throwable cause) { * @since 1.13 */ @API(status = MAINTAINED, since = "1.13") - protected JUnitException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + protected JUnitException(@Nullable String message, @Nullable Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { super(message, cause, enableSuppression, writableStackTrace); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java index 0771766bc2de..2d9e1a5385f4 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/PreconditionViolationException.java @@ -15,6 +15,7 @@ import java.io.Serial; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Thrown if a precondition is violated. @@ -31,7 +32,7 @@ public PreconditionViolationException(String message) { super(message); } - public PreconditionViolationException(String message, Throwable cause) { + public PreconditionViolationException(String message, @Nullable Throwable cause) { super(message, cause); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java index 66e1cf2aa51c..18945b31c25e 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java @@ -8,4 +8,7 @@ * APIs by external parties is not supported! */ +@NullMarked package org.junit.platform.commons; + +import org.jspecify.annotations.NullMarked; From 87e82d861d6828d7f6e8b772462b019c93787529 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 16:32:24 +0200 Subject: [PATCH 087/521] Add `Try.getNonNull{OrThrow}` method to ease null handling --- .../junit/platform/commons/function/Try.java | 39 +++++++++++++++++++ .../platform/commons/function/TryTests.java | 4 ++ 2 files changed, 43 insertions(+) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java index cab3a5a4b623..31f8f172efc3 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java @@ -10,6 +10,7 @@ package org.junit.platform.commons.function; +import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.Objects; @@ -20,6 +21,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.NonNull; import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; @@ -150,6 +152,22 @@ private Try() { */ public abstract V get() throws Exception; + /** + * If this {@code Try} is a success, get the contained value; if this + * {@code Try} is a failure, throw the contained exception. + * + * @return the contained value, if available + * @throws Exception if this {@code Try} is a failure or the contained value + * is {@code null} + * + * @since 6.0 + */ + @API(status = EXPERIMENTAL, since = "6.0") + public final @NonNull V getNonNull() throws Exception { + var value = get(); + return checkNotNull(value, "value"); + } + /** * If this {@code Try} is a success, get the contained value; if this * {@code Try} is a failure, call the supplied {@link Function} with the @@ -162,6 +180,27 @@ private Try() { */ public abstract V getOrThrow(Function exceptionTransformer) throws E; + /** + * If this {@code Try} is a success, get the contained value; if this + * {@code Try} is a failure, call the supplied {@link Function} with the + * contained exception and throw the resulting {@link Exception}. + * + * @param exceptionTransformer the transformer to be called with the + * contained exception, if available; must not be {@code null} + * @return the contained value, if available and not {@code null} + * @throws E if this {@code Try} is a failure or the contained value + * is {@code null} + */ + @API(status = EXPERIMENTAL, since = "6.0") + public final @NonNull V getNonNullOrThrow( + Function exceptionTransformer) throws E { + var value = getOrThrow(exceptionTransformer); + if (value == null) { + throw exceptionTransformer.apply(null); + } + return value; + } + /** * If this {@code Try} is a success, call the supplied {@link Consumer} with * the contained value; otherwise, do nothing. diff --git a/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java b/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java index 4ad2dce22055..7fabe5b52440 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java @@ -27,7 +27,9 @@ void successfulTriesCanBeTransformed() throws Exception { var success = Try.success("foo"); assertThat(success.get()).isEqualTo("foo"); + assertThat(success.getNonNull()).isEqualTo("foo"); assertThat(success.getOrThrow(RuntimeException::new)).isEqualTo("foo"); + assertThat(success.getNonNullOrThrow(RuntimeException::new)).isEqualTo("foo"); assertThat(success.toOptional()).contains("foo"); assertThat(success.andThen(v -> { @@ -74,7 +76,9 @@ void failedTriesCanBeTransformed() throws Exception { void successfulTriesCanStoreNull() throws Exception { var success = Try.success(null); assertThat(success.get()).isNull(); + assertThrows(JUnitException.class, success::getNonNull); assertThat(success.getOrThrow(RuntimeException::new)).isNull(); + assertThrows(RuntimeException.class, () -> success.getNonNullOrThrow(RuntimeException::new)); assertThat(success.toOptional()).isEmpty(); } From ea91f0e7f3acd43e78b6113580508b1af84c7aee Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 19 May 2025 16:36:27 +0200 Subject: [PATCH 088/521] Annotate nullability in `org.junit.platform.commons.support` package --- .../commons/support/AnnotationSupport.java | 22 ++++++++++--------- .../commons/support/ReflectionSupport.java | 10 +++++---- .../commons/support/package-info.java | 3 +++ 3 files changed, 21 insertions(+), 14 deletions(-) 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 2da05b6e2ccf..d8a0c6164fec 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 @@ -24,6 +24,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.AnnotationUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; @@ -70,7 +71,7 @@ private AnnotationSupport() { * @see #findRepeatableAnnotations(Optional, Class) */ @API(status = MAINTAINED, since = "1.3") - public static boolean isAnnotated(Optional element, + public static boolean isAnnotated(@Nullable Optional element, Class annotationType) { return AnnotationUtils.isAnnotated(element, annotationType); @@ -93,7 +94,7 @@ public static boolean isAnnotated(Optional element, * @see #findAnnotation(AnnotatedElement, Class) * @see #findRepeatableAnnotations(AnnotatedElement, Class) */ - public static boolean isAnnotated(AnnotatedElement element, Class annotationType) { + public static boolean isAnnotated(@Nullable AnnotatedElement element, Class annotationType) { return AnnotationUtils.isAnnotated(element, annotationType); } @@ -112,8 +113,8 @@ public static boolean isAnnotated(AnnotatedElement element, Class Optional findAnnotation(Optional element, - Class annotationType) { + public static Optional findAnnotation( + @Nullable Optional element, Class annotationType) { return AnnotationUtils.findAnnotation(element, annotationType); } @@ -135,7 +136,8 @@ public static Optional findAnnotation(Optional Optional findAnnotation(AnnotatedElement element, Class annotationType) { + public static Optional findAnnotation(@Nullable AnnotatedElement element, + Class annotationType) { return AnnotationUtils.findAnnotation(element, annotationType); } @@ -173,7 +175,7 @@ public static Optional findAnnotation(AnnotatedElement @Deprecated @API(status = DEPRECATED, since = "1.12") @SuppressWarnings("deprecation") - public static Optional findAnnotation(Class clazz, Class annotationType, + public static Optional findAnnotation(@Nullable Class clazz, Class annotationType, SearchOption searchOption) { Preconditions.notNull(searchOption, "SearchOption must not be null"); @@ -214,7 +216,7 @@ public static Optional findAnnotation(Class clazz, * @see #findAnnotation(AnnotatedElement, Class) */ @API(status = EXPERIMENTAL, since = "1.12") - public static Optional findAnnotation(Class clazz, Class annotationType, + public static Optional findAnnotation(@Nullable Class clazz, Class annotationType, List> enclosingInstanceTypes) { Preconditions.notNull(enclosingInstanceTypes, "enclosingInstanceTypes must not be null"); @@ -252,8 +254,8 @@ public static Optional findAnnotation(Class clazz, * @see #findRepeatableAnnotations(AnnotatedElement, Class) */ @API(status = MAINTAINED, since = "1.5") - public static List findRepeatableAnnotations(Optional element, - Class annotationType) { + public static List findRepeatableAnnotations( + @Nullable Optional element, Class annotationType) { return AnnotationUtils.findRepeatableAnnotations(element, annotationType); } @@ -297,7 +299,7 @@ public static List findRepeatableAnnotations(Optional< * @see java.lang.annotation.Repeatable * @see java.lang.annotation.Inherited */ - public static List findRepeatableAnnotations(AnnotatedElement element, + public static List findRepeatableAnnotations(@Nullable AnnotatedElement element, Class annotationType) { return AnnotationUtils.findRepeatableAnnotations(element, annotationType); 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 2d4d19e32aa5..634853f49403 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 @@ -23,6 +23,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.util.ExceptionUtils; @@ -447,12 +448,13 @@ public static T newInstance(Class clazz, Object... args) { * @param method the method to invoke; never {@code null} * @param target the object on which to invoke the method; may be * {@code null} if the method is {@code static} - * @param args the arguments to pass to the method + * @param args the arguments to pass to the method; never {@code null} * @return the value returned by the method invocation or {@code null} * if the return type is {@code void} * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ - public static Object invokeMethod(Method method, Object target, Object... args) { + @Nullable + public static Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { return ReflectionUtils.invokeMethod(method, target, args); } @@ -522,7 +524,7 @@ public static Stream streamFields(Class clazz, Predicate predic * @since 1.4 */ @API(status = MAINTAINED, since = "1.4") - public static Try tryToReadFieldValue(Field field, Object instance) { + public static Try<@Nullable Object> tryToReadFieldValue(Field field, @Nullable Object instance) { return ReflectionUtils.tryToReadFieldValue(field, instance); } @@ -547,7 +549,7 @@ public static Try tryToReadFieldValue(Field field, Object instance) { * but potentially empty if no such method could be found * @see #findMethod(Class, String, Class...) */ - public static Optional findMethod(Class clazz, String methodName, String parameterTypeNames) { + public static Optional findMethod(Class clazz, String methodName, @Nullable String parameterTypeNames) { return ReflectionUtils.findMethod(clazz, methodName, parameterTypeNames); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java index fae0c2a81547..68a77ec1bf22 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java @@ -8,4 +8,7 @@ * extensions with the same semantics as within the JUnit Platform itself. */ +@NullMarked package org.junit.platform.commons.support; + +import org.jspecify.annotations.NullMarked; From 6a9f846312ed6a735570ab7366b0b27447f29ed4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 08:36:51 +0200 Subject: [PATCH 089/521] Annotate nullability in `org.junit.platform.commons.util` package --- .../commons/util/AnnotationUtils.java | 33 +++++---- .../util/ClassNamePatternFilterUtils.java | 11 +-- .../platform/commons/util/ClassUtils.java | 12 ++- .../commons/util/CollectionUtils.java | 17 +++-- .../platform/commons/util/FunctionUtils.java | 4 +- .../commons/util/KotlinReflectionUtils.java | 7 +- .../platform/commons/util/Preconditions.java | 74 +++++++++++++------ .../commons/util/ReflectionUtils.java | 45 ++++++----- .../platform/commons/util/RuntimeUtils.java | 2 +- .../commons/util/ServiceLoaderUtils.java | 4 + .../platform/commons/util/StringUtils.java | 21 +++--- .../commons/util/ToStringBuilder.java | 5 +- .../commons/util/UnrecoverableExceptions.java | 3 +- .../platform/commons/util/package-info.java | 3 + 14 files changed, 153 insertions(+), 88 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index a1c16200f124..271a1085f0be 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -11,6 +11,7 @@ package org.junit.platform.commons.util; import static java.util.Arrays.asList; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; @@ -37,6 +38,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode; @@ -75,7 +77,8 @@ private AnnotationUtils() { * @see #findAnnotation(Optional, Class) * @see org.junit.platform.commons.support.AnnotationSupport#isAnnotated(Optional, Class) */ - public static boolean isAnnotated(Optional element, + @SuppressWarnings("NullableOptional") + public static boolean isAnnotated(@Nullable Optional element, Class annotationType) { return findAnnotation(element, annotationType).isPresent(); @@ -101,15 +104,16 @@ public static boolean isAnnotated(Parameter parameter, int index, Class annotationType) { + public static boolean isAnnotated(@Nullable AnnotatedElement element, Class annotationType) { return findAnnotation(element, annotationType).isPresent(); } /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(Optional, Class) */ - public static Optional findAnnotation(Optional element, - Class annotationType) { + @SuppressWarnings({ "OptionalAssignedToNull", "NullableOptional" }) + public static Optional findAnnotation( + @Nullable Optional element, Class annotationType) { if (element == null || element.isEmpty()) { return Optional.empty(); @@ -131,14 +135,15 @@ public static Optional findAnnotation(Parameter parame /** * @see org.junit.platform.commons.support.AnnotationSupport#findAnnotation(AnnotatedElement, Class) */ - public static Optional findAnnotation(AnnotatedElement element, Class annotationType) { + public static Optional findAnnotation(@Nullable AnnotatedElement element, + Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); boolean inherited = annotationType.isAnnotationPresent(Inherited.class); return findAnnotation(element, annotationType, inherited, new HashSet<>()); } - private static Optional findAnnotation(AnnotatedElement element, Class annotationType, - boolean inherited, Set visited) { + private static Optional findAnnotation(@Nullable AnnotatedElement element, + Class annotationType, boolean inherited, Set visited) { Preconditions.notNull(annotationType, "annotationType must not be null"); @@ -223,7 +228,7 @@ private static Optional findMetaAnnotation(Class an * @since 1.8 * @see #findAnnotation(AnnotatedElement, Class) */ - public static Optional findAnnotation(Class clazz, Class annotationType, + public static Optional findAnnotation(@Nullable Class clazz, Class annotationType, boolean searchEnclosingClasses) { Preconditions.notNull(annotationType, "annotationType must not be null"); @@ -247,8 +252,9 @@ public static Optional findAnnotation(Class clazz, * @since 1.5 * @see org.junit.platform.commons.support.AnnotationSupport#findRepeatableAnnotations(Optional, Class) */ - public static List findRepeatableAnnotations(Optional element, - Class annotationType) { + @SuppressWarnings({ "OptionalAssignedToNull", "NullableOptional" }) + public static List findRepeatableAnnotations( + @Nullable Optional element, Class annotationType) { if (element == null || element.isEmpty()) { return Collections.emptyList(); @@ -270,7 +276,7 @@ public static List findRepeatableAnnotations(Parameter /** * @see org.junit.platform.commons.support.AnnotationSupport#findRepeatableAnnotations(AnnotatedElement, Class) */ - public static List findRepeatableAnnotations(AnnotatedElement element, + public static List findRepeatableAnnotations(@Nullable AnnotatedElement element, Class annotationType) { Preconditions.notNull(annotationType, "annotationType must not be null"); @@ -346,14 +352,14 @@ else if (candidateAnnotationType.equals(containerType)) { cause)); Annotation[] containedAnnotations = (Annotation[]) ReflectionUtils.invokeMethod(method, candidate); - found.addAll((Collection) asList(containedAnnotations)); + found.addAll((Collection) asList(requireNonNull(containedAnnotations))); } // Nested container annotation? else if (isRepeatableAnnotationContainer(candidateAnnotationType)) { Method method = ReflectionUtils.tryToGetMethod(candidateAnnotationType, "value").toOptional().get(); Annotation[] containedAnnotations = (Annotation[]) ReflectionUtils.invokeMethod(method, candidate); - for (Annotation containedAnnotation : containedAnnotations) { + for (Annotation containedAnnotation : requireNonNull(containedAnnotations)) { findRepeatableAnnotations(containedAnnotation.getClass(), annotationType, containerType, inherited, found, visited); } @@ -419,6 +425,7 @@ private static boolean isRepeatableAnnotationContainer(Class Predicate excludeMatchingClasses(String patterns) { + public static Predicate excludeMatchingClasses(@Nullable String patterns) { return matchingClasses(patterns, object -> object.getClass().getName(), FilterType.EXCLUDE); } @@ -62,7 +63,7 @@ public static Predicate excludeMatchingClasses(String patterns) { * * @param patterns a comma-separated list of patterns */ - public static Predicate excludeMatchingClassNames(String patterns) { + public static Predicate excludeMatchingClassNames(@Nullable String patterns) { return matchingClasses(patterns, Function.identity(), FilterType.EXCLUDE); } @@ -73,7 +74,7 @@ public static Predicate excludeMatchingClassNames(String patterns) { * * @param patterns a comma-separated list of patterns */ - public static Predicate includeMatchingClasses(String patterns) { + public static Predicate includeMatchingClasses(@Nullable String patterns) { return matchingClasses(patterns, object -> object.getClass().getName(), FilterType.INCLUDE); } @@ -83,7 +84,7 @@ public static Predicate includeMatchingClasses(String patterns) { * * @param patterns a comma-separated list of patterns */ - public static Predicate includeMatchingClassNames(String patterns) { + public static Predicate includeMatchingClassNames(@Nullable String patterns) { return matchingClasses(patterns, Function.identity(), FilterType.INCLUDE); } @@ -91,7 +92,7 @@ private enum FilterType { INCLUDE, EXCLUDE } - private static Predicate matchingClasses(String patterns, Function classNameProvider, + private static Predicate matchingClasses(@Nullable String patterns, Function classNameProvider, FilterType type) { // @formatter:off return Optional.ofNullable(patterns) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassUtils.java index 9fc01426c2f6..51a6eb26f20c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassUtils.java @@ -17,6 +17,7 @@ import java.util.function.Function; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Collection of utilities for working with {@link Class classes}. @@ -49,7 +50,7 @@ private ClassUtils() { * @see #nullSafeToString(Class...) * @see StringUtils#nullSafeToString(Object) */ - public static String nullSafeToString(Class clazz) { + public static String nullSafeToString(@Nullable Class clazz) { return clazz == null ? "null" : clazz.getName(); } @@ -64,7 +65,7 @@ public static String nullSafeToString(Class clazz) { * @see #nullSafeToString(Function, Class...) * @see StringUtils#nullSafeToString(Object) */ - public static String nullSafeToString(Class... classes) { + public static String nullSafeToString(@Nullable Class @Nullable... classes) { return nullSafeToString(Class::getName, classes); } @@ -83,13 +84,16 @@ public static String nullSafeToString(Class... classes) { * @see #nullSafeToString(Class...) * @see StringUtils#nullSafeToString(Object) */ - public static String nullSafeToString(Function, ? extends String> mapper, Class... classes) { + public static String nullSafeToString(Function, ? extends String> mapper, + @Nullable Class @Nullable... classes) { Preconditions.notNull(mapper, "Mapping function must not be null"); if (classes == null || classes.length == 0) { return ""; } - return stream(classes).map(clazz -> clazz == null ? "null" : mapper.apply(clazz)).collect(joining(", ")); + return stream(classes) // + .map(clazz -> clazz == null ? "null" : mapper.apply(clazz)) // + .collect(joining(", ")); } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index 8e5a6f4d6621..ed4e255620b7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -37,6 +37,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; @@ -66,7 +67,7 @@ private CollectionUtils() { * @throws PreconditionViolationException if the collection is {@code null} * or does not contain exactly one element */ - public static T getOnlyElement(Collection collection) { + public static T getOnlyElement(Collection collection) { Preconditions.notNull(collection, "collection must not be null"); Preconditions.condition(collection.size() == 1, () -> "collection must contain exactly one element: " + collection); @@ -82,14 +83,14 @@ public static T getOnlyElement(Collection collection) { * @since 1.11 */ @API(status = INTERNAL, since = "1.11") - public static Optional getFirstElement(Collection collection) { + public static Optional getFirstElement(Collection collection) { Preconditions.notNull(collection, "collection must not be null"); return collection.isEmpty() // ? Optional.empty() // : Optional.ofNullable(firstElement(collection)); } - private static T firstElement(Collection collection) { + private static T firstElement(Collection collection) { return collection instanceof List // ? ((List) collection).get(0) // : collection.iterator().next(); @@ -104,7 +105,7 @@ private static T firstElement(Collection collection) { * @since 1.6 */ @API(status = INTERNAL, since = "1.6") - public static Set toSet(T[] values) { + public static Set toSet(T[] values) { Preconditions.notNull(values, "values array must not be null"); if (values.length == 0) { return Collections.emptySet(); @@ -112,7 +113,7 @@ public static Set toSet(T[] values) { if (values.length == 1) { return Collections.singleton(values[0]); } - Set set = new HashSet<>(); + var set = new HashSet(); Collections.addAll(set, values); return set; } @@ -135,7 +136,7 @@ public static Set toSet(T[] values) { * @return a {@code Collector} which collects all the input elements into * an unmodifiable list, in encounter order */ - public static Collector> toUnmodifiableList() { + public static Collector> toUnmodifiableList() { return collectingAndThen(toList(), Collections::unmodifiableList); } @@ -153,7 +154,7 @@ public static Set toSet(T[] values) { * @see #toStream(Object) */ @API(status = INTERNAL, since = "1.9.1") - public static boolean isConvertibleToStream(Class type) { + public static boolean isConvertibleToStream(@Nullable Class type) { if (type == null || type == void.class) { return false; } @@ -251,7 +252,7 @@ private static Optional findIteratorMethod(Class type) { * Call the supplied action on each element of the supplied {@link List} from last to first element. */ @API(status = INTERNAL, since = "1.9.2") - public static void forEachInReverseOrder(List list, Consumer action) { + public static void forEachInReverseOrder(List list, Consumer action) { if (list.isEmpty()) { return; } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/FunctionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/FunctionUtils.java index 9546914e2c6a..0e7470fbf099 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/FunctionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/FunctionUtils.java @@ -16,6 +16,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Collection of utilities for working with {@link Function Functions}, @@ -43,7 +44,8 @@ private FunctionUtils() { * @param function the function to apply * @param predicate the predicate to test against the result of the function */ - public static Predicate where(Function function, Predicate predicate) { + public static Predicate where(Function function, + Predicate predicate) { Preconditions.notNull(function, "function must not be null"); Preconditions.notNull(predicate, "predicate must not be null"); return input -> predicate.test(function.apply(input)); 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 index 8d897ed77751..424a1c8fb0aa 100644 --- 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 @@ -19,6 +19,7 @@ import java.lang.reflect.Type; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.function.Try; /** @@ -29,7 +30,9 @@ @API(status = INTERNAL, since = "6.0") public class KotlinReflectionUtils { + @Nullable private static final Class kotlinMetadata; + @Nullable private static final Class kotlinCoroutineContinuation; private static final boolean kotlinReflectPresent; private static final boolean kotlinxCoroutinesPresent; @@ -89,7 +92,9 @@ public static Class[] getKotlinSuspendingFunctionParameterTypes(Method method return KotlinReflectionUtilsKt.getParameterTypes(method); } - public static Object invokeKotlinSuspendingFunction(Method method, Object target, Object[] args) { + @Nullable + public static Object invokeKotlinSuspendingFunction(Method method, @Nullable Object target, + @Nullable Object[] args) { requireKotlinReflect(method); requireKotlinxCoroutines(method); return KotlinReflectionUtilsKt.invoke(method, target, args); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/Preconditions.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/Preconditions.java index 99c8ae49e6e6..c5e3e502c7c7 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/Preconditions.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/Preconditions.java @@ -17,6 +17,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; /** @@ -50,8 +51,10 @@ private Preconditions() { * @throws PreconditionViolationException if the supplied object is {@code null} * @see #notNull(Object, Supplier) */ - public static T notNull(T object, String message) throws PreconditionViolationException { - condition(object != null, message); + public static T notNull(@Nullable T object, String message) throws PreconditionViolationException { + if (object == null) { + throw new PreconditionViolationException(message); + } return object; } @@ -64,8 +67,12 @@ public static T notNull(T object, String message) throws PreconditionViolati * @throws PreconditionViolationException if the supplied object is {@code null} * @see #condition(boolean, Supplier) */ - public static T notNull(T object, Supplier messageSupplier) throws PreconditionViolationException { - condition(object != null, messageSupplier); + public static T notNull(@Nullable T object, Supplier messageSupplier) + throws PreconditionViolationException { + + if (object == null) { + throw new PreconditionViolationException(messageSupplier.get()); + } return object; } @@ -81,8 +88,10 @@ public static T notNull(T object, Supplier messageSupplier) throws P * @see #condition(boolean, String) */ @API(status = INTERNAL, since = "1.11") - public static int[] notEmpty(int[] array, String message) throws PreconditionViolationException { - condition(array != null && array.length > 0, message); + public static int[] notEmpty(int @Nullable [] array, String message) throws PreconditionViolationException { + if (array == null || array.length == 0) { + throw new PreconditionViolationException(message); + } return array; } @@ -100,8 +109,10 @@ public static int[] notEmpty(int[] array, String message) throws PreconditionVio * @see #containsNoNullElements(Object[], String) * @see #condition(boolean, String) */ - public static T[] notEmpty(T[] array, String message) throws PreconditionViolationException { - condition(array != null && array.length > 0, message); + public static T[] notEmpty(T @Nullable [] array, String message) throws PreconditionViolationException { + if (array == null || array.length == 0) { + throw new PreconditionViolationException(message); + } return array; } @@ -119,8 +130,12 @@ public static T[] notEmpty(T[] array, String message) throws PreconditionVio * @see #containsNoNullElements(Object[], String) * @see #condition(boolean, String) */ - public static T[] notEmpty(T[] array, Supplier messageSupplier) throws PreconditionViolationException { - condition(array != null && array.length > 0, messageSupplier); + public static T[] notEmpty(T @Nullable [] array, Supplier messageSupplier) + throws PreconditionViolationException { + + if (array == null || array.length == 0) { + throw new PreconditionViolationException(messageSupplier.get()); + } return array; } @@ -137,10 +152,12 @@ public static T[] notEmpty(T[] array, Supplier messageSupplier) thro * @see #containsNoNullElements(Collection, String) * @see #condition(boolean, String) */ - public static > T notEmpty(T collection, String message) + public static > T notEmpty(@Nullable T collection, String message) throws PreconditionViolationException { - condition(collection != null && !collection.isEmpty(), message); + if (collection == null || collection.isEmpty()) { + throw new PreconditionViolationException(message); + } return collection; } @@ -157,10 +174,12 @@ public static > T notEmpty(T collection, String message) * @see #containsNoNullElements(Collection, String) * @see #condition(boolean, String) */ - public static > T notEmpty(T collection, Supplier messageSupplier) + public static > T notEmpty(@Nullable T collection, Supplier messageSupplier) throws PreconditionViolationException { - condition(collection != null && !collection.isEmpty(), messageSupplier); + if (collection == null || collection.isEmpty()) { + throw new PreconditionViolationException(messageSupplier.get()); + } return collection; } @@ -177,7 +196,10 @@ public static > T notEmpty(T collection, Supplier T[] containsNoNullElements(T[] array, String message) throws PreconditionViolationException { + + public static T @Nullable [] containsNoNullElements(T @Nullable [] array, String message) + throws PreconditionViolationException { + if (array != null) { Arrays.stream(array).forEach(object -> notNull(object, message)); } @@ -197,7 +219,7 @@ public static T[] containsNoNullElements(T[] array, String message) throws P * any {@code null} elements * @see #notNull(Object, String) */ - public static T[] containsNoNullElements(T[] array, Supplier messageSupplier) + public static T @Nullable [] containsNoNullElements(T @Nullable [] array, Supplier messageSupplier) throws PreconditionViolationException { if (array != null) { @@ -219,7 +241,7 @@ public static T[] containsNoNullElements(T[] array, Supplier message * any {@code null} elements * @see #notNull(Object, String) */ - public static > T containsNoNullElements(T collection, String message) + public static > @Nullable T containsNoNullElements(@Nullable T collection, String message) throws PreconditionViolationException { if (collection != null) { @@ -241,8 +263,8 @@ public static > T containsNoNullElements(T collection, S * any {@code null} elements * @see #notNull(Object, String) */ - public static > T containsNoNullElements(T collection, Supplier messageSupplier) - throws PreconditionViolationException { + public static > @Nullable T containsNoNullElements(@Nullable T collection, + Supplier messageSupplier) throws PreconditionViolationException { if (collection != null) { collection.forEach(object -> notNull(object, messageSupplier)); @@ -262,8 +284,10 @@ public static > T containsNoNullElements(T collection, S * @throws PreconditionViolationException if the supplied string is blank * @see #notBlank(String, Supplier) */ - public static String notBlank(String str, String message) throws PreconditionViolationException { - condition(StringUtils.isNotBlank(str), message); + public static String notBlank(@Nullable String str, String message) throws PreconditionViolationException { + if (str == null || StringUtils.isBlank(str)) { + throw new PreconditionViolationException(message); + } return str; } @@ -280,8 +304,12 @@ public static String notBlank(String str, String message) throws PreconditionVio * @see StringUtils#isNotBlank(String) * @see #condition(boolean, Supplier) */ - public static String notBlank(String str, Supplier messageSupplier) throws PreconditionViolationException { - condition(StringUtils.isNotBlank(str), messageSupplier); + public static String notBlank(@Nullable String str, Supplier messageSupplier) + throws PreconditionViolationException { + + if (str == null || StringUtils.isBlank(str)) { + throw new PreconditionViolationException(messageSupplier.get()); + } return str; } 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 276d8a280901..0e34e0fdeee4 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 @@ -57,6 +57,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.Logger; @@ -379,7 +380,7 @@ public static boolean isInnerClass(Class clazz) { * @since 1.12 */ @API(status = INTERNAL, since = "1.12") - public static boolean isRecordObject(Object object) { + public static boolean isRecordObject(@Nullable Object object) { return object != null && isRecordClass(object.getClass()); } @@ -408,7 +409,7 @@ public static boolean returnsPrimitiveVoid(Method method) { * @param obj the object to test; potentially {@code null} * @return {@code true} if the object is an array */ - public static boolean isArray(Object obj) { + public static boolean isArray(@Nullable Object obj) { return (obj != null && obj.getClass().isArray()); } @@ -420,7 +421,7 @@ public static boolean isArray(Object obj) { * @since 1.3.2 */ @API(status = INTERNAL, since = "1.3.2") - public static boolean isMultidimensionalArray(Object obj) { + public static boolean isMultidimensionalArray(@Nullable Object obj) { return (obj != null && obj.getClass().isArray() && obj.getClass().getComponentType().isArray()); } @@ -480,7 +481,7 @@ public static boolean isAssignableTo(Class sourceType, Class targetType) { * @see Class#isAssignableFrom(Class) * @see #isAssignableTo(Class, Class) */ - public static boolean isAssignableTo(Object obj, Class targetType) { + public static boolean isAssignableTo(@Nullable Object obj, Class targetType) { Preconditions.notNull(targetType, "target type must not be null"); if (obj == null) { @@ -565,6 +566,7 @@ static boolean isWideningConversion(Class sourceType, Class targetType) { * @return the corresponding wrapper type or {@code null} if the * supplied type is {@code null} or not a primitive type */ + @Nullable public static Class getWrapperType(Class type) { return primitiveToWrapperMap.get(type); } @@ -601,7 +603,7 @@ public static T newInstance(Class clazz, Object... args) { * @see #newInstance(Class, Object...) * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ - public static T newInstance(Constructor constructor, Object... args) { + public static T newInstance(Constructor constructor, @Nullable Object... args) { Preconditions.notNull(constructor, "Constructor must not be null"); try { @@ -649,7 +651,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @see #tryToReadFieldValue(Class, String, Object) */ @API(status = INTERNAL, since = "1.4") - public static Try tryToReadFieldValue(Field field) { + public static Try<@Nullable Object> tryToReadFieldValue(Field field) { return tryToReadFieldValue(field, null); } @@ -659,7 +661,7 @@ public static Try tryToReadFieldValue(Field field) { * @see #tryToReadFieldValue(Class, String, Object) */ @API(status = INTERNAL, since = "1.4") - public static Try tryToReadFieldValue(Field field, Object instance) { + public static Try<@Nullable Object> tryToReadFieldValue(Field field, @Nullable Object instance) { Preconditions.notNull(field, "Field must not be null"); Preconditions.condition((instance != null || isStatic(field)), () -> String.format("Cannot read non-static field [%s] on a null instance.", field)); @@ -678,7 +680,7 @@ public static Try tryToReadFieldValue(Field field, Object instance) { * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - public static List readFieldValues(List fields, Object instance) { + public static List readFieldValues(List fields, @Nullable Object instance) { return readFieldValues(fields, instance, field -> true); } @@ -695,7 +697,8 @@ public static List readFieldValues(List fields, Object instance) * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - public static List readFieldValues(List fields, Object instance, Predicate predicate) { + public static List readFieldValues(List fields, @Nullable Object instance, + Predicate predicate) { Preconditions.notNull(fields, "fields list must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); @@ -712,7 +715,8 @@ public static List readFieldValues(List fields, Object instance, /** * @see org.junit.platform.commons.support.ReflectionSupport#invokeMethod(Method, Object, Object...) */ - public static Object invokeMethod(Method method, Object target, Object... args) { + @Nullable + public static Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { Preconditions.notNull(method, "Method must not be null"); Preconditions.condition((target != null || isStatic(method)), () -> String.format("Cannot invoke non-static method [%s] on a null target.", method.toGenericString())); @@ -749,7 +753,7 @@ public static Try> tryToLoadClass(String name) { */ @API(status = INTERNAL, since = "1.11") public static Class loadRequiredClass(String name, ClassLoader classLoader) throws JUnitException { - return tryToLoadClass(name, classLoader).getOrThrow( + return tryToLoadClass(name, classLoader).getNonNullOrThrow( cause -> new JUnitException(format("Could not load class [%s]", name), cause)); } @@ -881,7 +885,8 @@ public static String getFullyQualifiedMethodName(Class clazz, Method method) * @param parameterTypes the parameter types of the method; may be {@code null} or empty * @return fully qualified method name; never {@code null} */ - public static String getFullyQualifiedMethodName(Class clazz, String methodName, Class... parameterTypes) { + public static String getFullyQualifiedMethodName(Class clazz, String methodName, + Class @Nullable... parameterTypes) { Preconditions.notNull(clazz, "Class must not be null"); return getFullyQualifiedMethodName(clazz.getName(), methodName, ClassUtils.nullSafeToString(parameterTypes)); @@ -1413,7 +1418,7 @@ public static boolean isMethodPresent(Class clazz, Predicate predicat * @since 1.4 */ @API(status = INTERNAL, since = "1.4") - public static Try tryToGetMethod(Class clazz, String methodName, Class... parameterTypes) { + public static Try tryToGetMethod(Class clazz, String methodName, Class @Nullable... parameterTypes) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); @@ -1432,7 +1437,7 @@ public static Try tryToGetMethod(Class clazz, String methodName, Clas * @since 1.11 */ @API(status = INTERNAL, since = "1.11") - public static Method getInterfaceMethodIfPossible(Method method, Class targetClass) { + public static Method getInterfaceMethodIfPossible(Method method, @Nullable Class targetClass) { if (!isPublic(method) || method.getDeclaringClass().isInterface()) { return method; } @@ -1470,15 +1475,17 @@ private static Method findInterfaceMethodIfPossible(Method method, Class[] pa /** * @see org.junit.platform.commons.support.ReflectionSupport#findMethod(Class, String, String) */ - public static Optional findMethod(Class clazz, String methodName, String parameterTypeNames) { + public static Optional findMethod(Class clazz, String methodName, @Nullable String parameterTypeNames) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); return findMethod(clazz, methodName, resolveParameterTypes(clazz, methodName, parameterTypeNames)); } @API(status = INTERNAL, since = "1.10") - public static Class[] resolveParameterTypes(Class clazz, String methodName, String parameterTypeNames) { - if (StringUtils.isBlank(parameterTypeNames)) { + public static Class[] resolveParameterTypes(Class clazz, String methodName, + @Nullable String parameterTypeNames) { + + if (parameterTypeNames == null || StringUtils.isBlank(parameterTypeNames)) { return EMPTY_CLASS_ARRAY; } @@ -1495,7 +1502,7 @@ private static Class loadRequiredParameterType(Class clazz, String methodN // @formatter:off return tryToLoadClass(typeName, classLoader) - .getOrThrow(cause -> new JUnitException( + .getNonNullOrThrow(cause -> new JUnitException( String.format("Failed to load parameter type [%s] for method [%s] in class [%s].", typeName, methodName, clazz.getName()), cause)); // @formatter:on @@ -1971,7 +1978,7 @@ private static void getAllAssignmentCompatibleClasses(Class clazz, Set clazz) { + private static boolean isSearchable(@Nullable Class clazz) { return (clazz != null && clazz != Object.class); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java index 490d5c741c89..192e3f2c4d6b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/RuntimeUtils.java @@ -61,7 +61,7 @@ static Optional> getInputArguments() { // See https://github.com/junit-team/junit4/pull/1187 try { Object bean = managementFactoryClass.get().getMethod("getRuntimeMXBean").invoke(null); - Class mx = ReflectionUtils.tryToLoadClass("java.lang.management.RuntimeMXBean").get(); + Class mx = ReflectionUtils.tryToLoadClass("java.lang.management.RuntimeMXBean").getNonNull(); @SuppressWarnings("unchecked") List args = (List) mx.getMethod("getInputArguments").invoke(bean); return Optional.of(args); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java index db209116b615..d9f179b6b381 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ServiceLoaderUtils.java @@ -45,6 +45,10 @@ private ServiceLoaderUtils() { */ public static Stream filter(ServiceLoader serviceLoader, Predicate> providerPredicate) { + + Preconditions.notNull(serviceLoader, "serviceLoader must not be null"); + Preconditions.notNull(providerPredicate, "providerPredicate must not be null"); + // @formatter:off return serviceLoader .stream() diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java index 18949e91eb9c..cdef22876436 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java @@ -20,6 +20,7 @@ import java.util.regex.Pattern; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Collection of utilities for working with {@link String Strings}, @@ -67,7 +68,7 @@ private StringUtils() { * @return {@code true} if the string is blank * @see #isNotBlank(String) */ - public static boolean isBlank(String str) { + public static boolean isBlank(@Nullable String str) { return (str == null || str.trim().isEmpty()); } @@ -79,7 +80,7 @@ public static boolean isBlank(String str) { * @return {@code true} if the string is not blank * @see #isBlank(String) */ - public static boolean isNotBlank(String str) { + public static boolean isNotBlank(@Nullable String str) { return !isBlank(str); } @@ -91,7 +92,7 @@ public static boolean isNotBlank(String str) { * @see #containsIsoControlCharacter(String) * @see Character#isWhitespace(int) */ - public static boolean containsWhitespace(String str) { + public static boolean containsWhitespace(@Nullable String str) { return str != null && str.codePoints().anyMatch(Character::isWhitespace); } @@ -105,7 +106,7 @@ public static boolean containsWhitespace(String str) { * @see #containsIsoControlCharacter(String) * @see Character#isWhitespace(int) */ - public static boolean doesNotContainWhitespace(String str) { + public static boolean doesNotContainWhitespace(@Nullable String str) { return !containsWhitespace(str); } @@ -117,7 +118,7 @@ public static boolean doesNotContainWhitespace(String str) { * @see #containsWhitespace(String) * @see Character#isISOControl(int) */ - public static boolean containsIsoControlCharacter(String str) { + public static boolean containsIsoControlCharacter(@Nullable String str) { return str != null && str.codePoints().anyMatch(Character::isISOControl); } @@ -131,7 +132,7 @@ public static boolean containsIsoControlCharacter(String str) { * @see #containsWhitespace(String) * @see Character#isISOControl(int) */ - public static boolean doesNotContainIsoControlCharacter(String str) { + public static boolean doesNotContainIsoControlCharacter(@Nullable String str) { return !containsIsoControlCharacter(str); } @@ -157,7 +158,7 @@ public static boolean doesNotContainIsoControlCharacter(String str) { * @see Arrays#deepToString(Object[]) * @see ClassUtils#nullSafeToString(Class...) */ - public static String nullSafeToString(Object obj) { + public static String nullSafeToString(@Nullable Object obj) { if (obj == null) { return "null"; } @@ -221,7 +222,7 @@ public static String nullSafeToString(Object obj) { * @see #nullSafeToString(Object) * @see ClassUtils#nullSafeToString(Class...) */ - public static String defaultToString(Object obj) { + public static String defaultToString(@Nullable Object obj) { if (obj == null) { return "null"; } @@ -239,7 +240,7 @@ public static String defaultToString(Object obj) { * @since 1.4 */ @API(status = INTERNAL, since = "1.4") - public static String replaceIsoControlCharacters(String str, String replacement) { + public static @Nullable String replaceIsoControlCharacters(@Nullable String str, String replacement) { Preconditions.notNull(replacement, "replacement must not be null"); return str == null ? null : ISO_CONTROL_PATTERN.matcher(str).replaceAll(replacement); } @@ -254,7 +255,7 @@ public static String replaceIsoControlCharacters(String str, String replacement) * @since 1.4 */ @API(status = INTERNAL, since = "1.4") - public static String replaceWhitespaceCharacters(String str, String replacement) { + public static @Nullable String replaceWhitespaceCharacters(@Nullable String str, String replacement) { Preconditions.notNull(replacement, "replacement must not be null"); return str == null ? null : WHITESPACE_PATTERN.matcher(str).replaceAll(replacement); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ToStringBuilder.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ToStringBuilder.java index eabaf3dcc09a..97bfb1a6cc30 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ToStringBuilder.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ToStringBuilder.java @@ -17,6 +17,7 @@ import java.util.List; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Simple builder for generating strings in custom implementations of @@ -50,13 +51,13 @@ public ToStringBuilder(String typeName) { this.typeName = Preconditions.notNull(typeName, "Type name must not be null"); } - public ToStringBuilder append(String name, Object value) { + public ToStringBuilder append(String name, @Nullable Object value) { Preconditions.notBlank(name, "Name must not be null or blank"); this.values.add(name + " = " + toString(value)); return this; } - private String toString(Object obj) { + private String toString(@Nullable Object obj) { return (obj instanceof CharSequence) ? ("'" + obj + "'") : StringUtils.nullSafeToString(obj); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/UnrecoverableExceptions.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/UnrecoverableExceptions.java index 23589c2a1672..7799476137a1 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/UnrecoverableExceptions.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/UnrecoverableExceptions.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Internal utilities for working with unrecoverable exceptions. @@ -47,7 +48,7 @@ private UnrecoverableExceptions() { *

If the supplied {@code exception} is not unrecoverable, this * method does nothing. */ - public static void rethrowIfUnrecoverable(Throwable exception) { + public static void rethrowIfUnrecoverable(@Nullable Throwable exception) { if (exception instanceof OutOfMemoryError) { throw ExceptionUtils.throwAsUncheckedException(exception); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java index 119940686c89..3d9e974b50f9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java @@ -8,4 +8,7 @@ * Use at your own risk! */ +@NullMarked package org.junit.platform.commons.util; + +import org.jspecify.annotations.NullMarked; From c9c584350df060500085d3c77dbe8aced50c9f9e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 09:09:52 +0200 Subject: [PATCH 090/521] Enable NullAway in junit-platform-engine --- junit-platform-engine/junit-platform-engine.gradle.kts | 2 ++ junit-platform-engine/src/main/java/module-info.java | 3 +++ .../jar-describe-module/junit-platform-engine.expected.txt | 1 + 3 files changed, 6 insertions(+) diff --git a/junit-platform-engine/junit-platform-engine.gradle.kts b/junit-platform-engine/junit-platform-engine.gradle.kts index 416b227b00c1..09282c6e49f3 100644 --- a/junit-platform-engine/junit-platform-engine.gradle.kts +++ b/junit-platform-engine/junit-platform-engine.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") `java-test-fixtures` } @@ -11,6 +12,7 @@ dependencies { api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) + compileOnlyApi(libs.jspecify) testImplementation(libs.assertj) diff --git a/junit-platform-engine/src/main/java/module-info.java b/junit-platform-engine/src/main/java/module-info.java index 4727b0182960..c81836121c9c 100644 --- a/junit-platform-engine/src/main/java/module-info.java +++ b/junit-platform-engine/src/main/java/module-info.java @@ -17,7 +17,10 @@ * @since 1.0 */ module org.junit.platform.engine { + requires static transitive org.apiguardian.api; + requires static transitive org.jspecify; + requires transitive org.junit.platform.commons; requires transitive org.opentest4j; diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt index 7849ee4adb77..4997294a0477 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt @@ -9,6 +9,7 @@ exports org.junit.platform.engine.support.hierarchical exports org.junit.platform.engine.support.store requires java.base mandated requires org.apiguardian.api static transitive +requires org.jspecify static transitive requires org.junit.platform.commons transitive requires org.opentest4j transitive uses org.junit.platform.engine.discovery.DiscoverySelectorIdentifierParser From e49bdf384d17883fcc96964dd91e4057a091b098 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 09:10:48 +0200 Subject: [PATCH 091/521] Annotate nullability in `org.junit.platform.engine.support.config` --- .../org/junit/platform/engine/support/config/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java index 05f555a220ea..76d01748f8e3 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java @@ -3,4 +3,7 @@ * classes intended to be used by test engine implementations. */ +@NullMarked package org.junit.platform.engine.support.config; + +import org.jspecify.annotations.NullMarked; From a50800b2b54c9c707d14f927daf7dc24dd6354a5 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 09:45:54 +0200 Subject: [PATCH 092/521] Annotate nullability in `org.junit.platform.engine.support.descriptor` --- .../descriptor/AbstractTestDescriptor.java | 11 +++--- .../support/descriptor/ClassSource.java | 13 ++++--- .../descriptor/ClasspathResourceSource.java | 7 ++-- .../support/descriptor/FilePosition.java | 3 ++ .../engine/support/descriptor/FileSource.java | 10 ++++-- .../support/descriptor/MethodSource.java | 35 +++++++++++-------- .../support/descriptor/package-info.java | 3 ++ 7 files changed, 55 insertions(+), 27 deletions(-) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java index 336b6d686d95..0454b5c34dad 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java @@ -22,6 +22,7 @@ import java.util.function.UnaryOperator; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; @@ -44,8 +45,10 @@ public abstract class AbstractTestDescriptor implements TestDescriptor { private final String displayName; + @Nullable private final TestSource source; + @Nullable private TestDescriptor parent; /** @@ -87,7 +90,7 @@ protected AbstractTestDescriptor(UniqueId uniqueId, String displayName) { * {@code TestDescriptor}; can be {@code null} * @see #AbstractTestDescriptor(UniqueId, String) */ - protected AbstractTestDescriptor(UniqueId uniqueId, String displayName, TestSource source) { + protected AbstractTestDescriptor(UniqueId uniqueId, String displayName, @Nullable TestSource source) { this.uniqueId = Preconditions.notNull(uniqueId, "UniqueId must not be null"); this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or blank"); this.source = source; @@ -119,7 +122,7 @@ public final Optional getParent() { } @Override - public final void setParent(TestDescriptor parent) { + public final void setParent(@Nullable TestDescriptor parent) { this.parent = parent; } @@ -144,8 +147,8 @@ public void removeChild(TestDescriptor child) { @Override public void removeFromHierarchy() { - Preconditions.condition(!isRoot(), "cannot remove the root of a hierarchy"); - this.parent.removeChild(this); + var parent = Preconditions.notNull(this.parent, "cannot remove the root of a hierarchy"); + parent.removeChild(this); this.children.forEach(child -> child.setParent(null)); this.children.clear(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java index ce76cc6549db..f31e3d948a14 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.Preconditions; @@ -71,7 +72,7 @@ public static ClassSource from(String className) { * @param className the class name; must not be {@code null} or blank * @param filePosition the position in the source file; may be {@code null} */ - public static ClassSource from(String className, FilePosition filePosition) { + public static ClassSource from(String className, @Nullable FilePosition filePosition) { return new ClassSource(className, filePosition); } @@ -132,14 +133,18 @@ public static ClassSource from(URI uri) { } private final String className; + + @Nullable private final FilePosition filePosition; + + @Nullable private Class javaClass; private ClassSource(String className) { this(className, null); } - private ClassSource(String className, FilePosition filePosition) { + private ClassSource(String className, @Nullable FilePosition filePosition) { this.className = Preconditions.notBlank(className, "Class name must not be null or blank"); this.filePosition = filePosition; } @@ -148,7 +153,7 @@ private ClassSource(Class javaClass) { this(javaClass, null); } - private ClassSource(Class javaClass, FilePosition filePosition) { + private ClassSource(Class javaClass, @Nullable FilePosition filePosition) { this.javaClass = Preconditions.notNull(javaClass, "Class must not be null"); this.className = this.javaClass.getName(); this.filePosition = filePosition; @@ -177,7 +182,7 @@ public final String getClassName() { public final Class getJavaClass() { if (this.javaClass == null) { // @formatter:off - this.javaClass = ReflectionSupport.tryToLoadClass(this.className).getOrThrow( + this.javaClass = ReflectionSupport.tryToLoadClass(this.className).getNonNullOrThrow( cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java index 303bdc5bc5c4..3f547a564606 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ResourceUtils; @@ -79,7 +80,7 @@ public static ClasspathResourceSource from(String classpathResourceName) { * {@code null} or blank * @param filePosition the position in the classpath resource; may be {@code null} */ - public static ClasspathResourceSource from(String classpathResourceName, FilePosition filePosition) { + public static ClasspathResourceSource from(String classpathResourceName, @Nullable FilePosition filePosition) { return new ClasspathResourceSource(classpathResourceName, filePosition); } @@ -112,13 +113,15 @@ public static ClasspathResourceSource from(URI uri) { } private final String classpathResourceName; + + @Nullable private final FilePosition filePosition; private ClasspathResourceSource(String classpathResourceName) { this(classpathResourceName, null); } - private ClasspathResourceSource(String classpathResourceName, FilePosition filePosition) { + private ClasspathResourceSource(String classpathResourceName, @Nullable FilePosition filePosition) { Preconditions.notBlank(classpathResourceName, "Classpath resource name must not be null or blank"); boolean startsWithSlash = classpathResourceName.startsWith("/"); this.classpathResourceName = (startsWithSlash ? classpathResourceName.substring(1) : classpathResourceName); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java index 28d4246a8cdd..de653d5fcacb 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; @@ -116,6 +117,8 @@ else if (column == null && "column".equals(key)) { } private final int line; + + @Nullable private final Integer column; private FilePosition(int line) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java index b07fddbe7b65..b82e113ff5ee 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java @@ -20,6 +20,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -53,18 +54,20 @@ public static FileSource from(File file) { * @param file the source file; must not be {@code null} * @param filePosition the position in the source file; may be {@code null} */ - public static FileSource from(File file, FilePosition filePosition) { + public static FileSource from(File file, @Nullable FilePosition filePosition) { return new FileSource(file, filePosition); } private final File file; + + @Nullable private final FilePosition filePosition; private FileSource(File file) { this(file, null); } - private FileSource(File file, FilePosition filePosition) { + private FileSource(File file, @Nullable FilePosition filePosition) { Preconditions.notNull(file, "file must not be null"); try { this.file = file.getCanonicalFile(); @@ -111,7 +114,8 @@ public boolean equals(Object o) { return false; } FileSource that = (FileSource) o; - return Objects.equals(this.file, that.file) && Objects.equals(this.filePosition, that.filePosition); + return Objects.equals(this.file, that.file) // + && Objects.equals(this.filePosition, that.filePosition); } @Override diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java index c00af72f9b45..3ffc0ceae2ea 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java @@ -18,6 +18,7 @@ import java.util.Objects; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.Preconditions; @@ -108,15 +109,21 @@ public static MethodSource from(Class testClass, Method testMethod) { private final String className; private final String methodName; + + @Nullable private final String methodParameterTypes; + + @Nullable private Class javaClass; + + @Nullable private transient Method javaMethod; private MethodSource(String className, String methodName) { this(className, methodName, null); } - private MethodSource(String className, String methodName, String methodParameterTypes) { + private MethodSource(String className, String methodName, @Nullable String methodParameterTypes) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); this.className = className; @@ -158,6 +165,7 @@ public final String getMethodName() { /** * Get the method parameter types of this source. */ + @Nullable public final String getMethodParameterTypes() { return this.methodParameterTypes; } @@ -174,8 +182,7 @@ public final String getMethodParameterTypes() { */ @API(status = STABLE, since = "1.7") public final Class getJavaClass() { - lazyLoadJavaClass(); - return this.javaClass; + return lazyLoadJavaClass(); } /** @@ -190,37 +197,37 @@ public final Class getJavaClass() { */ @API(status = STABLE, since = "1.7") public final Method getJavaMethod() { - lazyLoadJavaMethod(); - return this.javaMethod; + return lazyLoadJavaMethod(); } - private void lazyLoadJavaClass() { + private Class lazyLoadJavaClass() { if (this.javaClass == null) { // @formatter:off - this.javaClass = ReflectionSupport.tryToLoadClass(this.className).getOrThrow( + this.javaClass = ReflectionSupport.tryToLoadClass(this.className).getNonNullOrThrow( cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } + return this.javaClass; } - private void lazyLoadJavaMethod() { - lazyLoadJavaClass(); - + private Method lazyLoadJavaMethod() { if (this.javaMethod == null) { + Class javaClass = getJavaClass(); if (StringUtils.isNotBlank(this.methodParameterTypes)) { - this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName, + this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName, this.methodParameterTypes).orElseThrow( () -> new PreconditionViolationException( "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( - this.methodName, this.methodParameterTypes, this.javaClass.getName()))); + this.methodName, this.methodParameterTypes, javaClass.getName()))); } else { - this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName).orElseThrow( + this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( "Could not find method with name [%s] in class [%s].".formatted(this.methodName, - this.javaClass.getName()))); + javaClass.getName()))); } } + return this.javaMethod; } @Override diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java index 9f063532a19a..eabc3dab0055 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java @@ -4,4 +4,7 @@ * the launcher. */ +@NullMarked package org.junit.platform.engine.support.descriptor; + +import org.jspecify.annotations.NullMarked; From 0a5eba108e9d25dc666c79df9898154e18d6f575 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 09:49:52 +0200 Subject: [PATCH 093/521] Annotate nullability in `org.junit.platform.engine.support.discovery` --- .../discovery/EngineDiscoveryRequestResolution.java | 10 +++++----- .../engine/support/discovery/package-info.java | 3 +++ 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java index 2c4590fd11be..1726376ffa67 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/EngineDiscoveryRequestResolution.java @@ -10,6 +10,7 @@ package org.junit.platform.engine.support.discovery; +import static java.util.Objects.requireNonNullElse; import static java.util.stream.Collectors.joining; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.SelectorResolutionResult.failed; @@ -28,6 +29,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.DiscoverySelector; @@ -199,18 +201,16 @@ private Optional resolve(DiscoverySelector selector, private class DefaultContext implements Context { + @Nullable private final TestDescriptor parent; - DefaultContext(TestDescriptor parent) { + DefaultContext(@Nullable TestDescriptor parent) { this.parent = parent; } @Override public Optional addToParent(Function> creator) { - if (parent != null) { - return createAndAdd(parent, creator); - } - return createAndAdd(engineDescriptor, creator); + return createAndAdd(requireNonNullElse(parent, engineDescriptor), creator); } @Override diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java index 1f0ea1ff308a..3d6b8dd4a0aa 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java @@ -6,4 +6,7 @@ * @see org.junit.platform.engine.support.discovery.SelectorResolver */ +@NullMarked package org.junit.platform.engine.support.discovery; + +import org.jspecify.annotations.NullMarked; From 537346dc9814b0b26396db25ccfe7be30d3a55c1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 10:15:05 +0200 Subject: [PATCH 094/521] Annotate nullability in `org.junit.platform.engine.support.hierarchical` --- ...arallelExecutionConfigurationStrategy.java | 5 +- ...inPoolHierarchicalTestExecutorService.java | 3 +- .../HierarchicalTestExecutorService.java | 3 +- .../engine/support/hierarchical/Node.java | 5 +- .../support/hierarchical/NodeTestTask.java | 56 ++++++++++++++----- .../ParallelExecutionConfiguration.java | 4 +- ...ThreadHierarchicalTestExecutorService.java | 3 +- .../hierarchical/ThrowableCollector.java | 13 +++-- .../support/hierarchical/package-info.java | 3 + .../DemoHierarchicalContainerDescriptor.java | 6 +- .../DemoHierarchicalEngineDescriptor.java | 3 + .../DemoHierarchicalTestDescriptor.java | 11 +++- .../DemoHierarchicalTestEngine.java | 8 ++- 13 files changed, 88 insertions(+), 35 deletions(-) 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 7bf7c9581f95..91bc18a23589 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,6 +10,7 @@ package org.junit.platform.engine.support.hierarchical; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; @@ -106,8 +107,8 @@ public ParallelExecutionConfiguration createConfiguration(ConfigurationParameter + ParallelExecutionConfigurationStrategy.class); return (ParallelExecutionConfigurationStrategy) ReflectionSupport.newInstance(strategyClass); }) // - .andThenTry(strategy -> strategy.createConfiguration(configurationParameters)) // - .getOrThrow(cause -> new JUnitException( + .andThenTry(strategy -> requireNonNull(strategy).createConfiguration(configurationParameters)) // + .getNonNullOrThrow(cause -> new JUnitException( "Could not create configuration for strategy class: " + className, cause)); } }; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java index 9ccb3747680f..5d6979cf8b32 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java @@ -35,6 +35,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.logging.LoggerFactory; @@ -126,7 +127,7 @@ private static Callable sinceJava7ConstructorInvocation(ParallelEx } @Override - public Future submit(TestTask testTask) { + public Future<@Nullable Void> submit(TestTask testTask) { ExclusiveTask exclusiveTask = new ExclusiveTask(testTask); if (!isAlreadyRunningInForkJoinPool()) { // ensure we're running inside the ForkJoinPool so we diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutorService.java index d879aa2b5978..1fed0663e519 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutorService.java @@ -16,6 +16,7 @@ import java.util.concurrent.Future; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.support.hierarchical.Node.ExecutionMode; @@ -49,7 +50,7 @@ public interface HierarchicalTestExecutorService extends AutoCloseable { * to be finished * @see #invokeAll(List) */ - Future submit(TestTask testTask); + Future<@Nullable Void> submit(TestTask testTask); /** * Invoke all supplied {@linkplain TestTask test tasks} and block until diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/Node.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/Node.java index f2616e60a6cb..1fa014c92d14 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/Node.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/Node.java @@ -19,6 +19,7 @@ import java.util.concurrent.Future; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; @@ -218,7 +219,7 @@ class SkipResult { * may be {@code null} * @return a skipped {@code SkipResult} with the given reason */ - public static SkipResult skip(String reason) { + public static SkipResult skip(@Nullable String reason) { return new SkipResult(true, reason); } @@ -233,7 +234,7 @@ public static SkipResult doNotSkip() { return alwaysExecuteSkipResult; } - private SkipResult(boolean skipped, String reason) { + private SkipResult(boolean skipped, @Nullable String reason) { this.skipped = skipped; this.reason = Optional.ofNullable(reason); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java index 4bdbcbbcdd26..5ad5e15a37a4 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java @@ -10,6 +10,8 @@ package org.junit.platform.engine.support.hierarchical; +import static java.util.Objects.requireNonNull; +import static java.util.Objects.requireNonNullElse; import static java.util.concurrent.CompletableFuture.completedFuture; import static java.util.stream.Collectors.toCollection; import static org.junit.platform.engine.TestExecutionResult.failed; @@ -23,6 +25,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; @@ -51,11 +54,18 @@ class NodeTestTask implements TestTask { private final Node node; private final Runnable finalizer; + @Nullable private C parentContext; + + @Nullable private C context; + @Nullable private SkipResult skipResult; + private boolean started; + + @Nullable private ThrowableCollector throwableCollector; NodeTestTask(NodeTestTaskContext taskContext, TestDescriptor testDescriptor) { @@ -85,7 +95,7 @@ public String toString() { return "NodeTestTask [" + testDescriptor + "]"; } - void setParentContext(C parentContext) { + void setParentContext(@Nullable C parentContext) { this.parentContext = parentContext; } @@ -97,7 +107,7 @@ public void execute() { if (throwableCollector.isEmpty()) { checkWhetherSkipped(); } - if (throwableCollector.isEmpty() && !skipResult.isSkipped()) { + if (throwableCollector.isEmpty() && !requiredSkipResult().isSkipped()) { executeRecursively(); } if (context != null) { @@ -126,7 +136,7 @@ public void execute() { } private void prepare() { - throwableCollector.execute(() -> context = node.prepare(parentContext)); + requiredThrowableCollector().execute(() -> context = node.prepare(requireNonNull(parentContext))); // Clear reference to parent context to allow it to be garbage collected. // See https://github.com/junit-team/junit5/issues/1578 @@ -134,15 +144,17 @@ private void prepare() { } private void checkWhetherSkipped() { - throwableCollector.execute(() -> skipResult = node.shouldBeSkipped(context)); + requiredThrowableCollector().execute(() -> skipResult = node.shouldBeSkipped(requiredContext())); } private void executeRecursively() { taskContext.getListener().executionStarted(testDescriptor); started = true; + var throwableCollector = requiredThrowableCollector(); + throwableCollector.execute(() -> { - node.around(context, ctx -> { + node.around(requiredContext(), ctx -> { context = ctx; throwableCollector.execute(() -> { // @formatter:off @@ -151,10 +163,10 @@ private void executeRecursively() { .collect(toCollection(ArrayList::new)); // @formatter:on - context = node.before(context); + context = node.before(requiredContext()); final DynamicTestExecutor dynamicTestExecutor = new DefaultDynamicTestExecutor(); - context = node.execute(context, dynamicTestExecutor); + context = node.execute(requiredContext(), dynamicTestExecutor); if (!children.isEmpty()) { children.forEach(child -> child.setParentContext(context)); @@ -164,19 +176,23 @@ private void executeRecursively() { throwableCollector.execute(dynamicTestExecutor::awaitFinished); }); - throwableCollector.execute(() -> node.after(context)); + throwableCollector.execute(() -> node.after(requiredContext())); }); }); } private void cleanUp() { - throwableCollector.execute(() -> node.cleanUp(context)); + requiredThrowableCollector().execute(() -> node.cleanUp(requiredContext())); } private void reportCompletion() { - if (throwableCollector.isEmpty() && skipResult.isSkipped()) { + + var throwableCollector = requiredThrowableCollector(); + + if (throwableCollector.isEmpty() && requiredSkipResult().isSkipped()) { + var skipResult = requiredSkipResult(); try { - node.nodeSkipped(context, testDescriptor, skipResult); + node.nodeSkipped(requiredContext(), testDescriptor, skipResult); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); @@ -191,7 +207,7 @@ private void reportCompletion() { taskContext.getListener().executionStarted(testDescriptor); } try { - node.nodeFinished(context, testDescriptor, throwableCollector.toTestExecutionResult()); + node.nodeFinished(requiredContext(), testDescriptor, throwableCollector.toTestExecutionResult()); } catch (Throwable throwable) { UnrecoverableExceptions.rethrowIfUnrecoverable(throwable); @@ -199,7 +215,19 @@ private void reportCompletion() { () -> "Failed to invoke nodeFinished() on Node %s".formatted(testDescriptor.getUniqueId())); } taskContext.getListener().executionFinished(testDescriptor, throwableCollector.toTestExecutionResult()); - throwableCollector = null; + this.throwableCollector = null; + } + + private C requiredContext() { + return requireNonNull(context); + } + + private SkipResult requiredSkipResult() { + return requireNonNull(skipResult); + } + + private ThrowableCollector requiredThrowableCollector() { + return requireNonNull(throwableCollector); } private class DefaultDynamicTestExecutor implements DynamicTestExecutor { @@ -245,7 +273,7 @@ public void awaitFinished() throws InterruptedException { // Futures returned by execute() may have been cancelled } catch (ExecutionException e) { - throw ExceptionUtils.throwAsUncheckedException(e.getCause()); + throw ExceptionUtils.throwAsUncheckedException(requireNonNullElse(e.getCause(), e)); } } } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java index 15f9a3184e7e..6a953cbbd9da 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java @@ -16,6 +16,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Configuration to use for parallel test execution. @@ -66,9 +67,10 @@ public interface ParallelExecutionConfiguration { * @return the saturate predicate to be passed to the {@code ForkJoinPool} constructor; may be {@code null} * @since 1.9 * @see ForkJoinPool#ForkJoinPool(int, ForkJoinPool.ForkJoinWorkerThreadFactory, Thread.UncaughtExceptionHandler, - * boolean, int, int, int, Predicate, long, TimeUnit) + * boolean, int, int, int, Predicate, long, java.util.concurrent.TimeUnit) */ @API(status = STABLE, since = "1.11") + @Nullable default Predicate getSaturatePredicate() { return null; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java index d6293ed7874b..9255e9df16e7 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java @@ -17,6 +17,7 @@ import java.util.concurrent.Future; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * A simple {@linkplain HierarchicalTestExecutorService executor service} that @@ -31,7 +32,7 @@ public SameThreadHierarchicalTestExecutorService() { } @Override - public Future submit(TestTask testTask) { + public Future<@Nullable Void> submit(TestTask testTask) { testTask.execute(); return completedFuture(null); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java index 88e83cdb9ed5..7cfe656b926b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java @@ -18,6 +18,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -42,6 +43,7 @@ public class ThrowableCollector { private final Predicate abortedExecutionPredicate; + @Nullable private Throwable throwable; /** @@ -121,6 +123,7 @@ else if (throwable != t) { * @see #isEmpty() * @see #assertEmpty() */ + @Nullable public Throwable getThrowable() { return this.throwable; } @@ -157,7 +160,7 @@ public boolean isNotEmpty() { * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ public void assertEmpty() { - if (!isEmpty()) { + if (this.throwable != null) { throw ExceptionUtils.throwAsUncheckedException(this.throwable); } } @@ -174,13 +177,13 @@ public void assertEmpty() { */ @API(status = MAINTAINED, since = "1.6") public TestExecutionResult toTestExecutionResult() { - if (isEmpty()) { + if (this.throwable == null) { return successful(); } - if (hasAbortedExecution(throwable)) { - return aborted(throwable); + if (hasAbortedExecution(this.throwable)) { + return aborted(this.throwable); } - return failed(throwable); + return failed(this.throwable); } private boolean hasAbortedExecution(Throwable t) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java index 033745ba7795..925cfac6bfec 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java @@ -5,4 +5,7 @@ * {@link org.junit.platform.engine.support.hierarchical.Node} abstraction. */ +@NullMarked package org.junit.platform.engine.support.hierarchical; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java index 00ead8e16784..ea0e595862c7 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java @@ -12,6 +12,7 @@ import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.doNotSkip; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.AbstractTestDescriptor; @@ -22,10 +23,11 @@ public class DemoHierarchicalContainerDescriptor extends AbstractTestDescriptor implements Node { + @Nullable private final Runnable beforeBlock; - public DemoHierarchicalContainerDescriptor(UniqueId uniqueId, String displayName, TestSource source, - Runnable beforeBlock) { + public DemoHierarchicalContainerDescriptor(UniqueId uniqueId, String displayName, @Nullable TestSource source, + @Nullable Runnable beforeBlock) { super(uniqueId, displayName, source); this.beforeBlock = beforeBlock; } diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java index 5dd40c886bbb..49aa67dd32f8 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java @@ -13,6 +13,7 @@ import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.doNotSkip; import static org.junit.platform.engine.support.hierarchical.Node.SkipResult.skip; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.EngineDescriptor; @@ -21,7 +22,9 @@ */ public class DemoHierarchicalEngineDescriptor extends EngineDescriptor implements Node { + @Nullable private String skippedReason; + private boolean skipped; private Runnable beforeAllBehavior = () -> { }; diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java index 29b57733512a..26b696be0387 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java @@ -15,6 +15,7 @@ import java.util.function.BiConsumer; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.UniqueId; @@ -25,17 +26,21 @@ */ public class DemoHierarchicalTestDescriptor extends AbstractTestDescriptor implements Node { + @Nullable private final BiConsumer executeBlock; + + @Nullable private String skippedReason; + private boolean skipped; public DemoHierarchicalTestDescriptor(UniqueId uniqueId, String displayName, - BiConsumer executeBlock) { + @Nullable BiConsumer executeBlock) { this(uniqueId, displayName, null, executeBlock); } - public DemoHierarchicalTestDescriptor(UniqueId uniqueId, String displayName, TestSource source, - BiConsumer executeBlock) { + public DemoHierarchicalTestDescriptor(UniqueId uniqueId, String displayName, @Nullable TestSource source, + @Nullable BiConsumer executeBlock) { super(uniqueId, displayName, source); this.executeBlock = executeBlock; } diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestEngine.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestEngine.java index ff5e32299dde..e381e3504380 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestEngine.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestEngine.java @@ -13,6 +13,7 @@ import java.util.function.BiConsumer; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -61,7 +62,8 @@ public DemoHierarchicalTestDescriptor addTest(String uniqueName, String displayN "test"); } - public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, TestSource source) { + public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, + @Nullable TestSource source) { return addContainer(uniqueName, displayName, source, null); } @@ -69,8 +71,8 @@ public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, Runna return addContainer(uniqueName, uniqueName, null, beforeBlock); } - public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, TestSource source, - Runnable beforeBlock) { + public DemoHierarchicalContainerDescriptor addContainer(String uniqueName, String displayName, + @Nullable TestSource source, @Nullable Runnable beforeBlock) { return addChild(uniqueName, uniqueId -> new DemoHierarchicalContainerDescriptor(uniqueId, displayName, source, beforeBlock), From adb207e96654b1668d89e9d77aa4c04da5e21a57 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 10:25:18 +0200 Subject: [PATCH 095/521] Annotate nullability in `org.junit.platform.engine.support.store` --- .../store/NamespacedHierarchicalStore.java | 62 +++++++++++++------ .../engine/support/store/package-info.java | 3 + 2 files changed, 46 insertions(+), 19 deletions(-) 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 916a87bcd97e..08f5727ed8e9 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,6 +11,7 @@ package org.junit.platform.engine.support.store; import static java.util.Comparator.comparing; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; @@ -25,6 +26,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -51,8 +53,10 @@ public final class NamespacedHierarchicalStore implements AutoCloseable { private final ConcurrentMap, StoredValue> storedValues = new ConcurrentHashMap<>(4); + @Nullable private final NamespacedHierarchicalStore parentStore; + @Nullable private final CloseAction closeAction; private volatile boolean closed = false; @@ -62,7 +66,7 @@ public final class NamespacedHierarchicalStore implements AutoCloseable { * * @param parentStore the parent store to use for lookups; may be {@code null} */ - public NamespacedHierarchicalStore(NamespacedHierarchicalStore parentStore) { + public NamespacedHierarchicalStore(@Nullable NamespacedHierarchicalStore parentStore) { this(parentStore, null); } @@ -73,7 +77,8 @@ public NamespacedHierarchicalStore(NamespacedHierarchicalStore parentStore) { * @param closeAction the action to be called for each stored value when this * store is closed; may be {@code null} */ - public NamespacedHierarchicalStore(NamespacedHierarchicalStore parentStore, CloseAction closeAction) { + public NamespacedHierarchicalStore(@Nullable NamespacedHierarchicalStore parentStore, + @Nullable CloseAction closeAction) { this.parentStore = parentStore; this.closeAction = closeAction; } @@ -152,6 +157,7 @@ public void close() { * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ + @Nullable public Object get(N namespace, Object key) { StoredValue storedValue = getStoredValue(new CompositeKey<>(namespace, key)); return StoredValue.evaluateIfNotNull(storedValue); @@ -168,6 +174,7 @@ public Object get(N namespace, Object key) { * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ + @Nullable public T get(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = get(namespace, key); return castToRequiredType(key, value, requiredType); @@ -185,13 +192,14 @@ public T get(N namespace, Object key, Class requiredType) throws Namespac * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ - public Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { + @Nullable + public Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); CompositeKey compositeKey = new CompositeKey<>(namespace, key); StoredValue storedValue = getStoredValue(compositeKey); if (storedValue == null) { storedValue = this.storedValues.computeIfAbsent(compositeKey, - __ -> storedValue(new MemoizingSupplier(() -> { + __ -> newStoredValue(new MemoizingSupplier(() -> { rejectIfClosed(); return defaultCreator.apply(key); }))); @@ -213,8 +221,9 @@ public Object getOrComputeIfAbsent(N namespace, K key, Function def * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ - public V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, Class requiredType) - throws NamespacedHierarchicalStoreException { + @Nullable + public V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, + Class requiredType) throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); return castToRequiredType(key, value, requiredType); @@ -234,9 +243,10 @@ public V getOrComputeIfAbsent(N namespace, K key, Function defaultC * @throws NamespacedHierarchicalStoreException if an error occurs while * storing the value, or if this store has already been closed */ - public Object put(N namespace, Object key, Object value) throws NamespacedHierarchicalStoreException { + @Nullable + public Object put(N namespace, Object key, @Nullable Object value) throws NamespacedHierarchicalStoreException { rejectIfClosed(); - StoredValue oldValue = this.storedValues.put(new CompositeKey<>(namespace, key), storedValue(() -> value)); + StoredValue oldValue = this.storedValues.put(new CompositeKey<>(namespace, key), newStoredValue(() -> value)); return StoredValue.evaluateIfNotNull(oldValue); } @@ -253,6 +263,7 @@ public Object put(N namespace, Object key, Object value) throws NamespacedHierar * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ + @Nullable public Object remove(N namespace, Object key) { rejectIfClosed(); StoredValue previous = this.storedValues.remove(new CompositeKey<>(namespace, key)); @@ -273,16 +284,18 @@ public Object remove(N namespace, Object key) { * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ + @Nullable public T remove(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { rejectIfClosed(); Object value = remove(namespace, key); return castToRequiredType(key, value, requiredType); } - private StoredValue storedValue(Supplier value) { + private StoredValue newStoredValue(Supplier<@Nullable Object> value) { return new StoredValue(this.insertOrderSequence.getAndIncrement(), value); } + @Nullable private StoredValue getStoredValue(CompositeKey compositeKey) { StoredValue storedValue = this.storedValues.get(compositeKey); if (storedValue != null) { @@ -294,15 +307,16 @@ private StoredValue getStoredValue(CompositeKey compositeKey) { return null; } + @Nullable @SuppressWarnings("unchecked") - private T castToRequiredType(Object key, Object value, Class requiredType) { + private T castToRequiredType(Object key, @Nullable Object value, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); if (value == null) { return null; } if (isAssignableTo(value, requiredType)) { if (requiredType.isPrimitive()) { - return (T) getWrapperType(requiredType).cast(value); + return (T) requireNonNull(getWrapperType(requiredType)).cast(value); } return requiredType.cast(value); } @@ -351,13 +365,14 @@ public int hashCode() { private static class StoredValue { private final int order; - private final Supplier supplier; + private final Supplier<@Nullable Object> supplier; - StoredValue(int order, Supplier supplier) { + StoredValue(int order, Supplier<@Nullable Object> supplier) { this.order = order; this.supplier = supplier; } + @Nullable private EvaluatedValue evaluateSafely(CompositeKey compositeKey) { try { return new EvaluatedValue<>(compositeKey, this.order, evaluate()); @@ -368,11 +383,13 @@ private EvaluatedValue evaluateSafely(CompositeKey compositeKey) { } } + @Nullable private Object evaluate() { return this.supplier.get(); } - static Object evaluateIfNotNull(StoredValue value) { + @Nullable + static Object evaluateIfNotNull(@Nullable StoredValue value) { return value != null ? value.evaluate() : null; } @@ -385,16 +402,20 @@ private static class EvaluatedValue { private final CompositeKey compositeKey; private final int order; + + @Nullable private final Object value; - private EvaluatedValue(CompositeKey compositeKey, int order, Object value) { + private EvaluatedValue(CompositeKey compositeKey, int order, @Nullable Object value) { this.compositeKey = compositeKey; this.order = order; this.value = value; } private void close(CloseAction closeAction) throws Throwable { - closeAction.close(this.compositeKey.namespace, this.compositeKey.key, this.value); + if (this.value != null) { + closeAction.close(this.compositeKey.namespace, this.compositeKey.key, this.value); + } } } @@ -408,18 +429,21 @@ private void close(CloseAction closeAction) throws Throwable { * * @see StoredValue */ - private static class MemoizingSupplier implements Supplier { + private static class MemoizingSupplier implements Supplier<@Nullable Object> { private static final Object NO_VALUE_SET = new Object(); - private final Supplier delegate; + private final Supplier<@Nullable Object> delegate; + + @Nullable private volatile Object value = NO_VALUE_SET; - private MemoizingSupplier(Supplier delegate) { + private MemoizingSupplier(Supplier<@Nullable Object> delegate) { this.delegate = delegate; } @Override + @Nullable public Object get() { if (this.value == NO_VALUE_SET) { computeValue(); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java index d40e1e88e974..e754a7b508de 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java @@ -2,4 +2,7 @@ * Reusable data structures for test engines and their extensions. */ +@NullMarked package org.junit.platform.engine.support.store; + +import org.jspecify.annotations.NullMarked; From 74749a80e9dd22f9e0beef957c885a5920092eb1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 10:35:14 +0200 Subject: [PATCH 096/521] Annotate nullability in `org.junit.platform.engine` --- .../platform/engine/ConfigurationParameters.java | 3 ++- .../platform/engine/DefaultDiscoveryIssue.java | 13 +++++++++++-- .../org/junit/platform/engine/DiscoveryIssue.java | 5 +++-- .../platform/engine/EngineDiscoveryRequest.java | 6 ++++-- .../junit/platform/engine/ExecutionRequest.java | 9 +++++++-- .../org/junit/platform/engine/FilterResult.java | 15 ++++++++------- .../platform/engine/SelectorResolutionResult.java | 5 ++++- .../org/junit/platform/engine/TestDescriptor.java | 3 ++- .../platform/engine/TestExecutionResult.java | 9 ++++++--- .../java/org/junit/platform/engine/TestTag.java | 3 ++- .../java/org/junit/platform/engine/UniqueId.java | 2 ++ .../org/junit/platform/engine/package-info.java | 3 +++ 12 files changed, 54 insertions(+), 22 deletions(-) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java index b447c70f642b..d721066ce792 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java @@ -17,6 +17,7 @@ import java.util.function.Function; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; @@ -116,7 +117,7 @@ public interface ConfigurationParameters { * @see #CONFIG_FILE_NAME */ @API(status = STABLE, since = "1.3") - default Optional get(String key, Function transformer) { + default Optional get(String key, Function transformer) { Preconditions.notNull(transformer, "transformer must not be null"); return get(key).map(input -> { try { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java index 055aa4029191..f722facb7fa0 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java @@ -13,6 +13,7 @@ import java.util.Objects; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ToStringBuilder; /** @@ -22,7 +23,11 @@ final class DefaultDiscoveryIssue implements DiscoveryIssue { private final Severity severity; private final String message; + + @Nullable private final TestSource source; + + @Nullable private final Throwable cause; DefaultDiscoveryIssue(Builder builder) { @@ -86,7 +91,11 @@ static class Builder implements DiscoveryIssue.Builder { private final Severity severity; private final String message; + + @Nullable private TestSource source; + + @Nullable public Throwable cause; Builder(Severity severity, String message) { @@ -95,13 +104,13 @@ static class Builder implements DiscoveryIssue.Builder { } @Override - public Builder source(TestSource source) { + public Builder source(@Nullable TestSource source) { this.source = source; return this; } @Override - public Builder cause(Throwable cause) { + public Builder cause(@Nullable Throwable cause) { this.cause = cause; return this; } 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..adc0e8005b63 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 @@ -16,6 +16,7 @@ import java.util.function.UnaryOperator; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -138,7 +139,7 @@ default Builder source(Optional source) { * @param source the {@link TestSource} for the {@code DiscoveryIssue}; * may be {@code null} */ - Builder source(TestSource source); + Builder source(@Nullable TestSource source); /** * Set the {@link Throwable} that caused the {@code DiscoveryIssue}. @@ -157,7 +158,7 @@ default Builder cause(Optional cause) { * @param cause the {@link Throwable} that caused the * {@code DiscoveryIssue}; may be {@code null} */ - Builder cause(Throwable cause); + Builder cause(@Nullable Throwable cause); /** * Build the {@code DiscoveryIssue}. 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..3e429b6c4fb9 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 @@ -46,7 +46,8 @@ public interface EngineDiscoveryRequest { * Get the {@link DiscoverySelector DiscoverySelectors} for this request, * filtered by a particular type. * - * @param selectorType the type of {@link DiscoverySelector} to filter by + * @param selectorType the type of {@link DiscoverySelector} to filter by; + * never {@code null} * @return all selectors of this request that are instances of * {@code selectorType}; never {@code null} but potentially empty */ @@ -59,7 +60,8 @@ public interface EngineDiscoveryRequest { *

The returned filters are to be combined using AND semantics, i.e. all * of them have to include a resource for it to end up in the test plan. * - * @param filterType the type of {@link DiscoveryFilter} to filter by + * @param filterType the type of {@link DiscoveryFilter} to filter by; + * never {@code null} * @return all filters of this request that are instances of * {@code filterType}; never {@code null} but potentially empty */ 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..7bff6ea78605 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 @@ -16,6 +16,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.reporting.OutputDirectoryProvider; @@ -41,7 +42,11 @@ public class ExecutionRequest { private final TestDescriptor rootTestDescriptor; private final EngineExecutionListener engineExecutionListener; private final ConfigurationParameters configurationParameters; + + @Nullable private final OutputDirectoryProvider outputDirectoryProvider; + + @Nullable private final NamespacedHierarchicalStore requestLevelStore; @Deprecated @@ -52,8 +57,8 @@ public ExecutionRequest(TestDescriptor rootTestDescriptor, EngineExecutionListen } private ExecutionRequest(TestDescriptor rootTestDescriptor, EngineExecutionListener engineExecutionListener, - ConfigurationParameters configurationParameters, OutputDirectoryProvider outputDirectoryProvider, - NamespacedHierarchicalStore requestLevelStore) { + ConfigurationParameters configurationParameters, @Nullable OutputDirectoryProvider outputDirectoryProvider, + @Nullable NamespacedHierarchicalStore requestLevelStore) { this.rootTestDescriptor = Preconditions.notNull(rootTestDescriptor, "rootTestDescriptor must not be null"); this.engineExecutionListener = Preconditions.notNull(engineExecutionListener, "engineExecutionListener must not be null"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/FilterResult.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/FilterResult.java index b2bfae49122b..eabfcfe20815 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/FilterResult.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/FilterResult.java @@ -16,6 +16,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ToStringBuilder; /** @@ -32,7 +33,7 @@ public class FilterResult { * @param reason the reason why the filtered object was included * @return an included {@code FilterResult} with the given reason */ - public static FilterResult included(String reason) { + public static FilterResult included(@Nullable String reason) { return new FilterResult(true, reason); } @@ -42,14 +43,14 @@ public static FilterResult included(String reason) { * @param reason the reason why the filtered object was excluded * @return an excluded {@code FilterResult} with the given reason */ - public static FilterResult excluded(String reason) { + public static FilterResult excluded(@Nullable String reason) { return new FilterResult(false, reason); } /** * Factory for creating filter results based on the condition given. * - * @param included whether or not the filtered object should be included + * @param included whether the filtered object should be included * @return a valid {@code FilterResult} for the given condition */ public static FilterResult includedIf(boolean included) { @@ -59,13 +60,13 @@ public static FilterResult includedIf(boolean included) { /** * Factory for creating filter results based on the condition given. * - * @param included whether or not the filtered object should be included + * @param included whether the filtered object should be included * @param inclusionReasonSupplier supplier for the reason in case of inclusion * @param exclusionReasonSupplier supplier for the reason in case of exclusion * @return a valid {@code FilterResult} for the given condition */ - public static FilterResult includedIf(boolean included, Supplier inclusionReasonSupplier, - Supplier exclusionReasonSupplier) { + public static FilterResult includedIf(boolean included, Supplier<@Nullable String> inclusionReasonSupplier, + Supplier<@Nullable String> exclusionReasonSupplier) { return included ? included(inclusionReasonSupplier.get()) : excluded(exclusionReasonSupplier.get()); } @@ -73,7 +74,7 @@ public static FilterResult includedIf(boolean included, Supplier inclusi private final Optional reason; - private FilterResult(boolean included, String reason) { + private FilterResult(boolean included, @Nullable String reason) { this.included = included; this.reason = Optional.ofNullable(reason); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java index 105bf9d09e7d..2b2b1a2f0951 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java @@ -15,6 +15,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ToStringBuilder; /** @@ -86,9 +87,11 @@ public static SelectorResolutionResult failed(Throwable throwable) { } private final Status status; + + @Nullable private final Throwable throwable; - private SelectorResolutionResult(Status status, Throwable throwable) { + private SelectorResolutionResult(Status status, @Nullable Throwable throwable) { this.status = status; this.throwable = throwable; } 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 f3113a41be5a..e07b0d52ce89 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 @@ -22,6 +22,7 @@ import java.util.function.UnaryOperator; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -99,7 +100,7 @@ default String getLegacyReportingName() { * * @param parent the new parent of this descriptor; may be {@code null}. */ - void setParent(TestDescriptor parent); + void setParent(@Nullable TestDescriptor parent); /** * Get the immutable set of children of this descriptor. diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java index 4bd69d935d05..2052cf360459 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -77,7 +78,7 @@ public static TestExecutionResult successful() { * {@code null} * @return the {@code TestExecutionResult}; never {@code null} */ - public static TestExecutionResult aborted(Throwable throwable) { + public static TestExecutionResult aborted(@Nullable Throwable throwable) { return new TestExecutionResult(ABORTED, throwable); } @@ -89,14 +90,16 @@ public static TestExecutionResult aborted(Throwable throwable) { * {@code null} * @return the {@code TestExecutionResult}; never {@code null} */ - public static TestExecutionResult failed(Throwable throwable) { + public static TestExecutionResult failed(@Nullable Throwable throwable) { return new TestExecutionResult(FAILED, throwable); } private final Status status; + + @Nullable private final Throwable throwable; - private TestExecutionResult(Status status, Throwable throwable) { + private TestExecutionResult(Status status, @Nullable Throwable throwable) { this.status = Preconditions.notNull(status, "Status must not be null"); this.throwable = throwable; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index 70a04ce893dc..bf3ee3fc6d47 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -21,6 +21,7 @@ import java.util.Set; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; @@ -84,7 +85,7 @@ public final class TestTag implements Serializable { * @see #RESERVED_CHARACTERS * @see TestTag#create(String) */ - public static boolean isValid(String name) { + public static boolean isValid(@Nullable String name) { if (name == null) { return false; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java index 49d15a8bbb19..ce1bb7654029 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java @@ -23,6 +23,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -92,6 +93,7 @@ public static UniqueId root(String segmentType, String value) { private transient int hashCode; // lazily computed + @Nullable private transient SoftReference toString; private UniqueId(UniqueIdFormat uniqueIdFormat, Segment segment) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java index 63bb41729648..02ab768dc6f8 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java @@ -2,4 +2,7 @@ * Public API for test engines. */ +@NullMarked package org.junit.platform.engine; + +import org.jspecify.annotations.NullMarked; From 42b695a6ace309436182af03c08ccab1b1f27e62 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 10:48:54 +0200 Subject: [PATCH 097/521] Annotate nullability in `org.junit.platform.engine.discovery` --- .../engine/discovery/ClassSelector.java | 9 ++- .../discovery/ClasspathResourceSelector.java | 7 ++- .../DiscoverySelectorIdentifierParsers.java | 5 +- .../engine/discovery/DiscoverySelectors.java | 28 +++++----- .../engine/discovery/FilePosition.java | 3 + .../engine/discovery/FileSelector.java | 5 +- .../engine/discovery/MethodSelector.java | 55 ++++++++++--------- .../engine/discovery/NestedClassSelector.java | 6 +- .../discovery/NestedMethodSelector.java | 6 +- .../engine/discovery/package-info.java | 3 + 10 files changed, 80 insertions(+), 47 deletions(-) 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..a2ec7a37801a 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 @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.support.ReflectionSupport; @@ -47,12 +48,15 @@ @API(status = STABLE, since = "1.0") public class ClassSelector implements DiscoverySelector { + @Nullable private final ClassLoader classLoader; + private final String className; + @Nullable private Class javaClass; - ClassSelector(ClassLoader classLoader, String className) { + ClassSelector(@Nullable ClassLoader classLoader, String className) { this.className = className; this.classLoader = classLoader; } @@ -70,6 +74,7 @@ public class ClassSelector implements DiscoverySelector { * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") + @Nullable public ClassLoader getClassLoader() { return this.classLoader; } @@ -94,7 +99,7 @@ public Class getJavaClass() { Try> tryToLoadClass = this.classLoader == null ? ReflectionSupport.tryToLoadClass(this.className) : ReflectionSupport.tryToLoadClass(this.className, this.classLoader); - this.javaClass = tryToLoadClass.getOrThrow(cause -> + this.javaClass = tryToLoadClass.getNonNullOrThrow(cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); // @formatter:on } 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 052462be8e93..774b917d2267 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 @@ -21,6 +21,7 @@ import java.util.Set; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; import org.junit.platform.commons.support.Resource; @@ -55,10 +56,14 @@ public class ClasspathResourceSelector implements DiscoverySelector { private final String classpathResourceName; + + @Nullable private final FilePosition position; + + @Nullable private Set classpathResources; - ClasspathResourceSelector(String classpathResourceName, FilePosition position) { + ClasspathResourceSelector(String classpathResourceName, @Nullable FilePosition position) { boolean startsWithSlash = classpathResourceName.startsWith("/"); this.classpathResourceName = (startsWithSlash ? classpathResourceName.substring(1) : classpathResourceName); this.position = position; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java index 63aacfb900f0..f844100d44d6 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/DiscoverySelectorIdentifierParsers.java @@ -54,8 +54,9 @@ static Optional parse(String identifier) { static Optional parse(DiscoverySelectorIdentifier identifier) { Preconditions.notNull(identifier, "identifier must not be null"); - DiscoverySelectorIdentifierParser parser = Singleton.INSTANCE.parsersByPrefix.get(identifier.getPrefix()); - Preconditions.notNull(parser, "No parser for prefix: " + identifier.getPrefix()); + DiscoverySelectorIdentifierParser parser = Preconditions.notNull( + Singleton.INSTANCE.parsersByPrefix.get(identifier.getPrefix()), + "No parser for prefix: " + identifier.getPrefix()); return parser.parse(identifier, DiscoverySelectorIdentifierParsers::parse); } 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 5b0edccb7c3f..d65b7977ed1e 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 @@ -29,6 +29,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.support.Resource; @@ -153,7 +154,7 @@ public static FileSelector selectFile(File file) { * @see #selectDirectory(String) * @see #selectDirectory(File) */ - public static FileSelector selectFile(String path, FilePosition position) { + public static FileSelector selectFile(String path, @Nullable FilePosition position) { Preconditions.notBlank(path, "File path must not be null or blank"); return new FileSelector(path, position); } @@ -174,7 +175,7 @@ public static FileSelector selectFile(String path, FilePosition position) { * @see #selectDirectory(String) * @see #selectDirectory(File) */ - public static FileSelector selectFile(File file, FilePosition position) { + public static FileSelector selectFile(File file, @Nullable FilePosition position) { Preconditions.notNull(file, "File must not be null"); Preconditions.condition(file.isFile(), () -> "The supplied java.io.File [%s] must represent an existing file".formatted(file)); @@ -321,7 +322,7 @@ public static ClasspathResourceSelector selectClasspathResource(String classpath * @see ClassLoader#getResources(String) */ public static ClasspathResourceSelector selectClasspathResource(String classpathResourceName, - FilePosition position) { + @Nullable FilePosition position) { Preconditions.notBlank(classpathResourceName, "classpath resource name must not be null or blank"); return new ClasspathResourceSelector(classpathResourceName, position); } @@ -446,7 +447,7 @@ public static ClassSelector selectClass(String className) { * @see ClassSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static ClassSelector selectClass(ClassLoader classLoader, String className) { + public static ClassSelector selectClass(@Nullable ClassLoader classLoader, String className) { Preconditions.notBlank(className, "Class name must not be null or blank"); return new ClassSelector(classLoader, className); } @@ -514,7 +515,7 @@ public static MethodSelector selectMethod(String fullyQualifiedMethodName) throw * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static MethodSelector selectMethod(ClassLoader classLoader, String fullyQualifiedMethodName) + public static MethodSelector selectMethod(@Nullable ClassLoader classLoader, String fullyQualifiedMethodName) throws PreconditionViolationException { String[] methodParts = ReflectionUtils.parseFullyQualifiedMethodName(fullyQualifiedMethodName); return selectMethod(classLoader, methodParts[0], methodParts[1], methodParts[2]); @@ -546,7 +547,7 @@ public static MethodSelector selectMethod(String className, String methodName) { * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName) { + public static MethodSelector selectMethod(@Nullable ClassLoader classLoader, String className, String methodName) { return selectMethod(classLoader, className, methodName, ""); } @@ -590,7 +591,7 @@ public static MethodSelector selectMethod(String className, String methodName, S * @see MethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static MethodSelector selectMethod(ClassLoader classLoader, String className, String methodName, + public static MethodSelector selectMethod(@Nullable ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { Preconditions.notBlank(className, "Class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); @@ -731,8 +732,8 @@ public static NestedClassSelector selectNestedClass(List enclosingClassN * @see NestedClassSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static NestedClassSelector selectNestedClass(ClassLoader classLoader, List enclosingClassNames, - String nestedClassName) { + public static NestedClassSelector selectNestedClass(@Nullable ClassLoader classLoader, + List enclosingClassNames, String nestedClassName) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); return new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); @@ -767,8 +768,9 @@ public static NestedMethodSelector selectNestedMethod(List enclosingClas * @see NestedMethodSelector */ @API(status = EXPERIMENTAL, since = "1.10") - public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, - String nestedClassName, String methodName) throws PreconditionViolationException { + public static NestedMethodSelector selectNestedMethod(@Nullable ClassLoader classLoader, + List enclosingClassNames, String nestedClassName, String methodName) + throws PreconditionViolationException { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); Preconditions.notBlank(methodName, "Method name must not be null or blank"); @@ -815,8 +817,8 @@ public static NestedMethodSelector selectNestedMethod(List enclosingClas * @see #selectNestedMethod(List, String, String, String) */ @API(status = EXPERIMENTAL, since = "1.10") - public static NestedMethodSelector selectNestedMethod(ClassLoader classLoader, List enclosingClassNames, - String nestedClassName, String methodName, String parameterTypeNames) { + public static NestedMethodSelector selectNestedMethod(@Nullable ClassLoader classLoader, + List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { Preconditions.notEmpty(enclosingClassNames, "Enclosing class names must not be null or empty"); Preconditions.notBlank(nestedClassName, "Nested class name must not be null or blank"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java index 0383e03179fb..eed02fb5ecc7 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; @@ -121,6 +122,8 @@ else if (column == null && "column".equals(key)) { } private final int line; + + @Nullable private final Integer column; private FilePosition(int line) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java index cd59c69e7fbf..04f9ffb4c23c 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java @@ -21,6 +21,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; @@ -44,9 +45,11 @@ public class FileSelector implements DiscoverySelector { private final String path; + + @Nullable private final FilePosition position; - FileSelector(String path, FilePosition position) { + FileSelector(String path, @Nullable FilePosition position) { this.path = path; this.position = position; } 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 7817c0d1f6fe..22c3343dab73 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 @@ -19,6 +19,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.function.Try; @@ -59,19 +60,24 @@ @API(status = STABLE, since = "1.0") public class MethodSelector implements DiscoverySelector { + @Nullable private final ClassLoader classLoader; private final String className; private final String methodName; private final String parameterTypeNames; + @Nullable private volatile Class javaClass; + + @Nullable private volatile Method javaMethod; - private volatile Class[] parameterTypes; + + private volatile Class @Nullable [] parameterTypes; /** * @since 1.10 */ - MethodSelector(ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { + MethodSelector(@Nullable ClassLoader classLoader, String className, String methodName, String parameterTypeNames) { this.classLoader = classLoader; this.className = className; this.methodName = methodName; @@ -89,7 +95,7 @@ public class MethodSelector implements DiscoverySelector { /** * @since 1.10 */ - MethodSelector(ClassLoader classLoader, String className, String methodName, Class... parameterTypes) { + MethodSelector(@Nullable ClassLoader classLoader, String className, String methodName, Class... parameterTypes) { this.classLoader = classLoader; this.className = className; this.methodName = methodName; @@ -125,6 +131,7 @@ public class MethodSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ + @Nullable @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.classLoader; @@ -176,8 +183,7 @@ public String getParameterTypeNames() { * @see #getJavaMethod() */ public Class getJavaClass() { - lazyLoadJavaClass(); - return this.javaClass; + return lazyLoadJavaClass(); } /** @@ -190,8 +196,7 @@ public Class getJavaClass() { * @see #getJavaClass() */ public Method getJavaMethod() { - lazyLoadJavaMethod(); - return this.javaMethod; + return lazyLoadJavaMethod(); } /** @@ -211,48 +216,48 @@ public Method getJavaMethod() { */ @API(status = EXPERIMENTAL, since = "1.10") public Class[] getParameterTypes() { - lazyLoadParameterTypes(); - return this.parameterTypes.clone(); + return lazyLoadParameterTypes().clone(); } - private void lazyLoadJavaClass() { + private Class lazyLoadJavaClass() { // @formatter:off if (this.javaClass == null) { Try> tryToLoadClass = this.classLoader == null ? ReflectionSupport.tryToLoadClass(this.className) : ReflectionSupport.tryToLoadClass(this.className, this.classLoader); - this.javaClass = tryToLoadClass.getOrThrow(cause -> + this.javaClass = tryToLoadClass.getNonNullOrThrow(cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); } // @formatter:on + return this.javaClass; } - private void lazyLoadJavaMethod() { + private Method lazyLoadJavaMethod() { if (this.javaMethod == null) { - lazyLoadJavaClass(); - lazyLoadParameterTypes(); - if (this.parameterTypes.length > 0) { - this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName, - this.parameterTypes).orElseThrow( - () -> new PreconditionViolationException( - "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( - this.methodName, this.parameterTypeNames, this.javaClass.getName()))); + Class javaClass = lazyLoadJavaClass(); + var parameterTypes = lazyLoadParameterTypes(); + if (parameterTypes.length > 0) { + this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName, parameterTypes).orElseThrow( + () -> new PreconditionViolationException( + "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( + this.methodName, this.parameterTypeNames, javaClass.getName()))); } else { - this.javaMethod = ReflectionSupport.findMethod(this.javaClass, this.methodName).orElseThrow( + this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( "Could not find method with name [%s] in class [%s].".formatted(this.methodName, - this.javaClass.getName()))); + javaClass.getName()))); } } + return this.javaMethod; } - private void lazyLoadParameterTypes() { + private Class[] lazyLoadParameterTypes() { if (this.parameterTypes == null) { - lazyLoadJavaClass(); - this.parameterTypes = ReflectionUtils.resolveParameterTypes(this.javaClass, this.methodName, + this.parameterTypes = ReflectionUtils.resolveParameterTypes(lazyLoadJavaClass(), this.methodName, this.parameterTypeNames); } + return this.parameterTypes; } /** 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..46901b7c06f0 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 @@ -24,6 +24,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.DiscoverySelector; @@ -54,11 +55,13 @@ @API(status = STABLE, since = "1.6") public class NestedClassSelector implements DiscoverySelector { + @Nullable private final ClassLoader classLoader; + private final List enclosingClassSelectors; private final ClassSelector nestedClassSelector; - NestedClassSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName) { + NestedClassSelector(@Nullable ClassLoader classLoader, List enclosingClassNames, String nestedClassName) { this.classLoader = classLoader; this.enclosingClassSelectors = enclosingClassNames.stream() // .map(className -> new ClassSelector(classLoader, className)) // @@ -78,6 +81,7 @@ public class NestedClassSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ + @Nullable @API(status = EXPERIMENTAL, since = "1.10") 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 7d57ec1751ec..bd0353b1a5bb 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 @@ -21,6 +21,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.ToStringBuilder; @@ -60,7 +61,7 @@ public class NestedMethodSelector implements DiscoverySelector { private final NestedClassSelector nestedClassSelector; private final MethodSelector methodSelector; - NestedMethodSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, + NestedMethodSelector(@Nullable ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, String parameterTypeNames) { this.nestedClassSelector = new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); this.methodSelector = new MethodSelector(classLoader, nestedClassName, methodName, parameterTypeNames); @@ -69,7 +70,7 @@ public class NestedMethodSelector implements DiscoverySelector { /** * @since 1.10 */ - NestedMethodSelector(ClassLoader classLoader, List enclosingClassNames, String nestedClassName, + NestedMethodSelector(@Nullable ClassLoader classLoader, List enclosingClassNames, String nestedClassName, String methodName, Class... parameterTypes) { this.nestedClassSelector = new NestedClassSelector(classLoader, enclosingClassNames, nestedClassName); this.methodSelector = new MethodSelector(classLoader, nestedClassName, methodName, parameterTypes); @@ -100,6 +101,7 @@ public class NestedMethodSelector implements DiscoverySelector { * * @since 1.10 */ + @Nullable @API(status = EXPERIMENTAL, since = "1.10") public ClassLoader getClassLoader() { return this.nestedClassSelector.getClassLoader(); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java index 55321771b8e4..9f8135af9449 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java @@ -4,4 +4,7 @@ * {@linkplain org.junit.platform.engine.EngineDiscoveryRequest discovery requests}. */ +@NullMarked package org.junit.platform.engine.discovery; + +import org.jspecify.annotations.NullMarked; From abc58f53e537df90aeea51688e4207a5b385f567 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 10:50:33 +0200 Subject: [PATCH 098/521] Annotate nullability in `org.junit.platform.engine.reporting` --- .../org/junit/platform/engine/reporting/FileEntry.java | 7 +++++-- .../org/junit/platform/engine/reporting/package-info.java | 3 +++ 2 files changed, 8 insertions(+), 2 deletions(-) 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..2c74c860c7c3 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 @@ -17,6 +17,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -38,15 +39,17 @@ public final class FileEntry { * @param mediaType the media type of the path to publish; may be * {@code null} */ - public static FileEntry from(Path path, String mediaType) { + public static FileEntry from(Path path, @Nullable String mediaType) { return new FileEntry(path, mediaType); } private final LocalDateTime timestamp = LocalDateTime.now(); private final Path path; + + @Nullable private final String mediaType; - private FileEntry(Path path, String mediaType) { + private FileEntry(Path path, @Nullable String mediaType) { this.path = Preconditions.notNull(path, "path must not be null"); this.mediaType = mediaType; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java index 11965058d1ab..6cafad5c020e 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java @@ -3,4 +3,7 @@ * listeners. */ +@NullMarked package org.junit.platform.engine.reporting; + +import org.jspecify.annotations.NullMarked; From 8aec161387a8725ed60f33ea210f6620607cdaf4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 11:55:21 +0200 Subject: [PATCH 099/521] Enable and fail on all compile warnings in test fixtures --- ...tbuild.java-library-conventions.gradle.kts | 7 ++++++- ...nerWithCustomUniqueIdsAndDisplayNames.java | 9 --------- .../vintage/engine/samples/junit4/Label.java | 20 +++++++++++++++++++ 3 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/Label.java 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 d8d6c70a810a..9c8b4ba5b31a 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 @@ -1,5 +1,5 @@ + import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar -import junitbuild.extensions.javaModuleName import junitbuild.extensions.isSnapshot import org.gradle.plugins.ide.eclipse.model.Classpath import org.gradle.plugins.ide.eclipse.model.Library @@ -279,5 +279,10 @@ pluginManager.withPlugin("java-test-fixtures") { } tasks.named("compileTestFixturesJava") { options.release = extension.testJavaVersion.map { it.majorVersion.toInt() } + options.compilerArgs.addAll(listOf( + "-Xlint:all", // Enables all recommended warnings. + "-Werror", // Terminates compilation when warnings occur. + "-parameters" // Generates metadata for reflection on method parameters. + )) } } diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java index 07dab7575284..b8a91e6d2a2d 100644 --- a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/JUnit4TestCaseWithRunnerWithCustomUniqueIdsAndDisplayNames.java @@ -10,10 +10,6 @@ package org.junit.vintage.engine.samples.junit4; -import static java.lang.annotation.RetentionPolicy.RUNTIME; - -import java.lang.annotation.Retention; - import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; @@ -32,8 +28,3 @@ public void test() { } } - -@Retention(RUNTIME) -@interface Label { - String value(); -} diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/Label.java b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/Label.java new file mode 100644 index 000000000000..5450edc8bb8c --- /dev/null +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/Label.java @@ -0,0 +1,20 @@ +/* + * 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.vintage.engine.samples.junit4; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; + +@Retention(RUNTIME) +@interface Label { + String value(); +} From c8549c0c026a4de9d58dcd62ed7f9f6fa581a580 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 12:26:18 +0200 Subject: [PATCH 100/521] Annotate nullability in `org.junit.platform.fakes` --- .../java/org/junit/platform/fakes/TestEngineSpy.java | 2 ++ .../java/org/junit/platform/fakes/package-info.java | 5 +++++ 2 files changed, 7 insertions(+) create mode 100644 junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/package-info.java diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java index 7754c75f411b..040fe144e446 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java @@ -10,6 +10,7 @@ package org.junit.platform.fakes; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -23,6 +24,7 @@ public class TestEngineSpy implements TestEngine { private final String id; + @Nullable public ExecutionRequest requestForExecution; public TestEngineSpy() { diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/package-info.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/package-info.java new file mode 100644 index 000000000000..fae5df1a599a --- /dev/null +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package org.junit.platform.fakes; + +import org.jspecify.annotations.NullMarked; From 874ef281e12deb228eec5663b1f83ed80bb9b8f7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 12:28:30 +0200 Subject: [PATCH 101/521] Treat root package and all subpackages as `@NullMarked` * For NullAway, the config is now in the build setup because it doesn't yet support module descriptors (see uber/NullAway#1083) * For IntelliJ, the config is now in the module descriptors --- CONTRIBUTING.md | 11 +++++++++++ ...junitbuild.java-nullability-conventions.gradle.kts | 3 ++- junit-platform-commons/src/main/java/module-info.java | 3 +++ .../platform/commons/annotation/package-info.java | 3 --- .../junit/platform/commons/function/package-info.java | 3 --- .../junit/platform/commons/logging/package-info.java | 3 --- .../java/org/junit/platform/commons/package-info.java | 3 --- .../commons/support/conversion/package-info.java | 3 --- .../junit/platform/commons/support/package-info.java | 3 --- .../commons/support/scanning/package-info.java | 3 --- .../org/junit/platform/commons/util/package-info.java | 3 --- junit-platform-engine/src/main/java/module-info.java | 3 +++ .../junit/platform/engine/discovery/package-info.java | 3 --- .../java/org/junit/platform/engine/package-info.java | 3 --- .../junit/platform/engine/reporting/package-info.java | 3 --- .../platform/engine/support/config/package-info.java | 3 --- .../engine/support/descriptor/package-info.java | 3 --- .../engine/support/discovery/package-info.java | 3 --- .../engine/support/hierarchical/package-info.java | 3 --- .../platform/engine/support/store/package-info.java | 3 --- 20 files changed, 19 insertions(+), 49 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 072b521a24c5..e4184c29e388 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -120,6 +120,17 @@ See [`ExtensionContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/e [`ParameterContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterContext.java) for example Javadoc. +### Nullability + +This project uses JSpecify's annotation to indicate nullability. In general, the approach +is as follows: + +- The Gradle build is set up to treat all code as being `@NullMarked` +- The descriptor of each module is annotated with `@NullMarked` for IDEs such as IntelliJ + IDEA to treat code correctly. +- Fields, parameters, return types etc. may be annotated with `@Nullable` +- A package can be excluded (temporarily) using `@NullUnmarked` + ### Tests #### Naming diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index dbc7f58e2e8b..e4e112a68372 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -1,4 +1,5 @@ import junitbuild.extensions.dependencyFromLibs +import junitbuild.extensions.javaModuleName import net.ltgt.gradle.errorprone.errorprone plugins { @@ -13,7 +14,7 @@ dependencies { } nullaway { - onlyNullMarked = true + annotatedPackages.add(javaModuleName) } tasks.withType().configureEach { diff --git a/junit-platform-commons/src/main/java/module-info.java b/junit-platform-commons/src/main/java/module-info.java index 092c654cdd51..c902b3da89c1 100644 --- a/junit-platform-commons/src/main/java/module-info.java +++ b/junit-platform-commons/src/main/java/module-info.java @@ -8,11 +8,14 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Common APIs and support utilities for the JUnit Platform. * * @since 1.0 */ +@NullMarked module org.junit.platform.commons { requires java.logging; requires java.management; // needed by RuntimeUtils to determine input arguments diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java index 1221aebb8f50..f5f0eaf51493 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java @@ -2,7 +2,4 @@ * Common annotations for the JUnit Platform. */ -@NullMarked package org.junit.platform.commons.annotation; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java index 79d053801103..8f031faf22e0 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java @@ -2,7 +2,4 @@ * Functional interfaces and support classes. */ -@NullMarked package org.junit.platform.commons.function; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java index 9fe567592387..75260c34a99a 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java @@ -8,7 +8,4 @@ * Use at your own risk! */ -@NullMarked package org.junit.platform.commons.logging; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java index 18945b31c25e..66e1cf2aa51c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java @@ -8,7 +8,4 @@ * APIs by external parties is not supported! */ -@NullMarked package org.junit.platform.commons; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java index 79ba440a7609..18807d6a4e90 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java @@ -2,7 +2,4 @@ * Conversion APIs provided by the JUnit Platform. */ -@NullMarked package org.junit.platform.commons.support.conversion; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java index 68a77ec1bf22..fae0c2a81547 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java @@ -8,7 +8,4 @@ * extensions with the same semantics as within the JUnit Platform itself. */ -@NullMarked package org.junit.platform.commons.support; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java index 2da61c5d8ce9..769733a65aef 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java @@ -2,7 +2,4 @@ * Classpath scanning APIs provided by the JUnit Platform. */ -@NullMarked package org.junit.platform.commons.support.scanning; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java index 3d9e974b50f9..119940686c89 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java @@ -8,7 +8,4 @@ * Use at your own risk! */ -@NullMarked package org.junit.platform.commons.util; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/module-info.java b/junit-platform-engine/src/main/java/module-info.java index c81836121c9c..ad2b0934cf48 100644 --- a/junit-platform-engine/src/main/java/module-info.java +++ b/junit-platform-engine/src/main/java/module-info.java @@ -8,6 +8,8 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Public API for test engines. * @@ -16,6 +18,7 @@ * * @since 1.0 */ +@NullMarked module org.junit.platform.engine { requires static transitive org.apiguardian.api; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java index 9f8135af9449..55321771b8e4 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java @@ -4,7 +4,4 @@ * {@linkplain org.junit.platform.engine.EngineDiscoveryRequest discovery requests}. */ -@NullMarked package org.junit.platform.engine.discovery; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java index 02ab768dc6f8..63bb41729648 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java @@ -2,7 +2,4 @@ * Public API for test engines. */ -@NullMarked package org.junit.platform.engine; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java index 6cafad5c020e..11965058d1ab 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java @@ -3,7 +3,4 @@ * listeners. */ -@NullMarked package org.junit.platform.engine.reporting; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java index 76d01748f8e3..05f555a220ea 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java @@ -3,7 +3,4 @@ * classes intended to be used by test engine implementations. */ -@NullMarked package org.junit.platform.engine.support.config; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java index eabc3dab0055..9f063532a19a 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java @@ -4,7 +4,4 @@ * the launcher. */ -@NullMarked package org.junit.platform.engine.support.descriptor; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java index 3d6b8dd4a0aa..1f0ea1ff308a 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java @@ -6,7 +6,4 @@ * @see org.junit.platform.engine.support.discovery.SelectorResolver */ -@NullMarked package org.junit.platform.engine.support.discovery; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java index 925cfac6bfec..033745ba7795 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java @@ -5,7 +5,4 @@ * {@link org.junit.platform.engine.support.hierarchical.Node} abstraction. */ -@NullMarked package org.junit.platform.engine.support.hierarchical; - -import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java index e754a7b508de..d40e1e88e974 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java @@ -2,7 +2,4 @@ * Reusable data structures for test engines and their extensions. */ -@NullMarked package org.junit.platform.engine.support.store; - -import org.jspecify.annotations.NullMarked; From cb77a6d1e829e925b7d26fc579488965417dea0a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 12:46:32 +0200 Subject: [PATCH 102/521] Enable NullAway in junit-platform-suite-api --- junit-platform-suite-api/junit-platform-suite-api.gradle.kts | 2 ++ junit-platform-suite-api/src/main/java/module-info.java | 3 +++ 2 files changed, 5 insertions(+) diff --git a/junit-platform-suite-api/junit-platform-suite-api.gradle.kts b/junit-platform-suite-api/junit-platform-suite-api.gradle.kts index cc5eb1d08bb7..a5f73150fae6 100644 --- a/junit-platform-suite-api/junit-platform-suite-api.gradle.kts +++ b/junit-platform-suite-api/junit-platform-suite-api.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") } description = "JUnit Platform Suite API" @@ -9,6 +10,7 @@ dependencies { api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) diff --git a/junit-platform-suite-api/src/main/java/module-info.java b/junit-platform-suite-api/src/main/java/module-info.java index 9d8df8da3cf0..acb1f901d834 100644 --- a/junit-platform-suite-api/src/main/java/module-info.java +++ b/junit-platform-suite-api/src/main/java/module-info.java @@ -8,11 +8,14 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Annotations for configuring a test suite on the JUnit Platform. * * @since 1.0 */ +@NullMarked module org.junit.platform.suite.api { requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; From eee971fa452e70e92345e25cc6a1b3d77bd76af0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 12:51:48 +0200 Subject: [PATCH 103/521] Enable NullAway in junit-platform-suite-commons --- .../junit-platform-suite-commons.gradle.kts | 2 ++ .../src/main/java/module-info.java | 3 +++ .../SuiteLauncherDiscoveryRequestBuilder.java | 18 ++++++++++++------ 3 files changed, 17 insertions(+), 6 deletions(-) diff --git a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts index fdc4062f36ce..cb43e5d6963c 100644 --- a/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts +++ b/junit-platform-suite-commons/junit-platform-suite-commons.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") } description = "JUnit Platform Suite Commons" @@ -9,6 +10,7 @@ dependencies { api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) implementation(projects.junitPlatformEngine) implementation(projects.junitPlatformSuiteApi) diff --git a/junit-platform-suite-commons/src/main/java/module-info.java b/junit-platform-suite-commons/src/main/java/module-info.java index 52c508bdace7..ddb988a135e2 100644 --- a/junit-platform-suite-commons/src/main/java/module-info.java +++ b/junit-platform-suite-commons/src/main/java/module-info.java @@ -8,11 +8,14 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Common support utilities for declarative test suites. * * @since 1.8 */ +@NullMarked module org.junit.platform.suite.commons { requires static transitive org.apiguardian.api; requires org.junit.platform.suite.api; diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java index 292a2aea605e..8176e6b070a5 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java @@ -32,6 +32,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.ConfigurationParameters; @@ -120,7 +121,10 @@ public final class SuiteLauncherDiscoveryRequestBuilder { private final Set selectedClassNames = new LinkedHashSet<>(); private boolean includeClassNamePatternsUsed; private boolean filterStandardClassNamePatterns = false; + + @Nullable private ConfigurationParameters parentConfigurationParameters; + private boolean enableParentConfigurationParameters = true; private SuiteLauncherDiscoveryRequestBuilder() { @@ -516,14 +520,16 @@ private static MethodSelector toMethodSelectorFromFQMN(Class suiteClass, Sele return DiscoverySelectors.selectMethod(annotation.value()); } - private static MethodSelector toMethodSelector(Class suiteClass, Class type, String typeName, - Class[] parameterTypes, String methodName, String parameterTypeNames) { + private static MethodSelector toMethodSelector(Class suiteClass, @Nullable Class type, + @Nullable String typeName, Class @Nullable [] parameterTypes, String methodName, + String parameterTypeNames) { if (type == null) { - Preconditions.notBlank(typeName, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, - "type must be set or type name must not be blank")); + String nonBlankTypeName = Preconditions.notBlank(typeName, + () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, + "type must be set or type name must not be blank")); return parameterTypes == null // - ? DiscoverySelectors.selectMethod(typeName, methodName, parameterTypeNames) // - : DiscoverySelectors.selectMethod(typeName, methodName, parameterTypes); + ? DiscoverySelectors.selectMethod(nonBlankTypeName, methodName, parameterTypeNames) // + : DiscoverySelectors.selectMethod(nonBlankTypeName, methodName, parameterTypes); } else { Preconditions.condition(typeName == null, () -> prefixErrorMessageForInvalidSelectMethodUsage(suiteClass, From d4ecf774d05623b839d2c208c829b6a5c64d8631 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 12:57:35 +0200 Subject: [PATCH 104/521] Enable NullAway in junit-platform-suite-engine --- .../junit-platform-suite-engine.gradle.kts | 2 ++ .../src/main/java/module-info.java | 3 +++ .../suite/engine/SuiteTestDescriptor.java | 19 +++++++++++++------ 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts b/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts index 36abcdbc088d..7e777400ca8b 100644 --- a/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts +++ b/junit-platform-suite-engine/junit-platform-suite-engine.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") } description = "JUnit Platform Suite Engine" @@ -10,6 +11,7 @@ dependencies { api(projects.junitPlatformSuiteApi) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) implementation(projects.junitPlatformSuiteCommons) diff --git a/junit-platform-suite-engine/src/main/java/module-info.java b/junit-platform-suite-engine/src/main/java/module-info.java index e8a43bf80e1c..779dc9cf0349 100644 --- a/junit-platform-suite-engine/src/main/java/module-info.java +++ b/junit-platform-suite-engine/src/main/java/module-info.java @@ -8,6 +8,8 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Provides a {@link org.junit.platform.engine.TestEngine} for running * declarative test suites. @@ -15,6 +17,7 @@ * @since 1.8 * @provides org.junit.platform.engine.TestEngine */ +@NullMarked module org.junit.platform.suite.engine { requires static org.apiguardian.api; requires org.junit.platform.suite.api; diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index 0ab81c9e3836..79ba4a9630de 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -10,6 +10,7 @@ package org.junit.platform.suite.engine; +import static java.util.Objects.requireNonNull; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.joining; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; @@ -21,6 +22,7 @@ import java.util.function.BiFunction; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.Preconditions; @@ -71,7 +73,10 @@ final class SuiteTestDescriptor extends AbstractTestDescriptor { private final Class suiteClass; private final LifecycleMethods lifecycleMethods; + @Nullable private LauncherDiscoveryResult launcherDiscoveryResult; + + @Nullable private SuiteLauncher launcher; SuiteTestDescriptor(UniqueId id, Class suiteClass, ConfigurationParameters configurationParameters, @@ -174,6 +179,7 @@ private void executeBeforeSuiteMethods(ThrowableCollector throwableCollector) { } } + @Nullable private TestExecutionSummary executeTests(EngineExecutionListener parentEngineExecutionListener, NamespacedHierarchicalStore requestLevelStore, ThrowableCollector throwableCollector) { if (throwableCollector.isNotEmpty()) { @@ -183,9 +189,9 @@ private TestExecutionSummary executeTests(EngineExecutionListener parentEngineEx // #2838: The discovery result from a suite may have been filtered by // post discovery filters from the launcher. The discovery result should // be pruned accordingly. - LauncherDiscoveryResult discoveryResult = this.launcherDiscoveryResult.withRetainedEngines( + LauncherDiscoveryResult discoveryResult = requireNonNull(this.launcherDiscoveryResult).withRetainedEngines( getChildren()::contains); - return launcher.execute(discoveryResult, parentEngineExecutionListener, requestLevelStore); + return requireNonNull(launcher).execute(discoveryResult, parentEngineExecutionListener, requestLevelStore); } private void executeAfterSuiteMethods(ThrowableCollector throwableCollector) { @@ -194,12 +200,13 @@ private void executeAfterSuiteMethods(ThrowableCollector throwableCollector) { } } - private TestExecutionResult computeTestExecutionResult(TestExecutionSummary summary, + private TestExecutionResult computeTestExecutionResult(@Nullable TestExecutionSummary summary, ThrowableCollector throwableCollector) { - if (throwableCollector.isNotEmpty()) { - return TestExecutionResult.failed(throwableCollector.getThrowable()); + var throwable = throwableCollector.getThrowable(); + if (throwable != null) { + return TestExecutionResult.failed(throwable); } - if (failIfNoTests && summary.getTestsFoundCount() == 0) { + if (failIfNoTests && requireNonNull(summary).getTestsFoundCount() == 0) { return TestExecutionResult.failed(new NoTestsDiscoveredException(suiteClass)); } return TestExecutionResult.successful(); From 0609c8798dc4d5f11c814353125e2efbaba4e8fe Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 13:22:43 +0200 Subject: [PATCH 105/521] Enable NullAway in junit-vintage-engine --- junit-vintage-engine/junit-vintage-engine.gradle.kts | 7 ++++++- junit-vintage-engine/src/main/java/module-info.java | 3 +++ .../vintage/engine/descriptor/DescriptionUtils.java | 2 ++ .../engine/descriptor/RunnerTestDescriptor.java | 3 +++ .../engine/descriptor/TestSourceProvider.java | 3 +++ .../engine/descriptor/VintageTestDescriptor.java | 6 ++++-- .../DefensiveAllDefaultPossibilitiesBuilder.java | 4 ++++ .../engine/discovery/MethodSelectorResolver.java | 2 +- .../vintage/engine/discovery/UniqueIdFilter.java | 5 +++++ .../org/junit/vintage/engine/execution/TestRun.java | 12 +++++++++--- .../vintage/engine/execution/VintageExecutor.java | 3 ++- .../vintage/engine/samples/junit4/package-info.java | 5 +++++ 12 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/package-info.java diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index af2455f46c31..9eef3cf490fc 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") `java-test-fixtures` @@ -14,6 +15,7 @@ dependencies { api(libs.junit4) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) testFixturesApi(platform(libs.groovy2.bom)) testFixturesApi(libs.spock1) @@ -43,10 +45,13 @@ tasks { bundle { val junit4Min = libs.versions.junit4Min.get() val version = project.version + val importAPIGuardian: String by extra + val importJSpecify: String by extra bnd(""" # Import JUnit4 packages with a version Import-Package: \ - ${extra["importAPIGuardian"]},\ + ${importAPIGuardian},\ + ${importJSpecify},\ junit.runner;version="[${junit4Min},5)",\ org.junit;version="[${junit4Min},5)",\ org.junit.experimental.categories;version="[${junit4Min},5)",\ diff --git a/junit-vintage-engine/src/main/java/module-info.java b/junit-vintage-engine/src/main/java/module-info.java index 6880a39df91d..dbc7a87af0d1 100644 --- a/junit-vintage-engine/src/main/java/module-info.java +++ b/junit-vintage-engine/src/main/java/module-info.java @@ -8,6 +8,8 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Provides a {@link org.junit.platform.engine.TestEngine} for running JUnit 3 * and 4 based tests on the platform. @@ -16,6 +18,7 @@ * @provides org.junit.platform.engine.TestEngine The {@code VintageTestEngine} * runs JUnit 3 and 4 based tests on the platform. */ +@NullMarked module org.junit.vintage.engine { requires junit; // 4 requires static org.apiguardian.api; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java index a55ffd3c572f..23f50a48387c 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java @@ -11,6 +11,7 @@ package org.junit.vintage.engine.descriptor; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.runner.Description; @API(status = API.Status.INTERNAL, since = "5.8") @@ -19,6 +20,7 @@ public class DescriptionUtils { private DescriptionUtils() { } + @Nullable public static String getMethodName(Description description) { String displayName = description.getDisplayName(); int i = displayName.indexOf('('); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java index dfe014468d7f..d5d55a8176dc 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/RunnerTestDescriptor.java @@ -26,6 +26,7 @@ import java.util.function.Consumer; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; @@ -54,6 +55,8 @@ public class RunnerTestDescriptor extends VintageTestDescriptor { private Runner runner; private final boolean ignored; private boolean wasFiltered; + + @Nullable private List filters = new ArrayList<>(); public RunnerTestDescriptor(UniqueId uniqueId, Class testClass, Runner runner, boolean ignored) { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java index 2037f7aeb8d8..a8973bf6a0d8 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java @@ -24,6 +24,7 @@ import java.util.concurrent.ConcurrentHashMap; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.support.ModifierSupport; import org.junit.platform.commons.util.LruCache; import org.junit.platform.engine.TestSource; @@ -44,6 +45,7 @@ public class TestSourceProvider { private final Map testSourceCache = new ConcurrentHashMap<>(); private final Map, List> methodsCache = synchronizedMap(new LruCache<>(31)); + @Nullable public TestSource findTestSource(Description description) { TestSource testSource = testSourceCache.computeIfAbsent(description, this::computeTestSource); return testSource == NULL_SOURCE ? null : testSource; @@ -72,6 +74,7 @@ private String sanitizeMethodName(String methodName) { return methodName; } + @Nullable private Method findMethod(Class testClass, String methodName) { List methods = methodsCache.computeIfAbsent(testClass, clazz -> findMethods(clazz, m -> true, TOP_DOWN)).stream() // diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/VintageTestDescriptor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/VintageTestDescriptor.java index 47319da6e3b6..d9ad9ea0ac73 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/VintageTestDescriptor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/VintageTestDescriptor.java @@ -23,6 +23,7 @@ import java.util.Set; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.experimental.categories.Category; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; @@ -45,15 +46,16 @@ public class VintageTestDescriptor extends AbstractTestDescriptor { protected Description description; - public VintageTestDescriptor(UniqueId uniqueId, Description description, TestSource source) { + public VintageTestDescriptor(UniqueId uniqueId, Description description, @Nullable TestSource source) { this(uniqueId, description, generateDisplayName(description), source); } - VintageTestDescriptor(UniqueId uniqueId, Description description, String displayName, TestSource source) { + VintageTestDescriptor(UniqueId uniqueId, Description description, String displayName, @Nullable TestSource source) { super(uniqueId, displayName, source); this.description = description; } + @SuppressWarnings("NullAway") private static String generateDisplayName(Description description) { String methodName = DescriptionUtils.getMethodName(description); return isNotBlank(methodName) ? methodName : description.getDisplayName(); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java index db80b987d897..dceb9cce4461 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java @@ -13,6 +13,7 @@ import java.lang.reflect.Method; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.Ignore; import org.junit.internal.builders.AllDefaultPossibilitiesBuilder; import org.junit.internal.builders.AnnotatedBuilder; @@ -108,6 +109,7 @@ private static class DefensiveAnnotatedBuilder extends AnnotatedBuilder { super(suiteBuilder); } + @Nullable @Override public Runner buildRunner(Class runnerClass, Class testClass) throws Exception { // Referenced by name because it might not be available at runtime. @@ -127,6 +129,7 @@ private static class DefensiveJUnit4Builder extends JUnit4Builder { private static final Predicate isPotentialJUnit4TestMethod = new IsPotentialJUnit4TestMethod(); + @Nullable @Override public Runner runnerForClass(Class testClass) throws Throwable { if (containsTestMethods(testClass)) { @@ -146,6 +149,7 @@ private boolean containsTestMethods(Class testClass) { * @since 5.1 */ private static class NullIgnoredBuilder extends IgnoredBuilder { + @Nullable @Override public Runner runnerForClass(Class testClass) { // don't ignore entire test classes just yet diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java index 4f86e78b6579..1e14ea908c7c 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/MethodSelectorResolver.java @@ -107,7 +107,7 @@ public boolean shouldRun(Description description) { private boolean isParameterizedMethod(Description description) { String methodName = DescriptionUtils.getMethodName(description); - return methodName.startsWith(desiredMethodName + "["); + return methodName != null && methodName.startsWith(desiredMethodName + "["); } @Override diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java index a6d15af76b80..427bcae80943 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java @@ -18,6 +18,7 @@ import java.util.Optional; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.runner.Description; @@ -33,7 +34,10 @@ class UniqueIdFilter extends Filter { private final RunnerTestDescriptor runnerTestDescriptor; private final UniqueId uniqueId; + @Nullable private Deque path; + + @Nullable private Set descendants; UniqueIdFilter(RunnerTestDescriptor runnerTestDescriptor, UniqueId uniqueId) { @@ -74,6 +78,7 @@ private Set determineDescendants(Optional } @Override + @SuppressWarnings({ "NullAway", "DataFlowIssue" }) public boolean shouldRun(Description description) { ensureInitialized(); return path.contains(description) || descendants.contains(description); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java index dd9ba6d31e21..8ddde9d15c66 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java @@ -11,6 +11,7 @@ package org.junit.vintage.engine.execution; import static java.util.Collections.emptyList; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; @@ -123,7 +124,7 @@ private Optional lookupUnambiguouslyOrApplyFallback(Descr void markSkipped(TestDescriptor testDescriptor) { skippedDescriptors.add(testDescriptor); if (testDescriptor instanceof VintageTestDescriptor vintageDescriptor) { - descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); + getVintageDescriptors(vintageDescriptor).incrementSkippedOrStarted(); } } @@ -140,10 +141,15 @@ void markStarted(TestDescriptor testDescriptor, EventType eventType) { startedDescriptors.add(testDescriptor); if (testDescriptor instanceof VintageTestDescriptor vintageDescriptor) { inProgressDescriptorsByStartingThread.get().addLast(vintageDescriptor); - descriptionToDescriptors.get(vintageDescriptor.getDescription()).incrementSkippedOrStarted(); + getVintageDescriptors(vintageDescriptor).incrementSkippedOrStarted(); } } + private VintageDescriptors getVintageDescriptors(VintageTestDescriptor vintageDescriptor) { + return requireNonNull(descriptionToDescriptors.get(vintageDescriptor.getDescription()), + () -> "No descriptors for " + vintageDescriptor); + } + boolean isNotStarted(TestDescriptor testDescriptor) { return !startedDescriptors.contains(testDescriptor); } @@ -191,7 +197,7 @@ TestExecutionResult getStoredResultOrSuccessful(TestDescriptor testDescriptor) { List failures = testExecutionResults .stream() .map(TestExecutionResult::getThrowable) - .map(Optional::get) + .map(Optional::orElseThrow) .collect(toList()); // @formatter:on MultipleFailuresError multipleFailuresError = new MultipleFailuresError("", failures); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java index 0ca61c6655fe..64bc1dc03b1a 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java @@ -10,6 +10,7 @@ package org.junit.vintage.engine.execution; +import static java.util.Objects.requireNonNullElse; import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.vintage.engine.Constants.PARALLEL_CLASS_EXECUTION; @@ -165,7 +166,7 @@ private boolean executeClassesInParallel(List runnerTestDe wasInterrupted = true; } catch (ExecutionException e) { - throw ExceptionUtils.throwAsUncheckedException(e.getCause()); + throw ExceptionUtils.throwAsUncheckedException(requireNonNullElse(e.getCause(), e)); } finally { shutdownExecutorService(executorService); diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/package-info.java b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/package-info.java new file mode 100644 index 000000000000..678ca9e2e64c --- /dev/null +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/package-info.java @@ -0,0 +1,5 @@ + +@NullUnmarked +package org.junit.vintage.engine.samples.junit4; + +import org.jspecify.annotations.NullUnmarked; From 9e0434c0f50a679bd52fe6409ec8ff67918bd155 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 13:24:59 +0200 Subject: [PATCH 106/521] Let NullAway handle assertions in test code --- .../junitbuild.java-nullability-conventions.gradle.kts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index e4e112a68372..d14b72f7904b 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -1,6 +1,7 @@ import junitbuild.extensions.dependencyFromLibs import junitbuild.extensions.javaModuleName import net.ltgt.gradle.errorprone.errorprone +import net.ltgt.gradle.nullaway.nullaway plugins { `java-library` @@ -23,3 +24,9 @@ tasks.withType().configureEach { enable("NullAway") } } + +tasks.compileTestJava { + options.errorprone.nullaway { + handleTestAssertionLibraries = true + } +} From 639325fd0c24d43bcf87846841f5b77e89398dc1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 14:11:23 +0200 Subject: [PATCH 107/521] Enable NullAway in junit-platform-testkit --- .../junit-platform-testkit.gradle.kts | 2 ++ .../src/main/java/module-info.java | 3 +++ .../platform/testkit/engine/EngineTestKit.java | 4 +++- .../org/junit/platform/testkit/engine/Event.java | 7 +++++-- .../platform/testkit/engine/EventConditions.java | 2 +- .../org/junit/platform/testkit/engine/Events.java | 2 ++ .../platform/testkit/engine/TerminationInfo.java | 13 ++++++++++--- 7 files changed, 26 insertions(+), 7 deletions(-) diff --git a/junit-platform-testkit/junit-platform-testkit.gradle.kts b/junit-platform-testkit/junit-platform-testkit.gradle.kts index 38e89344db34..7cb29ac6f662 100644 --- a/junit-platform-testkit/junit-platform-testkit.gradle.kts +++ b/junit-platform-testkit/junit-platform-testkit.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") } description = "JUnit Platform Test Kit" @@ -11,6 +12,7 @@ dependencies { api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) diff --git a/junit-platform-testkit/src/main/java/module-info.java b/junit-platform-testkit/src/main/java/module-info.java index 58f2033bcf62..4e74f159445f 100644 --- a/junit-platform-testkit/src/main/java/module-info.java +++ b/junit-platform-testkit/src/main/java/module-info.java @@ -8,12 +8,15 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Defines the Test Kit API for the JUnit Platform. * * @since 1.4 * @uses org.junit.platform.engine.TestEngine */ +@NullMarked module org.junit.platform.testkit { requires static transitive org.apiguardian.api; requires transitive org.assertj.core; 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 9732fda836c1..96e8fbcad24f 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 @@ -25,6 +25,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.CollectionUtils; @@ -276,7 +277,8 @@ private static void withRequestLevelStore(Consumer newStore(NamespacedHierarchicalStore parentStore) { + private static NamespacedHierarchicalStore newStore( + @Nullable NamespacedHierarchicalStore parentStore) { return new NamespacedHierarchicalStore<>(parentStore, closeAutoCloseables()); } 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..4085b126483f 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 @@ -19,6 +19,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestDescriptor; @@ -93,7 +94,7 @@ public static Event dynamicTestRegistered(TestDescriptor testDescriptor) { * @return the newly created {@code Event} * @see EventType#SKIPPED */ - public static Event executionSkipped(TestDescriptor testDescriptor, String reason) { + public static Event executionSkipped(TestDescriptor testDescriptor, @Nullable String reason) { return new Event(EventType.SKIPPED, testDescriptor, reason); } @@ -170,6 +171,8 @@ public static Predicate byTestDescriptor(Predicate byTestDescriptor(Predicate events, SoftAssertions softly, Co } } + @Nullable private static Event findEvent(List events, SoftAssertions softly, Condition condition) { // @formatter:off Optional matchedEvent = events.stream() diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java index 092c10fe1440..fdc425c1955f 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestExecutionResult; @@ -38,7 +39,7 @@ public class TerminationInfo { * @return the created {@code TerminationInfo}; never {@code null} * @see #executed(TestExecutionResult) */ - public static TerminationInfo skipped(String reason) { + public static TerminationInfo skipped(@Nullable String reason) { return new TerminationInfo(true, reason, null); } @@ -58,10 +59,15 @@ public static TerminationInfo executed(TestExecutionResult testExecutionResult) // ------------------------------------------------------------------------- private final boolean skipped; + + @Nullable private final String skipReason; + + @Nullable private final TestExecutionResult testExecutionResult; - private TerminationInfo(boolean skipped, String skipReason, TestExecutionResult testExecutionResult) { + private TerminationInfo(boolean skipped, @Nullable String skipReason, + @Nullable TestExecutionResult testExecutionResult) { boolean executed = (testExecutionResult != null); Preconditions.condition((skipped ^ executed), "TerminationInfo must represent either a skipped execution or a TestExecutionResult but not both"); @@ -109,6 +115,7 @@ public boolean executed() { * @throws UnsupportedOperationException if this {@code TerminationInfo} * does not represent a skipped execution */ + @Nullable public String getSkipReason() throws UnsupportedOperationException { if (skipped()) { return this.skipReason; @@ -125,7 +132,7 @@ public String getSkipReason() throws UnsupportedOperationException { * does not represent a completed execution */ public TestExecutionResult getExecutionResult() throws UnsupportedOperationException { - if (executed()) { + if (this.testExecutionResult != null) { return this.testExecutionResult; } // else From f35f7b49e70dc266d47a947b965a8ec0f43dc809 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 16:03:13 +0200 Subject: [PATCH 108/521] Use open-test-reporting snapshots To benefit from ota4j-team/open-test-reporting#481 --- gradle/libs.versions.toml | 2 +- settings.gradle.kts | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9a5e3e813cb8..9e629f71513f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ ktlint = "1.6.0" log4j = "2.24.3" logback = "1.5.18" opentest4j = "1.3.0" -openTestReporting = "0.2.3" +openTestReporting = "0.3.0-SNAPSHOT" snapshotTests = "1.11.0" surefire = "3.5.3" xmlunit = "2.10.2" diff --git a/settings.gradle.kts b/settings.gradle.kts index 3cb5c303cc6f..3d3cd294178d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,6 +15,12 @@ plugins { dependencyResolutionManagement { repositories { mavenCentral() + maven(url = "https://central.sonatype.com/repository/maven-snapshots") { + mavenContent { + snapshotsOnly() + includeGroup("org.opentest4j.reporting") + } + } } } From 734b4c5998e5fa6951fe25e99fcf9cbbfb0373b3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 14:40:30 +0200 Subject: [PATCH 109/521] Enable NullAway in junit-platform-reporting --- .../junit-platform-reporting.gradle.kts | 3 +++ .../src/main/java/module-info.java | 3 +++ .../reporting/legacy/LegacyReportingUtils.java | 3 +++ .../xml/LegacyXmlReportGeneratingListener.java | 17 ++++++++++++----- .../reporting/legacy/xml/XmlReportData.java | 4 +++- .../reporting/legacy/xml/XmlReportWriter.java | 8 +++++--- .../xml/OpenTestReportGeneratingListener.java | 9 +++++++-- 7 files changed, 36 insertions(+), 11 deletions(-) diff --git a/junit-platform-reporting/junit-platform-reporting.gradle.kts b/junit-platform-reporting/junit-platform-reporting.gradle.kts index ebf83f3e7a9b..81f6274eb72a 100644 --- a/junit-platform-reporting/junit-platform-reporting.gradle.kts +++ b/junit-platform-reporting/junit-platform-reporting.gradle.kts @@ -2,6 +2,7 @@ import junitbuild.extensions.javaModuleName plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.shadow-conventions") `java-test-fixtures` } @@ -13,6 +14,8 @@ dependencies { api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) + compileOnlyApi(libs.openTestReporting.tooling.spi) shadowed(libs.openTestReporting.events) diff --git a/junit-platform-reporting/src/main/java/module-info.java b/junit-platform-reporting/src/main/java/module-info.java index f1fe8cd51dca..5f2071c64f1f 100644 --- a/junit-platform-reporting/src/main/java/module-info.java +++ b/junit-platform-reporting/src/main/java/module-info.java @@ -8,11 +8,14 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Defines the JUnit Platform Reporting API. * * @since 1.4 */ +@NullMarked module org.junit.platform.reporting { requires java.xml; requires static transitive org.apiguardian.api; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java index 1f76a53869b1..eb6580723431 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.MAINTAINED; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.TestIdentifier; @@ -62,10 +63,12 @@ public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifi return getParentLegacyReportingName(testPlan, testIdentifier); } + @Nullable private static TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { return testPlan.getParent(testIdentifier).orElse(null); } + @Nullable private static ClassSource getClassSource(TestIdentifier current) { // @formatter:off return current.getSource() diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java index 4d885ee80c2d..4287192fa408 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java @@ -10,6 +10,7 @@ package org.junit.platform.reporting.legacy.xml; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.STABLE; import java.io.IOException; @@ -22,6 +23,7 @@ import javax.xml.stream.XMLStreamException; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestExecutionListener; @@ -48,6 +50,7 @@ public class LegacyXmlReportGeneratingListener implements TestExecutionListener private final PrintWriter out; private final Clock clock; + @Nullable private XmlReportData reportData; public LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out) { @@ -83,23 +86,23 @@ public void testPlanExecutionFinished(TestPlan testPlan) { @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { - this.reportData.markSkipped(testIdentifier, reason); + requiredReportData().markSkipped(testIdentifier, reason); writeXmlReportInCaseOfRoot(testIdentifier); } @Override public void executionStarted(TestIdentifier testIdentifier) { - this.reportData.markStarted(testIdentifier); + requiredReportData().markStarted(testIdentifier); } @Override public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry entry) { - this.reportData.addReportEntry(testIdentifier, entry); + requiredReportData().addReportEntry(testIdentifier, entry); } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult result) { - this.reportData.markFinished(testIdentifier, result); + requiredReportData().markFinished(testIdentifier, result); writeXmlReportInCaseOfRoot(testIdentifier); } @@ -113,13 +116,17 @@ private void writeXmlReportInCaseOfRoot(TestIdentifier testIdentifier) { private void writeXmlReportSafely(TestIdentifier testIdentifier, String rootName) { Path xmlFile = this.reportsDir.resolve("TEST-" + rootName + ".xml"); try (Writer fileWriter = Files.newBufferedWriter(xmlFile)) { - new XmlReportWriter(this.reportData).writeXmlReport(testIdentifier, fileWriter); + new XmlReportWriter(requiredReportData()).writeXmlReport(testIdentifier, fileWriter); } catch (XMLStreamException | IOException e) { printException("Could not write XML report: " + xmlFile, e); } } + private XmlReportData requiredReportData() { + return requireNonNull(this.reportData); + } + private boolean isRoot(TestIdentifier testIdentifier) { return testIdentifier.getParentIdObject().isEmpty(); } diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java index f1ce85be73cb..477c314d2541 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java @@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; @@ -60,7 +61,7 @@ Clock getClock() { return this.clock; } - void markSkipped(TestIdentifier testIdentifier, String reason) { + void markSkipped(TestIdentifier testIdentifier, @Nullable String reason) { this.skippedTests.put(testIdentifier, reason == null ? "" : reason); } @@ -94,6 +95,7 @@ boolean wasSkipped(TestIdentifier testIdentifier) { return Duration.between(startInstant, endInstant).toMillis() / (double) MILLIS_PER_SECOND; } + @Nullable String getSkipReason(TestIdentifier testIdentifier) { return findSkippedAncestor(testIdentifier).map(skippedTestIdentifier -> { String reason = this.skippedTests.get(skippedTestIdentifier); diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java index d3ae6b008bd9..203cac3e3f15 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java @@ -15,6 +15,7 @@ import static java.util.Collections.emptyList; import static java.util.Collections.unmodifiableMap; import static java.util.Comparator.naturalOrder; +import static java.util.Objects.requireNonNull; import static java.util.function.Function.identity; import static java.util.stream.Collectors.counting; import static java.util.stream.Collectors.groupingBy; @@ -55,6 +56,7 @@ import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.ReportEntry; import org.junit.platform.launcher.TestIdentifier; @@ -244,10 +246,10 @@ private void writeSkippedOrErrorOrFailureElement(TestIdentifier testIdentifier, } } - private void writeSkippedElement(String reason, XMLStreamWriter writer) throws XMLStreamException { + private void writeSkippedElement(@Nullable String reason, XMLStreamWriter writer) throws XMLStreamException { if (isNotBlank(reason)) { writer.writeStartElement("skipped"); - writeCDataSafely(reason); + writeCDataSafely(requireNonNull(reason)); writer.writeEndElement(); } else { @@ -256,7 +258,7 @@ private void writeSkippedElement(String reason, XMLStreamWriter writer) throws X newLine(); } - private void writeErrorOrFailureElement(Type type, Throwable throwable, XMLStreamWriter writer) + private void writeErrorOrFailureElement(Type type, @Nullable Throwable throwable, XMLStreamWriter writer) throws XMLStreamException { String elementName = type == FAILURE ? "failure" : "error"; 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 2fae334d983a..4726702e5a30 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,6 +10,7 @@ package org.junit.platform.reporting.open.xml; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.junit.platform.commons.util.StringUtils.isNotBlank; import static org.junit.platform.launcher.LauncherConstants.STDERR_REPORT_ENTRY_KEY; @@ -71,6 +72,7 @@ import java.util.function.BiConsumer; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.StringUtils; @@ -114,6 +116,8 @@ public class OpenTestReportGeneratingListener implements TestExecutionListener { private final Map inProgressIds = new ConcurrentHashMap<>(); private DocumentWriter eventsFileWriter = DocumentWriter.noop(); private final Path workingDir; + + @Nullable private Path outputDir; @SuppressWarnings("unused") // Used via ServiceLoader @@ -361,7 +365,8 @@ public void reportingEntryPublished(TestIdentifier testIdentifier, ReportEntry e })); } - private static void attachOutput(Attachments attachments, LocalDateTime timestamp, String content, String source) { + private static void attachOutput(Attachments attachments, LocalDateTime timestamp, @Nullable String content, + String source) { if (content != null) { attachments.append(output(timestamp), output -> output.withSource(source).withContent(content)); } @@ -373,7 +378,7 @@ public void fileEntryPublished(TestIdentifier testIdentifier, FileEntry entry) { eventsFileWriter.append(reported(id, Instant.now()), // reported -> reported.append(attachments(), attachments -> attachments.append(file(entry.getTimestamp()), // file -> { - file.withPath(outputDir.relativize(entry.getPath()).toString()); + file.withPath(requireNonNull(outputDir).relativize(entry.getPath()).toString()); entry.getMediaType().ifPresent(file::withMediaType); }))); } From 6c042c4c5710365cc8205dcd843734a4037798c3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 14:51:48 +0200 Subject: [PATCH 110/521] Enable NullAway in junit-platform-jfr --- .../junit-platform-jfr.gradle.kts | 2 ++ .../src/main/java/module-info.java | 3 ++ .../jfr/FlightRecordingDiscoveryListener.java | 13 +++++-- .../jfr/FlightRecordingExecutionListener.java | 34 +++++++++++++++++-- 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/junit-platform-jfr/junit-platform-jfr.gradle.kts b/junit-platform-jfr/junit-platform-jfr.gradle.kts index 7d9e2d06a2a9..5608f5280e9e 100644 --- a/junit-platform-jfr/junit-platform-jfr.gradle.kts +++ b/junit-platform-jfr/junit-platform-jfr.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") } description = "JUnit Platform Flight Recorder Support" @@ -9,6 +10,7 @@ dependencies { api(projects.junitPlatformLauncher) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) if (java.toolchain.implementation.orNull == JvmImplementation.J9) { compileOnly(libs.jfrPolyfill) { diff --git a/junit-platform-jfr/src/main/java/module-info.java b/junit-platform-jfr/src/main/java/module-info.java index 6f38bf063cf7..4a8ada5dc3aa 100644 --- a/junit-platform-jfr/src/main/java/module-info.java +++ b/junit-platform-jfr/src/main/java/module-info.java @@ -8,6 +8,8 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Provides Java Flight Recorder events for the JUnit Platform. * @@ -19,6 +21,7 @@ * @see JEP 328: Flight Recorder * @since 1.7 */ +@NullMarked module org.junit.platform.jfr { requires jdk.jfr; requires static org.apiguardian.api; diff --git a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingDiscoveryListener.java b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingDiscoveryListener.java index ed34f1289360..b0cef89f0f7f 100644 --- a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingDiscoveryListener.java +++ b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingDiscoveryListener.java @@ -10,6 +10,7 @@ package org.junit.platform.jfr; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.STABLE; import java.util.Map; @@ -23,6 +24,7 @@ import jdk.jfr.StackTrace; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoveryIssue; @@ -41,7 +43,7 @@ @API(status = STABLE, since = "1.11") public class FlightRecordingDiscoveryListener implements LauncherDiscoveryListener { - private final AtomicReference launcherDiscoveryEvent = new AtomicReference<>(); + private final AtomicReference<@Nullable LauncherDiscoveryEvent> launcherDiscoveryEvent = new AtomicReference<>(); private final Map engineDiscoveryEvents = new ConcurrentHashMap<>(); @Override @@ -55,7 +57,7 @@ public void launcherDiscoveryStarted(LauncherDiscoveryRequest request) { @Override public void launcherDiscoveryFinished(LauncherDiscoveryRequest request) { - launcherDiscoveryEvent.getAndSet(null).commit(); + requireNonNull(launcherDiscoveryEvent.getAndSet(null)).commit(); } @Override @@ -106,9 +108,11 @@ static class EngineDiscoveryEvent extends DiscoveryEvent { @UniqueId @Label("Unique Id") + @Nullable String uniqueId; @Label("Result") + @Nullable String result; } @@ -117,18 +121,23 @@ static class EngineDiscoveryEvent extends DiscoveryEvent { static class DiscoveryIssueEvent extends DiscoveryEvent { @Label("Engine Id") + @Nullable String engineId; @Label("Severity") + @Nullable String severity; @Label("Message") + @Nullable String message; @Label("Source") + @Nullable String source; @Label("Cause") + @Nullable String cause; } } diff --git a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingExecutionListener.java b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingExecutionListener.java index a854b81d98ec..6a2031770605 100644 --- a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingExecutionListener.java +++ b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/FlightRecordingExecutionListener.java @@ -10,6 +10,7 @@ package org.junit.platform.jfr; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.STABLE; import java.util.Map; @@ -25,6 +26,7 @@ import jdk.jfr.StackTrace; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.FileEntry; import org.junit.platform.engine.reporting.ReportEntry; @@ -42,7 +44,7 @@ @API(status = STABLE, since = "1.11") public class FlightRecordingExecutionListener implements TestExecutionListener { - private final AtomicReference testPlanExecutionEvent = new AtomicReference<>(); + private final AtomicReference<@Nullable TestPlanExecutionEvent> testPlanExecutionEvent = new AtomicReference<>(); private final Map testExecutionEvents = new ConcurrentHashMap<>(); @Override @@ -57,7 +59,7 @@ public void testPlanExecutionStarted(TestPlan plan) { @Override public void testPlanExecutionFinished(TestPlan plan) { - testPlanExecutionEvent.getAndSet(null).commit(); + requireNonNull(testPlanExecutionEvent.getAndSet(null)).commit(); } @Override @@ -114,21 +116,32 @@ abstract static class ExecutionEvent extends Event { @Label("Test Execution") @Name("org.junit.TestPlanExecution") static class TestPlanExecutionEvent extends ExecutionEvent { + @Label("Contains Tests") boolean containsTests; + @Label("Engine Names") + @Nullable String engineNames; } abstract static class TestEvent extends ExecutionEvent { + @UniqueId @Label("Unique Id") + @Nullable String uniqueId; + @Label("Display Name") + @Nullable String displayName; + @Label("Tags") + @Nullable String tags; + @Label("Type") + @Nullable String type; void initialize(TestIdentifier test) { @@ -143,39 +156,56 @@ void initialize(TestIdentifier test) { @Name("org.junit.SkippedTest") static class SkippedTestEvent extends TestEvent { @Label("Reason") + @Nullable String reason; } @Label("Test") @Name("org.junit.TestExecution") static class TestExecutionEvent extends TestEvent { + @Label("Result") + @Nullable String result; + @Label("Exception Class") + @Nullable Class exceptionClass; + @Label("Exception Message") + @Nullable String exceptionMessage; } @Label("Report Entry") @Name("org.junit.ReportEntry") static class ReportEntryEvent extends ExecutionEvent { + @UniqueId @Label("Unique Id") + @Nullable String uniqueId; + @Label("Key") + @Nullable String key; + @Label("Value") + @Nullable String value; } @Label("File Entry") @Name("org.junit.FileEntry") static class FileEntryEvent extends ExecutionEvent { + @UniqueId @Label("Unique Id") + @Nullable String uniqueId; + @Label("Path") + @Nullable String path; } } From 1aac601c2bac37cc3e37627d092f07251709d73e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 20 May 2025 15:56:36 +0200 Subject: [PATCH 111/521] Enable NullAway in junit-platform-console --- .../junit-platform-console.gradle.kts | 11 +++++++++++ .../src/main/java/module-info.java | 3 +++ .../platform/console/options/CommandResult.java | 7 +++++-- .../console/options/ExecuteTestsCommand.java | 7 +++++-- .../platform/console/options/MainCommand.java | 6 +++++- .../options/TestConsoleOutputOptions.java | 17 ++++++++++++++--- .../options/TestConsoleOutputOptionsMixin.java | 5 +++++ .../console/options/TestDiscoveryOptions.java | 6 +++++- .../options/TestDiscoveryOptionsMixin.java | 2 ++ .../console/tasks/DiscoveryRequestCreator.java | 6 ++++-- .../console/tasks/StandardStreamsHandler.java | 7 +++++-- .../console/tasks/TestFeedPrintingListener.java | 6 +++++- .../junit/platform/console/tasks/TreeNode.java | 12 +++++++++++- .../platform/console/tasks/TreePrinter.java | 3 ++- .../console/tasks/TreePrintingListener.java | 15 +++++++++++---- 15 files changed, 93 insertions(+), 20 deletions(-) diff --git a/junit-platform-console/junit-platform-console.gradle.kts b/junit-platform-console/junit-platform-console.gradle.kts index 78c5f19c0e9d..0dd0f1b66209 100644 --- a/junit-platform-console/junit-platform-console.gradle.kts +++ b/junit-platform-console/junit-platform-console.gradle.kts @@ -1,8 +1,11 @@ import junitbuild.extensions.javaModuleName import junitbuild.java.UpdateJarAction +import net.ltgt.gradle.errorprone.errorprone +import net.ltgt.gradle.nullaway.nullaway plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.shadow-conventions") } @@ -13,6 +16,7 @@ dependencies { api(projects.junitPlatformReporting) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) shadowed(libs.picocli) @@ -27,6 +31,13 @@ tasks { "--add-modules", "info.picocli", "--add-reads", "${javaModuleName}=info.picocli" )) + options.errorprone.nullaway { + excludedFieldAnnotations.addAll( + "picocli.CommandLine.ArgGroup", + "picocli.CommandLine.Mixin", + "picocli.CommandLine.Spec", + ) + } } javadoc { (options as StandardJavadocDocletOptions).apply { diff --git a/junit-platform-console/src/main/java/module-info.java b/junit-platform-console/src/main/java/module-info.java index 166aff5ee795..98c7380c9053 100644 --- a/junit-platform-console/src/main/java/module-info.java +++ b/junit-platform-console/src/main/java/module-info.java @@ -8,12 +8,15 @@ * https://www.eclipse.org/legal/epl-v20.html */ +import org.jspecify.annotations.NullMarked; + /** * Support for launching the JUnit Platform from the console. * * @since 1.0 * @provides java.util.spi.ToolProvider */ +@NullMarked module org.junit.platform.console { requires static org.apiguardian.api; requires org.junit.platform.commons; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java index 87a202e0560a..2044347f8265 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java @@ -15,6 +15,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * @since 1.10 @@ -40,14 +41,16 @@ public static CommandResult failure() { return create(FAILURE, null); } - public static CommandResult create(int exitCode, T value) { + public static CommandResult create(int exitCode, @Nullable T value) { return new CommandResult<>(exitCode, value); } private final int exitCode; + + @Nullable private final T value; - private CommandResult(int exitCode, T value) { + private CommandResult(int exitCode, @Nullable T value) { this.exitCode = exitCode; this.value = value; } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java index 2f592de24919..ca6c4d0281c8 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ExecuteTestsCommand.java @@ -16,6 +16,7 @@ import java.nio.file.Path; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.platform.console.tasks.ConsoleTestExecutor; import org.junit.platform.launcher.listeners.TestExecutionSummary; @@ -23,6 +24,7 @@ import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Command; import picocli.CommandLine.Mixin; +import picocli.CommandLine.Option; @Command(// name = "execute", // @@ -93,10 +95,11 @@ public int getExitCode() { static class ReportingOptions { - @CommandLine.Option(names = "--fail-if-no-tests", description = "Fail and return exit status code 2 if no tests are found.") + @Option(names = "--fail-if-no-tests", description = "Fail and return exit status code 2 if no tests are found.") private boolean failIfNoTests; // no single-dash equivalent: was introduced in 5.3-M1 - @CommandLine.Option(names = "--reports-dir", paramLabel = "DIR", description = "Enable report output into a specified local directory (will be created if it does not exist).") + @Nullable + @Option(names = "--reports-dir", paramLabel = "DIR", description = "Enable report output into a specified local directory (will be created if it does not exist).") private Path reportsDir; Optional getReportsDir() { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java index b04249508a16..90bbf2d42c6f 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/MainCommand.java @@ -10,8 +10,11 @@ package org.junit.platform.console.options; +import static java.util.Objects.requireNonNull; + import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.platform.console.tasks.ConsoleTestExecutor; import picocli.CommandLine; @@ -56,6 +59,7 @@ class MainCommand implements Runnable, IExitCodeGenerator { @Spec CommandSpec commandSpec; + @Nullable CommandResult commandResult; MainCommand(ConsoleTestExecutor.Factory consoleTestExecutorFactory) { @@ -79,7 +83,7 @@ else if (versionRequested) { @Override public int getExitCode() { - return commandResult.getExitCode(); + return requireNonNull(commandResult).getExitCode(); } CommandResult run(String[] args, diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java index 73f4fc4a2416..e157715be6a6 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java @@ -16,6 +16,7 @@ import java.util.Locale; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * @since 1.10 @@ -28,11 +29,18 @@ public class TestConsoleOutputOptions { static final Theme DEFAULT_THEME = Theme.valueOf(ConsoleUtils.charset()); private boolean ansiColorOutputDisabled; + + @Nullable private Path colorPalettePath; + private boolean isSingleColorPalette; private Details details = DEFAULT_DETAILS; private Theme theme = DEFAULT_THEME; + + @Nullable private Path stdoutPath; + + @Nullable private Path stderrPath; public boolean isAnsiColorOutputDisabled() { @@ -43,11 +51,12 @@ public void setAnsiColorOutputDisabled(boolean ansiColorOutputDisabled) { this.ansiColorOutputDisabled = ansiColorOutputDisabled; } + @Nullable public Path getColorPalettePath() { return colorPalettePath; } - public void setColorPalettePath(Path colorPalettePath) { + public void setColorPalettePath(@Nullable Path colorPalettePath) { this.colorPalettePath = colorPalettePath; } @@ -76,22 +85,24 @@ public void setTheme(Theme theme) { } @API(status = INTERNAL, since = "1.13") + @Nullable public Path getStdoutPath() { return this.stdoutPath; } @API(status = INTERNAL, since = "1.13") - public void setStdoutPath(Path stdoutPath) { + public void setStdoutPath(@Nullable Path stdoutPath) { this.stdoutPath = stdoutPath; } @API(status = INTERNAL, since = "1.13") + @Nullable public Path getStderrPath() { return this.stderrPath; } @API(status = INTERNAL, since = "1.13") - public void setStderrPath(Path stderrPath) { + public void setStderrPath(@Nullable Path stderrPath) { this.stderrPath = stderrPath; } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java index 3faa6cc3fe48..54d3cbd34a29 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptionsMixin.java @@ -16,6 +16,8 @@ import java.nio.file.Path; +import org.jspecify.annotations.Nullable; + import picocli.CommandLine.ArgGroup; import picocli.CommandLine.Option; @@ -26,6 +28,7 @@ class TestConsoleOutputOptionsMixin { static class ConsoleOutputOptions { + @Nullable @Option(names = "--color-palette", paramLabel = "FILE", description = "Specify a path to a properties file to customize ANSI style of output (not supported by all terminals).") private Path colorPalette; @@ -41,9 +44,11 @@ static class ConsoleOutputOptions { + "Use one of: ${COMPLETION-CANDIDATES}. Default is detected based on default character encoding.") private final Theme theme = DEFAULT_THEME; + @Nullable @Option(names = "--redirect-stdout", paramLabel = "FILE", description = "Redirect test output to stdout to a file.") private Path stdout; + @Nullable @Option(names = "--redirect-stderr", paramLabel = "FILE", description = "Redirect test output to stderr to a file.") private Path stderr; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java index 0345dde65603..449a436acbc0 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java @@ -24,6 +24,7 @@ import java.util.Map; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.DiscoverySelector; import org.junit.platform.engine.DiscoverySelectorIdentifier; import org.junit.platform.engine.discovery.ClassSelector; @@ -46,6 +47,8 @@ public class TestDiscoveryOptions { private boolean scanClasspath; private List additionalClasspathEntries = emptyList(); + + @Nullable private List selectedClasspathEntries = emptyList(); private boolean scanModulepath; @@ -104,11 +107,12 @@ public void setAdditionalClasspathEntries(List additionalClasspathEntries) this.additionalClasspathEntries = additionalClasspathEntries; } + @Nullable public List getSelectedClasspathEntries() { return this.selectedClasspathEntries; } - public void setSelectedClasspathEntries(List selectedClasspathEntries) { + public void setSelectedClasspathEntries(@Nullable List selectedClasspathEntries) { this.selectedClasspathEntries = selectedClasspathEntries; } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java index 0c59318a95a8..18ff561a96dc 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptionsMixin.java @@ -16,6 +16,7 @@ import java.util.List; import java.util.Map; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.DiscoverySelectorIdentifier; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; @@ -50,6 +51,7 @@ class TestDiscoveryOptionsMixin { static class SelectorOptions { + @Nullable @Option(names = { "--scan-classpath", "--scan-class-path" }, converter = ClasspathEntriesConverter.class, paramLabel = "PATH", arity = "0..1", description = "Scan all directories on the classpath or explicit classpath roots. " // + "Without arguments, only directories on the system classpath as well as additional classpath " // diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java index d85bed36ca35..fd687ba632be 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/DiscoveryRequestCreator.java @@ -82,12 +82,14 @@ private static List createClasspathRootSelectors(TestDisc } private static Set determineClasspathRoots(TestDiscoveryOptions options) { - if (options.getSelectedClasspathEntries().isEmpty()) { + var selectedClasspathEntries = Preconditions.notNull(options.getSelectedClasspathEntries(), + () -> "No classpath entries selected"); + if (selectedClasspathEntries.isEmpty()) { Set rootDirs = new LinkedHashSet<>(ReflectionUtils.getAllClasspathRootDirectories()); rootDirs.addAll(options.getExistingAdditionalClasspathEntries()); return rootDirs; } - return new LinkedHashSet<>(options.getSelectedClasspathEntries()); + return new LinkedHashSet<>(selectedClasspathEntries); } private static void addFilters(LauncherDiscoveryRequestBuilder requestBuilder, TestDiscoveryOptions options, diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java index 50bcb1309054..9cb91fce9418 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java @@ -15,12 +15,15 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; class StandardStreamsHandler implements AutoCloseable { + @Nullable private PrintStream stdout; + @Nullable private PrintStream stderr; public StandardStreamsHandler() { @@ -39,7 +42,7 @@ public StandardStreamsHandler() { * @param stderrPath the file path for standard error, or {@code null} to * indicate no redirection */ - public void redirectStandardStreams(Path stdoutPath, Path stderrPath) { + public void redirectStandardStreams(@Nullable Path stdoutPath, @Nullable Path stderrPath) { if (isSameFile(stdoutPath, stderrPath)) { try { PrintStream commonStream = new PrintStream(Files.newOutputStream(stdoutPath), true); @@ -92,7 +95,7 @@ public void close() { } } - private static boolean isSameFile(Path path1, Path path2) { + private static boolean isSameFile(@Nullable Path path1, @Nullable Path path2) { if (path1 == null || path2 == null) { return false; } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java index e44b4bec561e..b549494b0507 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java @@ -10,12 +10,14 @@ package org.junit.platform.console.tasks; +import static java.util.Objects.requireNonNull; import static org.junit.platform.engine.TestExecutionResult.Status.SUCCESSFUL; import java.io.PrintWriter; import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; @@ -29,6 +31,8 @@ class TestFeedPrintingListener implements DetailsPrintingListener { private final PrintWriter out; private final ColorPalette colorPalette; + + @Nullable private TestPlan testPlan; TestFeedPrintingListener(PrintWriter out, ColorPalette colorPalette) { @@ -94,7 +98,7 @@ private List collectDisplayNames(UniqueId uniqueId) { int size = uniqueId.getSegments().size(); List displayNames = new ArrayList<>(size); for (int i = 0; i < size; i++) { - displayNames.add(0, testPlan.getTestIdentifier(uniqueId).getDisplayName()); + displayNames.add(0, requireNonNull(testPlan).getTestIdentifier(uniqueId).getDisplayName()); if (i < size - 1) { uniqueId = uniqueId.removeLastSegment(); } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java index e60a07146fa2..55e05009a24f 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java @@ -10,10 +10,13 @@ package org.junit.platform.console.tasks; +import static java.util.Objects.requireNonNull; + import java.util.Optional; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.reporting.FileEntry; @@ -28,9 +31,16 @@ class TreeNode { private final String caption; private final long creation; long duration; + + @Nullable private String reason; + + @Nullable private TestIdentifier identifier; + + @Nullable private TestExecutionResult result; + final Queue reports = new ConcurrentLinkedQueue<>(); final Queue files = new ConcurrentLinkedQueue<>(); final Queue children = new ConcurrentLinkedQueue<>(); @@ -94,6 +104,6 @@ static String createCaption(String displayName) { boolean normal = displayName.length() <= 80; String caption = normal ? displayName : displayName.substring(0, 80) + "..."; String whites = StringUtils.replaceWhitespaceCharacters(caption, " "); - return StringUtils.replaceIsoControlCharacters(whites, "."); + return requireNonNull(StringUtils.replaceIsoControlCharacters(whites, ".")); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java index 6e6201031ca0..a967498be2ce 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrinter.java @@ -10,6 +10,7 @@ package org.junit.platform.console.tasks; +import static java.util.Objects.requireNonNull; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import java.io.PrintWriter; @@ -128,7 +129,7 @@ private void printThrowable(String indent, TestExecutionResult result) { if (StringUtils.isBlank(message)) { message = throwable.toString(); } - printMessage(Style.FAILED, indent, message); + printMessage(Style.FAILED, indent, requireNonNull(message)); } private void printReportEntry(String indent, ReportEntry reportEntry) { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java index 49ec53d48ec8..d8d7130e400a 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java @@ -10,10 +10,14 @@ package org.junit.platform.console.tasks; +import static java.util.Objects.requireNonNull; +import static java.util.Objects.requireNonNullElse; + import java.io.PrintWriter; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import org.jspecify.annotations.Nullable; import org.junit.platform.console.options.Theme; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; @@ -28,20 +32,23 @@ class TreePrintingListener implements DetailsPrintingListener { private final Map nodesByUniqueId = new ConcurrentHashMap<>(); - private TreeNode root; private final TreePrinter treePrinter; + @Nullable + private TreeNode root; + TreePrintingListener(PrintWriter out, ColorPalette colorPalette, Theme theme) { this.treePrinter = new TreePrinter(out, theme, colorPalette); } private void addNode(TestIdentifier testIdentifier, TreeNode node) { nodesByUniqueId.put(testIdentifier.getUniqueIdObject(), node); - testIdentifier.getParentIdObject().map(nodesByUniqueId::get).orElse(root).addChild(node); + TreeNode parent = testIdentifier.getParentIdObject().map(nodesByUniqueId::get).orElse(null); + requireNonNullElse(parent, root).addChild(node); } private TreeNode getNode(TestIdentifier testIdentifier) { - return nodesByUniqueId.get(testIdentifier.getUniqueIdObject()); + return requireNonNull(nodesByUniqueId.get(testIdentifier.getUniqueIdObject())); } @Override @@ -51,7 +58,7 @@ public void testPlanExecutionStarted(TestPlan testPlan) { @Override public void testPlanExecutionFinished(TestPlan testPlan) { - treePrinter.print(root); + treePrinter.print(requireNonNull(root)); } @Override From fceae1e5ad599661936afa3242673730b9fd4fee Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 08:11:18 +0200 Subject: [PATCH 112/521] Add ArchUnit check for `@NullMarked` on all packages --- .../platform-tooling-support-tests.gradle.kts | 4 +++ .../tooling/support/tests/ArchUnitTests.java | 34 +++++++++++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index 176e862221e9..a88d8b140243 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -120,6 +120,10 @@ val archUnit by testing.suites.registering(JvmTestSuite::class) { implementation(libs.apiguardian) { because("we validate that public classes are annotated") } + implementation(libs.jspecify) { + because("we validate that packages are annotated") + } + implementation(libs.assertj) runtimeOnly.bundle(libs.bundles.log4j) val modularProjects: List by rootProject modularProjects.forEach { diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index c54641f46604..e4b07bca2515 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -15,7 +15,6 @@ import static com.tngtech.archunit.core.domain.JavaClass.Predicates.ANONYMOUS_CLASSES; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.TOP_LEVEL_CLASSES; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAPackage; -import static com.tngtech.archunit.core.domain.JavaClass.Predicates.resideInAnyPackage; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleName; import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleNameEndingWith; import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC; @@ -27,6 +26,7 @@ import static com.tngtech.archunit.lang.conditions.ArchPredicates.have; import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.classes; import static com.tngtech.archunit.library.dependencies.SlicesRuleDefinition.slices; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; import java.lang.annotation.Annotation; @@ -35,10 +35,13 @@ import java.lang.annotation.Target; import java.util.Arrays; import java.util.function.BiPredicate; +import java.util.stream.Stream; import com.tngtech.archunit.base.DescribedPredicate; import com.tngtech.archunit.core.domain.JavaClass; import com.tngtech.archunit.core.domain.JavaClasses; +import com.tngtech.archunit.core.domain.JavaPackage; +import com.tngtech.archunit.core.domain.PackageMatcher; import com.tngtech.archunit.junit.AnalyzeClasses; import com.tngtech.archunit.junit.ArchTest; import com.tngtech.archunit.lang.ArchCondition; @@ -46,6 +49,7 @@ import com.tngtech.archunit.library.GeneralCodingRules; import org.apiguardian.api.API; +import org.jspecify.annotations.NullMarked; @AnalyzeClasses(packages = { "org.junit.platform", "org.junit.jupiter", "org.junit.vintage" }) class ArchUnitTests { @@ -64,7 +68,7 @@ class ArchUnitTests { .and(not(describe("are Kotlin SAM type implementations", simpleName("")))) // .and(not(describe("are Kotlin-generated classes that contain only top-level functions", simpleNameEndingWith("Kt")))) // - .and(not(describe("are shadowed", resideInAnyPackage("..shadow..")))) // + .and(not(describe("are shadowed", resideInAPackage("..shadow..")))) // .should().beAnnotatedWith(API.class); @SuppressWarnings("unused") @@ -76,6 +80,32 @@ class ArchUnitTests { .should(haveContainerAnnotationWithSameRetentionPolicy()) // .andShould(haveContainerAnnotationWithSameTargetTypes()); + @ArchTest + void packagesShouldBeNullMarked(JavaClasses classes) { + var exclusions = Stream.of( // + "..shadow..", // + "org.junit.jupiter.api..", // + "org.junit.jupiter.engine..", // + "org.junit.jupiter.migrationsupport..", // + "org.junit.jupiter.params..", // + "org.junit.platform.launcher.." // + ).map(PackageMatcher::of).toList(); + + var subpackages = Stream.of("org.junit.platform", "org.junit.jupiter", "org.junit.vintage") // + .map(classes::getPackage) // + .flatMap(rootPackage -> rootPackage.getSubpackagesInTree().stream()) // + .filter(pkg -> exclusions.stream().noneMatch(it -> it.matches(pkg.getName()))) // + .filter(pkg -> !pkg.getClasses().isEmpty()) // + .toList(); + assertThat(subpackages).isNotEmpty(); + + var violations = subpackages.stream() // + .filter(pkg -> !pkg.isAnnotatedWith(NullMarked.class)) // + .map(JavaPackage::getName) // + .sorted(); + assertThat(violations).describedAs("The following packages are missing the @NullMarked annotation").isEmpty(); + } + @ArchTest void allAreIn(JavaClasses classes) { // about 928 classes found in all jars From 333c43457008157f70f204e2e5c1b38024d544b2 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 08:12:43 +0200 Subject: [PATCH 113/521] Annotate packages to support downstream classpath compilation --- .../junitbuild.java-nullability-conventions.gradle.kts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index d14b72f7904b..294ad34bf6f3 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -1,5 +1,4 @@ import junitbuild.extensions.dependencyFromLibs -import junitbuild.extensions.javaModuleName import net.ltgt.gradle.errorprone.errorprone import net.ltgt.gradle.nullaway.nullaway @@ -15,13 +14,15 @@ dependencies { } nullaway { - annotatedPackages.add(javaModuleName) + onlyNullMarked = true } tasks.withType().configureEach { options.errorprone { disableAllChecks = true - enable("NullAway") + nullaway { + enable() + } } } From 8f7bee93641cbfeae49e85f67f6d82b04b9da35a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 08:24:19 +0200 Subject: [PATCH 114/521] Move `@NullMarked` annotations to packages --- junit-platform-commons/src/main/java/module-info.java | 3 --- .../org/junit/platform/commons/annotation/package-info.java | 3 +++ .../java/org/junit/platform/commons/function/package-info.java | 3 +++ .../java/org/junit/platform/commons/logging/package-info.java | 3 +++ .../src/main/java/org/junit/platform/commons/package-info.java | 3 +++ .../platform/commons/support/conversion/package-info.java | 3 +++ .../java/org/junit/platform/commons/support/package-info.java | 3 +++ .../junit/platform/commons/support/scanning/package-info.java | 3 +++ .../java/org/junit/platform/commons/util/package-info.java | 3 +++ junit-platform-console/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/console/options/package-info.java | 3 +++ .../src/main/java/org/junit/platform/console/package-info.java | 3 +++ .../java/org/junit/platform/console/tasks/package-info.java | 3 +++ junit-platform-engine/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/engine/discovery/package-info.java | 3 +++ .../src/main/java/org/junit/platform/engine/package-info.java | 3 +++ .../java/org/junit/platform/engine/reporting/package-info.java | 3 +++ .../org/junit/platform/engine/support/config/package-info.java | 3 +++ .../junit/platform/engine/support/descriptor/package-info.java | 3 +++ .../junit/platform/engine/support/discovery/package-info.java | 3 +++ .../platform/engine/support/hierarchical/package-info.java | 3 +++ .../org/junit/platform/engine/support/store/package-info.java | 3 +++ junit-platform-jfr/src/main/java/module-info.java | 3 --- .../src/main/java/org/junit/platform/jfr/package-info.java | 3 +++ junit-platform-reporting/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/reporting/legacy/package-info.java | 3 +++ .../org/junit/platform/reporting/legacy/xml/package-info.java | 3 +++ .../org/junit/platform/reporting/open/xml/package-info.java | 3 +++ .../main/java/org/junit/platform/reporting/package-info.java | 3 +++ junit-platform-suite-api/src/main/java/module-info.java | 3 --- .../main/java/org/junit/platform/suite/api/package-info.java | 3 +++ junit-platform-suite-commons/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/suite/commons/package-info.java | 3 +++ junit-platform-suite-engine/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/suite/engine/package-info.java | 3 +++ junit-platform-testkit/src/main/java/module-info.java | 3 --- .../java/org/junit/platform/testkit/engine/package-info.java | 3 +++ .../src/main/java/org/junit/platform/testkit/package-info.java | 3 +++ junit-vintage-engine/src/main/java/module-info.java | 3 --- .../java/org/junit/vintage/engine/descriptor/package-info.java | 3 +++ .../java/org/junit/vintage/engine/discovery/package-info.java | 3 +++ .../java/org/junit/vintage/engine/execution/package-info.java | 3 +++ .../src/main/java/org/junit/vintage/engine/package-info.java | 3 +++ .../java/org/junit/vintage/engine/support/package-info.java | 3 +++ 44 files changed, 102 insertions(+), 30 deletions(-) diff --git a/junit-platform-commons/src/main/java/module-info.java b/junit-platform-commons/src/main/java/module-info.java index c902b3da89c1..092c654cdd51 100644 --- a/junit-platform-commons/src/main/java/module-info.java +++ b/junit-platform-commons/src/main/java/module-info.java @@ -8,14 +8,11 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Common APIs and support utilities for the JUnit Platform. * * @since 1.0 */ -@NullMarked module org.junit.platform.commons { requires java.logging; requires java.management; // needed by RuntimeUtils to determine input arguments diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java index f5f0eaf51493..1221aebb8f50 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/annotation/package-info.java @@ -2,4 +2,7 @@ * Common annotations for the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.annotation; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java index 8f031faf22e0..79d053801103 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/package-info.java @@ -2,4 +2,7 @@ * Functional interfaces and support classes. */ +@NullMarked package org.junit.platform.commons.function; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java index 75260c34a99a..9fe567592387 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/package-info.java @@ -8,4 +8,7 @@ * Use at your own risk! */ +@NullMarked package org.junit.platform.commons.logging; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java index 66e1cf2aa51c..18945b31c25e 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/package-info.java @@ -8,4 +8,7 @@ * APIs by external parties is not supported! */ +@NullMarked package org.junit.platform.commons; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java index 18807d6a4e90..79ba440a7609 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/package-info.java @@ -2,4 +2,7 @@ * Conversion APIs provided by the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.support.conversion; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java index fae0c2a81547..68a77ec1bf22 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/package-info.java @@ -8,4 +8,7 @@ * extensions with the same semantics as within the JUnit Platform itself. */ +@NullMarked package org.junit.platform.commons.support; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java index 769733a65aef..2da61c5d8ce9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/package-info.java @@ -2,4 +2,7 @@ * Classpath scanning APIs provided by the JUnit Platform. */ +@NullMarked package org.junit.platform.commons.support.scanning; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java index 119940686c89..3d9e974b50f9 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/package-info.java @@ -8,4 +8,7 @@ * Use at your own risk! */ +@NullMarked package org.junit.platform.commons.util; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-console/src/main/java/module-info.java b/junit-platform-console/src/main/java/module-info.java index 98c7380c9053..166aff5ee795 100644 --- a/junit-platform-console/src/main/java/module-info.java +++ b/junit-platform-console/src/main/java/module-info.java @@ -8,15 +8,12 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Support for launching the JUnit Platform from the console. * * @since 1.0 * @provides java.util.spi.ToolProvider */ -@NullMarked module org.junit.platform.console { requires static org.apiguardian.api; requires org.junit.platform.commons; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/package-info.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/package-info.java index babb46e295da..f06150fae4b5 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/package-info.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/package-info.java @@ -2,4 +2,7 @@ * Configuration options for JUnit's console launcher. */ +@NullMarked package org.junit.platform.console.options; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/package-info.java b/junit-platform-console/src/main/java/org/junit/platform/console/package-info.java index 73bc1b41dceb..3b0816fca102 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/package-info.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/package-info.java @@ -2,4 +2,7 @@ * Support for launching the JUnit Platform from the console. */ +@NullMarked package org.junit.platform.console; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/package-info.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/package-info.java index bcfe3d83e71c..39f268bb129d 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/package-info.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/package-info.java @@ -2,4 +2,7 @@ * Internal execution tasks for JUnit's console launcher. */ +@NullMarked package org.junit.platform.console.tasks; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/module-info.java b/junit-platform-engine/src/main/java/module-info.java index ad2b0934cf48..c81836121c9c 100644 --- a/junit-platform-engine/src/main/java/module-info.java +++ b/junit-platform-engine/src/main/java/module-info.java @@ -8,8 +8,6 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Public API for test engines. * @@ -18,7 +16,6 @@ * * @since 1.0 */ -@NullMarked module org.junit.platform.engine { requires static transitive org.apiguardian.api; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java index 55321771b8e4..9f8135af9449 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/package-info.java @@ -4,4 +4,7 @@ * {@linkplain org.junit.platform.engine.EngineDiscoveryRequest discovery requests}. */ +@NullMarked package org.junit.platform.engine.discovery; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java index 63bb41729648..02ab768dc6f8 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/package-info.java @@ -2,4 +2,7 @@ * Public API for test engines. */ +@NullMarked package org.junit.platform.engine; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java index 11965058d1ab..6cafad5c020e 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/reporting/package-info.java @@ -3,4 +3,7 @@ * listeners. */ +@NullMarked package org.junit.platform.engine.reporting; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java index 05f555a220ea..76d01748f8e3 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/package-info.java @@ -3,4 +3,7 @@ * classes intended to be used by test engine implementations. */ +@NullMarked package org.junit.platform.engine.support.config; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java index 9f063532a19a..eabc3dab0055 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/package-info.java @@ -4,4 +4,7 @@ * the launcher. */ +@NullMarked package org.junit.platform.engine.support.descriptor; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java index 1f0ea1ff308a..3d6b8dd4a0aa 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/discovery/package-info.java @@ -6,4 +6,7 @@ * @see org.junit.platform.engine.support.discovery.SelectorResolver */ +@NullMarked package org.junit.platform.engine.support.discovery; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java index 033745ba7795..925cfac6bfec 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/package-info.java @@ -5,4 +5,7 @@ * {@link org.junit.platform.engine.support.hierarchical.Node} abstraction. */ +@NullMarked package org.junit.platform.engine.support.hierarchical; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java index d40e1e88e974..e754a7b508de 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/store/package-info.java @@ -2,4 +2,7 @@ * Reusable data structures for test engines and their extensions. */ +@NullMarked package org.junit.platform.engine.support.store; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-jfr/src/main/java/module-info.java b/junit-platform-jfr/src/main/java/module-info.java index 4a8ada5dc3aa..6f38bf063cf7 100644 --- a/junit-platform-jfr/src/main/java/module-info.java +++ b/junit-platform-jfr/src/main/java/module-info.java @@ -8,8 +8,6 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Provides Java Flight Recorder events for the JUnit Platform. * @@ -21,7 +19,6 @@ * @see JEP 328: Flight Recorder * @since 1.7 */ -@NullMarked module org.junit.platform.jfr { requires jdk.jfr; requires static org.apiguardian.api; diff --git a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/package-info.java b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/package-info.java index 0a8c981374f7..3da51bbd60f8 100644 --- a/junit-platform-jfr/src/main/java/org/junit/platform/jfr/package-info.java +++ b/junit-platform-jfr/src/main/java/org/junit/platform/jfr/package-info.java @@ -2,4 +2,7 @@ * Java Flight Recorder support package. */ +@NullMarked package org.junit.platform.jfr; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-reporting/src/main/java/module-info.java b/junit-platform-reporting/src/main/java/module-info.java index 5f2071c64f1f..f1fe8cd51dca 100644 --- a/junit-platform-reporting/src/main/java/module-info.java +++ b/junit-platform-reporting/src/main/java/module-info.java @@ -8,14 +8,11 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Defines the JUnit Platform Reporting API. * * @since 1.4 */ -@NullMarked module org.junit.platform.reporting { requires java.xml; requires static transitive org.apiguardian.api; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/package-info.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/package-info.java index f7a50ee115f0..af41a0a5efbe 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/package-info.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/package-info.java @@ -2,4 +2,7 @@ * Support for legacy reporting formats. */ +@NullMarked package org.junit.platform.reporting.legacy; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/package-info.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/package-info.java index d41e891b296a..bdec16594877 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/package-info.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/package-info.java @@ -4,4 +4,7 @@ * by the Ant build system. */ +@NullMarked package org.junit.platform.reporting.legacy.xml; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/package-info.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/package-info.java index 5befd7af7b57..15a76f02d2c6 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/package-info.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/open/xml/package-info.java @@ -2,4 +2,7 @@ * Support for generating Open Test Reporting compatible XML event reports. */ +@NullMarked package org.junit.platform.reporting.open.xml; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/package-info.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/package-info.java index d7c603241d19..09fb2bd2538e 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/package-info.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/package-info.java @@ -2,4 +2,7 @@ * JUnit Platform Reporting. */ +@NullMarked package org.junit.platform.reporting; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-suite-api/src/main/java/module-info.java b/junit-platform-suite-api/src/main/java/module-info.java index acb1f901d834..9d8df8da3cf0 100644 --- a/junit-platform-suite-api/src/main/java/module-info.java +++ b/junit-platform-suite-api/src/main/java/module-info.java @@ -8,14 +8,11 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Annotations for configuring a test suite on the JUnit Platform. * * @since 1.0 */ -@NullMarked module org.junit.platform.suite.api { requires static transitive org.apiguardian.api; requires transitive org.junit.platform.commons; diff --git a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java index 1e54ed53ef68..7463a9aa06e8 100644 --- a/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java +++ b/junit-platform-suite-api/src/main/java/org/junit/platform/suite/api/package-info.java @@ -6,4 +6,7 @@ * {@code junit-platform-suite-engine} module. */ +@NullMarked package org.junit.platform.suite.api; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-suite-commons/src/main/java/module-info.java b/junit-platform-suite-commons/src/main/java/module-info.java index ddb988a135e2..52c508bdace7 100644 --- a/junit-platform-suite-commons/src/main/java/module-info.java +++ b/junit-platform-suite-commons/src/main/java/module-info.java @@ -8,14 +8,11 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Common support utilities for declarative test suites. * * @since 1.8 */ -@NullMarked module org.junit.platform.suite.commons { requires static transitive org.apiguardian.api; requires org.junit.platform.suite.api; diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/package-info.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/package-info.java index 3eeb635013aa..422ebf466472 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/package-info.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/package-info.java @@ -8,4 +8,7 @@ * APIs by external parties is not supported! */ +@NullMarked package org.junit.platform.suite.commons; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-suite-engine/src/main/java/module-info.java b/junit-platform-suite-engine/src/main/java/module-info.java index 779dc9cf0349..e8a43bf80e1c 100644 --- a/junit-platform-suite-engine/src/main/java/module-info.java +++ b/junit-platform-suite-engine/src/main/java/module-info.java @@ -8,8 +8,6 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Provides a {@link org.junit.platform.engine.TestEngine} for running * declarative test suites. @@ -17,7 +15,6 @@ * @since 1.8 * @provides org.junit.platform.engine.TestEngine */ -@NullMarked module org.junit.platform.suite.engine { requires static org.apiguardian.api; requires org.junit.platform.suite.api; diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/package-info.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/package-info.java index fa4237d3cec4..09748becae7e 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/package-info.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/package-info.java @@ -2,4 +2,7 @@ * Core package for the JUnit Platform Suite test engine. */ +@NullMarked package org.junit.platform.suite.engine; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-testkit/src/main/java/module-info.java b/junit-platform-testkit/src/main/java/module-info.java index 4e74f159445f..58f2033bcf62 100644 --- a/junit-platform-testkit/src/main/java/module-info.java +++ b/junit-platform-testkit/src/main/java/module-info.java @@ -8,15 +8,12 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Defines the Test Kit API for the JUnit Platform. * * @since 1.4 * @uses org.junit.platform.engine.TestEngine */ -@NullMarked module org.junit.platform.testkit { requires static transitive org.apiguardian.api; requires transitive org.assertj.core; diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/package-info.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/package-info.java index c50fec3e29c1..808c8a16ef53 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/package-info.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/package-info.java @@ -3,4 +3,7 @@ * running on the JUnit Platform. */ +@NullMarked package org.junit.platform.testkit.engine; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/package-info.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/package-info.java index 7a10b625264b..3a5c5b1062d3 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/package-info.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/package-info.java @@ -2,4 +2,7 @@ * Test Kit for the JUnit Platform. */ +@NullMarked package org.junit.platform.testkit; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-vintage-engine/src/main/java/module-info.java b/junit-vintage-engine/src/main/java/module-info.java index dbc7a87af0d1..6880a39df91d 100644 --- a/junit-vintage-engine/src/main/java/module-info.java +++ b/junit-vintage-engine/src/main/java/module-info.java @@ -8,8 +8,6 @@ * https://www.eclipse.org/legal/epl-v20.html */ -import org.jspecify.annotations.NullMarked; - /** * Provides a {@link org.junit.platform.engine.TestEngine} for running JUnit 3 * and 4 based tests on the platform. @@ -18,7 +16,6 @@ * @provides org.junit.platform.engine.TestEngine The {@code VintageTestEngine} * runs JUnit 3 and 4 based tests on the platform. */ -@NullMarked module org.junit.vintage.engine { requires junit; // 4 requires static org.apiguardian.api; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/package-info.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/package-info.java index bef751cbdc9f..7743a7448580 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/package-info.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/package-info.java @@ -2,4 +2,7 @@ * Test descriptors used within the JUnit Vintage test engine. */ +@NullMarked package org.junit.vintage.engine.descriptor; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/package-info.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/package-info.java index a22ae3939187..4e99c954b753 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/package-info.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/package-info.java @@ -2,4 +2,7 @@ * Internal classes for test discovery within the JUnit Vintage test engine. */ +@NullMarked package org.junit.vintage.engine.discovery; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/package-info.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/package-info.java index 43e48e1d4ad6..3749427c181f 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/package-info.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/package-info.java @@ -2,4 +2,7 @@ * Internal classes for test execution within the JUnit Vintage test engine. */ +@NullMarked package org.junit.vintage.engine.execution; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/package-info.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/package-info.java index af7d60d30f7e..05e48ea8ece3 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/package-info.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/package-info.java @@ -2,4 +2,7 @@ * Core package for the JUnit Vintage test engine. */ +@NullMarked package org.junit.vintage.engine; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/package-info.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/package-info.java index bb5a291af76f..35401fcf225c 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/package-info.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/support/package-info.java @@ -3,4 +3,7 @@ * Vintage test engine. */ +@NullMarked package org.junit.vintage.engine.support; + +import org.jspecify.annotations.NullMarked; From e2770d9c0b1cb9aa24020f339cf89f79ebe808da Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 09:46:33 +0200 Subject: [PATCH 115/521] Enable NullAway in junit-platform-launcher --- .../junit-platform-launcher.gradle.kts | 2 + .../launcher/AbstractMethodFilter.java | 4 +- .../launcher/EngineDiscoveryResult.java | 7 ++- .../launcher/ExcludeMethodFilter.java | 5 +- .../launcher/IncludeMethodFilter.java | 5 +- .../launcher/LauncherInterceptor.java | 5 +- .../junit/platform/launcher/TagFilter.java | 3 +- .../platform/launcher/TestIdentifier.java | 16 ++++++- .../core/ClasspathAlignmentChecker.java | 3 +- .../launcher/core/DefaultLauncher.java | 2 +- .../core/DiscoveryIssueCollector.java | 2 + .../launcher/core/DiscoveryIssueNotifier.java | 14 ++++-- .../HierarchicalOutputDirectoryProvider.java | 3 ++ .../launcher/core/InterceptingLauncher.java | 2 + .../core/LauncherConfigurationParameters.java | 8 ++++ .../core/LauncherDiscoveryRequestBuilder.java | 5 ++ .../core/LauncherDiscoveryResult.java | 9 +++- ...utcomeDelayingEngineExecutionListener.java | 21 ++++++-- .../launcher/core/ServiceLoaderRegistry.java | 3 +- .../launcher/core/StreamInterceptor.java | 3 ++ .../platform/launcher/core/package-info.java | 3 ++ .../launcher/listeners/LoggingListener.java | 5 +- .../MutableTestExecutionSummary.java | 2 +- .../listeners/SummaryGeneratingListener.java | 48 ++++++++++++------- .../listeners/UniqueIdTrackingListener.java | 6 ++- .../listeners/discovery/package-info.java | 3 ++ .../launcher/listeners/package-info.java | 3 ++ .../listeners/session/package-info.java | 3 ++ .../junit/platform/launcher/package-info.java | 3 ++ .../launcher/tagexpression/DequeStack.java | 6 ++- .../launcher/tagexpression/Operator.java | 12 ++++- .../launcher/tagexpression/Operators.java | 7 ++- .../launcher/tagexpression/ParseResult.java | 2 +- .../launcher/tagexpression/ParseStatus.java | 7 ++- .../launcher/tagexpression/Parser.java | 6 ++- .../launcher/tagexpression/ShuntingYard.java | 7 +-- .../launcher/tagexpression/TagExpression.java | 6 ++- .../launcher/tagexpression/Tokenizer.java | 4 +- .../launcher/tagexpression/package-info.java | 3 ++ .../tagexpression/ParserErrorTests.java | 7 +-- .../tagexpression/TokenizerTests.java | 5 +- .../tooling/support/tests/ArchUnitTests.java | 3 +- 42 files changed, 200 insertions(+), 73 deletions(-) diff --git a/junit-platform-launcher/junit-platform-launcher.gradle.kts b/junit-platform-launcher/junit-platform-launcher.gradle.kts index a9b3630762c8..dd6a9ff2a991 100644 --- a/junit-platform-launcher/junit-platform-launcher.gradle.kts +++ b/junit-platform-launcher/junit-platform-launcher.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") `java-test-fixtures` } @@ -10,6 +11,7 @@ dependencies { api(projects.junitPlatformEngine) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) osgiVerification(projects.junitJupiterEngine) } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java index 9ac17deea90c..9b60eecb1c6a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java @@ -18,6 +18,7 @@ import java.util.Optional; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; @@ -42,13 +43,14 @@ abstract class AbstractMethodFilter implements MethodFilter { this.patternDescription = Arrays.stream(patterns).collect(joining("' OR '", "'", "'")); } - protected Optional findMatchingPattern(String methodName) { + protected Optional findMatchingPattern(@Nullable String methodName) { if (methodName == null) { return Optional.empty(); } return this.patterns.stream().filter(pattern -> pattern.matcher(methodName).matches()).findAny(); } + @Nullable protected String getFullyQualifiedMethodNameFromDescriptor(TestDescriptor descriptor) { return descriptor.getSource() // .filter(source -> source instanceof MethodSource) // diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java index b3c104b57fa2..c266f3319ab0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java @@ -15,6 +15,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.ToStringBuilder; /** @@ -66,14 +67,16 @@ public static EngineDiscoveryResult successful() { * {@code null} * @return the {@code EngineDiscoveryResult}; never {@code null} */ - public static EngineDiscoveryResult failed(Throwable throwable) { + public static EngineDiscoveryResult failed(@Nullable Throwable throwable) { return new EngineDiscoveryResult(Status.FAILED, throwable); } private final Status status; + + @Nullable private final Throwable throwable; - private EngineDiscoveryResult(Status status, Throwable throwable) { + private EngineDiscoveryResult(Status status, @Nullable Throwable throwable) { this.status = status; this.throwable = throwable; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java index 4b17bfb54453..0466277e0894 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/ExcludeMethodFilter.java @@ -15,6 +15,7 @@ import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; @@ -41,11 +42,11 @@ public FilterResult apply(TestDescriptor descriptor) { .orElseGet(() -> included(formatInclusionReason(methodName))); } - private String formatInclusionReason(String methodName) { + private String formatInclusionReason(@Nullable String methodName) { return "Method name [%s] does not match any excluded pattern: %s".formatted(methodName, patternDescription); } - private String formatExclusionReason(String methodName, Pattern pattern) { + private String formatExclusionReason(@Nullable String methodName, Pattern pattern) { return "Method name [%s] matches excluded pattern: '%s'".formatted(methodName, pattern); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java index 26a467f9552c..ff0c979f53a4 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/IncludeMethodFilter.java @@ -15,6 +15,7 @@ import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.FilterResult; import org.junit.platform.engine.TestDescriptor; @@ -41,11 +42,11 @@ public FilterResult apply(TestDescriptor descriptor) { .orElseGet(() -> excluded(formatExclusionReason(methodName))); } - private String formatInclusionReason(String methodName, Pattern pattern) { + private String formatInclusionReason(@Nullable String methodName, Pattern pattern) { return "Method name [%s] matches included pattern: '%s'".formatted(methodName, pattern); } - private String formatExclusionReason(String methodName) { + private String formatExclusionReason(@Nullable String methodName) { return "Method name [%s] does not match any included pattern: %s".formatted(methodName, patternDescription); } 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..04dd3edb4c69 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 @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * Interceptor for test discovery and execution by a {@link Launcher} in the @@ -63,7 +64,7 @@ public interface LauncherInterceptor { * @param invocation the intercepted invocation; never {@code null} * @return the result of the invocation */ - T intercept(Invocation invocation); + T intercept(Invocation invocation); /** * Closes this interceptor. @@ -78,7 +79,7 @@ public interface LauncherInterceptor { * *

This interface is not intended to be implemented by clients. */ - interface Invocation { + interface Invocation { T proceed(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java index 406b28d3d613..51e37f95dbc6 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java @@ -20,6 +20,7 @@ import java.util.stream.Collectors; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.FilterResult; @@ -175,7 +176,7 @@ private static List parseAll(List tagExpressions) { return tagExpressions.stream().map(TagFilter::parse).collect(toUnmodifiableList()); } - private static TagExpression parse(String tagExpression) { + private static TagExpression parse(@Nullable String tagExpression) { return TagExpression.parseFrom(tagExpression).tagExpressionOrThrow( message -> new PreconditionViolationException( "Unable to parse tag expression \"" + tagExpression + "\": " + message)); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index 1d4eca7a17e0..bd4329d26afc 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -30,6 +30,7 @@ import java.util.Set; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; import org.junit.platform.engine.TestDescriptor; @@ -56,9 +57,14 @@ public final class TestIdentifier implements Serializable { // These are effectively final but not technically due to late initialization when deserializing private /* final */ UniqueId uniqueId; + + @Nullable private /* final */ UniqueId parentId; + private /* final */ String displayName; private /* final */ String legacyReportingName; + + @Nullable private /* final */ TestSource source; private /* final */ Set tags; private /* final */ Type type; @@ -79,8 +85,8 @@ public static TestIdentifier from(TestDescriptor testDescriptor) { return new TestIdentifier(uniqueId, displayName, source, tags, type, parentId, legacyReportingName); } - private TestIdentifier(UniqueId uniqueId, String displayName, TestSource source, Set tags, Type type, - UniqueId parentId, String legacyReportingName) { + private TestIdentifier(UniqueId uniqueId, String displayName, @Nullable TestSource source, Set tags, + Type type, @Nullable UniqueId parentId, String legacyReportingName) { Preconditions.notNull(type, "TestDescriptor.Type must not be null"); this.uniqueId = uniqueId; this.parentId = parentId; @@ -303,10 +309,16 @@ private static class SerializedForm implements Serializable { private static final long serialVersionUID = 1L; private final String uniqueId; + + @Nullable private final String parentId; + private final String displayName; private final String legacyReportingName; + + @Nullable private final TestSource source; + @SuppressWarnings({ "serial", "RedundantSuppression" }) // always used with serializable implementation (see TestIdentifier#copyOf()) private final Set tags; private final Type type; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 09a436d7507c..08d811926ec3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -22,6 +22,7 @@ import java.util.Optional; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.ClassLoaderUtils; @@ -60,7 +61,7 @@ static Optional check(LinkageError error) { } // VisibleForTesting - static Optional check(LinkageError error, Function packageLookup) { + static Optional check(LinkageError error, Function packageLookup) { Map> packagesByVersions = new HashMap<>(); WELL_KNOWN_PACKAGES.stream() // .map(packageLookup) // diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java index c4691503ba1f..509467bf108a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultLauncher.java @@ -56,7 +56,7 @@ class DefaultLauncher implements Launcher { */ DefaultLauncher(Iterable testEngines, Collection postDiscoveryFilters, NamespacedHierarchicalStore sessionLevelStore) { - Preconditions.condition(testEngines != null && testEngines.iterator().hasNext(), + Preconditions.condition(testEngines.iterator().hasNext(), () -> "Cannot create Launcher without at least one TestEngine; " + "consider adding an engine implementation JAR to the classpath"); Preconditions.notNull(postDiscoveryFilters, "PostDiscoveryFilter array must not be null"); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java index e78e720272dd..573b4032bd99 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Locale; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.ConfigurationParameters; @@ -77,6 +78,7 @@ else if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelecto } } + @Nullable static TestSource toSource(DiscoverySelector selector) { if (selector instanceof ClassSelector classSelector) { return ClassSource.from(classSelector.getClassName()); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java index f7b3abe14c22..6dbae69407c3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java @@ -21,6 +21,7 @@ import java.util.function.Consumer; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.Preconditions; @@ -42,15 +43,21 @@ class DiscoveryIssueNotifier { private final List criticalIssues; private final List nonCriticalIssues; + @SuppressWarnings("NullAway") static DiscoveryIssueNotifier from(Severity criticalSeverity, List issues) { - Map> issuesByCriticality = issues.stream() // - .sorted(comparing(DiscoveryIssue::severity).reversed()) // - .collect(partitioningBy(issue -> issue.severity().compareTo(criticalSeverity) >= 0)); + var issuesByCriticality = partitionByCriticality(criticalSeverity, issues); List criticalIssues = issuesByCriticality.get(true); List nonCriticalIssues = issuesByCriticality.get(false); return new DiscoveryIssueNotifier(new ArrayList<>(issues), criticalIssues, nonCriticalIssues); } + private static Map> partitionByCriticality(Severity criticalSeverity, + List issues) { + return issues.stream() // + .sorted(comparing(DiscoveryIssue::severity).reversed()) // + .collect(partitioningBy(issue -> issue.severity().compareTo(criticalSeverity) >= 0)); + } + private DiscoveryIssueNotifier(List allIssues, List criticalIssues, List nonCriticalIssues) { this.allIssues = allIssues; @@ -74,6 +81,7 @@ void logNonCriticalIssues(TestEngine testEngine) { logIssues(testEngine, nonCriticalIssues, "non-critical"); } + @Nullable DiscoveryIssueException createExceptionForCriticalIssues(TestEngine testEngine) { if (criticalIssues.isEmpty()) { return null; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java index c5a9772d67a0..0012a5add088 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java @@ -17,6 +17,7 @@ import java.util.function.Supplier; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId.Segment; @@ -34,6 +35,8 @@ class HierarchicalOutputDirectoryProvider implements OutputDirectoryProvider { private static final String REPLACEMENT = "_"; private final Supplier rootDirSupplier; + + @Nullable private volatile Path rootDir; HierarchicalOutputDirectoryProvider(Supplier rootDirSupplier) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java index 44656ff04a51..063b60a51d22 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java @@ -34,6 +34,7 @@ public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { } @Override + @SuppressWarnings("NullAway") public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { interceptor.intercept(() -> { super.execute(launcherDiscoveryRequest, listeners); @@ -42,6 +43,7 @@ public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecu } @Override + @SuppressWarnings("NullAway") public void execute(TestPlan testPlan, TestExecutionListener... listeners) { interceptor.intercept(() -> { super.execute(testPlan, listeners); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java index 9523a05e9b75..1d4f797a4c61 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java @@ -29,6 +29,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; @@ -70,6 +71,7 @@ public Set keySet() { Collectors.toSet()); } + @Nullable private String getProperty(String key) { Preconditions.notBlank(key, "key must not be null or blank"); return providers.stream() // @@ -92,6 +94,8 @@ static final class Builder { private final List configResources = new ArrayList<>(); private boolean implicitProvidersEnabled = true; private String configFileName = ConfigurationParameters.CONFIG_FILE_NAME; + + @Nullable private ConfigurationParameters parentConfigurationParameters; private Builder() { @@ -149,6 +153,7 @@ LauncherConfigurationParameters build() { private interface ParameterProvider { + @Nullable String getValue(String key); default int size() { @@ -160,6 +165,7 @@ default int size() { static ParameterProvider explicit(Map configParams) { return new ParameterProvider() { @Override + @Nullable public String getValue(String key) { return configParams.get(key); } @@ -186,6 +192,7 @@ public String toString() { static ParameterProvider systemProperties() { return new ParameterProvider() { @Override + @Nullable public String getValue(String key) { try { return System.getProperty(key); @@ -233,6 +240,7 @@ public String toString() { static ParameterProvider inherited(ConfigurationParameters configParams) { return new ParameterProvider() { @Override + @Nullable public String getValue(String key) { return configParams.get(key).orElse(null); } 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 8154f4024d25..8f821985f3d6 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 @@ -22,6 +22,7 @@ import java.util.Map; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; @@ -109,7 +110,11 @@ public final class LauncherDiscoveryRequestBuilder { private final List configurationParametersResources = new ArrayList<>(); private final List discoveryListeners = new ArrayList<>(); private boolean implicitConfigurationParametersEnabled = true; + + @Nullable private ConfigurationParameters parentConfigurationParameters; + + @Nullable private OutputDirectoryProvider outputDirectoryProvider; /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java index 7b3db9368915..9be73b2ed4c8 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java @@ -11,6 +11,7 @@ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableMap; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toMap; import static org.apiguardian.api.API.Status.INTERNAL; @@ -23,6 +24,7 @@ import java.util.stream.Collectors; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.ConfigurationParameters; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.TestDescriptor; @@ -59,7 +61,7 @@ public List getDiscoveryIssues(TestEngine testEngine) { } EngineResultInfo getEngineResult(TestEngine testEngine) { - return this.testEngineResults.get(testEngine); + return requireNonNull(this.testEngineResults.get(testEngine)); } ConfigurationParameters getConfigurationParameters() { @@ -116,11 +118,14 @@ static EngineResultInfo errored(TestDescriptor rootDescriptor, DiscoveryIssueNot } private final TestDescriptor rootDescriptor; + + @Nullable private final Throwable cause; + private final DiscoveryIssueNotifier discoveryIssueNotifier; EngineResultInfo(TestDescriptor rootDescriptor, DiscoveryIssueNotifier discoveryIssueNotifier, - Throwable cause) { + @Nullable Throwable cause) { this.rootDescriptor = rootDescriptor; this.discoveryIssueNotifier = discoveryIssueNotifier; this.cause = cause; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java index 7bdfe458e03f..4ea6111553ce 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java @@ -10,6 +10,11 @@ package org.junit.platform.launcher.core; +import static java.util.Objects.requireNonNull; + +import java.util.Optional; + +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestExecutionResult; @@ -25,8 +30,14 @@ class OutcomeDelayingEngineExecutionListener extends DelegatingEngineExecutionLi private final TestDescriptor engineDescriptor; private volatile boolean engineStarted; + + @Nullable private volatile Outcome outcome; + + @Nullable private volatile String skipReason; + + @Nullable private volatile TestExecutionResult executionResult; OutcomeDelayingEngineExecutionListener(EngineExecutionListener delegate, TestDescriptor engineDescriptor) { @@ -66,10 +77,10 @@ public void executionFinished(TestDescriptor testDescriptor, TestExecutionResult void reportEngineOutcome() { if (outcome == Outcome.FINISHED) { - super.executionFinished(engineDescriptor, executionResult); + super.executionFinished(engineDescriptor, requireNonNull(executionResult)); } else if (outcome == Outcome.SKIPPED) { - super.executionSkipped(engineDescriptor, skipReason); + super.executionSkipped(engineDescriptor, requireNonNull(skipReason)); } } @@ -80,9 +91,9 @@ void reportEngineStartIfNecessary() { } void reportEngineFailure(Throwable throwable) { - if (executionResult != null && executionResult.getThrowable().isPresent()) { - throwable.addSuppressed(executionResult.getThrowable().get()); - } + Optional.ofNullable(this.executionResult) // + .flatMap(TestExecutionResult::getThrowable) // + .ifPresent(throwable::addSuppressed); super.executionFinished(engineDescriptor, TestExecutionResult.failed(throwable)); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java index ebab21e42302..f090b2bbdf12 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java @@ -18,6 +18,7 @@ import java.util.function.Function; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.ClassLoaderUtils; @@ -45,7 +46,7 @@ static Iterable load(@SuppressWarnings("SameParameterValue") Class typ return load(type, collectingClassNameFilter, instances -> logLoadedInstances(type, instances, exclusions)); } - private static String logLoadedInstances(Class type, List instances, List exclusions) { + private static String logLoadedInstances(Class type, List instances, @Nullable List exclusions) { String typeName = type.getSimpleName(); if (exclusions == null) { return "Loaded %s instances: %s".formatted(typeName, instances); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java index 85b69f64bb26..430c961688df 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java @@ -18,6 +18,8 @@ import java.util.concurrent.ConcurrentLinkedDeque; import java.util.function.Consumer; +import org.jspecify.annotations.Nullable; + /** * @since 1.3 */ @@ -112,6 +114,7 @@ private void pushToTop(RewindableByteArrayOutputStream out) { } } + @Nullable private RewindableByteArrayOutputStream getOutput() { RewindableByteArrayOutputStream out = output.get(); return out.isMarked() ? out : mostRecentOutputs.peek(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/package-info.java index 779b81d67b93..fca61aab1372 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/package-info.java @@ -5,4 +5,7 @@ * LauncherDiscoveryRequestBuilder}. */ +@NullMarked package org.junit.platform.launcher.core; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java index eb0fd73cdd74..a17b48147a40 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java @@ -18,6 +18,7 @@ import java.util.logging.Logger; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; @@ -82,7 +83,7 @@ public static LoggingListener forBiConsumer(BiConsumer> logger; + private final BiConsumer<@Nullable Throwable, Supplier> logger; private LoggingListener(BiConsumer> logger) { this.logger = Preconditions.notNull(logger, "logger must not be null"); @@ -123,7 +124,7 @@ private void log(String message, Object... args) { logWithThrowable(message, null, args); } - private void logWithThrowable(String message, Throwable t, Object... args) { + private void logWithThrowable(String message, @Nullable Throwable t, Object... args) { this.logger.accept(t, () -> message.formatted(args)); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java index 0ef6826b016b..f53d3381756d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java @@ -250,7 +250,7 @@ private void printStackTrace(PrintWriter writer, StackTraceElement[] parentTrace seenThrowables.add(throwable); StackTraceElement[] trace = throwable.getStackTrace(); - if (parentTrace != null && parentTrace.length > 0) { + if (parentTrace.length > 0) { writer.printf("%s%s%s%n", indentation, caption, throwable); } int duplicates = numberOfCommonFrames(trace, parentTrace); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java index 751888b2ae86..49d20e0331aa 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java @@ -10,13 +10,16 @@ package org.junit.platform.launcher.listeners; +import static java.util.Objects.requireNonNull; import static java.util.stream.Stream.concat; import static org.apiguardian.api.API.Status.MAINTAINED; import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; +import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.launcher.TestExecutionListener; import org.junit.platform.launcher.TestIdentifier; @@ -32,7 +35,10 @@ @API(status = MAINTAINED, since = "1.0") public class SummaryGeneratingListener implements TestExecutionListener { + @Nullable private TestPlan testPlan; + + @Nullable private MutableTestExecutionSummary summary; public SummaryGeneratingListener() { @@ -43,7 +49,11 @@ public SummaryGeneratingListener() { * Get the summary generated by this listener. */ public TestExecutionSummary getSummary() { - return this.summary; + return getMutableSummary(); + } + + private MutableTestExecutionSummary getMutableSummary() { + return Preconditions.notNull(this.summary, "No tests have yet been executed"); } @Override @@ -54,22 +64,25 @@ public void testPlanExecutionStarted(TestPlan testPlan) { @Override public void testPlanExecutionFinished(TestPlan testPlan) { - this.summary.timeFinished = System.currentTimeMillis(); - this.summary.timeFinishedNanos = System.nanoTime(); + var summary = getMutableSummary(); + summary.timeFinished = System.currentTimeMillis(); + summary.timeFinishedNanos = System.nanoTime(); } @Override public void dynamicTestRegistered(TestIdentifier testIdentifier) { + var summary = getMutableSummary(); if (testIdentifier.isContainer()) { - this.summary.containersFound.incrementAndGet(); + summary.containersFound.incrementAndGet(); } if (testIdentifier.isTest()) { - this.summary.testsFound.incrementAndGet(); + summary.testsFound.incrementAndGet(); } } @Override public void executionSkipped(TestIdentifier testIdentifier, String reason) { + var testPlan = requireNonNull(this.testPlan); // @formatter:off long skippedContainers = concat(Stream.of(testIdentifier), testPlan.getDescendants(testIdentifier).stream()) .filter(TestIdentifier::isContainer) @@ -78,54 +91,57 @@ public void executionSkipped(TestIdentifier testIdentifier, String reason) { .filter(TestIdentifier::isTest) .count(); // @formatter:on - this.summary.containersSkipped.addAndGet(skippedContainers); - this.summary.testsSkipped.addAndGet(skippedTests); + var summary = getMutableSummary(); + summary.containersSkipped.addAndGet(skippedContainers); + summary.testsSkipped.addAndGet(skippedTests); } @Override public void executionStarted(TestIdentifier testIdentifier) { + var summary = getMutableSummary(); if (testIdentifier.isContainer()) { - this.summary.containersStarted.incrementAndGet(); + summary.containersStarted.incrementAndGet(); } if (testIdentifier.isTest()) { - this.summary.testsStarted.incrementAndGet(); + summary.testsStarted.incrementAndGet(); } } @Override public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) { + var summary = getMutableSummary(); switch (testExecutionResult.getStatus()) { case SUCCESSFUL: { if (testIdentifier.isContainer()) { - this.summary.containersSucceeded.incrementAndGet(); + summary.containersSucceeded.incrementAndGet(); } if (testIdentifier.isTest()) { - this.summary.testsSucceeded.incrementAndGet(); + summary.testsSucceeded.incrementAndGet(); } break; } case ABORTED: { if (testIdentifier.isContainer()) { - this.summary.containersAborted.incrementAndGet(); + summary.containersAborted.incrementAndGet(); } if (testIdentifier.isTest()) { - this.summary.testsAborted.incrementAndGet(); + summary.testsAborted.incrementAndGet(); } break; } case FAILED: { if (testIdentifier.isContainer()) { - this.summary.containersFailed.incrementAndGet(); + summary.containersFailed.incrementAndGet(); } if (testIdentifier.isTest()) { - this.summary.testsFailed.incrementAndGet(); + summary.testsFailed.incrementAndGet(); } testExecutionResult.getThrowable().ifPresent( - throwable -> this.summary.addFailure(testIdentifier, throwable)); + throwable -> summary.addFailure(testIdentifier, throwable)); break; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java index e25e4319da31..2c05881a5bfb 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.listeners; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.STABLE; import java.io.IOException; @@ -23,6 +24,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.ConfigurationParameters; @@ -134,6 +136,8 @@ public class UniqueIdTrackingListener implements TestExecutionListener { private final List uniqueIds = new ArrayList<>(); private boolean enabled; + + @Nullable private TestPlan testPlan; public UniqueIdTrackingListener() { @@ -165,7 +169,7 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult private void trackTestUidRecursively(TestIdentifier testIdentifier) { boolean tracked = trackTestUid(testIdentifier); if (!tracked) { - this.testPlan.getChildren(testIdentifier).forEach(this::trackTestUidRecursively); + requireNonNull(this.testPlan).getChildren(testIdentifier).forEach(this::trackTestUidRecursively); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/package-info.java index 371df34d4fb3..de2821f42f91 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/package-info.java @@ -6,4 +6,7 @@ * @since 1.6 */ +@NullMarked package org.junit.platform.launcher.listeners.discovery; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/package-info.java index d8a0a06ea0a9..e662ea8e912e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/package-info.java @@ -4,4 +4,7 @@ * the {@link org.junit.platform.launcher.Launcher Launcher}. */ +@NullMarked package org.junit.platform.launcher.listeners; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/package-info.java index 97541a153cba..7c6f4f5167ac 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/package-info.java @@ -6,4 +6,7 @@ * @since 1.8 */ +@NullMarked package org.junit.platform.launcher.listeners.session; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/package-info.java index 4005a8426267..4101c31e89d5 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/package-info.java @@ -4,4 +4,7 @@ *

This API is typically used by IDEs and build tools. */ +@NullMarked package org.junit.platform.launcher; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/DequeStack.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/DequeStack.java index 4d3899199cee..6cff93dd5af6 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/DequeStack.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/DequeStack.java @@ -13,6 +13,8 @@ import java.util.ArrayDeque; import java.util.Deque; +import org.junit.platform.commons.util.Preconditions; + /** * @since 1.1 */ @@ -27,12 +29,12 @@ public void push(T t) { @Override public T peek() { - return deque.peek(); + return Preconditions.notNull(deque.peek(), () -> "stack is empty"); } @Override public T pop() { - return deque.pollFirst(); + return Preconditions.notNull(deque.pollFirst(), () -> "stack is empty"); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java index 7adc69050a06..1d6731b7f2e3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.tagexpression; +import static java.util.Objects.requireNonNull; import static org.junit.platform.launcher.tagexpression.Operator.Associativity.Left; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingOperatorBetween; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingRhsOperand; @@ -19,6 +20,8 @@ import java.util.function.BiFunction; import java.util.function.Function; +import org.jspecify.annotations.Nullable; + /** * @since 1.1 */ @@ -36,6 +39,7 @@ static Operator nullaryOperator(String representation, int precedence) { return new Operator(representation, precedence, 0, null, (expressions, operatorToken) -> success()); } + @SuppressWarnings("SameParameterValue") static Operator unaryOperator(String representation, int precedence, Associativity associativity, Function unaryExpression) { @@ -50,6 +54,7 @@ static Operator unaryOperator(String representation, int precedence, Associativi }); } + @SuppressWarnings("SameParameterValue") static Operator binaryOperator(String representation, int precedence, Associativity associativity, BiFunction binaryExpression) { @@ -75,10 +80,13 @@ static Operator binaryOperator(String representation, int precedence, Associativ private final String representation; private final int precedence; private final int arity; + + @Nullable private final Associativity associativity; + private final TagExpressionCreator tagExpressionCreator; - private Operator(String representation, int precedence, int arity, Associativity associativity, + private Operator(String representation, int precedence, int arity, @Nullable Associativity associativity, TagExpressionCreator tagExpressionCreator) { this.representation = representation; @@ -126,7 +134,7 @@ private String createMissingOperandMessage(Stack> expre if (2 == mismatch) { return "missing lhs and rhs operand"; } - return missingOneOperand(operatorToken.isLeftOf(expressions.peek().token) ? "lhs" : "rhs"); + return missingOneOperand(operatorToken.isLeftOf(requireNonNull(expressions.peek()).token) ? "lhs" : "rhs"); } return "missing operand"; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operators.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operators.java index 541ceb976bb1..3ea407374d4c 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operators.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operators.java @@ -18,6 +18,8 @@ import java.util.Map; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; + /** * @since 1.1 */ @@ -30,10 +32,7 @@ class Operators { private final Map representationToOperator = Stream.of(Not, And, Or).collect( toMap(Operator::representation, identity())); - boolean isOperator(String token) { - return representationToOperator.containsKey(token); - } - + @Nullable Operator operatorFor(String token) { return representationToOperator.get(token); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseResult.java index 0882acda8ede..befc5227eaaa 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseResult.java @@ -41,7 +41,7 @@ default TagExpression tagExpressionOrThrow(Function ex if (errorMessage().isPresent()) { throw exceptionCreator.apply(errorMessage().get()); } - return tagExpression().get(); + return tagExpression().orElseThrow(); } /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java index 695ef20c70ac..06aa9db6703b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java @@ -12,6 +12,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * @since 1.1 */ @@ -56,13 +58,14 @@ private static String format(int indexInTagExpression) { return "<" + indexInTagExpression + ">"; } - private static ParseStatus error(String errorMessage) { + private static ParseStatus error(@Nullable String errorMessage) { return new ParseStatus(errorMessage); } + @Nullable final String errorMessage; - private ParseStatus(String errorMessage) { + private ParseStatus(@Nullable String errorMessage) { this.errorMessage = errorMessage; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Parser.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Parser.java index 417cf3e52aad..5605ba4ac3a2 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Parser.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Parser.java @@ -12,6 +12,8 @@ import java.util.List; +import org.jspecify.annotations.Nullable; + /** * @since 1.1 */ @@ -19,11 +21,11 @@ class Parser { private final Tokenizer tokenizer = new Tokenizer(); - ParseResult parse(String infixTagExpression) { + ParseResult parse(@Nullable String infixTagExpression) { return constructExpressionFrom(tokensDerivedFrom(infixTagExpression)); } - private List tokensDerivedFrom(String infixTagExpression) { + private List tokensDerivedFrom(@Nullable String infixTagExpression) { return tokenizer.tokenize(infixTagExpression); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java index b54d40f5b6a9..3808ad6c6f5b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java @@ -11,6 +11,7 @@ package org.junit.platform.launcher.tagexpression; import static java.lang.Integer.MIN_VALUE; +import static java.util.Objects.requireNonNull; import static org.junit.platform.launcher.tagexpression.Operator.nullaryOperator; import static org.junit.platform.launcher.tagexpression.ParseStatus.emptyTagExpression; import static org.junit.platform.launcher.tagexpression.ParseStatus.missingClosingParenthesis; @@ -53,7 +54,7 @@ public ParseResult execute() { .process(this::ensureOnlySingleExpressionRemains); // @formatter:on if (parseStatus.isError()) { - return ParseResults.error(parseStatus.errorMessage); + return ParseResults.error(requireNonNull(parseStatus.errorMessage)); } return ParseResults.success(expressions.pop().element); } @@ -75,8 +76,8 @@ private ParseStatus process(Token token) { if (RightParenthesis.represents(trimmed)) { return findMatchingLeftParenthesis(token); } - if (validOperators.isOperator(trimmed)) { - Operator operator = validOperators.operatorFor(trimmed); + var operator = validOperators.operatorFor(trimmed); + if (operator != null) { return findOperands(token, operator); } pushExpressionAt(token, convertLeafTokenToExpression(trimmed)); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TagExpression.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TagExpression.java index ac101b2a6810..46f04acee8d1 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TagExpression.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TagExpression.java @@ -15,6 +15,7 @@ import java.util.Collection; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestTag; /** @@ -30,11 +31,12 @@ public interface TagExpression { * Attempt to parse a {@link TagExpression} from the supplied tag * expression string. * - * @param infixTagExpression the tag expression string to parse; never {@code null}. + * @param infixTagExpression the tag expression string to parse; may be + * {@code null}. * @see ParseResult */ @API(status = INTERNAL, since = "1.1") - static ParseResult parseFrom(String infixTagExpression) { + static ParseResult parseFrom(@Nullable String infixTagExpression) { return new Parser().parse(infixTagExpression); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java index f21dd73aa332..042f97eb12b1 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java @@ -18,6 +18,8 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; + /** * @since 1.1 */ @@ -26,7 +28,7 @@ class Tokenizer { private static final Pattern PATTERN = Pattern.compile("\\s*(?:(?:(?:any|none)\\(\\))|[()!|&]|(?:[^\\s()!|&]+))", CASE_INSENSITIVE); - List tokenize(String infixTagExpression) { + List tokenize(@Nullable String infixTagExpression) { if (infixTagExpression == null) { return emptyList(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/package-info.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/package-info.java index 53e2a7fac56d..efab367f98dc 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/package-info.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/package-info.java @@ -2,4 +2,7 @@ * The tag expression language parser and related support classes. */ +@NullMarked package org.junit.platform.launcher.tagexpression; + +import org.jspecify.annotations.NullMarked; diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java index 648d624cac3c..71a3b70779fe 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java @@ -15,6 +15,7 @@ import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; @@ -24,11 +25,6 @@ class ParserErrorTests { private final Parser parser = new Parser(); - @Test - void cantParseExpressionFromNull() { - assertThat(parseErrorFromParsing(null)).contains("empty tag expression"); - } - @Test void emptyExpression() { assertThat(parseErrorFromParsing("")).contains("empty tag expression"); @@ -94,6 +90,7 @@ private static Stream data() { // @formatter:on } + @Nullable private String parseErrorFromParsing(String tagExpression) { try { var parseResult = parser.parse(tagExpression); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java index 37cfb09786e6..f305c8b26362 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; class TokenizerTests { @@ -85,11 +86,11 @@ private Stream rawStringsExtractedFrom(String expression) { return tokensExtractedFrom(expression).map(token -> token.rawString); } - private List tokenStringsExtractedFrom(String expression) { + private List tokenStringsExtractedFrom(@Nullable String expression) { return tokensExtractedFrom(expression).map(Token::string).toList(); } - private Stream tokensExtractedFrom(String expression) { + private Stream tokensExtractedFrom(@Nullable String expression) { return new Tokenizer().tokenize(expression).stream(); } } diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index e4b07bca2515..0a8080d8b11e 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -87,8 +87,7 @@ void packagesShouldBeNullMarked(JavaClasses classes) { "org.junit.jupiter.api..", // "org.junit.jupiter.engine..", // "org.junit.jupiter.migrationsupport..", // - "org.junit.jupiter.params..", // - "org.junit.platform.launcher.." // + "org.junit.jupiter.params.." // ).map(PackageMatcher::of).toList(); var subpackages = Stream.of("org.junit.platform", "org.junit.jupiter", "org.junit.vintage") // From 1c5115753c5147f3747d7f04fe4b0b5d1cf7a3ff Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:20:30 +0200 Subject: [PATCH 116/521] Enable NullAway in junit-jupiter-api --- junit-jupiter-api/junit-jupiter-api.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/junit-jupiter-api/junit-jupiter-api.gradle.kts b/junit-jupiter-api/junit-jupiter-api.gradle.kts index 402b5323eb57..f2592212772c 100644 --- a/junit-jupiter-api/junit-jupiter-api.gradle.kts +++ b/junit-jupiter-api/junit-jupiter-api.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.kotlin-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.code-generator") `java-test-fixtures` } @@ -12,6 +13,7 @@ dependencies { api(projects.junitPlatformCommons) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) compileOnly(kotlin("stdlib")) From 3c4a4eef9725f9b34aeba39ca02c3d6d78609ad6 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:20:50 +0200 Subject: [PATCH 117/521] Annotate nullability in `org.junit.jupiter.api.condition` --- .../condition/DisabledIfEnvironmentVariableCondition.java | 2 ++ .../condition/EnabledIfEnvironmentVariableCondition.java | 2 ++ .../junit/jupiter/api/condition/MethodBasedCondition.java | 6 ++++++ .../src/main/java/org/junit/jupiter/api/condition/OS.java | 7 ++++++- .../java/org/junit/jupiter/api/condition/package-info.java | 3 +++ 5 files changed, 19 insertions(+), 1 deletion(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java index 571ab2067d43..df55d472b802 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java @@ -13,6 +13,7 @@ import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; @@ -67,6 +68,7 @@ protected ConditionEvaluationResult evaluate(DisabledIfEnvironmentVariable annot * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ + @Nullable protected String getEnvironmentVariable(String name) { return System.getenv(name); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java index 53dab802e793..984066484e2b 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java @@ -13,6 +13,7 @@ import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.util.Preconditions; @@ -66,6 +67,7 @@ protected ConditionEvaluationResult evaluate(EnabledIfEnvironmentVariable annota * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ + @Nullable protected String getEnvironmentVariable(String name) { return System.getenv(name); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java index 16a468daf4fd..b7103c4898f6 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java @@ -20,6 +20,7 @@ import java.util.function.Function; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.jupiter.api.extension.ExtensionContext; @@ -84,6 +85,11 @@ private boolean invokeConditionMethod(Method method, ExtensionContext context) { () -> "Method [%s] must accept either an ExtensionContext or no arguments".formatted(method)); Object testInstance = context.getTestInstance().orElse(null); + return invokeMethod(method, context, testInstance); + } + + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + private static boolean invokeMethod(Method method, ExtensionContext context, @Nullable Object testInstance) { if (method.getParameterCount() == 0) { return (boolean) ReflectionSupport.invokeMethod(method, testInstance); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java index 49878580bd66..f1e1c2b1592d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java @@ -15,6 +15,7 @@ import java.util.Locale; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.commons.util.StringUtils; @@ -94,22 +95,26 @@ public enum OS { private static final Logger logger = LoggerFactory.getLogger(OS.class); + @Nullable private static final OS CURRENT_OS = determineCurrentOs(); /** - * Get the current operating system. + * {@return the current operating system, if known; otherwise, {@code null}} * * @since 5.9 */ @API(status = STABLE, since = "5.10") + @Nullable public static OS current() { return CURRENT_OS; } + @Nullable private static OS determineCurrentOs() { return parse(System.getProperty("os.name")); } + @Nullable static OS parse(String osName) { if (StringUtils.isBlank(osName)) { logger.debug( diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/package-info.java index 14d1f7fb2a80..77ddff4c5100 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/package-info.java @@ -2,4 +2,7 @@ * Annotation-based conditions for enabling or disabling tests in JUnit Jupiter. */ +@NullMarked package org.junit.jupiter.api.condition; + +import org.jspecify.annotations.NullMarked; From bf8ebb4b68cd59b438ee8ba32b00ee33de84b27e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:22:13 +0200 Subject: [PATCH 118/521] Annotate nullability in `org.junit.jupiter.api.extension.support` --- .../api/extension/support/TypeBasedParameterResolver.java | 8 +++++--- .../junit/jupiter/api/extension/support/package-info.java | 3 +++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java index f2bcf2f73a50..b7746e962622 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java @@ -16,6 +16,7 @@ import java.lang.reflect.Type; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; @@ -29,7 +30,7 @@ * @since 5.6 */ @API(status = STABLE, since = "5.10") -public abstract class TypeBasedParameterResolver implements ParameterResolver { +public abstract class TypeBasedParameterResolver implements ParameterResolver { private final Type supportedParameterType; @@ -51,8 +52,8 @@ private Type getParameterType(ParameterContext parameterContext) { } private Type enclosedTypeOfParameterResolver() { - ParameterizedType typeBasedParameterResolverSuperclass = findTypeBasedParameterResolverSuperclass(getClass()); - Preconditions.notNull(typeBasedParameterResolverSuperclass, + ParameterizedType typeBasedParameterResolverSuperclass = Preconditions.notNull( + findTypeBasedParameterResolverSuperclass(getClass()), () -> String.format( "Failed to discover parameter type supported by %s; " + "potentially caused by lacking parameterized type in class declaration.", @@ -60,6 +61,7 @@ private Type enclosedTypeOfParameterResolver() { return typeBasedParameterResolverSuperclass.getActualTypeArguments()[0]; } + @Nullable private ParameterizedType findTypeBasedParameterResolverSuperclass(Class clazz) { Class superclass = clazz.getSuperclass(); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/package-info.java index 3d4156a34d6b..897de7983f57 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/package-info.java @@ -2,4 +2,7 @@ * JUnit Jupiter API support for writing extensions. */ +@NullMarked package org.junit.jupiter.api.extension.support; + +import org.jspecify.annotations.NullMarked; From d12879657e7aa754a6e92fcd5142b24406f47f86 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:36:24 +0200 Subject: [PATCH 119/521] Annotate nullability in `org.junit.jupiter.api.extension` --- .../api/extension/ExecutableInvoker.java | 7 ++++-- .../api/extension/ExtensionContext.java | 17 +++++++++---- .../extension/ExtensionContextException.java | 5 ++-- .../api/extension/InvocationInterceptor.java | 24 ++++++++++--------- .../api/extension/ParameterResolver.java | 2 ++ .../jupiter/api/extension/TestWatcher.java | 5 ++-- .../jupiter/api/extension/package-info.java | 3 +++ 7 files changed, 42 insertions(+), 21 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java index 37645f08e1ee..9365c05dffc2 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java @@ -16,6 +16,7 @@ import java.lang.reflect.Method; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * {@code ExecutableInvoker} allows invoking methods and constructors @@ -33,6 +34,7 @@ public interface ExecutableInvoker { * @param method the method to invoke and resolve parameters for * @see #invoke(Method, Object) */ + @Nullable default Object invoke(Method method) { return invoke(method, null); } @@ -44,7 +46,8 @@ default Object invoke(Method method) { * @param target the target on which the executable will be invoked; * can be {@code null} for {@code static} methods */ - Object invoke(Method method, Object target); + @Nullable + Object invoke(Method method, @Nullable Object target); /** * Invoke the supplied top-level constructor with dynamic parameter resolution. @@ -67,6 +70,6 @@ default T invoke(Constructor constructor) { * to the constructor; must be {@code null} for top-level classes * or {@code static} nested classes */ - T invoke(Constructor constructor, Object outerInstance); + T invoke(Constructor constructor, @Nullable Object outerInstance); } 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 1f1eeda903f4..5cdc8e48c48e 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 @@ -29,6 +29,7 @@ import java.util.function.Function; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.jupiter.api.parallel.ExecutionMode; @@ -535,6 +536,7 @@ interface CloseableResource { * @see #get(Object, Class) * @see #getOrDefault(Object, Class, Object) */ + @Nullable Object get(Object key); /** @@ -553,6 +555,7 @@ interface CloseableResource { * @see #get(Object) * @see #getOrDefault(Object, Class, Object) */ + @Nullable V get(Object key, Class requiredType); /** @@ -570,7 +573,8 @@ interface CloseableResource { * @param requiredType the required type of the value; never {@code null} * @param defaultValue the default value * @param the value type - * @return the value; potentially {@code null} + * @return the value; potentially {@code null} if {@code defaultValue} + * is {@code null} * @since 5.5 * @see #get(Object, Class) */ @@ -613,6 +617,7 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @API(status = STABLE, since = "5.1") default V getOrComputeIfAbsent(Class type) { return getOrComputeIfAbsent(type, ReflectionSupport::newInstance, type); @@ -648,7 +653,8 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - Object getOrComputeIfAbsent(K key, Function defaultCreator); + @Nullable + Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the @@ -679,7 +685,8 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); + @Nullable + V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. @@ -700,7 +707,7 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - void put(Object key, Object value); + void put(Object key, @Nullable Object value); /** * Remove the value that was previously stored under the supplied {@code key}. @@ -717,6 +724,7 @@ default V getOrComputeIfAbsent(Class type) { * for the specified key * @see #remove(Object, Class) */ + @Nullable Object remove(Object key); /** @@ -734,6 +742,7 @@ default V getOrComputeIfAbsent(Class type) { * for the specified key * @see #remove(Object) */ + @Nullable V remove(Object key, Class requiredType); } 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 eb9ad1138504..0b1f08fa6071 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 @@ -16,6 +16,7 @@ import java.io.Serial; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.platform.commons.JUnitException; @@ -32,12 +33,12 @@ public class ExtensionContextException extends JUnitException { private static final long serialVersionUID = 1L; @SuppressWarnings("unused") - public ExtensionContextException(String message) { + public ExtensionContextException(@Nullable String message) { super(message); } @API(status = EXPERIMENTAL, since = "5.10") - public ExtensionContextException(String message, Throwable cause) { + public ExtensionContextException(@Nullable String message, Throwable cause) { super(message, cause); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java index 6f59a125b15e..933ce4588ef5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java @@ -16,6 +16,7 @@ import java.lang.reflect.Method; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -93,7 +94,7 @@ default T interceptTestClassConstructor(Invocation invocation, * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptBeforeAllMethod(Invocation invocation, + default void interceptBeforeAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -108,7 +109,7 @@ default void interceptBeforeAllMethod(Invocation invocation, * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptBeforeEachMethod(Invocation invocation, + default void interceptBeforeEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -123,8 +124,8 @@ default void interceptBeforeEachMethod(Invocation invocation, * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + default void interceptTestMethod(Invocation<@Nullable Void> invocation, + ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -142,7 +143,8 @@ default void interceptTestMethod(Invocation invocation, ReflectiveInvocati * @return the result of the invocation; potentially {@code null} * @throws Throwable in case of failures */ - default T interceptTestFactoryMethod(Invocation invocation, + @Nullable + default T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { return invocation.proceed(); } @@ -157,7 +159,7 @@ default T interceptTestFactoryMethod(Invocation invocation, * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptTestTemplateMethod(Invocation invocation, + default void interceptTestTemplateMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -173,8 +175,8 @@ default void interceptTestTemplateMethod(Invocation invocation, * @throws Throwable in case of failures */ @API(status = STABLE, since = "5.11") - default void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + default void interceptDynamicTest(Invocation<@Nullable Void> invocation, + DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -188,7 +190,7 @@ default void interceptDynamicTest(Invocation invocation, DynamicTestInvoca * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptAfterEachMethod(Invocation invocation, + default void interceptAfterEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -203,7 +205,7 @@ default void interceptAfterEachMethod(Invocation invocation, * @param extensionContext the current extension context; never {@code null} * @throws Throwable in case of failures */ - default void interceptAfterAllMethod(Invocation invocation, + default void interceptAfterAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); } @@ -217,7 +219,7 @@ default void interceptAfterAllMethod(Invocation invocation, * @since 5.5 */ @API(status = STABLE, since = "5.10") - interface Invocation { + interface Invocation { /** * Proceed with this invocation. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolver.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolver.java index 093fe276bcf5..898f73a94760 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolver.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ParameterResolver.java @@ -15,6 +15,7 @@ import java.lang.reflect.Parameter; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance; /** @@ -99,6 +100,7 @@ boolean supportsParameter(ParameterContext parameterContext, ExtensionContext ex * @see #supportsParameter * @see ParameterContext */ + @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestWatcher.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestWatcher.java index 54c7c24da942..4c4c129e320b 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestWatcher.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/TestWatcher.java @@ -15,6 +15,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * {@code TestWatcher} defines the API for {@link Extension Extensions} that @@ -103,7 +104,7 @@ default void testSuccessful(ExtensionContext context) { * @param context the current extension context; never {@code null} * @param cause the throwable responsible for the test being aborted; may be {@code null} */ - default void testAborted(ExtensionContext context, Throwable cause) { + default void testAborted(ExtensionContext context, @Nullable Throwable cause) { /* no-op */ } @@ -116,7 +117,7 @@ default void testAborted(ExtensionContext context, Throwable cause) { * @param context the current extension context; never {@code null} * @param cause the throwable that caused test failure; may be {@code null} */ - default void testFailed(ExtensionContext context, Throwable cause) { + default void testFailed(ExtensionContext context, @Nullable Throwable cause) { /* no-op */ } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/package-info.java index 68f070a2fb4d..940def614dd4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/package-info.java @@ -2,4 +2,7 @@ * JUnit Jupiter API for writing extensions. */ +@NullMarked package org.junit.jupiter.api.extension; + +import org.jspecify.annotations.NullMarked; From 6c592313104973690944e9c0c3ac73e2fa9ba3b5 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:37:32 +0200 Subject: [PATCH 120/521] Annotate nullability in `org.junit.jupiter.api.function` --- .../java/org/junit/jupiter/api/function/ThrowingConsumer.java | 3 ++- .../java/org/junit/jupiter/api/function/ThrowingSupplier.java | 3 ++- .../main/java/org/junit/jupiter/api/function/package-info.java | 3 +++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingConsumer.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingConsumer.java index ca32cf145b02..f9a897126f2d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingConsumer.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingConsumer.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * {@code ThrowingConsumer} is a functional interface that can be used to @@ -41,7 +42,7 @@ */ @FunctionalInterface @API(status = STABLE, since = "5.0") -public interface ThrowingConsumer { +public interface ThrowingConsumer { /** * Consume the supplied argument, potentially throwing an exception. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingSupplier.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingSupplier.java index 42212221844a..bfa2c4d87b55 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingSupplier.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/ThrowingSupplier.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * {@code ThrowingSupplier} is a functional interface that can be used to @@ -42,7 +43,7 @@ */ @FunctionalInterface @API(status = STABLE, since = "5.0") -public interface ThrowingSupplier { +public interface ThrowingSupplier { /** * Get a result, potentially throwing an exception. diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/package-info.java index aaebdbdb3aab..b70c3db4db85 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/function/package-info.java @@ -2,4 +2,7 @@ * Functional interfaces used within JUnit Jupiter. */ +@NullMarked package org.junit.jupiter.api.function; + +import org.jspecify.annotations.NullMarked; From 0dfbcffcd19992b4480da3602473e06deeecec1c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:38:17 +0200 Subject: [PATCH 121/521] Annotate nullability in `org.junit.jupiter.api.io` --- .../src/main/java/org/junit/jupiter/api/io/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/package-info.java index 7e8938932e9b..34a9dc7ef6bf 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/io/package-info.java @@ -2,4 +2,7 @@ * IO-related support in JUnit Jupiter. */ +@NullMarked package org.junit.jupiter.api.io; + +import org.jspecify.annotations.NullMarked; From a8ccca82be1844ccb3155b75dfa6a1fcb57ceaa3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 10:39:13 +0200 Subject: [PATCH 122/521] Annotate nullability in `org.junit.jupiter.api.parallel` --- .../main/java/org/junit/jupiter/api/parallel/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/package-info.java index 16b34edfb116..3969d01029d5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/parallel/package-info.java @@ -2,4 +2,7 @@ * JUnit Jupiter API for influencing parallel test execution. */ +@NullMarked package org.junit.jupiter.api.parallel; + +import org.jspecify.annotations.NullMarked; From aaa6552748f35ecf036f89b3ebab25a2482b21e3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:10:34 +0200 Subject: [PATCH 123/521] Annotate nullability in `org.junit.jupiter.api` --- .../java/org/junit/jupiter/api/AssertAll.java | 7 +- .../junit/jupiter/api/AssertArrayEquals.java | 258 +++++--- .../junit/jupiter/api/AssertDoesNotThrow.java | 21 +- .../org/junit/jupiter/api/AssertEquals.java | 48 +- .../org/junit/jupiter/api/AssertFalse.java | 12 +- .../junit/jupiter/api/AssertInstanceOf.java | 13 +- .../jupiter/api/AssertIterableEquals.java | 58 +- .../junit/jupiter/api/AssertLinesMatch.java | 16 +- .../junit/jupiter/api/AssertNotEquals.java | 49 +- .../org/junit/jupiter/api/AssertNotNull.java | 10 +- .../org/junit/jupiter/api/AssertNotSame.java | 11 +- .../org/junit/jupiter/api/AssertNull.java | 10 +- .../org/junit/jupiter/api/AssertSame.java | 12 +- .../org/junit/jupiter/api/AssertThrows.java | 8 +- .../jupiter/api/AssertThrowsExactly.java | 8 +- .../org/junit/jupiter/api/AssertTimeout.java | 20 +- .../api/AssertTimeoutPreemptively.java | 42 +- .../org/junit/jupiter/api/AssertTrue.java | 12 +- .../jupiter/api/AssertionFailureBuilder.java | 37 +- .../org/junit/jupiter/api/AssertionUtils.java | 16 +- .../org/junit/jupiter/api/Assertions.java | 619 ++++++++++-------- .../org/junit/jupiter/api/Assumptions.java | 23 +- .../jupiter/api/DisplayNameGenerator.java | 5 +- .../junit/jupiter/api/DynamicContainer.java | 5 +- .../org/junit/jupiter/api/DynamicNode.java | 4 +- .../org/junit/jupiter/api/DynamicTest.java | 5 +- .../java/org/junit/jupiter/api/Named.java | 9 +- .../org/junit/jupiter/api/package-info.java | 3 + .../jupiter/api/KotlinFailAssertionsTests.kt | 6 +- 29 files changed, 813 insertions(+), 534 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java index ae5f2828c795..666b7bb75dcc 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java @@ -17,6 +17,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -38,7 +39,7 @@ static void assertAll(Executable... executables) { assertAll(null, executables); } - static void assertAll(String heading, Executable... executables) { + static void assertAll(@Nullable String heading, Executable... executables) { Preconditions.notEmpty(executables, "executables array must not be null or empty"); Preconditions.containsNoNullElements(executables, "individual executables must not be null"); assertAll(heading, Arrays.stream(executables)); @@ -48,7 +49,7 @@ static void assertAll(Collection executables) { assertAll(null, executables); } - static void assertAll(String heading, Collection executables) { + static void assertAll(@Nullable String heading, Collection executables) { Preconditions.notNull(executables, "executables collection must not be null"); Preconditions.containsNoNullElements(executables, "individual executables must not be null"); assertAll(heading, executables.stream()); @@ -58,7 +59,7 @@ static void assertAll(Stream executables) { assertAll(null, executables); } - static void assertAll(String heading, Stream executables) { + static void assertAll(@Nullable String heading, Stream executables) { Preconditions.notNull(executables, "executables stream must not be null"); List failures = executables // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java index 883b7bd841cf..35bc69437fae 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertArrayEquals.java @@ -19,6 +19,9 @@ import java.util.Objects; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; +import org.opentest4j.AssertionFailedError; + /** * {@code AssertArrayEquals} is a collection of utility methods that support asserting * array equality in tests. @@ -31,145 +34,165 @@ private AssertArrayEquals() { /* no-op */ } - static void assertArrayEquals(boolean[] expected, boolean[] actual) { + static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(boolean[] expected, boolean[] actual, String message) { + static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual, + @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(boolean[] expected, boolean[] actual, Supplier messageSupplier) { + static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(char[] expected, char[] actual, String message) { + static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(char[] expected, char[] actual) { + static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(char[] expected, char[] actual, Supplier messageSupplier) { + static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual, + @Nullable Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(byte[] expected, byte[] actual) { + static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(byte[] expected, byte[] actual, String message) { + static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(byte[] expected, byte[] actual, Supplier messageSupplier) { + static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(short[] expected, short[] actual) { + static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(short[] expected, short[] actual, String message) { + static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(short[] expected, short[] actual, Supplier messageSupplier) { + static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(int[] expected, int[] actual) { + static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(int[] expected, int[] actual, String message) { + static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(int[] expected, int[] actual, Supplier messageSupplier) { + static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(long[] expected, long[] actual) { + static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(long[] expected, long[] actual, String message) { + static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(long[] expected, long[] actual, Supplier messageSupplier) { + static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(float[] expected, float[] actual) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(float[] expected, float[] actual, String message) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(float[] expected, float[] actual, Supplier messageSupplier) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(float[] expected, float[] actual, float delta) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta) { assertArrayEquals(expected, actual, delta, (String) null); } - static void assertArrayEquals(float[] expected, float[] actual, float delta, String message) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta, + @Nullable String message) { assertArrayEquals(expected, actual, delta, null, message); } - static void assertArrayEquals(float[] expected, float[] actual, float delta, Supplier messageSupplier) { + static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, delta, null, messageSupplier); } - static void assertArrayEquals(double[] expected, double[] actual) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(double[] expected, double[] actual, String message) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, @Nullable String message) { assertArrayEquals(expected, actual, null, message); } - static void assertArrayEquals(double[] expected, double[] actual, Supplier messageSupplier) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, null, messageSupplier); } - static void assertArrayEquals(double[] expected, double[] actual, double delta) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta) { assertArrayEquals(expected, actual, delta, (String) null); } - static void assertArrayEquals(double[] expected, double[] actual, double delta, String message) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta, + @Nullable String message) { assertArrayEquals(expected, actual, delta, null, message); } - static void assertArrayEquals(double[] expected, double[] actual, double delta, Supplier messageSupplier) { + static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, delta, null, messageSupplier); } - static void assertArrayEquals(Object[] expected, Object[] actual) { + static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual) { assertArrayEquals(expected, actual, (String) null); } - static void assertArrayEquals(Object[] expected, Object[] actual, String message) { + static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual, + @Nullable String message) { assertArrayEquals(expected, actual, new ArrayDeque<>(), message); } - static void assertArrayEquals(Object[] expected, Object[] actual, Supplier messageSupplier) { + static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { assertArrayEquals(expected, actual, new ArrayDeque<>(), messageSupplier); } - private static void assertArrayEquals(boolean[] expected, boolean[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -179,13 +202,19 @@ private static void assertArrayEquals(boolean[] expected, boolean[] actual, Dequ } } - private static void assertArrayEquals(char[] expected, char[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -195,13 +224,19 @@ private static void assertArrayEquals(char[] expected, char[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -211,13 +246,19 @@ private static void assertArrayEquals(byte[] expected, byte[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -227,13 +268,19 @@ private static void assertArrayEquals(short[] expected, short[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -243,13 +290,19 @@ private static void assertArrayEquals(int[] expected, int[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -259,13 +312,19 @@ private static void assertArrayEquals(long[] expected, long[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -275,14 +334,20 @@ private static void assertArrayEquals(float[] expected, float[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { AssertionUtils.assertValidDelta(delta); if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -292,13 +357,19 @@ private static void assertArrayEquals(float[] expected, float[] actual, float de } } - private static void assertArrayEquals(double[] expected, double[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -308,14 +379,20 @@ private static void assertArrayEquals(double[] expected, double[] actual, Deque< } } - private static void assertArrayEquals(double[] expected, double[] actual, double delta, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { AssertionUtils.assertValidDelta(delta); if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -325,13 +402,19 @@ private static void assertArrayEquals(double[] expected, double[] actual, double } } - private static void assertArrayEquals(Object[] expected, Object[] actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual, + Deque indexes, @Nullable Object messageOrSupplier) { if (expected == actual) { return; } - assertArraysNotNull(expected, actual, indexes, messageOrSupplier); + + if (expected == null) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } assertArraysHaveSameLength(expected.length, actual.length, indexes, messageOrSupplier); for (int i = 0; i < expected.length; i++) { @@ -348,8 +431,8 @@ private static void assertArrayEquals(Object[] expected, Object[] actual, Deque< } } - private static void assertArrayElementsEqual(Object expected, Object actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArrayElementsEqual(@Nullable Object expected, @Nullable Object actual, + Deque indexes, @Nullable Object messageOrSupplier) { if (expected instanceof Object[] expectedArray && actual instanceof Object[] actualArray) { assertArrayEquals(expectedArray, actualArray, indexes, messageOrSupplier); @@ -391,33 +474,32 @@ else if (isArray(expected) && actual == null) { } } - private static void assertArraysNotNull(Object expected, Object actual, Deque indexes, - Object messageOrSupplier) { - - if (expected == null) { - failExpectedArrayIsNull(indexes, messageOrSupplier); - } - if (actual == null) { - failActualArrayIsNull(indexes, messageOrSupplier); - } + private static void failExpectedArrayIsNull(@Nullable Deque indexes, @Nullable Object messageOrSupplier) { + throw expectedArrayIsNullFailure(indexes, messageOrSupplier); } - private static void failExpectedArrayIsNull(Deque indexes, Object messageOrSupplier) { - assertionFailure() // + private static AssertionFailedError expectedArrayIsNullFailure(@Nullable Deque indexes, + @Nullable Object messageOrSupplier) { + return assertionFailure() // .message(messageOrSupplier) // .reason("expected array was " + formatIndexes(indexes)) // - .buildAndThrow(); + .build(); } - private static void failActualArrayIsNull(Deque indexes, Object messageOrSupplier) { - assertionFailure() // + private static void failActualArrayIsNull(@Nullable Deque indexes, @Nullable Object messageOrSupplier) { + throw actualArrayIsNullFailure(indexes, messageOrSupplier); + } + + private static AssertionFailedError actualArrayIsNullFailure(@Nullable Deque indexes, + @Nullable Object messageOrSupplier) { + return assertionFailure() // .message(messageOrSupplier) // .reason("actual array was " + formatIndexes(indexes)) // - .buildAndThrow(); + .build(); } - private static void assertArraysHaveSameLength(int expected, int actual, Deque indexes, - Object messageOrSupplier) { + private static void assertArraysHaveSameLength(int expected, int actual, @Nullable Deque indexes, + @Nullable Object messageOrSupplier) { if (expected != actual) { assertionFailure() // @@ -429,8 +511,8 @@ private static void assertArraysHaveSameLength(int expected, int actual, Deque indexes, - Object messageOrSupplier) { + private static void failArraysNotEqual(@Nullable Object expected, @Nullable Object actual, + @Nullable Deque indexes, @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // @@ -440,7 +522,7 @@ private static void failArraysNotEqual(Object expected, Object actual, Deque nullSafeIndexes(Deque indexes, int newIndex) { + private static Deque nullSafeIndexes(@Nullable Deque indexes, int newIndex) { Deque result = (indexes != null ? indexes : new ArrayDeque<>()); result.addLast(newIndex); return result; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java index 439e9795d780..82e15c85a41a 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertDoesNotThrow.java @@ -16,6 +16,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.util.StringUtils; @@ -38,15 +39,15 @@ static void assertDoesNotThrow(Executable executable) { assertDoesNotThrow(executable, (Object) null); } - static void assertDoesNotThrow(Executable executable, String message) { + static void assertDoesNotThrow(Executable executable, @Nullable String message) { assertDoesNotThrow(executable, (Object) message); } - static void assertDoesNotThrow(Executable executable, Supplier messageSupplier) { + static void assertDoesNotThrow(Executable executable, Supplier<@Nullable String> messageSupplier) { assertDoesNotThrow(executable, (Object) messageSupplier); } - private static void assertDoesNotThrow(Executable executable, Object messageOrSupplier) { + private static void assertDoesNotThrow(Executable executable, @Nullable Object messageOrSupplier) { try { executable.execute(); } @@ -56,19 +57,21 @@ private static void assertDoesNotThrow(Executable executable, Object messageOrSu } } - static T assertDoesNotThrow(ThrowingSupplier supplier) { + static T assertDoesNotThrow(ThrowingSupplier supplier) { return assertDoesNotThrow(supplier, (Object) null); } - static T assertDoesNotThrow(ThrowingSupplier supplier, String message) { + static T assertDoesNotThrow(ThrowingSupplier supplier, @Nullable String message) { return assertDoesNotThrow(supplier, (Object) message); } - static T assertDoesNotThrow(ThrowingSupplier supplier, Supplier messageSupplier) { + static T assertDoesNotThrow(ThrowingSupplier supplier, + Supplier<@Nullable String> messageSupplier) { return assertDoesNotThrow(supplier, (Object) messageSupplier); } - private static T assertDoesNotThrow(ThrowingSupplier supplier, Object messageOrSupplier) { + private static T assertDoesNotThrow(ThrowingSupplier supplier, + @Nullable Object messageOrSupplier) { try { return supplier.get(); } @@ -79,7 +82,7 @@ private static T assertDoesNotThrow(ThrowingSupplier supplier, Object mes } @API(status = INTERNAL, since = "6.0") - public static AssertionFailedError createAssertionFailedError(Object messageOrSupplier, Throwable t) { + public static AssertionFailedError createAssertionFailedError(@Nullable Object messageOrSupplier, Throwable t) { return assertionFailure() // .message(messageOrSupplier) // .reason("Unexpected exception thrown: " + t.getClass().getName() + buildSuffix(t.getMessage())) // @@ -87,7 +90,7 @@ public static AssertionFailedError createAssertionFailedError(Object messageOrSu .build(); } - private static String buildSuffix(String message) { + private static String buildSuffix(@Nullable String message) { return StringUtils.isNotBlank(message) ? ": " + message : ""; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java index 94afc3fe49c7..2e38bdb6f1c6 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertEquals.java @@ -17,6 +17,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertEquals} is a collection of utility methods that support asserting * equality on objects and primitives in tests. @@ -33,13 +35,13 @@ static void assertEquals(byte expected, byte actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(byte expected, byte actual, String message) { + static void assertEquals(byte expected, byte actual, @Nullable String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } - static void assertEquals(byte expected, byte actual, Supplier messageSupplier) { + static void assertEquals(byte expected, byte actual, Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } @@ -49,13 +51,13 @@ static void assertEquals(char expected, char actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(char expected, char actual, String message) { + static void assertEquals(char expected, char actual, @Nullable String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } - static void assertEquals(char expected, char actual, Supplier messageSupplier) { + static void assertEquals(char expected, char actual, Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } @@ -65,13 +67,13 @@ static void assertEquals(double expected, double actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(double expected, double actual, String message) { + static void assertEquals(double expected, double actual, @Nullable String message) { if (!doublesAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } - static void assertEquals(double expected, double actual, Supplier messageSupplier) { + static void assertEquals(double expected, double actual, Supplier<@Nullable String> messageSupplier) { if (!doublesAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } @@ -81,13 +83,13 @@ static void assertEquals(double expected, double actual, double delta) { assertEquals(expected, actual, delta, (String) null); } - static void assertEquals(double expected, double actual, double delta, String message) { + static void assertEquals(double expected, double actual, double delta, @Nullable String message) { if (!doublesAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, message); } } - static void assertEquals(double expected, double actual, double delta, Supplier messageSupplier) { + static void assertEquals(double expected, double actual, double delta, Supplier<@Nullable String> messageSupplier) { if (!doublesAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, messageSupplier); } @@ -97,13 +99,13 @@ static void assertEquals(float expected, float actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(float expected, float actual, String message) { + static void assertEquals(float expected, float actual, @Nullable String message) { if (!floatsAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } - static void assertEquals(float expected, float actual, Supplier messageSupplier) { + static void assertEquals(float expected, float actual, Supplier<@Nullable String> messageSupplier) { if (!floatsAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } @@ -113,13 +115,13 @@ static void assertEquals(float expected, float actual, float delta) { assertEquals(expected, actual, delta, (String) null); } - static void assertEquals(float expected, float actual, float delta, String message) { + static void assertEquals(float expected, float actual, float delta, @Nullable String message) { if (!floatsAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, message); } } - static void assertEquals(float expected, float actual, float delta, Supplier messageSupplier) { + static void assertEquals(float expected, float actual, float delta, Supplier<@Nullable String> messageSupplier) { if (!floatsAreEqual(expected, actual, delta)) { failNotEqual(expected, actual, messageSupplier); } @@ -129,13 +131,13 @@ static void assertEquals(short expected, short actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(short expected, short actual, String message) { + static void assertEquals(short expected, short actual, @Nullable String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } - static void assertEquals(short expected, short actual, Supplier messageSupplier) { + static void assertEquals(short expected, short actual, Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } @@ -145,13 +147,13 @@ static void assertEquals(int expected, int actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(int expected, int actual, String message) { + static void assertEquals(int expected, int actual, @Nullable String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } - static void assertEquals(int expected, int actual, Supplier messageSupplier) { + static void assertEquals(int expected, int actual, Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } @@ -161,35 +163,37 @@ static void assertEquals(long expected, long actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(long expected, long actual, String message) { + static void assertEquals(long expected, long actual, @Nullable String message) { if (expected != actual) { failNotEqual(expected, actual, message); } } - static void assertEquals(long expected, long actual, Supplier messageSupplier) { + static void assertEquals(long expected, long actual, Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotEqual(expected, actual, messageSupplier); } } - static void assertEquals(Object expected, Object actual) { + static void assertEquals(@Nullable Object expected, @Nullable Object actual) { assertEquals(expected, actual, (String) null); } - static void assertEquals(Object expected, Object actual, String message) { + static void assertEquals(@Nullable Object expected, @Nullable Object actual, @Nullable String message) { if (!objectsAreEqual(expected, actual)) { failNotEqual(expected, actual, message); } } - static void assertEquals(Object expected, Object actual, Supplier messageSupplier) { + static void assertEquals(@Nullable Object expected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { if (!objectsAreEqual(expected, actual)) { failNotEqual(expected, actual, messageSupplier); } } - private static void failNotEqual(Object expected, Object actual, Object messageOrSupplier) { + private static void failNotEqual(@Nullable Object expected, @Nullable Object actual, + @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(expected) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java index f7582574166d..ea248480a299 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertFalse.java @@ -15,6 +15,8 @@ import java.util.function.BooleanSupplier; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertFalse} is a collection of utility methods that support asserting * {@code false} in tests. @@ -31,13 +33,13 @@ static void assertFalse(boolean condition) { assertFalse(condition, (String) null); } - static void assertFalse(boolean condition, String message) { + static void assertFalse(boolean condition, @Nullable String message) { if (condition) { failNotFalse(message); } } - static void assertFalse(boolean condition, Supplier messageSupplier) { + static void assertFalse(boolean condition, Supplier<@Nullable String> messageSupplier) { if (condition) { failNotFalse(messageSupplier); } @@ -47,15 +49,15 @@ static void assertFalse(BooleanSupplier booleanSupplier) { assertFalse(booleanSupplier.getAsBoolean(), (String) null); } - static void assertFalse(BooleanSupplier booleanSupplier, String message) { + static void assertFalse(BooleanSupplier booleanSupplier, @Nullable String message) { assertFalse(booleanSupplier.getAsBoolean(), message); } - static void assertFalse(BooleanSupplier booleanSupplier, Supplier messageSupplier) { + static void assertFalse(BooleanSupplier booleanSupplier, Supplier<@Nullable String> messageSupplier) { assertFalse(booleanSupplier.getAsBoolean(), messageSupplier); } - private static void failNotFalse(Object messageOrSupplier) { + private static void failNotFalse(@Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(false) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java index 4d3197ba46fe..02f72aeffdc3 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertInstanceOf.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertInstanceOf} is a collection of utility methods that support * asserting that an object is of an expected type — in other words, if it @@ -27,19 +29,22 @@ private AssertInstanceOf() { /* no-op */ } - static T assertInstanceOf(Class expectedType, Object actualValue) { + static T assertInstanceOf(Class expectedType, @Nullable Object actualValue) { return assertInstanceOf(expectedType, actualValue, (Object) null); } - static T assertInstanceOf(Class expectedType, Object actualValue, String message) { + static T assertInstanceOf(Class expectedType, @Nullable Object actualValue, @Nullable String message) { return assertInstanceOf(expectedType, actualValue, (Object) message); } - static T assertInstanceOf(Class expectedType, Object actualValue, Supplier messageSupplier) { + static T assertInstanceOf(Class expectedType, @Nullable Object actualValue, + Supplier<@Nullable String> messageSupplier) { return assertInstanceOf(expectedType, actualValue, (Object) messageSupplier); } - private static T assertInstanceOf(Class expectedType, Object actualValue, Object messageOrSupplier) { + @SuppressWarnings("NullAway") + private static T assertInstanceOf(Class expectedType, @Nullable Object actualValue, + @Nullable Object messageOrSupplier) { if (!expectedType.isInstance(actualValue)) { assertionFailure() // .message(messageOrSupplier) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java index effc99618785..6512d10e8f12 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java @@ -22,6 +22,9 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; +import org.opentest4j.AssertionFailedError; + /** * {@code AssertIterable} is a collection of utility methods that support asserting * Iterable equality in tests. @@ -34,30 +37,37 @@ private AssertIterableEquals() { /* no-op */ } - static void assertIterableEquals(Iterable expected, Iterable actual) { + static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual) { assertIterableEquals(expected, actual, (String) null); } - static void assertIterableEquals(Iterable expected, Iterable actual, String message) { + static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + @Nullable String message) { assertIterableEquals(expected, actual, new ArrayDeque<>(), message); } - static void assertIterableEquals(Iterable expected, Iterable actual, Supplier messageSupplier) { + static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + Supplier<@Nullable String> messageSupplier) { assertIterableEquals(expected, actual, new ArrayDeque<>(), messageSupplier); } - private static void assertIterableEquals(Iterable expected, Iterable actual, Deque indexes, - Object messageOrSupplier) { + private static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + Deque indexes, @Nullable Object messageOrSupplier) { assertIterableEquals(expected, actual, indexes, messageOrSupplier, new LinkedHashMap<>()); } - private static void assertIterableEquals(Iterable expected, Iterable actual, Deque indexes, - Object messageOrSupplier, Map investigatedElements) { + private static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + Deque indexes, @Nullable Object messageOrSupplier, Map investigatedElements) { if (expected == actual) { return; } - assertIterablesNotNull(expected, actual, indexes, messageOrSupplier); + if (expected == null) { + throw expectedIterableIsNullFailure(indexes, messageOrSupplier); + } + if (actual == null) { + throw actualIterableIsNullFailure(indexes, messageOrSupplier); + } Iterator expectedIterator = expected.iterator(); Iterator actualIterator = actual.iterator(); @@ -80,7 +90,7 @@ private static void assertIterableEquals(Iterable expected, Iterable actua } private static void assertIterableElementsEqual(Object expected, Object actual, Deque indexes, - Object messageOrSupplier, Map investigatedElements) { + @Nullable Object messageOrSupplier, Map investigatedElements) { // If both are equal, we don't need to check recursively. if (Objects.equals(expected, actual)) { @@ -123,8 +133,8 @@ private static void assertIterableElementsEqual(Object expected, Object actual, } } - private static void assertIterablesNotNull(Object expected, Object actual, Deque indexes, - Object messageOrSupplier) { + private static void assertIterablesNotNull(@Nullable Object expected, @Nullable Object actual, + Deque indexes, @Nullable Object messageOrSupplier) { if (expected == null) { failExpectedIterableIsNull(indexes, messageOrSupplier); @@ -134,22 +144,32 @@ private static void assertIterablesNotNull(Object expected, Object actual, Deque } } - private static void failExpectedIterableIsNull(Deque indexes, Object messageOrSupplier) { - assertionFailure() // + private static void failExpectedIterableIsNull(Deque indexes, @Nullable Object messageOrSupplier) { + throw expectedIterableIsNullFailure(indexes, messageOrSupplier); + } + + private static AssertionFailedError expectedIterableIsNullFailure(Deque indexes, + @Nullable Object messageOrSupplier) { + return assertionFailure() // .message(messageOrSupplier) // .reason("expected iterable was " + formatIndexes(indexes)) // - .buildAndThrow(); + .build(); } - private static void failActualIterableIsNull(Deque indexes, Object messageOrSupplier) { - assertionFailure() // + private static void failActualIterableIsNull(Deque indexes, @Nullable Object messageOrSupplier) { + throw actualIterableIsNullFailure(indexes, messageOrSupplier); + } + + private static AssertionFailedError actualIterableIsNullFailure(Deque indexes, + @Nullable Object messageOrSupplier) { + return assertionFailure() // .message(messageOrSupplier) // .reason("actual iterable was " + formatIndexes(indexes)) // - .buildAndThrow(); + .build(); } private static void assertIteratorsAreEmpty(Iterator expected, Iterator actual, int processed, - Deque indexes, Object messageOrSupplier) { + Deque indexes, @Nullable Object messageOrSupplier) { if (expected.hasNext() || actual.hasNext()) { AtomicInteger expectedCount = new AtomicInteger(processed); @@ -168,7 +188,7 @@ private static void assertIteratorsAreEmpty(Iterator expected, Iterator ac } private static void failIterablesNotEqual(Object expected, Object actual, Deque indexes, - Object messageOrSupplier) { + @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java index 65a99466ac69..2f61fe53e8e1 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java @@ -23,6 +23,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; + /** * {@code AssertLinesMatch} is a collection of utility methods that support asserting * lines of {@link String} equality or {@link java.util.regex.Pattern}-match in tests. @@ -41,7 +43,7 @@ static void assertLinesMatch(List expectedLines, List actualLine assertLinesMatch(expectedLines, actualLines, (Object) null); } - static void assertLinesMatch(List expectedLines, List actualLines, String message) { + static void assertLinesMatch(List expectedLines, List actualLines, @Nullable String message) { assertLinesMatch(expectedLines, actualLines, (Object) message); } @@ -49,11 +51,12 @@ static void assertLinesMatch(Stream expectedLines, Stream actual assertLinesMatch(expectedLines, actualLines, (Object) null); } - static void assertLinesMatch(Stream expectedLines, Stream actualLines, String message) { + static void assertLinesMatch(Stream expectedLines, Stream actualLines, @Nullable String message) { assertLinesMatch(expectedLines, actualLines, (Object) message); } - static void assertLinesMatch(Stream expectedLines, Stream actualLines, Object messageOrSupplier) { + static void assertLinesMatch(Stream expectedLines, Stream actualLines, + @Nullable Object messageOrSupplier) { notNull(expectedLines, "expectedLines must not be null"); notNull(actualLines, "actualLines must not be null"); @@ -67,7 +70,8 @@ static void assertLinesMatch(Stream expectedLines, Stream actual assertLinesMatch(expectedListOfStrings, actualListOfStrings, messageOrSupplier); } - static void assertLinesMatch(List expectedLines, List actualLines, Object messageOrSupplier) { + static void assertLinesMatch(List expectedLines, List actualLines, + @Nullable Object messageOrSupplier) { notNull(expectedLines, "expectedLines must not be null"); notNull(actualLines, "actualLines must not be null"); @@ -83,9 +87,11 @@ private static class LinesMatcher { private final List expectedLines; private final List actualLines; + + @Nullable private final Object messageOrSupplier; - LinesMatcher(List expectedLines, List actualLines, Object messageOrSupplier) { + LinesMatcher(List expectedLines, List actualLines, @Nullable Object messageOrSupplier) { this.expectedLines = expectedLines; this.actualLines = actualLines; this.messageOrSupplier = messageOrSupplier; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java index 1ccc41b7bb13..e78a32eb4aa8 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotEquals.java @@ -17,6 +17,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertNotEquals} is a collection of utility methods that support asserting * inequality in objects and primitive values in tests. @@ -39,7 +41,7 @@ static void assertNotEquals(byte unexpected, byte actual) { /** * @since 5.4 */ - static void assertNotEquals(byte unexpected, byte actual, String message) { + static void assertNotEquals(byte unexpected, byte actual, @Nullable String message) { if (unexpected == actual) { failEqual(actual, message); } @@ -48,7 +50,7 @@ static void assertNotEquals(byte unexpected, byte actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { + static void assertNotEquals(byte unexpected, byte actual, Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } @@ -64,7 +66,7 @@ static void assertNotEquals(short unexpected, short actual) { /** * @since 5.4 */ - static void assertNotEquals(short unexpected, short actual, String message) { + static void assertNotEquals(short unexpected, short actual, @Nullable String message) { if (unexpected == actual) { failEqual(actual, message); } @@ -73,7 +75,7 @@ static void assertNotEquals(short unexpected, short actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { + static void assertNotEquals(short unexpected, short actual, Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } @@ -89,7 +91,7 @@ static void assertNotEquals(int unexpected, int actual) { /** * @since 5.4 */ - static void assertNotEquals(int unexpected, int actual, String message) { + static void assertNotEquals(int unexpected, int actual, @Nullable String message) { if (unexpected == actual) { failEqual(actual, message); } @@ -98,7 +100,7 @@ static void assertNotEquals(int unexpected, int actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(int unexpected, int actual, Supplier messageSupplier) { + static void assertNotEquals(int unexpected, int actual, Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } @@ -114,7 +116,7 @@ static void assertNotEquals(long unexpected, long actual) { /** * @since 5.4 */ - static void assertNotEquals(long unexpected, long actual, String message) { + static void assertNotEquals(long unexpected, long actual, @Nullable String message) { if (unexpected == actual) { failEqual(actual, message); } @@ -123,7 +125,7 @@ static void assertNotEquals(long unexpected, long actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { + static void assertNotEquals(long unexpected, long actual, Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } @@ -139,7 +141,7 @@ static void assertNotEquals(float unexpected, float actual) { /** * @since 5.4 */ - static void assertNotEquals(float unexpected, float actual, String message) { + static void assertNotEquals(float unexpected, float actual, @Nullable String message) { if (floatsAreEqual(unexpected, actual)) { failEqual(actual, message); } @@ -148,7 +150,7 @@ static void assertNotEquals(float unexpected, float actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { + static void assertNotEquals(float unexpected, float actual, Supplier<@Nullable String> messageSupplier) { if (floatsAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } @@ -164,7 +166,7 @@ static void assertNotEquals(float unexpected, float actual, float delta) { /** * @since 5.4 */ - static void assertNotEquals(float unexpected, float actual, float delta, String message) { + static void assertNotEquals(float unexpected, float actual, float delta, @Nullable String message) { if (floatsAreEqual(unexpected, actual, delta)) { failEqual(actual, message); } @@ -173,7 +175,8 @@ static void assertNotEquals(float unexpected, float actual, float delta, String /** * @since 5.4 */ - static void assertNotEquals(float unexpected, float actual, float delta, Supplier messageSupplier) { + static void assertNotEquals(float unexpected, float actual, float delta, + Supplier<@Nullable String> messageSupplier) { if (floatsAreEqual(unexpected, actual, delta)) { failEqual(actual, messageSupplier); } @@ -189,7 +192,7 @@ static void assertNotEquals(double unexpected, double actual) { /** * @since 5.4 */ - static void assertNotEquals(double unexpected, double actual, String message) { + static void assertNotEquals(double unexpected, double actual, @Nullable String message) { if (doublesAreEqual(unexpected, actual)) { failEqual(actual, message); } @@ -198,7 +201,7 @@ static void assertNotEquals(double unexpected, double actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { + static void assertNotEquals(double unexpected, double actual, Supplier<@Nullable String> messageSupplier) { if (doublesAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } @@ -214,7 +217,7 @@ static void assertNotEquals(double unexpected, double actual, double delta) { /** * @since 5.4 */ - static void assertNotEquals(double unexpected, double actual, double delta, String message) { + static void assertNotEquals(double unexpected, double actual, double delta, @Nullable String message) { if (doublesAreEqual(unexpected, actual, delta)) { failEqual(actual, message); } @@ -223,7 +226,8 @@ static void assertNotEquals(double unexpected, double actual, double delta, Stri /** * @since 5.4 */ - static void assertNotEquals(double unexpected, double actual, double delta, Supplier messageSupplier) { + static void assertNotEquals(double unexpected, double actual, double delta, + Supplier<@Nullable String> messageSupplier) { if (doublesAreEqual(unexpected, actual, delta)) { failEqual(actual, messageSupplier); } @@ -239,7 +243,7 @@ static void assertNotEquals(char unexpected, char actual) { /** * @since 5.4 */ - static void assertNotEquals(char unexpected, char actual, String message) { + static void assertNotEquals(char unexpected, char actual, @Nullable String message) { if (unexpected == actual) { failEqual(actual, message); } @@ -248,29 +252,30 @@ static void assertNotEquals(char unexpected, char actual, String message) { /** * @since 5.4 */ - static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { + static void assertNotEquals(char unexpected, char actual, Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failEqual(actual, messageSupplier); } } - static void assertNotEquals(Object unexpected, Object actual) { + static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual) { assertNotEquals(unexpected, actual, (String) null); } - static void assertNotEquals(Object unexpected, Object actual, String message) { + static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual, @Nullable String message) { if (objectsAreEqual(unexpected, actual)) { failEqual(actual, message); } } - static void assertNotEquals(Object unexpected, Object actual, Supplier messageSupplier) { + static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { if (objectsAreEqual(unexpected, actual)) { failEqual(actual, messageSupplier); } } - private static void failEqual(Object actual, Object messageOrSupplier) { + private static void failEqual(@Nullable Object actual, @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not equal but was: <" + actual + ">") // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java index f5fb9b849230..1f1208f297dc 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotNull.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertNotNull} is a collection of utility methods that support asserting * that there is an object. @@ -26,23 +28,23 @@ private AssertNotNull() { /* no-op */ } - static void assertNotNull(Object actual) { + static void assertNotNull(@Nullable Object actual) { assertNotNull(actual, (String) null); } - static void assertNotNull(Object actual, String message) { + static void assertNotNull(@Nullable Object actual, @Nullable String message) { if (actual == null) { failNull(message); } } - static void assertNotNull(Object actual, Supplier messageSupplier) { + static void assertNotNull(@Nullable Object actual, Supplier<@Nullable String> messageSupplier) { if (actual == null) { failNull(messageSupplier); } } - private static void failNull(Object messageOrSupplier) { + private static void failNull(@Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not ") // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java index 860371937076..d46c8f711fe1 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNotSame.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertNotSame} is a collection of utility methods that support asserting * two objects are not the same. @@ -26,23 +28,24 @@ private AssertNotSame() { /* no-op */ } - static void assertNotSame(Object unexpected, Object actual) { + static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual) { assertNotSame(unexpected, actual, (String) null); } - static void assertNotSame(Object unexpected, Object actual, String message) { + static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual, @Nullable String message) { if (unexpected == actual) { failSame(actual, message); } } - static void assertNotSame(Object unexpected, Object actual, Supplier messageSupplier) { + static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { if (unexpected == actual) { failSame(actual, messageSupplier); } } - private static void failSame(Object actual, Object messageOrSupplier) { + private static void failSame(@Nullable Object actual, @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .reason("expected: not same but was: <" + actual + ">") // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java index a81e7925415f..1acf4c1e6154 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertNull.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertNull} is a collection of utility methods that support asserting * there is no object. @@ -26,23 +28,23 @@ private AssertNull() { /* no-op */ } - static void assertNull(Object actual) { + static void assertNull(@Nullable Object actual) { assertNull(actual, (String) null); } - static void assertNull(Object actual, String message) { + static void assertNull(@Nullable Object actual, @Nullable String message) { if (actual != null) { failNotNull(actual, message); } } - static void assertNull(Object actual, Supplier messageSupplier) { + static void assertNull(@Nullable Object actual, Supplier<@Nullable String> messageSupplier) { if (actual != null) { failNotNull(actual, messageSupplier); } } - private static void failNotNull(Object actual, Object messageOrSupplier) { + private static void failNotNull(@Nullable Object actual, @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(null) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java index f006dab823ff..2cf1476f3742 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertSame.java @@ -14,6 +14,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertSame} is a collection of utility methods that support asserting * two objects are the same. @@ -26,23 +28,25 @@ private AssertSame() { /* no-op */ } - static void assertSame(Object expected, Object actual) { + static void assertSame(@Nullable Object expected, @Nullable Object actual) { assertSame(expected, actual, (String) null); } - static void assertSame(Object expected, Object actual, String message) { + static void assertSame(@Nullable Object expected, @Nullable Object actual, @Nullable String message) { if (expected != actual) { failNotSame(expected, actual, message); } } - static void assertSame(Object expected, Object actual, Supplier messageSupplier) { + static void assertSame(@Nullable Object expected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { if (expected != actual) { failNotSame(expected, actual, messageSupplier); } } - private static void failNotSame(Object expected, Object actual, Object messageOrSupplier) { + private static void failNotSame(@Nullable Object expected, @Nullable Object actual, + @Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(expected) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java index f8921615aabb..d198486087a4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrows.java @@ -15,6 +15,7 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -34,19 +35,20 @@ static T assertThrows(Class expectedType, Executable ex return assertThrows(expectedType, executable, (Object) null); } - static T assertThrows(Class expectedType, Executable executable, String message) { + static T assertThrows(Class expectedType, Executable executable, + @Nullable String message) { return assertThrows(expectedType, executable, (Object) message); } static T assertThrows(Class expectedType, Executable executable, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { return assertThrows(expectedType, executable, (Object) messageSupplier); } @SuppressWarnings("unchecked") private static T assertThrows(Class expectedType, Executable executable, - Object messageOrSupplier) { + @Nullable Object messageOrSupplier) { try { executable.execute(); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java index 0eebe693c380..59e72305be9e 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertThrowsExactly.java @@ -15,6 +15,7 @@ import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.UnrecoverableExceptions; @@ -34,19 +35,20 @@ static T assertThrowsExactly(Class expectedType, Execut return assertThrowsExactly(expectedType, executable, (Object) null); } - static T assertThrowsExactly(Class expectedType, Executable executable, String message) { + static T assertThrowsExactly(Class expectedType, Executable executable, + @Nullable String message) { return assertThrowsExactly(expectedType, executable, (Object) message); } static T assertThrowsExactly(Class expectedType, Executable executable, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { return assertThrowsExactly(expectedType, executable, (Object) messageSupplier); } @SuppressWarnings("unchecked") private static T assertThrowsExactly(Class expectedType, Executable executable, - Object messageOrSupplier) { + @Nullable Object messageOrSupplier) { try { executable.execute(); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java index 3aadf60f88af..0d188e166197 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java @@ -16,6 +16,7 @@ import java.time.Duration; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; @@ -35,36 +36,41 @@ static void assertTimeout(Duration timeout, Executable executable) { assertTimeout(timeout, executable, (String) null); } - static void assertTimeout(Duration timeout, Executable executable, String message) { + @SuppressWarnings("NullAway") + static void assertTimeout(Duration timeout, Executable executable, @Nullable String message) { assertTimeout(timeout, () -> { executable.execute(); return null; }, message); } - static void assertTimeout(Duration timeout, Executable executable, Supplier messageSupplier) { + @SuppressWarnings("NullAway") + static void assertTimeout(Duration timeout, Executable executable, Supplier<@Nullable String> messageSupplier) { assertTimeout(timeout, () -> { executable.execute(); return null; }, messageSupplier); } - static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { + static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { return assertTimeout(timeout, supplier, (Object) null); } - static T assertTimeout(Duration timeout, ThrowingSupplier supplier, String message) { + static T assertTimeout(Duration timeout, ThrowingSupplier supplier, + @Nullable String message) { return assertTimeout(timeout, supplier, (Object) message); } - static T assertTimeout(Duration timeout, ThrowingSupplier supplier, Supplier messageSupplier) { + static T assertTimeout(Duration timeout, ThrowingSupplier supplier, + Supplier<@Nullable String> messageSupplier) { return assertTimeout(timeout, supplier, (Object) messageSupplier); } - private static T assertTimeout(Duration timeout, ThrowingSupplier supplier, Object messageOrSupplier) { + private static T assertTimeout(Duration timeout, ThrowingSupplier supplier, + @Nullable Object messageOrSupplier) { long timeoutInMillis = timeout.toMillis(); long start = System.currentTimeMillis(); - T result = null; + T result; try { result = supplier.get(); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeoutPreemptively.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeoutPreemptively.java index 1eaea9ce4f3e..a2d277de1932 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeoutPreemptively.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeoutPreemptively.java @@ -10,9 +10,11 @@ package org.junit.jupiter.api; +import static java.util.Objects.requireNonNullElse; import static org.junit.jupiter.api.AssertionFailureBuilder.assertionFailure; import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; +import java.io.Serial; import java.time.Duration; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; @@ -25,6 +27,7 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.junit.platform.commons.JUnitException; @@ -43,37 +46,42 @@ static void assertTimeoutPreemptively(Duration timeout, Executable executable) { assertTimeoutPreemptively(timeout, executable, (String) null); } - static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message) { + @SuppressWarnings("NullAway") + static void assertTimeoutPreemptively(Duration timeout, Executable executable, @Nullable String message) { assertTimeoutPreemptively(timeout, () -> { executable.execute(); return null; }, message); } - static void assertTimeoutPreemptively(Duration timeout, Executable executable, Supplier messageSupplier) { + @SuppressWarnings("NullAway") + static void assertTimeoutPreemptively(Duration timeout, Executable executable, + Supplier<@Nullable String> messageSupplier) { assertTimeoutPreemptively(timeout, () -> { executable.execute(); return null; }, messageSupplier); } - static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier) { + static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier) { return assertTimeoutPreemptively(timeout, supplier, null, AssertTimeoutPreemptively::createAssertionFailure); } - static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, String message) { + static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, + @Nullable String message) { return assertTimeoutPreemptively(timeout, supplier, message == null ? null : () -> message, AssertTimeoutPreemptively::createAssertionFailure); } - static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, - Supplier messageSupplier) { + static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, + Supplier<@Nullable String> messageSupplier) { return assertTimeoutPreemptively(timeout, supplier, messageSupplier, AssertTimeoutPreemptively::createAssertionFailure); } - static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, - Supplier messageSupplier, Assertions.TimeoutFailureFactory failureFactory) throws E { + static T assertTimeoutPreemptively(Duration timeout, + ThrowingSupplier supplier, @Nullable Supplier<@Nullable String> messageSupplier, + Assertions.TimeoutFailureFactory failureFactory) throws E { AtomicReference threadReference = new AtomicReference<>(); ExecutorService executorService = Executors.newSingleThreadExecutor(new TimeoutThreadFactory()); @@ -87,8 +95,8 @@ static T assertTimeoutPreemptively(Duration timeout, Th } } - private static Future submitTask(ThrowingSupplier supplier, AtomicReference threadReference, - ExecutorService executorService) { + private static Future submitTask(ThrowingSupplier supplier, + AtomicReference threadReference, ExecutorService executorService) { return executorService.submit(() -> { try { threadReference.set(Thread.currentThread()); @@ -100,9 +108,10 @@ private static Future submitTask(ThrowingSupplier supplier, AtomicRefe }); } - private static T resolveFutureAndHandleException(Future future, Duration timeout, - Supplier messageSupplier, Supplier threadSupplier, - Assertions.TimeoutFailureFactory failureFactory) throws E { + private static T resolveFutureAndHandleException(Future future, + Duration timeout, @Nullable Supplier<@Nullable String> messageSupplier, + Supplier<@Nullable Thread> threadSupplier, Assertions.TimeoutFailureFactory failureFactory) + throws E, RuntimeException { try { return future.get(timeout.toMillis(), TimeUnit.MILLISECONDS); } @@ -116,15 +125,15 @@ private static T resolveFutureAndHandleException(Future throw failureFactory.createTimeoutFailure(timeout, messageSupplier, cause, thread); } catch (ExecutionException ex) { - throw throwAsUncheckedException(ex.getCause()); + throw throwAsUncheckedException(requireNonNullElse(ex.getCause(), ex)); } catch (Throwable ex) { throw throwAsUncheckedException(ex); } } - private static AssertionFailedError createAssertionFailure(Duration timeout, Supplier messageSupplier, - Throwable cause, Thread thread) { + private static AssertionFailedError createAssertionFailure(Duration timeout, + @Nullable Supplier<@Nullable String> messageSupplier, @Nullable Throwable cause, @Nullable Thread thread) { return assertionFailure() // .message(messageSupplier) // .reason("execution timed out after " + timeout.toMillis() + " ms") // @@ -134,6 +143,7 @@ private static AssertionFailedError createAssertionFailure(Duration timeout, Sup private static class ExecutionTimeoutException extends JUnitException { + @Serial private static final long serialVersionUID = 1L; ExecutionTimeoutException(String message) { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java index af43e0613263..c106e08995e5 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTrue.java @@ -15,6 +15,8 @@ import java.util.function.BooleanSupplier; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; + /** * {@code AssertTrue} is a collection of utility methods that support asserting * {@code true} in tests. @@ -31,13 +33,13 @@ static void assertTrue(boolean condition) { assertTrue(condition, (String) null); } - static void assertTrue(boolean condition, String message) { + static void assertTrue(boolean condition, @Nullable String message) { if (!condition) { failNotTrue(message); } } - static void assertTrue(boolean condition, Supplier messageSupplier) { + static void assertTrue(boolean condition, Supplier<@Nullable String> messageSupplier) { if (!condition) { failNotTrue(messageSupplier); } @@ -47,15 +49,15 @@ static void assertTrue(BooleanSupplier booleanSupplier) { assertTrue(booleanSupplier.getAsBoolean(), (String) null); } - static void assertTrue(BooleanSupplier booleanSupplier, String message) { + static void assertTrue(BooleanSupplier booleanSupplier, @Nullable String message) { assertTrue(booleanSupplier.getAsBoolean(), message); } - static void assertTrue(BooleanSupplier booleanSupplier, Supplier messageSupplier) { + static void assertTrue(BooleanSupplier booleanSupplier, Supplier<@Nullable String> messageSupplier) { assertTrue(booleanSupplier.getAsBoolean(), messageSupplier); } - private static void failNotTrue(Object messageOrSupplier) { + private static void failNotTrue(@Nullable Object messageOrSupplier) { assertionFailure() // .message(messageOrSupplier) // .expected(true) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java index 2af178c2ee46..13008d802204 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -16,6 +16,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.StringUtils; import org.opentest4j.AssertionFailedError; @@ -31,12 +32,23 @@ @API(status = STABLE, since = "5.9") public class AssertionFailureBuilder { + @Nullable private Object message; + + @Nullable private Throwable cause; + private boolean mismatch; + + @Nullable private Object expected; + + @Nullable private Object actual; + + @Nullable private String reason; + private boolean includeValuesInMessage = true; /** @@ -59,7 +71,7 @@ private AssertionFailureBuilder() { * @param message the user-defined failure message; may be {@code null} * @return this builder for method chaining */ - public AssertionFailureBuilder message(Object message) { + public AssertionFailureBuilder message(@Nullable Object message) { this.message = message; return this; } @@ -70,7 +82,7 @@ public AssertionFailureBuilder message(Object message) { * @param reason the failure reason; may be {@code null} * @return this builder for method chaining */ - public AssertionFailureBuilder reason(String reason) { + public AssertionFailureBuilder reason(@Nullable String reason) { this.reason = reason; return this; } @@ -81,7 +93,7 @@ public AssertionFailureBuilder reason(String reason) { * @param cause the failure cause; may be {@code null} * @return this builder for method chaining */ - public AssertionFailureBuilder cause(Throwable cause) { + public AssertionFailureBuilder cause(@Nullable Throwable cause) { this.cause = cause; return this; } @@ -92,7 +104,7 @@ public AssertionFailureBuilder cause(Throwable cause) { * @param expected the expected value; may be {@code null} * @return this builder for method chaining */ - public AssertionFailureBuilder expected(Object expected) { + public AssertionFailureBuilder expected(@Nullable Object expected) { this.mismatch = true; this.expected = expected; return this; @@ -104,7 +116,7 @@ public AssertionFailureBuilder expected(Object expected) { * @param actual the actual value; may be {@code null} * @return this builder for method chaining */ - public AssertionFailureBuilder actual(Object actual) { + public AssertionFailureBuilder actual(@Nullable Object actual) { this.mismatch = true; this.actual = actual; return this; @@ -152,7 +164,8 @@ public AssertionFailedError build() { : new AssertionFailedError(message, cause); } - private static String nullSafeGet(Object messageOrSupplier) { + @Nullable + private static String nullSafeGet(@Nullable Object messageOrSupplier) { if (messageOrSupplier == null) { return null; } @@ -163,11 +176,11 @@ private static String nullSafeGet(Object messageOrSupplier) { return StringUtils.nullSafeToString(messageOrSupplier); } - private static String buildPrefix(String message) { + private static String buildPrefix(@Nullable String message) { return (StringUtils.isNotBlank(message) ? message + " ==> " : ""); } - private static String formatValues(Object expected, Object actual) { + private static String formatValues(@Nullable Object expected, @Nullable Object actual) { String expectedString = toString(expected); String actualString = toString(actual); if (expectedString.equals(actualString)) { @@ -177,7 +190,7 @@ private static String formatValues(Object expected, Object actual) { return "expected: <%s> but was: <%s>".formatted(expectedString, actualString); } - private static String formatClassAndValue(Object value, String valueString) { + private static String formatClassAndValue(@Nullable Object value, String valueString) { // If the value is null, return instead of null. if (value == null) { return ""; @@ -187,18 +200,18 @@ private static String formatClassAndValue(Object value, String valueString) { return (value instanceof Class ? "<" + classAndHash + ">" : classAndHash + "<" + valueString + ">"); } - private static String toString(Object obj) { + private static String toString(@Nullable Object obj) { if (obj instanceof Class clazz) { return getCanonicalName(clazz); } return StringUtils.nullSafeToString(obj); } - private static String toHash(Object obj) { + private static String toHash(@Nullable Object obj) { return (obj == null ? "" : "@" + Integer.toHexString(System.identityHashCode(obj))); } - private static String getClassName(Object obj) { + private static String getClassName(@Nullable Object obj) { return (obj == null ? "null" : obj instanceof Class clazz ? getCanonicalName(clazz) : obj.getClass().getName()); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java index 9431e30b3940..3d64dc32c5dd 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java @@ -15,6 +15,7 @@ import java.util.Deque; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.opentest4j.AssertionFailedError; @@ -34,23 +35,24 @@ static void fail() { throw new AssertionFailedError(); } - static void fail(String message) { + static void fail(@Nullable String message) { throw new AssertionFailedError(message); } - static void fail(String message, Throwable cause) { + static void fail(@Nullable String message, @Nullable Throwable cause) { throw new AssertionFailedError(message, cause); } - static void fail(Throwable cause) { + static void fail(@Nullable Throwable cause) { throw new AssertionFailedError(null, cause); } - static void fail(Supplier messageSupplier) { + static void fail(Supplier<@Nullable String> messageSupplier) { throw new AssertionFailedError(nullSafeGet(messageSupplier)); } - static String nullSafeGet(Supplier messageSupplier) { + @Nullable + static String nullSafeGet(@Nullable Supplier<@Nullable String> messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } @@ -65,7 +67,7 @@ static String getCanonicalName(Class clazz) { } } - static String formatIndexes(Deque indexes) { + static String formatIndexes(@Nullable Deque indexes) { if (indexes == null || indexes.isEmpty()) { return ""; } @@ -103,7 +105,7 @@ static boolean doublesAreEqual(double value1, double value2) { return Double.doubleToLongBits(value1) == Double.doubleToLongBits(value2); } - static boolean objectsAreEqual(Object obj1, Object obj2) { + static boolean objectsAreEqual(@Nullable Object obj1, @Nullable Object obj2) { if (obj1 == null) { return (obj2 == null); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assertions.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assertions.java index cd037a416914..90f5837520af 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assertions.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assertions.java @@ -23,6 +23,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingSupplier; import org.opentest4j.MultipleFailuresError; @@ -115,6 +116,7 @@ protected Assertions() { *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ + @SuppressWarnings("NullAway") public static V fail() { AssertionUtils.fail(); return null; // appeasing the compiler: this line will never be executed. @@ -134,7 +136,8 @@ public static V fail() { * Stream.of().map(entry -> fail("should not be called")); * } */ - public static V fail(String message) { + @SuppressWarnings("NullAway") + public static V fail(@Nullable String message) { AssertionUtils.fail(message); return null; // appeasing the compiler: this line will never be executed. } @@ -146,7 +149,8 @@ public static V fail(String message) { *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ - public static V fail(String message, Throwable cause) { + @SuppressWarnings("NullAway") + public static V fail(@Nullable String message, @Nullable Throwable cause) { AssertionUtils.fail(message, cause); return null; // appeasing the compiler: this line will never be executed. } @@ -157,7 +161,8 @@ public static V fail(String message, Throwable cause) { *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ - public static V fail(Throwable cause) { + @SuppressWarnings("NullAway") + public static V fail(@Nullable Throwable cause) { AssertionUtils.fail(cause); return null; // appeasing the compiler: this line will never be executed. } @@ -169,7 +174,8 @@ public static V fail(Throwable cause) { *

See Javadoc for {@link #fail(String)} for an explanation of this method's * generic return type {@code V}. */ - public static V fail(Supplier messageSupplier) { + @SuppressWarnings("NullAway") + public static V fail(Supplier<@Nullable String> messageSupplier) { AssertionUtils.fail(messageSupplier); return null; // appeasing the compiler: this line will never be executed. } @@ -187,7 +193,7 @@ public static void assertTrue(boolean condition) { * Assert that the supplied {@code condition} is {@code true}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertTrue(boolean condition, Supplier messageSupplier) { + public static void assertTrue(boolean condition, Supplier<@Nullable String> messageSupplier) { AssertTrue.assertTrue(condition, messageSupplier); } @@ -202,7 +208,7 @@ public static void assertTrue(BooleanSupplier booleanSupplier) { * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code true}. *

Fails with the supplied failure {@code message}. */ - public static void assertTrue(BooleanSupplier booleanSupplier, String message) { + public static void assertTrue(BooleanSupplier booleanSupplier, @Nullable String message) { AssertTrue.assertTrue(booleanSupplier, message); } @@ -210,7 +216,7 @@ public static void assertTrue(BooleanSupplier booleanSupplier, String message) { * Assert that the supplied {@code condition} is {@code true}. *

Fails with the supplied failure {@code message}. */ - public static void assertTrue(boolean condition, String message) { + public static void assertTrue(boolean condition, @Nullable String message) { AssertTrue.assertTrue(condition, message); } @@ -218,7 +224,7 @@ public static void assertTrue(boolean condition, String message) { * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code true}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertTrue(BooleanSupplier booleanSupplier, Supplier messageSupplier) { + public static void assertTrue(BooleanSupplier booleanSupplier, Supplier<@Nullable String> messageSupplier) { AssertTrue.assertTrue(booleanSupplier, messageSupplier); } @@ -235,7 +241,7 @@ public static void assertFalse(boolean condition) { * Assert that the supplied {@code condition} is {@code false}. *

Fails with the supplied failure {@code message}. */ - public static void assertFalse(boolean condition, String message) { + public static void assertFalse(boolean condition, @Nullable String message) { AssertFalse.assertFalse(condition, message); } @@ -243,7 +249,7 @@ public static void assertFalse(boolean condition, String message) { * Assert that the supplied {@code condition} is {@code false}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertFalse(boolean condition, Supplier messageSupplier) { + public static void assertFalse(boolean condition, Supplier<@Nullable String> messageSupplier) { AssertFalse.assertFalse(condition, messageSupplier); } @@ -258,7 +264,7 @@ public static void assertFalse(BooleanSupplier booleanSupplier) { * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code false}. *

Fails with the supplied failure {@code message}. */ - public static void assertFalse(BooleanSupplier booleanSupplier, String message) { + public static void assertFalse(BooleanSupplier booleanSupplier, @Nullable String message) { AssertFalse.assertFalse(booleanSupplier, message); } @@ -266,7 +272,7 @@ public static void assertFalse(BooleanSupplier booleanSupplier, String message) * Assert that the boolean condition supplied by {@code booleanSupplier} is {@code false}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertFalse(BooleanSupplier booleanSupplier, Supplier messageSupplier) { + public static void assertFalse(BooleanSupplier booleanSupplier, Supplier<@Nullable String> messageSupplier) { AssertFalse.assertFalse(booleanSupplier, messageSupplier); } @@ -275,7 +281,7 @@ public static void assertFalse(BooleanSupplier booleanSupplier, Supplier /** * Assert that {@code actual} is {@code null}. */ - public static void assertNull(Object actual) { + public static void assertNull(@Nullable Object actual) { AssertNull.assertNull(actual); } @@ -283,7 +289,7 @@ public static void assertNull(Object actual) { * Assert that {@code actual} is {@code null}. *

Fails with the supplied failure {@code message}. */ - public static void assertNull(Object actual, String message) { + public static void assertNull(@Nullable Object actual, @Nullable String message) { AssertNull.assertNull(actual, message); } @@ -291,7 +297,7 @@ public static void assertNull(Object actual, String message) { * Assert that {@code actual} is {@code null}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertNull(Object actual, Supplier messageSupplier) { + public static void assertNull(@Nullable Object actual, Supplier<@Nullable String> messageSupplier) { AssertNull.assertNull(actual, messageSupplier); } @@ -300,7 +306,7 @@ public static void assertNull(Object actual, Supplier messageSupplier) { /** * Assert that {@code actual} is not {@code null}. */ - public static void assertNotNull(Object actual) { + public static void assertNotNull(@Nullable Object actual) { AssertNotNull.assertNotNull(actual); } @@ -308,7 +314,7 @@ public static void assertNotNull(Object actual) { * Assert that {@code actual} is not {@code null}. *

Fails with the supplied failure {@code message}. */ - public static void assertNotNull(Object actual, String message) { + public static void assertNotNull(@Nullable Object actual, @Nullable String message) { AssertNotNull.assertNotNull(actual, message); } @@ -316,7 +322,7 @@ public static void assertNotNull(Object actual, String message) { * Assert that {@code actual} is not {@code null}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertNotNull(Object actual, Supplier messageSupplier) { + public static void assertNotNull(@Nullable Object actual, Supplier<@Nullable String> messageSupplier) { AssertNotNull.assertNotNull(actual, messageSupplier); } @@ -332,14 +338,14 @@ public static void assertEquals(short expected, short actual) { /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(short expected, Short actual) { + public static void assertEquals(short expected, @Nullable Short actual) { AssertEquals.assertEquals((Short) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(Short expected, short actual) { + public static void assertEquals(@Nullable Short expected, short actual) { AssertEquals.assertEquals(expected, (Short) actual); } @@ -349,7 +355,7 @@ public static void assertEquals(Short expected, short actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Short expected, Short actual) { + public static void assertEquals(@Nullable Short expected, @Nullable Short actual) { AssertEquals.assertEquals(expected, actual); } @@ -357,7 +363,7 @@ public static void assertEquals(Short expected, Short actual) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(short expected, short actual, String message) { + public static void assertEquals(short expected, short actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -365,7 +371,7 @@ public static void assertEquals(short expected, short actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(short expected, Short actual, String message) { + public static void assertEquals(short expected, @Nullable Short actual, @Nullable String message) { AssertEquals.assertEquals((Short) expected, actual, message); } @@ -373,7 +379,7 @@ public static void assertEquals(short expected, Short actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Short expected, short actual, String message) { + public static void assertEquals(@Nullable Short expected, short actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Short) actual, message); } @@ -384,7 +390,7 @@ public static void assertEquals(Short expected, short actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Short expected, Short actual, String message) { + public static void assertEquals(@Nullable Short expected, @Nullable Short actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -392,7 +398,7 @@ public static void assertEquals(Short expected, Short actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(short expected, short actual, Supplier messageSupplier) { + public static void assertEquals(short expected, short actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -400,7 +406,8 @@ public static void assertEquals(short expected, short actual, Supplier m * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(short expected, Short actual, Supplier messageSupplier) { + public static void assertEquals(short expected, @Nullable Short actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Short) expected, actual, messageSupplier); } @@ -408,7 +415,8 @@ public static void assertEquals(short expected, Short actual, Supplier m * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Short expected, short actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Short expected, short actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Short) actual, messageSupplier); } @@ -419,7 +427,8 @@ public static void assertEquals(Short expected, short actual, Supplier m * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Short expected, Short actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Short expected, @Nullable Short actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -433,14 +442,14 @@ public static void assertEquals(byte expected, byte actual) { /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(byte expected, Byte actual) { + public static void assertEquals(byte expected, @Nullable Byte actual) { AssertEquals.assertEquals((Byte) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(Byte expected, byte actual) { + public static void assertEquals(@Nullable Byte expected, byte actual) { AssertEquals.assertEquals(expected, (Byte) actual); } @@ -450,7 +459,7 @@ public static void assertEquals(Byte expected, byte actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Byte expected, Byte actual) { + public static void assertEquals(@Nullable Byte expected, @Nullable Byte actual) { AssertEquals.assertEquals(expected, actual); } @@ -458,7 +467,7 @@ public static void assertEquals(Byte expected, Byte actual) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(byte expected, byte actual, String message) { + public static void assertEquals(byte expected, byte actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -466,7 +475,7 @@ public static void assertEquals(byte expected, byte actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(byte expected, Byte actual, String message) { + public static void assertEquals(byte expected, @Nullable Byte actual, @Nullable String message) { AssertEquals.assertEquals((Byte) expected, actual, message); } @@ -474,7 +483,7 @@ public static void assertEquals(byte expected, Byte actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Byte expected, byte actual, String message) { + public static void assertEquals(@Nullable Byte expected, byte actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Byte) actual, message); } @@ -485,7 +494,7 @@ public static void assertEquals(Byte expected, byte actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Byte expected, Byte actual, String message) { + public static void assertEquals(@Nullable Byte expected, @Nullable Byte actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -493,7 +502,7 @@ public static void assertEquals(Byte expected, Byte actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(byte expected, byte actual, Supplier messageSupplier) { + public static void assertEquals(byte expected, byte actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -501,7 +510,7 @@ public static void assertEquals(byte expected, byte actual, Supplier mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(byte expected, Byte actual, Supplier messageSupplier) { + public static void assertEquals(byte expected, @Nullable Byte actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Byte) expected, actual, messageSupplier); } @@ -509,7 +518,7 @@ public static void assertEquals(byte expected, Byte actual, Supplier mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Byte expected, byte actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Byte expected, byte actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Byte) actual, messageSupplier); } @@ -520,7 +529,8 @@ public static void assertEquals(Byte expected, byte actual, Supplier mes * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Byte expected, Byte actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Byte expected, @Nullable Byte actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -534,14 +544,14 @@ public static void assertEquals(int expected, int actual) { /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(int expected, Integer actual) { + public static void assertEquals(int expected, @Nullable Integer actual) { AssertEquals.assertEquals((Integer) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(Integer expected, int actual) { + public static void assertEquals(@Nullable Integer expected, int actual) { AssertEquals.assertEquals(expected, (Integer) actual); } @@ -551,7 +561,7 @@ public static void assertEquals(Integer expected, int actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Integer expected, Integer actual) { + public static void assertEquals(@Nullable Integer expected, @Nullable Integer actual) { AssertEquals.assertEquals(expected, actual); } @@ -559,7 +569,7 @@ public static void assertEquals(Integer expected, Integer actual) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(int expected, int actual, String message) { + public static void assertEquals(int expected, int actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -567,7 +577,7 @@ public static void assertEquals(int expected, int actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(int expected, Integer actual, String message) { + public static void assertEquals(int expected, @Nullable Integer actual, @Nullable String message) { AssertEquals.assertEquals((Integer) expected, actual, message); } @@ -575,7 +585,7 @@ public static void assertEquals(int expected, Integer actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Integer expected, int actual, String message) { + public static void assertEquals(@Nullable Integer expected, int actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Integer) actual, message); } @@ -586,7 +596,7 @@ public static void assertEquals(Integer expected, int actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Integer expected, Integer actual, String message) { + public static void assertEquals(@Nullable Integer expected, @Nullable Integer actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -594,7 +604,7 @@ public static void assertEquals(Integer expected, Integer actual, String message * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(int expected, int actual, Supplier messageSupplier) { + public static void assertEquals(int expected, int actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -602,7 +612,8 @@ public static void assertEquals(int expected, int actual, Supplier messa * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(int expected, Integer actual, Supplier messageSupplier) { + public static void assertEquals(int expected, @Nullable Integer actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Integer) expected, actual, messageSupplier); } @@ -610,7 +621,8 @@ public static void assertEquals(int expected, Integer actual, Supplier m * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Integer expected, int actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Integer expected, int actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Integer) actual, messageSupplier); } @@ -621,7 +633,8 @@ public static void assertEquals(Integer expected, int actual, Supplier m * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Integer expected, Integer actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Integer expected, @Nullable Integer actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -635,14 +648,14 @@ public static void assertEquals(long expected, long actual) { /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(long expected, Long actual) { + public static void assertEquals(long expected, @Nullable Long actual) { AssertEquals.assertEquals((Long) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(Long expected, long actual) { + public static void assertEquals(@Nullable Long expected, long actual) { AssertEquals.assertEquals(expected, (Long) actual); } @@ -652,7 +665,7 @@ public static void assertEquals(Long expected, long actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Long expected, Long actual) { + public static void assertEquals(@Nullable Long expected, @Nullable Long actual) { AssertEquals.assertEquals(expected, actual); } @@ -660,7 +673,7 @@ public static void assertEquals(Long expected, Long actual) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(long expected, long actual, String message) { + public static void assertEquals(long expected, long actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -668,7 +681,7 @@ public static void assertEquals(long expected, long actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(long expected, Long actual, String message) { + public static void assertEquals(long expected, @Nullable Long actual, @Nullable String message) { AssertEquals.assertEquals((Long) expected, actual, message); } @@ -676,7 +689,7 @@ public static void assertEquals(long expected, Long actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Long expected, long actual, String message) { + public static void assertEquals(@Nullable Long expected, long actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Long) actual, message); } @@ -687,7 +700,7 @@ public static void assertEquals(Long expected, long actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Long expected, Long actual, String message) { + public static void assertEquals(@Nullable Long expected, @Nullable Long actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -695,7 +708,7 @@ public static void assertEquals(Long expected, Long actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(long expected, long actual, Supplier messageSupplier) { + public static void assertEquals(long expected, long actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -703,7 +716,7 @@ public static void assertEquals(long expected, long actual, Supplier mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(long expected, Long actual, Supplier messageSupplier) { + public static void assertEquals(long expected, @Nullable Long actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Long) expected, actual, messageSupplier); } @@ -711,7 +724,7 @@ public static void assertEquals(long expected, Long actual, Supplier mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Long expected, long actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Long expected, long actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Long) actual, messageSupplier); } @@ -722,7 +735,8 @@ public static void assertEquals(Long expected, long actual, Supplier mes * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Long expected, Long actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Long expected, @Nullable Long actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -740,7 +754,7 @@ public static void assertEquals(float expected, float actual) { *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ - public static void assertEquals(float expected, Float actual) { + public static void assertEquals(float expected, @Nullable Float actual) { AssertEquals.assertEquals((Float) expected, actual); } @@ -749,7 +763,7 @@ public static void assertEquals(float expected, Float actual) { *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ - public static void assertEquals(Float expected, float actual) { + public static void assertEquals(@Nullable Float expected, float actual) { AssertEquals.assertEquals(expected, (Float) actual); } @@ -761,7 +775,7 @@ public static void assertEquals(Float expected, float actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Float expected, Float actual) { + public static void assertEquals(@Nullable Float expected, @Nullable Float actual) { AssertEquals.assertEquals(expected, actual); } @@ -771,7 +785,7 @@ public static void assertEquals(Float expected, Float actual) { * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(float expected, float actual, String message) { + public static void assertEquals(float expected, float actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -781,7 +795,7 @@ public static void assertEquals(float expected, float actual, String message) { * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(float expected, Float actual, String message) { + public static void assertEquals(float expected, @Nullable Float actual, @Nullable String message) { AssertEquals.assertEquals((Float) expected, actual, message); } @@ -791,7 +805,7 @@ public static void assertEquals(float expected, Float actual, String message) { * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Float expected, float actual, String message) { + public static void assertEquals(@Nullable Float expected, float actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Float) actual, message); } @@ -804,7 +818,7 @@ public static void assertEquals(Float expected, float actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Float expected, Float actual, String message) { + public static void assertEquals(@Nullable Float expected, @Nullable Float actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -814,7 +828,7 @@ public static void assertEquals(Float expected, Float actual, String message) { * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(float expected, float actual, Supplier messageSupplier) { + public static void assertEquals(float expected, float actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -824,7 +838,8 @@ public static void assertEquals(float expected, float actual, Supplier m * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(float expected, Float actual, Supplier messageSupplier) { + public static void assertEquals(float expected, @Nullable Float actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Float) expected, actual, messageSupplier); } @@ -834,7 +849,8 @@ public static void assertEquals(float expected, Float actual, Supplier m * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Float expected, float actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Float expected, float actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Float) actual, messageSupplier); } @@ -847,7 +863,8 @@ public static void assertEquals(Float expected, float actual, Supplier m * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Float expected, Float actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Float expected, @Nullable Float actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -866,7 +883,7 @@ public static void assertEquals(float expected, float actual, float delta) { * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(float expected, float actual, float delta, String message) { + public static void assertEquals(float expected, float actual, float delta, @Nullable String message) { AssertEquals.assertEquals(expected, actual, delta, message); } @@ -876,7 +893,8 @@ public static void assertEquals(float expected, float actual, float delta, Strin * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(float expected, float actual, float delta, Supplier messageSupplier) { + public static void assertEquals(float expected, float actual, float delta, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, delta, messageSupplier); } @@ -894,7 +912,7 @@ public static void assertEquals(double expected, double actual) { *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ - public static void assertEquals(double expected, Double actual) { + public static void assertEquals(double expected, @Nullable Double actual) { AssertEquals.assertEquals((Double) expected, actual); } @@ -903,7 +921,7 @@ public static void assertEquals(double expected, Double actual) { *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ - public static void assertEquals(Double expected, double actual) { + public static void assertEquals(@Nullable Double expected, double actual) { AssertEquals.assertEquals(expected, (Double) actual); } @@ -915,7 +933,7 @@ public static void assertEquals(Double expected, double actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Double expected, Double actual) { + public static void assertEquals(@Nullable Double expected, @Nullable Double actual) { AssertEquals.assertEquals(expected, actual); } @@ -925,7 +943,7 @@ public static void assertEquals(Double expected, Double actual) { * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(double expected, double actual, String message) { + public static void assertEquals(double expected, double actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -935,7 +953,7 @@ public static void assertEquals(double expected, double actual, String message) * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(double expected, Double actual, String message) { + public static void assertEquals(double expected, @Nullable Double actual, @Nullable String message) { AssertEquals.assertEquals((Double) expected, actual, message); } @@ -945,7 +963,7 @@ public static void assertEquals(double expected, Double actual, String message) * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Double expected, double actual, String message) { + public static void assertEquals(@Nullable Double expected, double actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Double) actual, message); } @@ -958,7 +976,7 @@ public static void assertEquals(Double expected, double actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Double expected, Double actual, String message) { + public static void assertEquals(@Nullable Double expected, @Nullable Double actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -968,7 +986,7 @@ public static void assertEquals(Double expected, Double actual, String message) * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(double expected, double actual, Supplier messageSupplier) { + public static void assertEquals(double expected, double actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -978,7 +996,8 @@ public static void assertEquals(double expected, double actual, Supplier * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(double expected, Double actual, Supplier messageSupplier) { + public static void assertEquals(double expected, @Nullable Double actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Double) expected, actual, messageSupplier); } @@ -988,7 +1007,8 @@ public static void assertEquals(double expected, Double actual, Supplier * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Double expected, double actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Double expected, double actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Double) actual, messageSupplier); } @@ -1001,7 +1021,8 @@ public static void assertEquals(Double expected, double actual, Supplier * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Double expected, Double actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Double expected, @Nullable Double actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -1020,7 +1041,7 @@ public static void assertEquals(double expected, double actual, double delta) { * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(double expected, double actual, double delta, String message) { + public static void assertEquals(double expected, double actual, double delta, @Nullable String message) { AssertEquals.assertEquals(expected, actual, delta, message); } @@ -1030,7 +1051,8 @@ public static void assertEquals(double expected, double actual, double delta, St * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(double expected, double actual, double delta, Supplier messageSupplier) { + public static void assertEquals(double expected, double actual, double delta, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, delta, messageSupplier); } @@ -1044,14 +1066,14 @@ public static void assertEquals(char expected, char actual) { /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(char expected, Character actual) { + public static void assertEquals(char expected, @Nullable Character actual) { AssertEquals.assertEquals((Character) expected, actual); } /** * Assert that {@code expected} and {@code actual} are equal. */ - public static void assertEquals(Character expected, char actual) { + public static void assertEquals(@Nullable Character expected, char actual) { AssertEquals.assertEquals(expected, (Character) actual); } @@ -1061,7 +1083,7 @@ public static void assertEquals(Character expected, char actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Character expected, Character actual) { + public static void assertEquals(@Nullable Character expected, @Nullable Character actual) { AssertEquals.assertEquals(expected, actual); } @@ -1069,7 +1091,7 @@ public static void assertEquals(Character expected, Character actual) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(char expected, char actual, String message) { + public static void assertEquals(char expected, char actual, @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -1077,7 +1099,7 @@ public static void assertEquals(char expected, char actual, String message) { * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(char expected, Character actual, String message) { + public static void assertEquals(char expected, @Nullable Character actual, @Nullable String message) { AssertEquals.assertEquals((Character) expected, actual, message); } @@ -1085,7 +1107,7 @@ public static void assertEquals(char expected, Character actual, String message) * Assert that {@code expected} and {@code actual} are equal. *

Fails with the supplied failure {@code message}. */ - public static void assertEquals(Character expected, char actual, String message) { + public static void assertEquals(@Nullable Character expected, char actual, @Nullable String message) { AssertEquals.assertEquals(expected, (Character) actual, message); } @@ -1096,7 +1118,8 @@ public static void assertEquals(Character expected, char actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertEquals(Character expected, Character actual, String message) { + public static void assertEquals(@Nullable Character expected, @Nullable Character actual, + @Nullable String message) { AssertEquals.assertEquals(expected, actual, message); } @@ -1104,7 +1127,7 @@ public static void assertEquals(Character expected, Character actual, String mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(char expected, char actual, Supplier messageSupplier) { + public static void assertEquals(char expected, char actual, Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -1112,7 +1135,8 @@ public static void assertEquals(char expected, char actual, Supplier mes * Assert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(char expected, Character actual, Supplier messageSupplier) { + public static void assertEquals(char expected, @Nullable Character actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals((Character) expected, actual, messageSupplier); } @@ -1120,7 +1144,8 @@ public static void assertEquals(char expected, Character actual, SupplierAssert that {@code expected} and {@code actual} are equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertEquals(Character expected, char actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Character expected, char actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, (Character) actual, messageSupplier); } @@ -1131,7 +1156,8 @@ public static void assertEquals(Character expected, char actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Character expected, @Nullable Character actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -1141,7 +1167,7 @@ public static void assertEquals(Character expected, Character actual, Supplier messageSupplier) { + public static void assertEquals(@Nullable Object expected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { AssertEquals.assertEquals(expected, actual, messageSupplier); } @@ -1173,7 +1200,7 @@ public static void assertEquals(Object expected, Object actual, Supplier * Assert that {@code expected} and {@code actual} boolean arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(boolean[] expected, boolean[] actual) { + public static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1182,7 +1209,8 @@ public static void assertArrayEquals(boolean[] expected, boolean[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(boolean[] expected, boolean[] actual, String message) { + public static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1191,7 +1219,8 @@ public static void assertArrayEquals(boolean[] expected, boolean[] actual, Strin *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(boolean[] expected, boolean[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(boolean @Nullable [] expected, boolean @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1199,7 +1228,7 @@ public static void assertArrayEquals(boolean[] expected, boolean[] actual, Suppl * Assert that {@code expected} and {@code actual} char arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(char[] expected, char[] actual) { + public static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1208,7 +1237,8 @@ public static void assertArrayEquals(char[] expected, char[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(char[] expected, char[] actual, String message) { + public static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1217,7 +1247,8 @@ public static void assertArrayEquals(char[] expected, char[] actual, String mess *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(char[] expected, char[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(char @Nullable [] expected, char @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1225,7 +1256,7 @@ public static void assertArrayEquals(char[] expected, char[] actual, SupplierAssert that {@code expected} and {@code actual} byte arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(byte[] expected, byte[] actual) { + public static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1234,7 +1265,8 @@ public static void assertArrayEquals(byte[] expected, byte[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(byte[] expected, byte[] actual, String message) { + public static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1243,7 +1275,8 @@ public static void assertArrayEquals(byte[] expected, byte[] actual, String mess *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(byte[] expected, byte[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(byte @Nullable [] expected, byte @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1251,7 +1284,7 @@ public static void assertArrayEquals(byte[] expected, byte[] actual, SupplierAssert that {@code expected} and {@code actual} short arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(short[] expected, short[] actual) { + public static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1260,7 +1293,8 @@ public static void assertArrayEquals(short[] expected, short[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(short[] expected, short[] actual, String message) { + public static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1269,7 +1303,8 @@ public static void assertArrayEquals(short[] expected, short[] actual, String me *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(short[] expected, short[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(short @Nullable [] expected, short @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1277,7 +1312,7 @@ public static void assertArrayEquals(short[] expected, short[] actual, Supplier< * Assert that {@code expected} and {@code actual} int arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(int[] expected, int[] actual) { + public static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1286,7 +1321,7 @@ public static void assertArrayEquals(int[] expected, int[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(int[] expected, int[] actual, String message) { + public static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual, @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1295,7 +1330,8 @@ public static void assertArrayEquals(int[] expected, int[] actual, String messag *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(int[] expected, int[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(int @Nullable [] expected, int @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1303,7 +1339,7 @@ public static void assertArrayEquals(int[] expected, int[] actual, SupplierAssert that {@code expected} and {@code actual} long arrays are equal. *

If both are {@code null}, they are considered equal. */ - public static void assertArrayEquals(long[] expected, long[] actual) { + public static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1312,7 +1348,8 @@ public static void assertArrayEquals(long[] expected, long[] actual) { *

If both are {@code null}, they are considered equal. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(long[] expected, long[] actual, String message) { + public static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1321,7 +1358,8 @@ public static void assertArrayEquals(long[] expected, long[] actual, String mess *

If both are {@code null}, they are considered equal. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(long[] expected, long[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(long @Nullable [] expected, long @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1330,7 +1368,7 @@ public static void assertArrayEquals(long[] expected, long[] actual, SupplierEquality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ - public static void assertArrayEquals(float[] expected, float[] actual) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1340,7 +1378,8 @@ public static void assertArrayEquals(float[] expected, float[] actual) { * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(float[] expected, float[] actual, String message) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1350,7 +1389,8 @@ public static void assertArrayEquals(float[] expected, float[] actual, String me * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(float[] expected, float[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1359,7 +1399,7 @@ public static void assertArrayEquals(float[] expected, float[] actual, Supplier< *

Equality imposed by this method is consistent with {@link Float#equals(Object)} and * {@link Float#compare(float, float)}. */ - public static void assertArrayEquals(float[] expected, float[] actual, float delta) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta) { AssertArrayEquals.assertArrayEquals(expected, actual, delta); } @@ -1369,7 +1409,8 @@ public static void assertArrayEquals(float[] expected, float[] actual, float del * {@link Float#compare(float, float)}. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(float[] expected, float[] actual, float delta, String message) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, message); } @@ -1379,8 +1420,8 @@ public static void assertArrayEquals(float[] expected, float[] actual, float del * {@link Float#compare(float, float)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(float[] expected, float[] actual, float delta, - Supplier messageSupplier) { + public static void assertArrayEquals(float @Nullable [] expected, float @Nullable [] actual, float delta, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, messageSupplier); } @@ -1389,7 +1430,7 @@ public static void assertArrayEquals(float[] expected, float[] actual, float del *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ - public static void assertArrayEquals(double[] expected, double[] actual) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1399,7 +1440,8 @@ public static void assertArrayEquals(double[] expected, double[] actual) { * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(double[] expected, double[] actual, String message) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1409,7 +1451,8 @@ public static void assertArrayEquals(double[] expected, double[] actual, String * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(double[] expected, double[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1418,7 +1461,7 @@ public static void assertArrayEquals(double[] expected, double[] actual, Supplie *

Equality imposed by this method is consistent with {@link Double#equals(Object)} and * {@link Double#compare(double, double)}. */ - public static void assertArrayEquals(double[] expected, double[] actual, double delta) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta) { AssertArrayEquals.assertArrayEquals(expected, actual, delta); } @@ -1428,7 +1471,8 @@ public static void assertArrayEquals(double[] expected, double[] actual, double * {@link Double#compare(double, double)}. *

Fails with the supplied failure {@code message}. */ - public static void assertArrayEquals(double[] expected, double[] actual, double delta, String message) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, message); } @@ -1438,8 +1482,8 @@ public static void assertArrayEquals(double[] expected, double[] actual, double * {@link Double#compare(double, double)}. *

If necessary, the failure message will be retrieved lazily from the supplied {@code messageSupplier}. */ - public static void assertArrayEquals(double[] expected, double[] actual, double delta, - Supplier messageSupplier) { + public static void assertArrayEquals(double @Nullable [] expected, double @Nullable [] actual, double delta, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, delta, messageSupplier); } @@ -1452,7 +1496,7 @@ public static void assertArrayEquals(double[] expected, double[] actual, double * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ - public static void assertArrayEquals(Object[] expected, Object[] actual) { + public static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual) { AssertArrayEquals.assertArrayEquals(expected, actual); } @@ -1466,7 +1510,8 @@ public static void assertArrayEquals(Object[] expected, Object[] actual) { * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ - public static void assertArrayEquals(Object[] expected, Object[] actual, String message) { + public static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual, + @Nullable String message) { AssertArrayEquals.assertArrayEquals(expected, actual, message); } @@ -1480,7 +1525,8 @@ public static void assertArrayEquals(Object[] expected, Object[] actual, String * @see Objects#equals(Object, Object) * @see Arrays#deepEquals(Object[], Object[]) */ - public static void assertArrayEquals(Object[] expected, Object[] actual, Supplier messageSupplier) { + public static void assertArrayEquals(@Nullable Object @Nullable [] expected, @Nullable Object @Nullable [] actual, + Supplier<@Nullable String> messageSupplier) { AssertArrayEquals.assertArrayEquals(expected, actual, messageSupplier); } @@ -1504,7 +1550,7 @@ public static void assertArrayEquals(Object[] expected, Object[] actual, Supplie * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[]) */ - public static void assertIterableEquals(Iterable expected, Iterable actual) { + public static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual) { AssertIterableEquals.assertIterableEquals(expected, actual); } @@ -1528,7 +1574,8 @@ public static void assertIterableEquals(Iterable expected, Iterable actual * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[], String) */ - public static void assertIterableEquals(Iterable expected, Iterable actual, String message) { + public static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + @Nullable String message) { AssertIterableEquals.assertIterableEquals(expected, actual, message); } @@ -1552,8 +1599,8 @@ public static void assertIterableEquals(Iterable expected, Iterable actual * @see Arrays#deepEquals(Object[], Object[]) * @see #assertArrayEquals(Object[], Object[], Supplier) */ - public static void assertIterableEquals(Iterable expected, Iterable actual, - Supplier messageSupplier) { + public static void assertIterableEquals(@Nullable Iterable expected, @Nullable Iterable actual, + Supplier<@Nullable String> messageSupplier) { AssertIterableEquals.assertIterableEquals(expected, actual, messageSupplier); } @@ -1613,7 +1660,8 @@ public static void assertLinesMatch(List expectedLines, List act * * @see #assertLinesMatch(List, List) */ - public static void assertLinesMatch(List expectedLines, List actualLines, String message) { + public static void assertLinesMatch(List expectedLines, List actualLines, + @Nullable String message) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, message); } @@ -1630,7 +1678,7 @@ public static void assertLinesMatch(List expectedLines, List act * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(List expectedLines, List actualLines, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, messageSupplier); } @@ -1664,7 +1712,8 @@ public static void assertLinesMatch(Stream expectedLines, Stream * @since 5.7 * @see #assertLinesMatch(List, List) */ - public static void assertLinesMatch(Stream expectedLines, Stream actualLines, String message) { + public static void assertLinesMatch(Stream expectedLines, Stream actualLines, + @Nullable String message) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, message); } @@ -1685,7 +1734,7 @@ public static void assertLinesMatch(Stream expectedLines, Stream * @see #assertLinesMatch(List, List) */ public static void assertLinesMatch(Stream expectedLines, Stream actualLines, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { AssertLinesMatch.assertLinesMatch(expectedLines, actualLines, messageSupplier); } @@ -1707,7 +1756,7 @@ public static void assertNotEquals(byte unexpected, byte actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(byte unexpected, Byte actual) { + public static void assertNotEquals(byte unexpected, @Nullable Byte actual) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual); } @@ -1717,7 +1766,7 @@ public static void assertNotEquals(byte unexpected, Byte actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Byte unexpected, byte actual) { + public static void assertNotEquals(@Nullable Byte unexpected, byte actual) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual); } @@ -1727,7 +1776,7 @@ public static void assertNotEquals(Byte unexpected, byte actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Byte unexpected, Byte actual) { + public static void assertNotEquals(@Nullable Byte unexpected, @Nullable Byte actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -1739,7 +1788,7 @@ public static void assertNotEquals(Byte unexpected, Byte actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(byte unexpected, byte actual, String message) { + public static void assertNotEquals(byte unexpected, byte actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -1751,7 +1800,7 @@ public static void assertNotEquals(byte unexpected, byte actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(byte unexpected, Byte actual, String message) { + public static void assertNotEquals(byte unexpected, @Nullable Byte actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual, message); } @@ -1763,7 +1812,7 @@ public static void assertNotEquals(byte unexpected, Byte actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Byte unexpected, byte actual, String message) { + public static void assertNotEquals(@Nullable Byte unexpected, byte actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual, message); } @@ -1775,7 +1824,7 @@ public static void assertNotEquals(Byte unexpected, byte actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Byte unexpected, Byte actual, String message) { + public static void assertNotEquals(@Nullable Byte unexpected, @Nullable Byte actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -1788,7 +1837,7 @@ public static void assertNotEquals(Byte unexpected, Byte actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { + public static void assertNotEquals(byte unexpected, byte actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -1801,7 +1850,8 @@ public static void assertNotEquals(byte unexpected, byte actual, Supplier messageSupplier) { + public static void assertNotEquals(byte unexpected, @Nullable Byte actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Byte) unexpected, actual, messageSupplier); } @@ -1814,7 +1864,8 @@ public static void assertNotEquals(byte unexpected, Byte actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Byte unexpected, byte actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Byte) actual, messageSupplier); } @@ -1827,7 +1878,8 @@ public static void assertNotEquals(Byte unexpected, byte actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Byte unexpected, @Nullable Byte actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -1847,7 +1899,7 @@ public static void assertNotEquals(short unexpected, short actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(short unexpected, Short actual) { + public static void assertNotEquals(short unexpected, @Nullable Short actual) { AssertNotEquals.assertNotEquals((Short) unexpected, actual); } @@ -1857,7 +1909,7 @@ public static void assertNotEquals(short unexpected, Short actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Short unexpected, short actual) { + public static void assertNotEquals(@Nullable Short unexpected, short actual) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual); } @@ -1867,7 +1919,7 @@ public static void assertNotEquals(Short unexpected, short actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Short unexpected, Short actual) { + public static void assertNotEquals(@Nullable Short unexpected, @Nullable Short actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -1879,7 +1931,7 @@ public static void assertNotEquals(Short unexpected, Short actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(short unexpected, short actual, String message) { + public static void assertNotEquals(short unexpected, short actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -1891,7 +1943,7 @@ public static void assertNotEquals(short unexpected, short actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(short unexpected, Short actual, String message) { + public static void assertNotEquals(short unexpected, @Nullable Short actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Short) unexpected, actual, message); } @@ -1903,7 +1955,7 @@ public static void assertNotEquals(short unexpected, Short actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Short unexpected, short actual, String message) { + public static void assertNotEquals(@Nullable Short unexpected, short actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual, message); } @@ -1915,7 +1967,7 @@ public static void assertNotEquals(Short unexpected, short actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Short unexpected, Short actual, String message) { + public static void assertNotEquals(@Nullable Short unexpected, @Nullable Short actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -1928,7 +1980,7 @@ public static void assertNotEquals(Short unexpected, Short actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { + public static void assertNotEquals(short unexpected, short actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -1941,7 +1993,8 @@ public static void assertNotEquals(short unexpected, short actual, Supplier messageSupplier) { + public static void assertNotEquals(short unexpected, @Nullable Short actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Short) unexpected, actual, messageSupplier); } @@ -1954,7 +2007,8 @@ public static void assertNotEquals(short unexpected, Short actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Short unexpected, short actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Short) actual, messageSupplier); } @@ -1967,7 +2021,8 @@ public static void assertNotEquals(Short unexpected, short actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Short unexpected, @Nullable Short actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -1987,7 +2042,7 @@ public static void assertNotEquals(int unexpected, int actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(int unexpected, Integer actual) { + public static void assertNotEquals(int unexpected, @Nullable Integer actual) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual); } @@ -1997,7 +2052,7 @@ public static void assertNotEquals(int unexpected, Integer actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Integer unexpected, int actual) { + public static void assertNotEquals(@Nullable Integer unexpected, int actual) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual); } @@ -2007,7 +2062,7 @@ public static void assertNotEquals(Integer unexpected, int actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Integer unexpected, Integer actual) { + public static void assertNotEquals(@Nullable Integer unexpected, @Nullable Integer actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2019,7 +2074,7 @@ public static void assertNotEquals(Integer unexpected, Integer actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(int unexpected, int actual, String message) { + public static void assertNotEquals(int unexpected, int actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2031,7 +2086,7 @@ public static void assertNotEquals(int unexpected, int actual, String message) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(int unexpected, Integer actual, String message) { + public static void assertNotEquals(int unexpected, @Nullable Integer actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual, message); } @@ -2043,7 +2098,7 @@ public static void assertNotEquals(int unexpected, Integer actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Integer unexpected, int actual, String message) { + public static void assertNotEquals(@Nullable Integer unexpected, int actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual, message); } @@ -2055,7 +2110,8 @@ public static void assertNotEquals(Integer unexpected, int actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Integer unexpected, Integer actual, String message) { + public static void assertNotEquals(@Nullable Integer unexpected, @Nullable Integer actual, + @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2068,7 +2124,7 @@ public static void assertNotEquals(Integer unexpected, Integer actual, String me * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(int unexpected, int actual, Supplier messageSupplier) { + public static void assertNotEquals(int unexpected, int actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2081,7 +2137,8 @@ public static void assertNotEquals(int unexpected, int actual, Supplier * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(int unexpected, Integer actual, Supplier messageSupplier) { + public static void assertNotEquals(int unexpected, @Nullable Integer actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Integer) unexpected, actual, messageSupplier); } @@ -2094,7 +2151,8 @@ public static void assertNotEquals(int unexpected, Integer actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Integer unexpected, int actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Integer) actual, messageSupplier); } @@ -2107,7 +2165,8 @@ public static void assertNotEquals(Integer unexpected, int actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Integer unexpected, @Nullable Integer actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2127,7 +2186,7 @@ public static void assertNotEquals(long unexpected, long actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(long unexpected, Long actual) { + public static void assertNotEquals(long unexpected, @Nullable Long actual) { AssertNotEquals.assertNotEquals((Long) unexpected, actual); } @@ -2137,7 +2196,7 @@ public static void assertNotEquals(long unexpected, Long actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Long unexpected, long actual) { + public static void assertNotEquals(@Nullable Long unexpected, long actual) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual); } @@ -2147,7 +2206,7 @@ public static void assertNotEquals(Long unexpected, long actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Long unexpected, Long actual) { + public static void assertNotEquals(@Nullable Long unexpected, @Nullable Long actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2159,7 +2218,7 @@ public static void assertNotEquals(Long unexpected, Long actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(long unexpected, long actual, String message) { + public static void assertNotEquals(long unexpected, long actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2171,7 +2230,7 @@ public static void assertNotEquals(long unexpected, long actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(long unexpected, Long actual, String message) { + public static void assertNotEquals(long unexpected, @Nullable Long actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Long) unexpected, actual, message); } @@ -2183,7 +2242,7 @@ public static void assertNotEquals(long unexpected, Long actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Long unexpected, long actual, String message) { + public static void assertNotEquals(@Nullable Long unexpected, long actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual, message); } @@ -2195,7 +2254,7 @@ public static void assertNotEquals(Long unexpected, long actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Long unexpected, Long actual, String message) { + public static void assertNotEquals(@Nullable Long unexpected, @Nullable Long actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2208,7 +2267,7 @@ public static void assertNotEquals(Long unexpected, Long actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { + public static void assertNotEquals(long unexpected, long actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2221,7 +2280,8 @@ public static void assertNotEquals(long unexpected, long actual, Supplier messageSupplier) { + public static void assertNotEquals(long unexpected, @Nullable Long actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Long) unexpected, actual, messageSupplier); } @@ -2234,7 +2294,8 @@ public static void assertNotEquals(long unexpected, Long actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Long unexpected, long actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Long) actual, messageSupplier); } @@ -2247,7 +2308,8 @@ public static void assertNotEquals(Long unexpected, long actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Long unexpected, @Nullable Long actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2273,7 +2335,7 @@ public static void assertNotEquals(float unexpected, float actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, Float actual) { + public static void assertNotEquals(float unexpected, @Nullable Float actual) { AssertNotEquals.assertNotEquals((Float) unexpected, actual); } @@ -2286,7 +2348,7 @@ public static void assertNotEquals(float unexpected, Float actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Float unexpected, float actual) { + public static void assertNotEquals(@Nullable Float unexpected, float actual) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual); } @@ -2299,7 +2361,7 @@ public static void assertNotEquals(Float unexpected, float actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Float unexpected, Float actual) { + public static void assertNotEquals(@Nullable Float unexpected, @Nullable Float actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2314,7 +2376,7 @@ public static void assertNotEquals(Float unexpected, Float actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, float actual, String message) { + public static void assertNotEquals(float unexpected, float actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2329,7 +2391,7 @@ public static void assertNotEquals(float unexpected, float actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, Float actual, String message) { + public static void assertNotEquals(float unexpected, @Nullable Float actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Float) unexpected, actual, message); } @@ -2344,7 +2406,7 @@ public static void assertNotEquals(float unexpected, Float actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Float unexpected, float actual, String message) { + public static void assertNotEquals(@Nullable Float unexpected, float actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual, message); } @@ -2359,7 +2421,7 @@ public static void assertNotEquals(Float unexpected, float actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Float unexpected, Float actual, String message) { + public static void assertNotEquals(@Nullable Float unexpected, @Nullable Float actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2372,7 +2434,7 @@ public static void assertNotEquals(Float unexpected, Float actual, String messag * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { + public static void assertNotEquals(float unexpected, float actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2385,7 +2447,8 @@ public static void assertNotEquals(float unexpected, float actual, Supplier messageSupplier) { + public static void assertNotEquals(float unexpected, @Nullable Float actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Float) unexpected, actual, messageSupplier); } @@ -2398,7 +2461,8 @@ public static void assertNotEquals(float unexpected, Float actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Float unexpected, float actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Float) actual, messageSupplier); } @@ -2411,7 +2475,8 @@ public static void assertNotEquals(Float unexpected, float actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Float unexpected, @Nullable Float actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2441,7 +2506,7 @@ public static void assertNotEquals(float unexpected, float actual, float delta) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, float actual, float delta, String message) { + public static void assertNotEquals(float unexpected, float actual, float delta, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, message); } @@ -2455,7 +2520,8 @@ public static void assertNotEquals(float unexpected, float actual, float delta, * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(float unexpected, float actual, float delta, Supplier messageSupplier) { + public static void assertNotEquals(float unexpected, float actual, float delta, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, messageSupplier); } @@ -2481,7 +2547,7 @@ public static void assertNotEquals(double unexpected, double actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(double unexpected, Double actual) { + public static void assertNotEquals(double unexpected, @Nullable Double actual) { AssertNotEquals.assertNotEquals((Double) unexpected, actual); } @@ -2494,7 +2560,7 @@ public static void assertNotEquals(double unexpected, Double actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Double unexpected, double actual) { + public static void assertNotEquals(@Nullable Double unexpected, double actual) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual); } @@ -2507,7 +2573,7 @@ public static void assertNotEquals(Double unexpected, double actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Double unexpected, Double actual) { + public static void assertNotEquals(@Nullable Double unexpected, @Nullable Double actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2522,7 +2588,7 @@ public static void assertNotEquals(Double unexpected, Double actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(double unexpected, double actual, String message) { + public static void assertNotEquals(double unexpected, double actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2537,7 +2603,7 @@ public static void assertNotEquals(double unexpected, double actual, String mess * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(double unexpected, Double actual, String message) { + public static void assertNotEquals(double unexpected, @Nullable Double actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Double) unexpected, actual, message); } @@ -2552,7 +2618,7 @@ public static void assertNotEquals(double unexpected, Double actual, String mess * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Double unexpected, double actual, String message) { + public static void assertNotEquals(@Nullable Double unexpected, double actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual, message); } @@ -2567,7 +2633,7 @@ public static void assertNotEquals(Double unexpected, double actual, String mess * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Double unexpected, Double actual, String message) { + public static void assertNotEquals(@Nullable Double unexpected, @Nullable Double actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2580,7 +2646,7 @@ public static void assertNotEquals(Double unexpected, Double actual, String mess * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { + public static void assertNotEquals(double unexpected, double actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2593,7 +2659,8 @@ public static void assertNotEquals(double unexpected, double actual, Supplier messageSupplier) { + public static void assertNotEquals(double unexpected, @Nullable Double actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Double) unexpected, actual, messageSupplier); } @@ -2606,7 +2673,8 @@ public static void assertNotEquals(double unexpected, Double actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Double unexpected, double actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Double) actual, messageSupplier); } @@ -2619,7 +2687,8 @@ public static void assertNotEquals(Double unexpected, double actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Double unexpected, @Nullable Double actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2649,7 +2718,7 @@ public static void assertNotEquals(double unexpected, double actual, double delt * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(double unexpected, double actual, double delta, String message) { + public static void assertNotEquals(double unexpected, double actual, double delta, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, message); } @@ -2664,7 +2733,7 @@ public static void assertNotEquals(double unexpected, double actual, double delt */ @API(status = STABLE, since = "5.4") public static void assertNotEquals(double unexpected, double actual, double delta, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, delta, messageSupplier); } @@ -2684,7 +2753,7 @@ public static void assertNotEquals(char unexpected, char actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(char unexpected, Character actual) { + public static void assertNotEquals(char unexpected, @Nullable Character actual) { AssertNotEquals.assertNotEquals((Character) unexpected, actual); } @@ -2694,7 +2763,7 @@ public static void assertNotEquals(char unexpected, Character actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Character unexpected, char actual) { + public static void assertNotEquals(@Nullable Character unexpected, char actual) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual); } @@ -2704,7 +2773,7 @@ public static void assertNotEquals(Character unexpected, char actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Character unexpected, Character actual) { + public static void assertNotEquals(@Nullable Character unexpected, @Nullable Character actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2716,7 +2785,7 @@ public static void assertNotEquals(Character unexpected, Character actual) { * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(char unexpected, char actual, String message) { + public static void assertNotEquals(char unexpected, char actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2728,7 +2797,7 @@ public static void assertNotEquals(char unexpected, char actual, String message) * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(char unexpected, Character actual, String message) { + public static void assertNotEquals(char unexpected, @Nullable Character actual, @Nullable String message) { AssertNotEquals.assertNotEquals((Character) unexpected, actual, message); } @@ -2740,7 +2809,7 @@ public static void assertNotEquals(char unexpected, Character actual, String mes * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Character unexpected, char actual, String message) { + public static void assertNotEquals(@Nullable Character unexpected, char actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual, message); } @@ -2752,7 +2821,8 @@ public static void assertNotEquals(Character unexpected, char actual, String mes * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(Character unexpected, Character actual, String message) { + public static void assertNotEquals(@Nullable Character unexpected, @Nullable Character actual, + @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2765,7 +2835,7 @@ public static void assertNotEquals(Character unexpected, Character actual, Strin * @since 5.4 */ @API(status = STABLE, since = "5.4") - public static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { + public static void assertNotEquals(char unexpected, char actual, Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2778,7 +2848,8 @@ public static void assertNotEquals(char unexpected, char actual, Supplier messageSupplier) { + public static void assertNotEquals(char unexpected, @Nullable Character actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals((Character) unexpected, actual, messageSupplier); } @@ -2791,7 +2862,8 @@ public static void assertNotEquals(char unexpected, Character actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Character unexpected, char actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, (Character) actual, messageSupplier); } @@ -2804,7 +2876,8 @@ public static void assertNotEquals(Character unexpected, char actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Character unexpected, @Nullable Character actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2815,7 +2888,7 @@ public static void assertNotEquals(Character unexpected, Character actual, Suppl * * @see Object#equals(Object) */ - public static void assertNotEquals(Object unexpected, Object actual) { + public static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual) { AssertNotEquals.assertNotEquals(unexpected, actual); } @@ -2828,7 +2901,7 @@ public static void assertNotEquals(Object unexpected, Object actual) { * * @see Object#equals(Object) */ - public static void assertNotEquals(Object unexpected, Object actual, String message) { + public static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual, @Nullable String message) { AssertNotEquals.assertNotEquals(unexpected, actual, message); } @@ -2842,7 +2915,8 @@ public static void assertNotEquals(Object unexpected, Object actual, String mess * * @see Object#equals(Object) */ - public static void assertNotEquals(Object unexpected, Object actual, Supplier messageSupplier) { + public static void assertNotEquals(@Nullable Object unexpected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { AssertNotEquals.assertNotEquals(unexpected, actual, messageSupplier); } @@ -2856,7 +2930,7 @@ public static void assertNotEquals(Object unexpected, Object actual, SupplierFails with the supplied failure {@code message}. */ - public static void assertSame(Object expected, Object actual, String message) { + public static void assertSame(@Nullable Object expected, @Nullable Object actual, @Nullable String message) { AssertSame.assertSame(expected, actual, message); } @@ -2883,7 +2957,8 @@ public static void assertSame(Object expected, Object actual, String message) { *

If necessary, the failure message will be retrieved lazily from the supplied * {@code messageSupplier}. */ - public static void assertSame(Object expected, Object actual, Supplier messageSupplier) { + public static void assertSame(@Nullable Object expected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { AssertSame.assertSame(expected, actual, messageSupplier); } @@ -2896,7 +2971,7 @@ public static void assertSame(Object expected, Object actual, Supplier m * objects. To assert that two objects or two primitive values are not * equal, use one of the {@code assertNotEquals(...)} methods instead. */ - public static void assertNotSame(Object unexpected, Object actual) { + public static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual) { AssertNotSame.assertNotSame(unexpected, actual); } @@ -2908,7 +2983,7 @@ public static void assertNotSame(Object unexpected, Object actual) { * equal, use one of the {@code assertNotEquals(...)} methods instead. *

Fails with the supplied failure {@code message}. */ - public static void assertNotSame(Object unexpected, Object actual, String message) { + public static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual, @Nullable String message) { AssertNotSame.assertNotSame(unexpected, actual, message); } @@ -2921,7 +2996,8 @@ public static void assertNotSame(Object unexpected, Object actual, String messag *

If necessary, the failure message will be retrieved lazily from the supplied * {@code messageSupplier}. */ - public static void assertNotSame(Object unexpected, Object actual, Supplier messageSupplier) { + public static void assertNotSame(@Nullable Object unexpected, @Nullable Object actual, + Supplier<@Nullable String> messageSupplier) { AssertNotSame.assertNotSame(unexpected, actual, messageSupplier); } @@ -2957,7 +3033,7 @@ public static void assertAll(Executable... executables) throws MultipleFailuresE * @see #assertAll(String, Collection) * @see #assertAll(String, Stream) */ - public static void assertAll(String heading, Executable... executables) throws MultipleFailuresError { + public static void assertAll(@Nullable String heading, Executable... executables) throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } @@ -2991,7 +3067,8 @@ public static void assertAll(Collection executables) throws Multiple * @see #assertAll(Stream) * @see #assertAll(String, Stream) */ - public static void assertAll(String heading, Collection executables) throws MultipleFailuresError { + public static void assertAll(@Nullable String heading, Collection executables) + throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } @@ -3035,7 +3112,8 @@ public static void assertAll(Stream executables) throws MultipleFail * @see #assertAll(String, Collection) * @see #assertAll(Stream) */ - public static void assertAll(String heading, Stream executables) throws MultipleFailuresError { + public static void assertAll(@Nullable String heading, Stream executables) + throws MultipleFailuresError { AssertAll.assertAll(heading, executables); } @@ -3080,7 +3158,7 @@ public static T assertThrowsExactly(Class expectedType, */ @API(status = STABLE, since = "5.10") public static T assertThrowsExactly(Class expectedType, Executable executable, - String message) { + @Nullable String message) { return AssertThrowsExactly.assertThrowsExactly(expectedType, executable, message); } @@ -3105,7 +3183,7 @@ public static T assertThrowsExactly(Class expectedType, */ @API(status = STABLE, since = "5.10") public static T assertThrowsExactly(Class expectedType, Executable executable, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { return AssertThrowsExactly.assertThrowsExactly(expectedType, executable, messageSupplier); } @@ -3149,7 +3227,8 @@ public static T assertThrows(Class expectedType, Execut * * @see #assertThrowsExactly(Class, Executable, String) */ - public static T assertThrows(Class expectedType, Executable executable, String message) { + public static T assertThrows(Class expectedType, Executable executable, + @Nullable String message) { return AssertThrows.assertThrows(expectedType, executable, message); } @@ -3176,7 +3255,7 @@ public static T assertThrows(Class expectedType, Execut * @see #assertThrowsExactly(Class, Executable, Supplier) */ public static T assertThrows(Class expectedType, Executable executable, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { return AssertThrows.assertThrows(expectedType, executable, messageSupplier); } @@ -3214,7 +3293,7 @@ public static void assertDoesNotThrow(Executable executable) { * @since 5.2 */ @API(status = STABLE, since = "5.2") - public static void assertDoesNotThrow(Executable executable, String message) { + public static void assertDoesNotThrow(Executable executable, @Nullable String message) { AssertDoesNotThrow.assertDoesNotThrow(executable, message); } @@ -3234,7 +3313,7 @@ public static void assertDoesNotThrow(Executable executable, String message) { * @since 5.2 */ @API(status = STABLE, since = "5.2") - public static void assertDoesNotThrow(Executable executable, Supplier messageSupplier) { + public static void assertDoesNotThrow(Executable executable, Supplier<@Nullable String> messageSupplier) { AssertDoesNotThrow.assertDoesNotThrow(executable, messageSupplier); } @@ -3255,7 +3334,7 @@ public static void assertDoesNotThrow(Executable executable, Supplier me * @since 5.2 */ @API(status = STABLE, since = "5.2") - public static T assertDoesNotThrow(ThrowingSupplier supplier) { + public static T assertDoesNotThrow(ThrowingSupplier supplier) { return AssertDoesNotThrow.assertDoesNotThrow(supplier); } @@ -3276,7 +3355,8 @@ public static T assertDoesNotThrow(ThrowingSupplier supplier) { * @since 5.2 */ @API(status = STABLE, since = "5.2") - public static T assertDoesNotThrow(ThrowingSupplier supplier, String message) { + public static T assertDoesNotThrow(ThrowingSupplier supplier, + @Nullable String message) { return AssertDoesNotThrow.assertDoesNotThrow(supplier, message); } @@ -3298,7 +3378,8 @@ public static T assertDoesNotThrow(ThrowingSupplier supplier, String mess * @since 5.2 */ @API(status = STABLE, since = "5.2") - public static T assertDoesNotThrow(ThrowingSupplier supplier, Supplier messageSupplier) { + public static T assertDoesNotThrow(ThrowingSupplier supplier, + Supplier<@Nullable String> messageSupplier) { return AssertDoesNotThrow.assertDoesNotThrow(supplier, messageSupplier); } @@ -3342,7 +3423,7 @@ public static void assertTimeout(Duration timeout, Executable executable) { * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, String) */ - public static void assertTimeout(Duration timeout, Executable executable, String message) { + public static void assertTimeout(Duration timeout, Executable executable, @Nullable String message) { AssertTimeout.assertTimeout(timeout, executable, message); } @@ -3364,7 +3445,8 @@ public static void assertTimeout(Duration timeout, Executable executable, String * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) */ - public static void assertTimeout(Duration timeout, Executable executable, Supplier messageSupplier) { + public static void assertTimeout(Duration timeout, Executable executable, + Supplier<@Nullable String> messageSupplier) { AssertTimeout.assertTimeout(timeout, executable, messageSupplier); } @@ -3387,7 +3469,7 @@ public static void assertTimeout(Duration timeout, Executable executable, Suppli * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable) */ - public static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { + public static T assertTimeout(Duration timeout, ThrowingSupplier supplier) { return AssertTimeout.assertTimeout(timeout, supplier); } @@ -3410,7 +3492,8 @@ public static T assertTimeout(Duration timeout, ThrowingSupplier supplier * @see #assertTimeout(Duration, ThrowingSupplier, Supplier) * @see #assertTimeoutPreemptively(Duration, Executable, String) */ - public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, String message) { + public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, + @Nullable String message) { return AssertTimeout.assertTimeout(timeout, supplier, message); } @@ -3434,8 +3517,8 @@ public static T assertTimeout(Duration timeout, ThrowingSupplier supplier * @see #assertTimeout(Duration, ThrowingSupplier, String) * @see #assertTimeoutPreemptively(Duration, Executable, Supplier) */ - public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, - Supplier messageSupplier) { + public static T assertTimeout(Duration timeout, ThrowingSupplier supplier, + Supplier<@Nullable String> messageSupplier) { return AssertTimeout.assertTimeout(timeout, supplier, messageSupplier); } @@ -3475,7 +3558,7 @@ public static void assertTimeoutPreemptively(Duration timeout, Executable execut * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable, String) */ - public static void assertTimeoutPreemptively(Duration timeout, Executable executable, String message) { + public static void assertTimeoutPreemptively(Duration timeout, Executable executable, @Nullable String message) { AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, executable, message); } @@ -3497,7 +3580,7 @@ public static void assertTimeoutPreemptively(Duration timeout, Executable execut * @see #assertTimeout(Duration, Executable, Supplier) */ public static void assertTimeoutPreemptively(Duration timeout, Executable executable, - Supplier messageSupplier) { + Supplier<@Nullable String> messageSupplier) { AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, executable, messageSupplier); } @@ -3519,7 +3602,8 @@ public static void assertTimeoutPreemptively(Duration timeout, Executable execut * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable) */ - public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier) { + public static T assertTimeoutPreemptively(Duration timeout, + ThrowingSupplier supplier) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier); } @@ -3541,7 +3625,8 @@ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, Supplier) * @see #assertTimeout(Duration, Executable, String) */ - public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, String message) { + public static T assertTimeoutPreemptively(Duration timeout, + ThrowingSupplier supplier, @Nullable String message) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, message); } @@ -3564,8 +3649,8 @@ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier * @see #assertTimeoutPreemptively(Duration, ThrowingSupplier, String) * @see #assertTimeout(Duration, Executable, Supplier) */ - public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, - Supplier messageSupplier) { + public static T assertTimeoutPreemptively(Duration timeout, + ThrowingSupplier supplier, Supplier<@Nullable String> messageSupplier) { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, messageSupplier); } @@ -3593,8 +3678,9 @@ public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier * @see #assertTimeout(Duration, Executable, Supplier) */ @API(status = INTERNAL, since = "5.9.1") - public static T assertTimeoutPreemptively(Duration timeout, ThrowingSupplier supplier, - Supplier messageSupplier, TimeoutFailureFactory failureFactory) throws E { + public static T assertTimeoutPreemptively(Duration timeout, + ThrowingSupplier supplier, Supplier<@Nullable String> messageSupplier, + TimeoutFailureFactory failureFactory) throws E { return AssertTimeoutPreemptively.assertTimeoutPreemptively(timeout, supplier, messageSupplier, failureFactory); } @@ -3610,7 +3696,7 @@ public static T assertTimeoutPreemptively(Duration time * @since 5.8 */ @API(status = STABLE, since = "5.10") - public static T assertInstanceOf(Class expectedType, Object actualValue) { + public static T assertInstanceOf(Class expectedType, @Nullable Object actualValue) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue); } @@ -3626,7 +3712,8 @@ public static T assertInstanceOf(Class expectedType, Object actualValue) * @since 5.8 */ @API(status = STABLE, since = "5.10") - public static T assertInstanceOf(Class expectedType, Object actualValue, String message) { + public static T assertInstanceOf(Class expectedType, @Nullable Object actualValue, + @Nullable String message) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue, message); } @@ -3643,7 +3730,8 @@ public static T assertInstanceOf(Class expectedType, Object actualValue, * @since 5.8 */ @API(status = STABLE, since = "5.10") - public static T assertInstanceOf(Class expectedType, Object actualValue, Supplier messageSupplier) { + public static T assertInstanceOf(Class expectedType, @Nullable Object actualValue, + Supplier<@Nullable String> messageSupplier) { return AssertInstanceOf.assertInstanceOf(expectedType, actualValue, messageSupplier); } @@ -3662,6 +3750,7 @@ public interface TimeoutFailureFactory { * * @return timeout failure; never {@code null} */ - T createTimeoutFailure(Duration timeout, Supplier messageSupplier, Throwable cause, Thread testThread); + T createTimeoutFailure(Duration timeout, @Nullable Supplier<@Nullable String> messageSupplier, + @Nullable Throwable cause, @Nullable Thread testThread); } } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assumptions.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assumptions.java index 6545518b4d3e..b0619ad3cc32 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assumptions.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Assumptions.java @@ -16,6 +16,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.StringUtils; @@ -89,7 +90,8 @@ public static void assumeTrue(BooleanSupplier assumptionSupplier) throws TestAbo * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ - public static void assumeTrue(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException { + public static void assumeTrue(BooleanSupplier assumptionSupplier, @Nullable String message) + throws TestAbortedException { assumeTrue(assumptionSupplier.getAsBoolean(), message); } @@ -101,7 +103,8 @@ public static void assumeTrue(BooleanSupplier assumptionSupplier, String message * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ - public static void assumeTrue(boolean assumption, Supplier messageSupplier) throws TestAbortedException { + public static void assumeTrue(boolean assumption, Supplier<@Nullable String> messageSupplier) + throws TestAbortedException { if (!assumption) { throwAssumptionFailed(messageSupplier.get()); } @@ -115,7 +118,7 @@ public static void assumeTrue(boolean assumption, Supplier messageSuppli * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ - public static void assumeTrue(boolean assumption, String message) throws TestAbortedException { + public static void assumeTrue(boolean assumption, @Nullable String message) throws TestAbortedException { if (!assumption) { throwAssumptionFailed(message); } @@ -129,7 +132,7 @@ public static void assumeTrue(boolean assumption, String message) throws TestAbo * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code true} */ - public static void assumeTrue(BooleanSupplier assumptionSupplier, Supplier messageSupplier) + public static void assumeTrue(BooleanSupplier assumptionSupplier, Supplier<@Nullable String> messageSupplier) throws TestAbortedException { assumeTrue(assumptionSupplier.getAsBoolean(), messageSupplier); @@ -165,7 +168,8 @@ public static void assumeFalse(BooleanSupplier assumptionSupplier) throws TestAb * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ - public static void assumeFalse(BooleanSupplier assumptionSupplier, String message) throws TestAbortedException { + public static void assumeFalse(BooleanSupplier assumptionSupplier, @Nullable String message) + throws TestAbortedException { assumeFalse(assumptionSupplier.getAsBoolean(), message); } @@ -177,7 +181,8 @@ public static void assumeFalse(BooleanSupplier assumptionSupplier, String messag * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ - public static void assumeFalse(boolean assumption, Supplier messageSupplier) throws TestAbortedException { + public static void assumeFalse(boolean assumption, Supplier<@Nullable String> messageSupplier) + throws TestAbortedException { if (assumption) { throwAssumptionFailed(messageSupplier.get()); } @@ -191,7 +196,7 @@ public static void assumeFalse(boolean assumption, Supplier messageSuppl * if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ - public static void assumeFalse(boolean assumption, String message) throws TestAbortedException { + public static void assumeFalse(boolean assumption, @Nullable String message) throws TestAbortedException { if (assumption) { throwAssumptionFailed(message); } @@ -205,7 +210,7 @@ public static void assumeFalse(boolean assumption, String message) throws TestAb * the {@code TestAbortedException} if the assumption is invalid * @throws TestAbortedException if the assumption is not {@code false} */ - public static void assumeFalse(BooleanSupplier assumptionSupplier, Supplier messageSupplier) + public static void assumeFalse(BooleanSupplier assumptionSupplier, Supplier<@Nullable String> messageSupplier) throws TestAbortedException { assumeFalse(assumptionSupplier.getAsBoolean(), messageSupplier); @@ -316,7 +321,7 @@ public static V abort(Supplier messageSupplier) { throw new TestAbortedException(messageSupplier.get()); } - private static void throwAssumptionFailed(String message) { + private static void throwAssumptionFailed(@Nullable String message) { throw new TestAbortedException( StringUtils.isNotBlank(message) ? "Assumption failed: " + message : "Assumption failed"); } 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 99c4ce49b939..f3e65a73436b 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 @@ -31,6 +31,7 @@ import java.util.function.Predicate; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.ClassUtils; import org.junit.platform.commons.util.Preconditions; @@ -386,14 +387,13 @@ public String generateDisplayNameForMethod(List> enclosingInstanceTypes private String getSentenceBeginning(Class testClass, List> enclosingInstanceTypes) { Class enclosingClass = enclosingInstanceTypes.isEmpty() ? null : enclosingInstanceTypes.get(enclosingInstanceTypes.size() - 1); - boolean topLevelTestClass = (enclosingClass == null || isStatic(testClass)); String sentenceFragment = findAnnotation(testClass, DisplayName.class)// .map(DisplayName::value)// .map(String::trim)// .orElseGet(() -> getSentenceFragment(testClass)); - if (topLevelTestClass) { + if (enclosingClass == null || isStatic(testClass)) { // top-level class if (sentenceFragment != null) { return sentenceFragment; } @@ -501,6 +501,7 @@ private static Optional findIndicativeSentencesGe return findAnnotation(testClass, IndicativeSentencesGeneration.class, enclosingInstanceTypes); } + @Nullable private static String getSentenceFragment(AnnotatedElement element) { return findAnnotation(element, SentenceFragment.class) // .map(SentenceFragment::value) // diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicContainer.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicContainer.java index da947b68c778..2bdf44fda25d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicContainer.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicContainer.java @@ -17,6 +17,7 @@ import java.util.stream.StreamSupport; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -84,7 +85,7 @@ public static DynamicContainer dynamicContainer(String displayName, Stream dynamicNodes) { return new DynamicContainer(displayName, testSourceUri, dynamicNodes); @@ -92,7 +93,7 @@ public static DynamicContainer dynamicContainer(String displayName, URI testSour private final Stream children; - private DynamicContainer(String displayName, URI testSourceUri, Stream children) { + private DynamicContainer(String displayName, @Nullable URI testSourceUri, Stream children) { super(displayName, testSourceUri); Preconditions.notNull(children, "children must not be null"); this.children = children; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java index 43574ee853a7..59c990ee8b99 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java @@ -16,6 +16,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -33,9 +34,10 @@ public abstract class DynamicNode { private final String displayName; /** Custom test source {@link URI} associated with this node; potentially {@code null}. */ + @Nullable private final URI testSourceUri; - DynamicNode(String displayName, URI testSourceUri) { + DynamicNode(String displayName, @Nullable URI testSourceUri) { this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or blank"); this.testSourceUri = testSourceUri; } 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..82e8018cb0ba 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 @@ -22,6 +22,7 @@ import java.util.stream.StreamSupport; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.platform.commons.util.Preconditions; @@ -78,7 +79,7 @@ public static DynamicTest dynamicTest(String displayName, Executable executable) * @since 5.3 * @see #stream(Iterator, Function, ThrowingConsumer) */ - public static DynamicTest dynamicTest(String displayName, URI testSourceUri, Executable executable) { + public static DynamicTest dynamicTest(String displayName, @Nullable URI testSourceUri, Executable executable) { return new DynamicTest(displayName, testSourceUri, executable); } @@ -290,7 +291,7 @@ public static , E extends Executable> Stream str private final Executable executable; - private DynamicTest(String displayName, URI testSourceUri, Executable executable) { + private DynamicTest(String displayName, @Nullable URI testSourceUri, Executable executable) { super(displayName, testSourceUri); this.executable = Preconditions.notNull(executable, "executable must not be null"); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Named.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Named.java index dfeff26354e4..2e3edf94164f 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Named.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/Named.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -23,7 +24,7 @@ * @since 5.8 */ @API(status = STABLE, since = "5.8") -public interface Named { +public interface Named { /** * Factory method for creating an instance of {@code Named} based on a @@ -37,10 +38,10 @@ public interface Named { * @return an instance of {@code Named}; never {@code null} * @see #named(String, java.lang.Object) */ - static Named of(String name, T payload) { + static Named of(String name, T payload) { Preconditions.notBlank(name, "name must not be null or blank"); - return new Named() { + return new Named<>() { @Override public String getName() { return name; @@ -73,7 +74,7 @@ public String toString() { * @param the type of the payload * @return an instance of {@code Named}; never {@code null} */ - static Named named(String name, T payload) { + static Named named(String name, T payload) { return of(name, payload); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/package-info.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/package-info.java index 38e623dde4aa..7b3888e95e0b 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/package-info.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/package-info.java @@ -2,4 +2,7 @@ * JUnit Jupiter API for writing tests. */ +@NullMarked package org.junit.jupiter.api; + +import org.jspecify.annotations.NullMarked; diff --git a/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinFailAssertionsTests.kt b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinFailAssertionsTests.kt index d0e026669a22..c5da45e59173 100644 --- a/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinFailAssertionsTests.kt +++ b/jupiter-tests/src/test/kotlin/org/junit/jupiter/api/KotlinFailAssertionsTests.kt @@ -65,7 +65,7 @@ class KotlinFailAssertionsTests { } assertMessageEquals(ex, message) val cause = ex.cause - assertMessageContains(cause, throwableCause) + assertMessageContains(cause!!, throwableCause) } @Test @@ -77,7 +77,7 @@ class KotlinFailAssertionsTests { } assertEmptyMessage(ex) val cause = ex.cause - assertMessageContains(cause, throwableCause) + assertMessageContains(cause!!, throwableCause) } @Test @@ -102,7 +102,7 @@ class KotlinFailAssertionsTests { } assertEmptyMessage(ex) val cause = ex.cause - assertMessageContains(cause, throwableCause) + assertMessageContains(cause!!, throwableCause) } @Test From e415a2264acf25e84e624a74d75688125ea9a176 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:10:51 +0200 Subject: [PATCH 124/521] Check `org.junit.jupiter.api..` --- .../java/platform/tooling/support/tests/ArchUnitTests.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index 0a8080d8b11e..ec6de0a6a1e0 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -84,7 +84,6 @@ class ArchUnitTests { void packagesShouldBeNullMarked(JavaClasses classes) { var exclusions = Stream.of( // "..shadow..", // - "org.junit.jupiter.api..", // "org.junit.jupiter.engine..", // "org.junit.jupiter.migrationsupport..", // "org.junit.jupiter.params.." // From 8fc7d8ab0df0c9a321250db22dd44d33659acf93 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:36:16 +0200 Subject: [PATCH 125/521] Enable NullAway in junit-jupiter-engine --- junit-jupiter-engine/junit-jupiter-engine.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts index 24937664e13b..7b3e9afcd3e7 100644 --- a/junit-jupiter-engine/junit-jupiter-engine.gradle.kts +++ b/junit-jupiter-engine/junit-jupiter-engine.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") `java-test-fixtures` } @@ -11,6 +12,7 @@ dependencies { api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) osgiVerification(projects.junitPlatformLauncher) } From b2c4ed5c187cb59b25d69471ba707c98eee9fad7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:36:45 +0200 Subject: [PATCH 126/521] Annotate nullability in `org.junit.jupiter.engine.config` --- .../java/org/junit/jupiter/engine/config/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/package-info.java index ede680886ac3..1ce02462c321 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/package-info.java @@ -2,4 +2,7 @@ * Configuration specific to the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.config; + +import org.jspecify.annotations.NullMarked; From 76b01bbd5d0d87022cf82d28ae334ed209daa490 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:36:52 +0200 Subject: [PATCH 127/521] Annotate nullability in `org.junit.jupiter.engine` --- .../src/main/java/org/junit/jupiter/engine/package-info.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/package-info.java index 17af1fecb552..cb01093df2b9 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/package-info.java @@ -2,4 +2,7 @@ * Core package for the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine; + +import org.jspecify.annotations.NullMarked; From 7215199dafd92652ee0290460c6b2312c9c2908b Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:37:01 +0200 Subject: [PATCH 128/521] Annotate nullability in `org.junit.jupiter.engine.descriptor` --- .../descriptor/AbstractExtensionContext.java | 11 +++-- .../descriptor/ClassBasedTestDescriptor.java | 41 +++++++++++++------ .../descriptor/ClassExtensionContext.java | 2 + ...ClassTemplateInvocationTestDescriptor.java | 19 ++++++--- .../engine/descriptor/DisplayNameUtils.java | 3 +- .../descriptor/DynamicNodeTestDescriptor.java | 3 +- .../descriptor/DynamicTestTestDescriptor.java | 30 ++++++++++---- .../ExclusiveResourceCollector.java | 3 ++ .../engine/descriptor/ExtensionUtils.java | 3 +- .../descriptor/JupiterTestDescriptor.java | 7 ++-- .../descriptor/MethodBasedTestDescriptor.java | 6 +-- .../descriptor/MethodExtensionContext.java | 2 + .../descriptor/NestedClassTestDescriptor.java | 3 +- .../engine/descriptor/ResourceLockAware.java | 4 +- .../descriptor/TestFactoryTestDescriptor.java | 9 +++- .../descriptor/TestMethodTestDescriptor.java | 34 ++++++++------- .../TestTemplateExtensionContext.java | 5 ++- .../TestTemplateInvocationTestDescriptor.java | 15 +++++-- .../engine/descriptor/package-info.java | 3 ++ 19 files changed, 136 insertions(+), 67 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index 7adb978fea33..8a9129bc5136 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -24,6 +24,7 @@ import java.util.Set; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; @@ -54,6 +55,7 @@ abstract class AbstractExtensionContext implements Ext private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExtensionContext.class); + @Nullable private final ExtensionContext parent; private final EngineExecutionListener engineExecutionListener; private final T testDescriptor; @@ -64,8 +66,8 @@ abstract class AbstractExtensionContext implements Ext private final LauncherStoreFacade launcherStoreFacade; private final NamespacedHierarchicalStore valuesStore; - AbstractExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, T testDescriptor, - JupiterConfiguration configuration, ExtensionRegistry extensionRegistry, + AbstractExtensionContext(@Nullable ExtensionContext parent, EngineExecutionListener engineExecutionListener, + T testDescriptor, JupiterConfiguration configuration, ExtensionRegistry extensionRegistry, LauncherStoreFacade launcherStoreFacade) { Preconditions.notNull(testDescriptor, "TestDescriptor must not be null"); @@ -109,7 +111,7 @@ private NamespacedHierarchicalStore.CloseAction createStore( - ExtensionContext parent, LauncherStoreFacade launcherStoreFacade, + @Nullable ExtensionContext parent, LauncherStoreFacade launcherStoreFacade, NamespacedHierarchicalStore.CloseAction closeAction) { NamespacedHierarchicalStore parentStore; if (parent == null) { @@ -172,7 +174,8 @@ private void publishFileEntry(String name, ThrowingConsumer action, Function fileEntryCreator) { Path dir = createOutputDirectory(); Path path = dir.resolve(name); - Preconditions.condition(path.getParent().equals(dir), () -> "name must not contain path separators: " + name); + Preconditions.condition(path.getParent() != null && path.getParent().equals(dir), + () -> "name must not contain path separators: " + name); try { action.accept(path); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index 09b0dd981361..3a6c2e1637b4 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.descriptor; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.engine.descriptor.CallbackSupport.invokeAfterCallbacks; @@ -37,6 +38,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -92,7 +94,10 @@ public abstract class ClassBasedTestDescriptor extends JupiterTestDescriptor protected final ClassInfo classInfo; + @Nullable private LifecycleMethods lifecycleMethods; + + @Nullable private TestInstanceFactory testInstanceFactory; ClassBasedTestDescriptor(UniqueId uniqueId, Class testClass, Supplier displayNameSupplier, @@ -148,7 +153,7 @@ private void validateDisplayNameAnnotation(DiscoveryIssueReporter reporter) { } protected void validateCoreLifecycleMethods(DiscoveryIssueReporter reporter) { - Validatable.reportAndClear(this.lifecycleMethods.discoveryIssues, reporter); + Validatable.reportAndClear(requireLifecycleMethods().discoveryIssues, reporter); } protected void validateClassTemplateInvocationLifecycleMethods(DiscoveryIssueReporter reporter) { @@ -198,7 +203,8 @@ public final JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext registerExtensionsFromConstructorParameters(registry, getTestClass()); } - this.lifecycleMethods.beforeAll.forEach(method -> registerExtensionsFromExecutableParameters(registry, method)); + requireLifecycleMethods().beforeAll.forEach( + method -> registerExtensionsFromExecutableParameters(registry, method)); // Since registerBeforeEachMethodAdapters() and registerAfterEachMethodAdapters() also // invoke registerExtensionsFromExecutableParameters(), we invoke those methods before // invoking registerExtensionsFromExecutableParameters() for @AfterAll methods, @@ -206,7 +212,8 @@ public final JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext // on parameters in lifecycle methods. registerBeforeEachMethodAdapters(registry); registerAfterEachMethodAdapters(registry); - this.lifecycleMethods.afterAll.forEach(method -> registerExtensionsFromExecutableParameters(registry, method)); + requireLifecycleMethods().afterAll.forEach( + method -> registerExtensionsFromExecutableParameters(registry, method)); registerExtensionsFromInstanceFields(registry, getTestClass()); ThrowableCollector throwableCollector = createThrowableCollector(); @@ -288,6 +295,7 @@ public void cleanUp(JupiterEngineExecutionContext context) throws Exception { this.testInstanceFactory = null; } + @Nullable private TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) { List factories = registry.getExtensions(TestInstanceFactory.class); @@ -347,19 +355,19 @@ protected final TestInstances instantiateTestClass(Optional outer invokeTestInstancePreConstructCallbacks(new DefaultTestInstanceFactoryContext(getTestClass(), outerInstance), registry, extensionContext); Object instance = this.testInstanceFactory != null // - ? invokeTestInstanceFactory(outerInstance, extensionContext) // + ? invokeTestInstanceFactory(this.testInstanceFactory, outerInstance, extensionContext) // : invokeTestClassConstructor(outerInstance, registry, extensionContext); return outerInstances.map(instances -> DefaultTestInstances.of(instances, instance)) // .orElse(DefaultTestInstances.of(instance)); } - private Object invokeTestInstanceFactory(Optional outerInstance, + private Object invokeTestInstanceFactory(TestInstanceFactory testInstanceFactory, Optional outerInstance, ExtensionContextSupplier extensionContext) { Object instance; try { - ExtensionContext actualExtensionContext = extensionContext.get(this.testInstanceFactory); - instance = this.testInstanceFactory.createTestInstance( + ExtensionContext actualExtensionContext = extensionContext.get(testInstanceFactory); + instance = testInstanceFactory.createTestInstance( new DefaultTestInstanceFactoryContext(getTestClass(), outerInstance), actualExtensionContext); } catch (Throwable throwable) { @@ -370,7 +378,7 @@ private Object invokeTestInstanceFactory(Optional outerInstance, } String message = "TestInstanceFactory [%s] failed to instantiate test class [%s]".formatted( - this.testInstanceFactory.getClass().getName(), getTestClass().getName()); + testInstanceFactory.getClass().getName(), getTestClass().getName()); if (StringUtils.isNotBlank(throwable.getMessage())) { message += ": " + throwable.getMessage(); } @@ -390,7 +398,7 @@ private Object invokeTestInstanceFactory(Optional outerInstance, instanceClassName += "@" + Integer.toHexString(System.identityHashCode(instanceClass)); } String message = "TestInstanceFactory [%s] failed to return an instance of [%s] and instead returned an instance of [%s].".formatted( - this.testInstanceFactory.getClass().getName(), testClassName, instanceClassName); + testInstanceFactory.getClass().getName(), testClassName, instanceClassName); throw new TestInstantiationException(message); } @@ -438,7 +446,7 @@ private void invokeBeforeAllMethods(JupiterEngineExecutionContext context) { ThrowableCollector throwableCollector = context.getThrowableCollector(); Object testInstance = extensionContext.getTestInstance().orElse(null); - for (Method method : this.lifecycleMethods.beforeAll) { + for (Method method : requireLifecycleMethods().beforeAll) { throwableCollector.execute(() -> { try { executableInvoker.invoke(method, testInstance, extensionContext, registry, @@ -467,7 +475,7 @@ private void invokeAfterAllMethods(JupiterEngineExecutionContext context) { ThrowableCollector throwableCollector = context.getThrowableCollector(); Object testInstance = extensionContext.getTestInstance().orElse(null); - this.lifecycleMethods.afterAll.forEach(method -> throwableCollector.execute(() -> { + requireLifecycleMethods().afterAll.forEach(method -> throwableCollector.execute(() -> { try { executableInvoker.invoke(method, testInstance, extensionContext, registry, ReflectiveInterceptorCall.ofVoidMethod(InvocationInterceptor::interceptAfterAllMethod)); @@ -500,13 +508,13 @@ private boolean isPerClassLifecycle(JupiterEngineExecutionContext context) { } private void registerBeforeEachMethodAdapters(ExtensionRegistrar registrar) { - registerMethodsAsExtensions(this.lifecycleMethods.beforeEach, registrar, + registerMethodsAsExtensions(requireLifecycleMethods().beforeEach, registrar, this::synthesizeBeforeEachMethodAdapter); } private void registerAfterEachMethodAdapters(ExtensionRegistrar registrar) { // Make a local copy since findAfterEachMethods() returns an immutable list. - List afterEachMethods = new ArrayList<>(this.lifecycleMethods.afterEach); + List afterEachMethods = new ArrayList<>(requireLifecycleMethods().afterEach); // Since the bottom-up ordering of afterEachMethods will later be reversed when the // synthesized AfterEachMethodAdapters are executed within TestMethodTestDescriptor, @@ -546,6 +554,10 @@ private void invokeMethodInExtensionContext(Method method, ExtensionContext cont ReflectiveInterceptorCall.ofVoidMethod(interceptorCall)); } + private LifecycleMethods requireLifecycleMethods() { + return requireNonNull(this.lifecycleMethods); + } + protected static class ClassInfo { private final List discoveryIssues = new ArrayList<>(); @@ -553,7 +565,10 @@ protected static class ClassInfo { final Class testClass; final Set tags; final Lifecycle lifecycle; + + @Nullable ExecutionMode defaultChildExecutionMode; + final ExclusiveResourceCollector exclusiveResourceCollector; ClassInfo(Class testClass, JupiterConfiguration configuration) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java index cc052d0a60f5..157ae5ccb84c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; @@ -33,6 +34,7 @@ final class ClassExtensionContext extends AbstractExtensionContext uniqueIdTransformer) { return new ClassTemplateInvocationTestDescriptor(uniqueIdTransformer.apply(getUniqueId()), parent, - this.invocationContext, this.index, getSource().orElse(null), this.configuration); + requiredInvocationContext(), this.index, getSource().orElse(null), this.configuration); } // --- TestDescriptor ------------------------------------------------------ @@ -111,18 +116,18 @@ public Function> getResou @Override public JupiterEngineExecutionContext prepare(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = context.getExtensionRegistry(); - List additionalExtensions = this.invocationContext.getAdditionalExtensions(); + List additionalExtensions = requiredInvocationContext().getAdditionalExtensions(); if (!additionalExtensions.isEmpty()) { MutableExtensionRegistry childRegistry = createRegistryFrom(registry, Stream.empty()); additionalExtensions.forEach( - extension -> childRegistry.registerExtension(extension, this.invocationContext)); + extension -> childRegistry.registerExtension(extension, requiredInvocationContext())); registry = childRegistry; } ExtensionContext extensionContext = new ClassTemplateInvocationExtensionContext(context.getExtensionContext(), context.getExecutionListener(), this, context.getConfiguration(), registry, context.getLauncherStoreFacade()); ThrowableCollector throwableCollector = createThrowableCollector(); - throwableCollector.execute(() -> this.invocationContext.prepareInvocation(extensionContext)); + throwableCollector.execute(() -> requiredInvocationContext().prepareInvocation(extensionContext)); return context.extend() // .withExtensionRegistry(registry) // .withExtensionContext(extensionContext) // @@ -177,4 +182,8 @@ public void cleanUp(JupiterEngineExecutionContext context) throws Exception { this.invocationContext = null; super.cleanUp(context); } + + private ClassTemplateInvocationContext requiredInvocationContext() { + return requireNonNull(this.invocationContext); + } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java index a25d2e16b6ee..edf8a8d117d0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java @@ -22,6 +22,7 @@ import java.util.function.BiFunction; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayNameGeneration; import org.junit.jupiter.api.DisplayNameGenerator; @@ -82,7 +83,7 @@ static String determineDisplayName(AnnotatedElement element, Supplier di } static void validateAnnotation(AnnotatedElement element, Supplier elementDescription, - Supplier sourceProvider, DiscoveryIssueReporter reporter) { + Supplier<@Nullable TestSource> sourceProvider, DiscoveryIssueReporter reporter) { findAnnotation(element, DisplayName.class) // .map(DisplayName::value) // .filter(StringUtils::isBlank) // diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicNodeTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicNodeTestDescriptor.java index 865e4044f52b..f68c98b480bf 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicNodeTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicNodeTestDescriptor.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.descriptor; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; @@ -27,7 +28,7 @@ abstract class DynamicNodeTestDescriptor extends JupiterTestDescriptor { protected final int index; - DynamicNodeTestDescriptor(UniqueId uniqueId, int index, DynamicNode dynamicNode, TestSource testSource, + DynamicNodeTestDescriptor(UniqueId uniqueId, int index, DynamicNode dynamicNode, @Nullable TestSource testSource, JupiterConfiguration configuration) { super(uniqueId, dynamicNode.getDisplayName(), testSource, configuration); this.index = index; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java index 9209b8c1f3d6..b45aefc619fd 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java @@ -10,8 +10,11 @@ package org.junit.jupiter.engine.descriptor; +import static java.util.Objects.requireNonNull; + import java.util.function.UnaryOperator; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.extension.DynamicTestInvocationContext; import org.junit.jupiter.api.extension.ExtensionContext; @@ -35,9 +38,10 @@ class DynamicTestTestDescriptor extends DynamicNodeTestDescriptor { private static final InvocationInterceptorChain interceptorChain = new InvocationInterceptorChain(); + @Nullable private DynamicTest dynamicTest; - DynamicTestTestDescriptor(UniqueId uniqueId, int index, DynamicTest dynamicTest, TestSource source, + DynamicTestTestDescriptor(UniqueId uniqueId, int index, DynamicTest dynamicTest, @Nullable TestSource source, JupiterConfiguration configuration) { super(uniqueId, index, dynamicTest, source, configuration); this.dynamicTest = dynamicTest; @@ -45,8 +49,8 @@ class DynamicTestTestDescriptor extends DynamicNodeTestDescriptor { @Override protected DynamicTestTestDescriptor withUniqueId(UnaryOperator uniqueIdTransformer) { - return new DynamicTestTestDescriptor(uniqueIdTransformer.apply(getUniqueId()), this.index, this.dynamicTest, - this.getSource().orElse(null), this.configuration); + return new DynamicTestTestDescriptor(uniqueIdTransformer.apply(getUniqueId()), this.index, + requireNonNull(this.dynamicTest), this.getSource().orElse(null), this.configuration); } @Override @@ -57,20 +61,24 @@ public Type getType() { @Override public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext context, DynamicTestExecutor dynamicTestExecutor) { - InvocationInterceptor.Invocation invocation = () -> { - dynamicTest.getExecutable().execute(); - return null; - }; DynamicTestInvocationContext dynamicTestInvocationContext = new DefaultDynamicTestInvocationContext( - dynamicTest.getExecutable()); + requiredDynamicTest().getExecutable()); ExtensionContext extensionContext = context.getExtensionContext(); ExtensionRegistry extensionRegistry = context.getExtensionRegistry(); - interceptorChain.invoke(invocation, extensionRegistry, InterceptorCall.ofVoid( + interceptorChain.invoke(toInvocation(), extensionRegistry, InterceptorCall.ofVoid( (interceptor, wrappedInvocation) -> interceptor.interceptDynamicTest(wrappedInvocation, dynamicTestInvocationContext, extensionContext))); return context; } + @SuppressWarnings("NullAway") + private InvocationInterceptor.Invocation toInvocation() { + return () -> { + requiredDynamicTest().getExecutable().execute(); + return null; + }; + } + /** * Avoid an {@link OutOfMemoryError} by releasing the reference to this * descriptor's {@link DynamicTest} which holds a reference to the user-supplied @@ -86,4 +94,8 @@ public void after(JupiterEngineExecutionContext context) throws Exception { this.dynamicTest = null; } + private DynamicTest requiredDynamicTest() { + return requireNonNull(dynamicTest); + } + } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java index 15e7d26b6db5..9e3dde197bbe 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java @@ -21,6 +21,7 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.parallel.ResourceAccessMode; import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.api.parallel.ResourceLockTarget; @@ -73,6 +74,8 @@ static ExclusiveResourceCollector from(AnnotatedElement element) { private static class DefaultExclusiveResourceCollector extends ExclusiveResourceCollector { private final List annotations; + + @Nullable private List providers; DefaultExclusiveResourceCollector(List annotations) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java index 65845e8ecca6..4ad96e1818db 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java @@ -29,6 +29,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.Extension; @@ -138,7 +139,7 @@ static void registerExtensionsFromInstanceFields(ExtensionRegistrar registrar, C /** * @since 5.11 */ - private static Extension readAndValidateExtensionFromField(Field field, Object instance, + private static Extension readAndValidateExtensionFromField(Field field, @Nullable Object instance, List> declarativeExtensionTypes) { Object value = tryToReadFieldValue(field, instance) // .getOrThrow(e -> new PreconditionViolationException( diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index fe5547cafd84..893234e8f017 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -31,6 +31,7 @@ import java.util.function.UnaryOperator; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.Extension; @@ -65,11 +66,11 @@ public abstract class JupiterTestDescriptor extends AbstractTestDescriptor final JupiterConfiguration configuration; JupiterTestDescriptor(UniqueId uniqueId, AnnotatedElement element, Supplier displayNameSupplier, - TestSource source, JupiterConfiguration configuration) { + @Nullable TestSource source, JupiterConfiguration configuration) { this(uniqueId, determineDisplayName(element, displayNameSupplier), source, configuration); } - JupiterTestDescriptor(UniqueId uniqueId, String displayName, TestSource source, + JupiterTestDescriptor(UniqueId uniqueId, String displayName, @Nullable TestSource source, JupiterConfiguration configuration) { super(uniqueId, displayName, source); this.configuration = configuration; @@ -79,7 +80,7 @@ public abstract class JupiterTestDescriptor extends AbstractTestDescriptor static Set getTags(AnnotatedElement element, Supplier elementDescription, Supplier sourceProvider, Consumer issueCollector) { - AtomicReference source = new AtomicReference<>(); + AtomicReference<@Nullable TestSource> source = new AtomicReference<>(); return findRepeatableAnnotations(element, Tag.class).stream() // .map(Tag::value) // .filter(tag -> { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java index c4d9af414bee..ae07732fdf70 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodBasedTestDescriptor.java @@ -156,10 +156,8 @@ protected Optional getExplicitExecutionMode() { */ @Override public void nodeSkipped(JupiterEngineExecutionContext context, TestDescriptor descriptor, SkipResult result) { - if (context != null) { - invokeTestWatchers(context, false, - watcher -> watcher.testDisabled(context.getExtensionContext(), result.getReason())); - } + invokeTestWatchers(context, false, + watcher -> watcher.testDisabled(context.getExtensionContext(), result.getReason())); } /** diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java index eaed0fe9418a..9f6711e0ea4b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/MethodExtensionContext.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; @@ -31,6 +32,7 @@ final class MethodExtensionContext extends AbstractExtensionContext> getEnclosingTestClasses() { } @API(status = INTERNAL, since = "5.12") - public static List> getEnclosingTestClasses(TestDescriptor parent) { + public static List> getEnclosingTestClasses(@Nullable TestDescriptor parent) { if (parent instanceof TestClassAware parentClassDescriptor) { List> result = new ArrayList<>(parentClassDescriptor.getEnclosingTestClasses()); result.add(parentClassDescriptor.getTestClass()); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java index c66398105f4b..47c1cf12bf6b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java @@ -23,6 +23,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.parallel.ResourceLocksProvider; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; @@ -71,8 +72,9 @@ default Stream determineOwnExclusiveResources( static Function> enclosingInstanceTypesDependentResourceLocksProviderEvaluator( Supplier>> enclosingInstanceTypesSupplier, BiFunction>, Set> evaluator) { - return new Function>() { + return new Function<>() { + @Nullable private List> enclosingInstanceTypes; @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java index a2d782bad1fa..7b50ac238292 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java @@ -25,6 +25,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DynamicContainer; import org.junit.jupiter.api.DynamicNode; import org.junit.jupiter.api.DynamicTest; @@ -58,7 +59,8 @@ public class TestFactoryTestDescriptor extends TestMethodTestDescriptor implemen public static final String DYNAMIC_CONTAINER_SEGMENT_TYPE = "dynamic-container"; public static final String DYNAMIC_TEST_SEGMENT_TYPE = "dynamic-test"; - private static final ReflectiveInterceptorCall interceptorCall = InvocationInterceptor::interceptTestFactoryMethod; + @SuppressWarnings("NullAway") + private static final ReflectiveInterceptorCall interceptorCall = InvocationInterceptor::interceptTestFactoryMethod; private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); private final DynamicDescendantFilter dynamicDescendantFilter; @@ -133,7 +135,10 @@ protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTe } @SuppressWarnings("unchecked") - private Stream toDynamicNodeStream(Object testFactoryMethodResult) { + private Stream toDynamicNodeStream(@Nullable Object testFactoryMethodResult) { + if (testFactoryMethodResult == null) { + throw new JUnitException("@TestFactory method must not return null"); + } if (testFactoryMethodResult instanceof DynamicNode node) { return Stream.of(node); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java index c6a416bd443a..bcf5a5fc21d7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java @@ -280,24 +280,22 @@ private void invokeTestInstancePreDestroyCallbacks(JupiterEngineExecutionContext public void nodeFinished(JupiterEngineExecutionContext context, TestDescriptor descriptor, TestExecutionResult result) { - if (context != null) { - ExtensionContext extensionContext = context.getExtensionContext(); - TestExecutionResult.Status status = result.getStatus(); - - invokeTestWatchers(context, true, watcher -> { - switch (status) { - case SUCCESSFUL: - watcher.testSuccessful(extensionContext); - break; - case ABORTED: - watcher.testAborted(extensionContext, result.getThrowable().orElse(null)); - break; - case FAILED: - watcher.testFailed(extensionContext, result.getThrowable().orElse(null)); - break; - } - }); - } + ExtensionContext extensionContext = context.getExtensionContext(); + TestExecutionResult.Status status = result.getStatus(); + + invokeTestWatchers(context, true, watcher -> { + switch (status) { + case SUCCESSFUL: + watcher.testSuccessful(extensionContext); + break; + case ABORTED: + watcher.testAborted(extensionContext, result.getThrowable().orElse(null)); + break; + case FAILED: + watcher.testFailed(extensionContext, result.getThrowable().orElse(null)); + break; + } + }); } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java index 9a30e567ba2b..1a947e808d74 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateExtensionContext.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.TestInstances; @@ -28,11 +29,13 @@ */ final class TestTemplateExtensionContext extends AbstractExtensionContext { + @Nullable private final TestInstances testInstances; TestTemplateExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, TestTemplateTestDescriptor testDescriptor, JupiterConfiguration configuration, - ExtensionRegistry extensionRegistry, LauncherStoreFacade launcherStoreFacade, TestInstances testInstances) { + ExtensionRegistry extensionRegistry, LauncherStoreFacade launcherStoreFacade, + @Nullable TestInstances testInstances) { super(parent, engineExecutionListener, testDescriptor, configuration, extensionRegistry, launcherStoreFacade); this.testInstances = testInstances; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java index 88d494a9731d..d768a62cfa97 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java @@ -11,6 +11,7 @@ package org.junit.jupiter.engine.descriptor; import static java.util.Collections.emptySet; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.INTERNAL; import java.lang.reflect.Method; @@ -18,6 +19,7 @@ import java.util.function.UnaryOperator; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; @@ -42,7 +44,9 @@ public class TestTemplateInvocationTestDescriptor extends TestMethodTestDescript private static final ReflectiveInterceptorCall interceptorCall = ReflectiveInterceptorCall.ofVoidMethod( InvocationInterceptor::interceptTestTemplateMethod); + @Nullable private TestTemplateInvocationContext invocationContext; + private final int index; TestTemplateInvocationTestDescriptor(UniqueId uniqueId, Class testClass, Method templateMethod, @@ -58,7 +62,7 @@ public class TestTemplateInvocationTestDescriptor extends TestMethodTestDescript @Override protected TestTemplateInvocationTestDescriptor withUniqueId(UnaryOperator uniqueIdTransformer) { return new TestTemplateInvocationTestDescriptor(uniqueIdTransformer.apply(getUniqueId()), getTestClass(), - getTestMethod(), this.invocationContext, this.index, this.configuration); + getTestMethod(), requiredInvocationContext(), this.index, this.configuration); } // --- TestDescriptor ------------------------------------------------------ @@ -77,14 +81,15 @@ public String getLegacyReportingName() { @Override protected MutableExtensionRegistry populateNewExtensionRegistry(JupiterEngineExecutionContext context) { MutableExtensionRegistry registry = super.populateNewExtensionRegistry(context); - this.invocationContext.getAdditionalExtensions().forEach( + var invocationContext = requiredInvocationContext(); + invocationContext.getAdditionalExtensions().forEach( extension -> registry.registerExtension(extension, invocationContext)); return registry; } @Override protected void prepareExtensionContext(ExtensionContext extensionContext) { - this.invocationContext.prepareInvocation(extensionContext); + requiredInvocationContext().prepareInvocation(extensionContext); } @Override @@ -93,4 +98,8 @@ public void after(JupiterEngineExecutionContext context) { this.invocationContext = null; } + private TestTemplateInvocationContext requiredInvocationContext() { + return requireNonNull(this.invocationContext); + } + } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/package-info.java index e3e0028ce4fb..62b21c2e4993 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/package-info.java @@ -2,4 +2,7 @@ * Test descriptors used within the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.descriptor; + +import org.jspecify.annotations.NullMarked; From cc5d39a835224dda3bd3b342f4680ef47981f5a4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 12:39:21 +0200 Subject: [PATCH 129/521] Check `org.junit.jupiter.engine..` --- .../java/platform/tooling/support/tests/ArchUnitTests.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index ec6de0a6a1e0..e950a77ca157 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -84,7 +84,10 @@ class ArchUnitTests { void packagesShouldBeNullMarked(JavaClasses classes) { var exclusions = Stream.of( // "..shadow..", // - "org.junit.jupiter.engine..", // + "org.junit.jupiter.engine.discovery..", // + "org.junit.jupiter.engine.execution..", // + "org.junit.jupiter.engine.extension..", // + "org.junit.jupiter.engine.support..", // "org.junit.jupiter.migrationsupport..", // "org.junit.jupiter.params.." // ).map(PackageMatcher::of).toList(); From ab45546e39028567c82c94e082d749f73196cbdf Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 15:17:17 +0200 Subject: [PATCH 130/521] Annotate nullability in remaining `org.junit.jupiter.engine..` packages --- .../discovery/AbstractOrderingVisitor.java | 10 ++++++++-- .../engine/discovery/package-info.java | 3 +++ .../discovery/predicates/package-info.java | 3 +++ .../execution/ConstructorInvocation.java | 5 +++-- .../execution/DefaultExecutableInvoker.java | 8 ++++++-- .../InterceptingExecutableInvoker.java | 10 +++++++--- .../execution/InvocationInterceptorChain.java | 10 ++++++---- .../JupiterEngineExecutionContext.java | 20 +++++++++++++++---- .../engine/execution/MethodInvocation.java | 10 +++++----- .../engine/execution/NamespaceAwareStore.java | 12 +++++++++-- .../execution/ParameterResolutionUtils.java | 15 ++++++++------ .../engine/execution/package-info.java | 3 +++ .../engine/extension/AutoCloseExtension.java | 8 +++++--- .../engine/extension/DisabledCondition.java | 3 ++- .../extension/MutableExtensionRegistry.java | 5 +++-- .../engine/extension/RepetitionExtension.java | 3 ++- .../SameThreadTimeoutInvocation.java | 4 +++- .../SeparateThreadTimeoutInvocation.java | 9 ++++++--- .../engine/extension/TempDirectory.java | 10 ++++++---- .../extension/TestInfoParameterResolver.java | 5 ++++- .../extension/TimeoutDurationParser.java | 3 ++- .../extension/TimeoutExceptionFactory.java | 4 +++- .../engine/extension/TimeoutExtension.java | 14 ++++++++----- .../engine/extension/package-info.java | 3 +++ .../engine/support/MethodReflectionUtils.java | 4 +++- .../jupiter/engine/support/package-info.java | 3 +++ .../tooling/support/tests/ArchUnitTests.java | 4 ---- 27 files changed, 133 insertions(+), 58 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java index 8f104923bf5c..fba71e40357a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java @@ -11,6 +11,7 @@ package org.junit.jupiter.engine.discovery; import static java.util.Comparator.comparing; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toList; @@ -23,6 +24,7 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoveryIssue.Severity; @@ -137,12 +139,15 @@ protected static DescriptorWrapperOrderer n return (DescriptorWrapperOrderer) NOOP; } + @Nullable private final ORDERER orderer; + @Nullable private final Consumer> orderingAction; + private final MessageGenerator descriptorsAddedMessageGenerator; private final MessageGenerator descriptorsRemovedMessageGenerator; - DescriptorWrapperOrderer(ORDERER orderer, Consumer> orderingAction, + DescriptorWrapperOrderer(@Nullable ORDERER orderer, @Nullable Consumer> orderingAction, MessageGenerator descriptorsAddedMessageGenerator, MessageGenerator descriptorsRemovedMessageGenerator) { @@ -152,6 +157,7 @@ protected static DescriptorWrapperOrderer n this.descriptorsRemovedMessageGenerator = descriptorsRemovedMessageGenerator; } + @Nullable ORDERER getOrderer() { return orderer; } @@ -162,7 +168,7 @@ private boolean canOrderWrappers() { private void orderWrappers(List wrappers, Consumer errorHandler) { List orderedWrappers = new ArrayList<>(wrappers); - this.orderingAction.accept(orderedWrappers); + requireNonNull(this.orderingAction).accept(orderedWrappers); Map distinctWrappersToIndex = distinctWrappersToIndex(orderedWrappers); int difference = orderedWrappers.size() - wrappers.size(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/package-info.java index 0426627d49ba..d9a5e573aafc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/package-info.java @@ -3,4 +3,7 @@ * Contains resolvers for Java elements. */ +@NullMarked package org.junit.jupiter.engine.discovery; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/package-info.java index 579eb486e17d..028f0bbbf8c0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/predicates/package-info.java @@ -2,4 +2,7 @@ * Internal predicate classes used by test discovery within the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.discovery.predicates; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConstructorInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConstructorInvocation.java index 79cbd46c6895..d046535c0a56 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConstructorInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ConstructorInvocation.java @@ -17,6 +17,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.platform.commons.util.ReflectionUtils; @@ -24,9 +25,9 @@ class ConstructorInvocation implements Invocation, ReflectiveInvocationContext> { private final Constructor constructor; - private final Object[] arguments; + private final @Nullable Object[] arguments; - ConstructorInvocation(Constructor constructor, Object[] arguments) { + ConstructorInvocation(Constructor constructor, @Nullable Object[] arguments) { this.constructor = constructor; this.arguments = arguments; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java index 122c122030eb..109593b6fc5b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java @@ -18,6 +18,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; @@ -39,14 +40,17 @@ public DefaultExecutableInvoker(ExtensionContext extensionContext, ExtensionRegi } @Override - public T invoke(Constructor constructor, Object outerInstance) { + public T invoke(Constructor constructor, @Nullable Object outerInstance) { + @Nullable Object[] arguments = resolveParameters(constructor, Optional.empty(), Optional.ofNullable(outerInstance), extensionContext, extensionRegistry); return ReflectionUtils.newInstance(constructor, arguments); } @Override - public Object invoke(Method method, Object target) { + @Nullable + public Object invoke(Method method, @Nullable Object target) { + @Nullable Object[] arguments = resolveParameters(method, Optional.ofNullable(target), extensionContext, extensionRegistry); return MethodReflectionUtils.invoke(method, target, arguments); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java index 9454d5829302..8dc93f242fa0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java @@ -19,6 +19,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; @@ -57,6 +58,7 @@ public T invoke(Constructor constructor, Optional outerInstance, ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall, T> interceptorCall) { + @Nullable Object[] arguments = resolveParameters(constructor, Optional.empty(), outerInstance, extensionContext, extensionRegistry); ConstructorInvocation invocation = new ConstructorInvocation<>(constructor, arguments); @@ -76,12 +78,13 @@ public T invoke(Constructor constructor, Optional outerInstance, * @param interceptorCall the call for intercepting this method invocation * via all registered {@linkplain InvocationInterceptor interceptors} */ - public T invoke(Method method, Object target, ExtensionContext extensionContext, + public T invoke(Method method, @Nullable Object target, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall interceptorCall) { @SuppressWarnings("unchecked") Optional optionalTarget = (target instanceof Optional ? (Optional) target : Optional.ofNullable(target)); + @Nullable Object[] arguments = resolveParameters(method, optionalTarget, extensionContext, extensionRegistry); MethodInvocation invocation = new MethodInvocation<>(method, optionalTarget, arguments); return invoke(invocation, invocation, extensionContext, extensionRegistry, interceptorCall); @@ -102,12 +105,13 @@ private T invoke(Invocation originalInvocation, extensionContext.get(interceptor))); } - public interface ReflectiveInterceptorCall { + public interface ReflectiveInterceptorCall { T apply(InvocationInterceptor interceptor, Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable; - static ReflectiveInterceptorCall ofVoidMethod(VoidMethodInterceptorCall call) { + @SuppressWarnings("NullAway") + static ReflectiveInterceptorCall ofVoidMethod(VoidMethodInterceptorCall call) { return ((interceptorChain, invocation, invocationContext, extensionContext) -> { call.apply(interceptorChain, invocation, invocationContext, extensionContext); return null; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java index 3b73cbc982e7..6f2352716f99 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java @@ -18,6 +18,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.engine.extension.ExtensionRegistry; @@ -69,11 +70,12 @@ private T proceed(Invocation invocation) { } @FunctionalInterface - public interface InterceptorCall { + public interface InterceptorCall { T apply(InvocationInterceptor interceptor, Invocation invocation) throws Throwable; - static InterceptorCall ofVoid(VoidInterceptorCall call) { + @SuppressWarnings("NullAway") + static InterceptorCall<@Nullable Void> ofVoid(VoidInterceptorCall call) { return ((interceptorChain, invocation) -> { call.apply(interceptorChain, invocation); return null; @@ -85,7 +87,7 @@ static InterceptorCall ofVoid(VoidInterceptorCall call) { @FunctionalInterface public interface VoidInterceptorCall { - void apply(InvocationInterceptor interceptor, Invocation invocation) throws Throwable; + void apply(InvocationInterceptor interceptor, Invocation<@Nullable Void> invocation) throws Throwable; } @@ -112,7 +114,7 @@ public void skip() { } } - private static class ValidatingInvocation implements Invocation { + private static class ValidatingInvocation implements Invocation { private static final Logger logger = LoggerFactory.getLogger(ValidatingInvocation.class); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java index f62338b9b272..d09caed6ad1f 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java @@ -10,9 +10,11 @@ package org.junit.jupiter.engine.execution; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.INTERNAL; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.jupiter.engine.descriptor.LauncherStoreFacade; @@ -68,19 +70,19 @@ public LauncherStoreFacade getLauncherStoreFacade() { } public TestInstancesProvider getTestInstancesProvider() { - return this.state.testInstancesProvider; + return requireNonNull(this.state.testInstancesProvider); } public MutableExtensionRegistry getExtensionRegistry() { - return this.state.extensionRegistry; + return requireNonNull(this.state.extensionRegistry); } public ExtensionContext getExtensionContext() { - return this.state.extensionContext; + return requireNonNull(this.state.extensionContext); } public ThrowableCollector getThrowableCollector() { - return this.state.throwableCollector; + return requireNonNull(this.state.throwableCollector); } /** @@ -125,9 +127,17 @@ private static final class State implements Cloneable { final EngineExecutionListener executionListener; final JupiterConfiguration configuration; final LauncherStoreFacade launcherStoreFacade; + + @Nullable TestInstancesProvider testInstancesProvider; + + @Nullable MutableExtensionRegistry extensionRegistry; + + @Nullable ExtensionContext extensionContext; + + @Nullable ThrowableCollector throwableCollector; State(EngineExecutionListener executionListener, JupiterConfiguration configuration, @@ -152,6 +162,8 @@ public State clone() { public static class Builder { private State originalState; + + @Nullable private State newState = null; private Builder(State originalState) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java index 5d42c754d1ba..6ef6f52f4bad 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/MethodInvocation.java @@ -17,17 +17,18 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.jupiter.engine.support.MethodReflectionUtils; -class MethodInvocation implements Invocation, ReflectiveInvocationContext { +class MethodInvocation implements Invocation, ReflectiveInvocationContext { private final Method method; private final Optional target; - private final Object[] arguments; + private final @Nullable Object[] arguments; - MethodInvocation(Method method, Optional target, Object[] arguments) { + MethodInvocation(Method method, Optional target, @Nullable Object[] arguments) { this.method = method; this.target = target; this.arguments = arguments; @@ -39,7 +40,6 @@ public Class getTargetClass() { } @Override - @SuppressWarnings("unchecked") public Optional getTarget() { return this.target; } @@ -55,7 +55,7 @@ public List getArguments() { } @Override - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "NullAway" }) public T proceed() { var actualTarget = this.target.orElse(null); return (T) MethodReflectionUtils.invoke(this.method, actualTarget, this.arguments); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java index d63c7f13a940..24cd4a985436 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java @@ -16,6 +16,7 @@ import java.util.function.Supplier; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.ExtensionContextException; import org.junit.platform.commons.util.Preconditions; @@ -38,12 +39,14 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override + @Nullable public Object get(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.get(this.namespace, key)); } @Override + @Nullable public T get(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); @@ -51,6 +54,7 @@ public T get(Object key, Class requiredType) { } @Override + @Nullable public Object getOrComputeIfAbsent(K key, Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); @@ -58,6 +62,7 @@ public Object getOrComputeIfAbsent(K key, Function defaultCreator) } @Override + @Nullable public V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); @@ -67,25 +72,28 @@ public V getOrComputeIfAbsent(K key, Function defaultCreator, Class } @Override - public void put(Object key, Object value) { + public void put(Object key, @Nullable Object value) { Preconditions.notNull(key, "key must not be null"); accessStore(() -> this.valuesStore.put(this.namespace, key, value)); } @Override + @Nullable public Object remove(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key)); } @Override + @Nullable public T remove(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key, requiredType)); } - private T accessStore(Supplier action) { + @Nullable + private T accessStore(Supplier<@Nullable T> action) { try { return action.get(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java index efd12ab21592..07d9cdb4b589 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java @@ -25,6 +25,7 @@ import java.util.Optional; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; @@ -60,8 +61,8 @@ public class ParameterResolutionUtils { * @return the array of Objects to be used as parameters in the executable * invocation; never {@code null} though potentially empty */ - public static Object[] resolveParameters(Method method, Optional target, ExtensionContext extensionContext, - ExtensionRegistry extensionRegistry) { + public static @Nullable Object[] resolveParameters(Method method, Optional target, + ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { return resolveParameters(method, target, Optional.empty(), __ -> extensionContext, extensionRegistry, isKotlinSuspendingFunction(method) // @@ -86,12 +87,12 @@ public static Object[] resolveParameters(Method method, Optional target, * @return the array of Objects to be used as parameters in the executable * invocation; never {@code null} though potentially empty */ - public static Object[] resolveParameters(Executable executable, Optional target, + public static @Nullable Object[] resolveParameters(Executable executable, Optional target, Optional outerInstance, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { return resolveParameters(executable, target, outerInstance, __ -> extensionContext, extensionRegistry); } - public static Object[] resolveParameters(Executable executable, Optional target, + public static @Nullable Object[] resolveParameters(Executable executable, Optional target, Optional outerInstance, ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry) { @@ -99,12 +100,13 @@ public static Object[] resolveParameters(Executable executable, Optional executable.getParameters()); } - private static Object[] resolveParameters(Executable executable, Optional target, + private static @Nullable Object[] resolveParameters(Executable executable, Optional target, Optional outerInstance, ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry, Parameter[] parameters) { Preconditions.notNull(target, "target must not be null"); + @Nullable Object[] values = new Object[parameters.length]; int start = 0; @@ -123,6 +125,7 @@ private static Object[] resolveParameters(Executable executable, Optional type = parameter.getType(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/package-info.java index 028111e0a0ca..cc5cec268e7d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/package-info.java @@ -2,4 +2,7 @@ * Internal classes for test execution within the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.execution; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java index b4d4261d772e..c3bf48d99ec9 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java @@ -16,6 +16,7 @@ import java.lang.reflect.Method; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AutoClose; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.ExtensionConfigurationException; @@ -59,14 +60,15 @@ public void afterAll(ExtensionContext context) { throwableCollector.assertEmpty(); } - private static void closeFields(Class testClass, Object testInstance, ThrowableCollector throwableCollector) { + private static void closeFields(Class testClass, @Nullable Object testInstance, + ThrowableCollector throwableCollector) { Predicate predicate = (testInstance == null ? ModifierSupport::isStatic : ModifierSupport::isNotStatic); AnnotationSupport.findAnnotatedFields(testClass, AutoClose.class, predicate, BOTTOM_UP).forEach( field -> throwableCollector.execute(() -> closeField(field, testInstance))); } - private static void closeField(Field field, Object testInstance) throws Exception { - String methodName = AnnotationSupport.findAnnotation(field, AutoClose.class).get().value(); + private static void closeField(Field field, @Nullable Object testInstance) throws Exception { + String methodName = AnnotationSupport.findAnnotation(field, AutoClose.class).orElseThrow().value(); Class fieldType = field.getType(); checkCondition(StringUtils.isNotBlank(methodName), "@AutoClose on field %s must specify a method name.", field); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DisabledCondition.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DisabledCondition.java index 5dedc43e9107..9d4e1e4d3727 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DisabledCondition.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DisabledCondition.java @@ -14,6 +14,7 @@ import java.lang.reflect.AnnotatedElement; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; @@ -44,7 +45,7 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con .orElse(ENABLED); } - private ConditionEvaluationResult toResult(AnnotatedElement element, Disabled annotation) { + private ConditionEvaluationResult toResult(@Nullable AnnotatedElement element, Disabled annotation) { String value = annotation.value(); String reason = StringUtils.isNotBlank(value) ? value : element + " is @Disabled"; return ConditionEvaluationResult.disabled(reason); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index 4dd3f44ff778..654d52995004 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -33,6 +33,7 @@ import java.util.stream.Stream; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.engine.config.JupiterConfiguration; import org.junit.platform.commons.logging.Logger; @@ -256,7 +257,7 @@ private void registerExtension(String category, Extension extension) { registerExtension(category, extension, null); } - private void registerExtension(String category, Extension extension, Object source) { + private void registerExtension(String category, Extension extension, @Nullable Object source) { Preconditions.notBlank(category, "category must not be null or blank"); Preconditions.notNull(extension, "extension must not be null"); @@ -266,7 +267,7 @@ private void registerExtension(String category, Extension extension, Object sour this.registeredExtensionTypes.add(extension.getClass()); } - private String buildSourceInfo(Object source) { + private String buildSourceInfo(@Nullable Object source) { if (source == null) { return ""; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java index b22d07419534..6eac77602c66 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java @@ -13,6 +13,7 @@ import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled; import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.RepeatedTest; import org.junit.jupiter.api.RepetitionInfo; import org.junit.jupiter.api.extension.ConditionEvaluationResult; @@ -61,7 +62,7 @@ public RepetitionInfo resolveParameter(ParameterContext parameterContext, Extens } @Override - public void testFailed(ExtensionContext context, Throwable cause) { + public void testFailed(ExtensionContext context, @Nullable Throwable cause) { this.repetitionInfo.failureCount.incrementAndGet(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java index 7a5a78ab1544..395726217fa9 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java @@ -16,13 +16,14 @@ import java.util.concurrent.ScheduledFuture; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.platform.commons.util.UnrecoverableExceptions; /** * @since 5.5 */ -class SameThreadTimeoutInvocation implements Invocation { +class SameThreadTimeoutInvocation implements Invocation { private final Invocation delegate; private final TimeoutDuration timeout; @@ -39,6 +40,7 @@ class SameThreadTimeoutInvocation implements Invocation { this.preInterruptCallback = preInterruptCallback; } + @SuppressWarnings("NullAway") @Override public T proceed() throws Throwable { InterruptTask interruptTask = new InterruptTask(Thread.currentThread(), preInterruptCallback); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java index 5500f773720e..d9783d1b7942 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java @@ -15,12 +15,13 @@ import java.util.concurrent.TimeoutException; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; /** * @since 5.9 */ -class SeparateThreadTimeoutInvocation implements Invocation { +class SeparateThreadTimeoutInvocation implements Invocation { private final Invocation delegate; private final TimeoutDuration timeout; @@ -39,8 +40,10 @@ class SeparateThreadTimeoutInvocation implements Invocation { public T proceed() throws Throwable { return assertTimeoutPreemptively(timeout.toDuration(), delegate::proceed, descriptionSupplier, (__, messageSupplier, cause, testThread) -> { - TimeoutException exception = TimeoutExceptionFactory.create(messageSupplier.get(), timeout, null); - preInterruptCallback.executePreInterruptCallback(testThread, exception::addSuppressed); + TimeoutException exception = TimeoutExceptionFactory.create(descriptionSupplier.get(), timeout, null); + if (testThread != null) { + preInterruptCallback.executePreInterruptCallback(testThread, exception::addSuppressed); + } exception.initCause(cause); return exception; }); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java index 5252b18f4f03..3339a17c8f23 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java @@ -12,6 +12,7 @@ import static java.nio.file.FileVisitResult.CONTINUE; import static java.nio.file.FileVisitResult.SKIP_SUBTREE; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; import static org.junit.jupiter.api.io.CleanupMode.DEFAULT; @@ -46,6 +47,7 @@ import java.util.TreeMap; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; @@ -146,7 +148,7 @@ private void injectInstanceFields(ExtensionContext context, Object instance) { } } - private void injectFields(ExtensionContext context, Object testInstance, Class testClass, + private void injectFields(ExtensionContext context, @Nullable Object testInstance, Class testClass, Predicate predicate) { findAnnotatedFields(testClass, TempDir.class, predicate).forEach(field -> { @@ -240,11 +242,11 @@ private static void assertSupportedType(String target, Class type) { private static Object getPathOrFile(Class elementType, AnnotatedElementContext elementContext, TempDirFactory factory, CleanupMode cleanupMode, ExtensionContext extensionContext) { - Path path = extensionContext.getStore(NAMESPACE.append(elementContext)) // + Path path = requireNonNull(extensionContext.getStore(NAMESPACE.append(elementContext)) // .getOrComputeIfAbsent(KEY, __ -> createTempDir(factory, cleanupMode, elementType, elementContext, extensionContext), - CloseablePath.class) // - .get(); + CloseablePath.class)) // + .get(); return (elementType == Path.class) ? path : path.toFile(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java index ad6c7f8f2143..dcf6d43d4f1f 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java @@ -14,6 +14,7 @@ import java.util.Optional; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -89,7 +90,9 @@ public String toString() { // @formatter:on } - private static Object nullSafeGet(Optional optional) { + @SuppressWarnings("OptionalAssignedToNull") + @Nullable + private static Object nullSafeGet(@Nullable Optional optional) { return optional != null ? optional.orElse(null) : null; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java index e5be5afefc3c..a0f01842181e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.extension; +import static java.util.Objects.requireNonNull; import static java.util.concurrent.TimeUnit.DAYS; import static java.util.concurrent.TimeUnit.HOURS; import static java.util.concurrent.TimeUnit.MICROSECONDS; @@ -56,7 +57,7 @@ TimeoutDuration parse(CharSequence text) throws DateTimeParseException { long value = Long.parseLong(matcher.group(1)); String unitAbbreviation = matcher.group(2); TimeUnit unit = unitAbbreviation == null ? SECONDS - : UNITS_BY_ABBREVIATION.get(unitAbbreviation.toLowerCase(Locale.ENGLISH)); + : requireNonNull(UNITS_BY_ABBREVIATION.get(unitAbbreviation.toLowerCase(Locale.ENGLISH))); return new TimeoutDuration(value, unit); } throw new DateTimeParseException("Timeout duration is not in the expected format ( [ns|μs|ms|s|m|h|d])", diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java index e911ac35ad74..2c52407d0c82 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactory.java @@ -12,6 +12,7 @@ import java.util.concurrent.TimeoutException; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -22,7 +23,8 @@ class TimeoutExceptionFactory { private TimeoutExceptionFactory() { } - static TimeoutException create(String methodSignature, TimeoutDuration timeoutDuration, Throwable failure) { + static TimeoutException create(String methodSignature, TimeoutDuration timeoutDuration, + @Nullable Throwable failure) { String message = "%s timed out after %s".formatted( Preconditions.notNull(methodSignature, "method signature must not be null"), Preconditions.notNull(timeoutDuration, "timeout duration must not be null")); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java index 555fb053ad1b..1c8deceef80f 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.extension; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Timeout.TIMEOUT_MODE_PROPERTY_NAME; import static org.junit.jupiter.api.Timeout.ThreadMode.SAME_THREAD; @@ -18,6 +19,7 @@ import java.util.Optional; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.Timeout.ThreadMode; import org.junit.jupiter.api.extension.BeforeAllCallback; @@ -153,14 +155,15 @@ private T interceptTestableMethod(Invocation invocation, } private T intercept(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext, TimeoutDuration explicitTimeout, TimeoutProvider defaultTimeoutProvider) - throws Throwable { + ExtensionContext extensionContext, @Nullable TimeoutDuration explicitTimeout, + TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = explicitTimeout == null ? getDefaultTimeout(extensionContext, defaultTimeoutProvider) : explicitTimeout; return decorate(invocation, invocationContext, extensionContext, timeout).proceed(); } + @Nullable private TimeoutDuration getDefaultTimeout(ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) { @@ -169,12 +172,12 @@ private TimeoutDuration getDefaultTimeout(ExtensionContext extensionContext, private TimeoutConfiguration getGlobalTimeoutConfiguration(ExtensionContext extensionContext) { ExtensionContext root = extensionContext.getRoot(); - return root.getStore(NAMESPACE).getOrComputeIfAbsent(GLOBAL_TIMEOUT_CONFIG_KEY, - key -> new TimeoutConfiguration(root), TimeoutConfiguration.class); + return requireNonNull(root.getStore(NAMESPACE).getOrComputeIfAbsent(GLOBAL_TIMEOUT_CONFIG_KEY, + key -> new TimeoutConfiguration(root), TimeoutConfiguration.class)); } private Invocation decorate(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext, TimeoutDuration timeout) { + ExtensionContext extensionContext, @Nullable TimeoutDuration timeout) { if (timeout == null || isTimeoutDisabled(extensionContext)) { return invocation; @@ -194,6 +197,7 @@ private ThreadMode resolveTimeoutThreadMode(ExtensionContext extensionContext) { return annotationThreadMode; } + @Nullable private ThreadMode getAnnotationThreadMode(ExtensionContext extensionContext) { return extensionContext.getStore(NAMESPACE).get(TESTABLE_METHOD_TIMEOUT_THREAD_MODE_KEY, ThreadMode.class); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/package-info.java index ff29b09a9c8f..96ac809f2bb2 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/package-info.java @@ -2,4 +2,7 @@ * Test extensions specific to the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.extension; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java index 1a9d753d305e..cd2a205c4c8d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/MethodReflectionUtils.java @@ -20,6 +20,7 @@ import java.lang.reflect.Type; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.support.ReflectionSupport; @API(status = INTERNAL, since = "6.0") @@ -37,7 +38,8 @@ public static Type getGenericReturnType(Method method) { : method.getGenericReturnType(); } - public static Object invoke(Method method, Object target, Object[] arguments) { + @Nullable + public static Object invoke(Method method, @Nullable Object target, @Nullable Object[] arguments) { if (isKotlinSuspendingFunction(method)) { return invokeKotlinSuspendingFunction(method, target, arguments); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/package-info.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/package-info.java index 6eecfd0f5120..83ffb2de0923 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/package-info.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/support/package-info.java @@ -2,4 +2,7 @@ * Internal support classes for the JUnit Jupiter test engine. */ +@NullMarked package org.junit.jupiter.engine.support; + +import org.jspecify.annotations.NullMarked; diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index e950a77ca157..5084568fc44a 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -84,10 +84,6 @@ class ArchUnitTests { void packagesShouldBeNullMarked(JavaClasses classes) { var exclusions = Stream.of( // "..shadow..", // - "org.junit.jupiter.engine.discovery..", // - "org.junit.jupiter.engine.execution..", // - "org.junit.jupiter.engine.extension..", // - "org.junit.jupiter.engine.support..", // "org.junit.jupiter.migrationsupport..", // "org.junit.jupiter.params.." // ).map(PackageMatcher::of).toList(); From a79d6785cd5c98401e04b4475e5f171bf1984ce8 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 15:24:44 +0200 Subject: [PATCH 131/521] Enable NullAway in junit-jupiter-migrationsupport --- .../junit-jupiter-migrationsupport.gradle.kts | 4 ++++ .../migrationsupport/conditions/IgnoreCondition.java | 3 ++- .../jupiter/migrationsupport/conditions/package-info.java | 3 +++ .../org/junit/jupiter/migrationsupport/package-info.java | 3 +++ .../migrationsupport/rules/ExpectedExceptionSupport.java | 4 ++-- .../jupiter/migrationsupport/rules/TestRuleSupport.java | 5 +++-- .../rules/adapter/AbstractTestRuleAdapter.java | 3 +++ .../migrationsupport/rules/adapter/package-info.java | 3 +++ .../rules/member/AbstractTestRuleAnnotatedMember.java | 6 ++++-- .../jupiter/migrationsupport/rules/member/package-info.java | 3 +++ .../junit/jupiter/migrationsupport/rules/package-info.java | 3 +++ .../java/platform/tooling/support/tests/ArchUnitTests.java | 1 - 12 files changed, 33 insertions(+), 8 deletions(-) diff --git a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts index b932ffe2021f..810408bfd4c4 100644 --- a/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts +++ b/junit-jupiter-migrationsupport/junit-jupiter-migrationsupport.gradle.kts @@ -1,5 +1,6 @@ plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.junit4-compatibility") } @@ -11,6 +12,7 @@ dependencies { api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) osgiVerification(projects.junitJupiterEngine) osgiVerification(projects.junitPlatformLauncher) @@ -23,10 +25,12 @@ tasks { jar { bundle { val importAPIGuardian: String by extra + val importJSpecify: String by extra bnd(""" # Import JUnit4 packages with a version Import-Package: \ $importAPIGuardian,\ + $importJSpecify,\ org.junit;version="[${libs.versions.junit4Min.get()},5)",\ org.junit.platform.commons.logging;status=INTERNAL,\ org.junit.rules;version="[${libs.versions.junit4Min.get()},5)",\ diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java index 59ab33098a59..efceb5723117 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java @@ -16,6 +16,7 @@ import java.lang.reflect.AnnotatedElement; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.Ignore; import org.junit.jupiter.api.extension.ConditionEvaluationResult; import org.junit.jupiter.api.extension.ExecutionCondition; @@ -53,7 +54,7 @@ public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext con .orElse(ENABLED); } - private ConditionEvaluationResult toResult(AnnotatedElement element, Ignore annotation) { + private ConditionEvaluationResult toResult(@Nullable AnnotatedElement element, Ignore annotation) { String value = annotation.value(); String reason = StringUtils.isNotBlank(value) ? value : element + " is disabled via @org.junit.Ignore"; return ConditionEvaluationResult.disabled(reason); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java index 530ff605d558..27c646ec3448 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java @@ -4,4 +4,7 @@ * Jupiter. */ +@NullMarked package org.junit.jupiter.migrationsupport.conditions; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java index 236a13fded50..1f14ec941a3c 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java @@ -2,4 +2,7 @@ * Support for migrating from JUnit 4 to JUnit Jupiter. */ +@NullMarked package org.junit.jupiter.migrationsupport; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java index adecfda66993..bf6abc2bcf39 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java @@ -57,8 +57,8 @@ public void handleTestExecutionException(ExtensionContext context, Throwable thr @Override public void afterEach(ExtensionContext context) throws Exception { - boolean handled = getStore(context).getOrComputeIfAbsent(EXCEPTION_WAS_HANDLED, key -> FALSE, Boolean.class); - if (!handled) { + Boolean handled = getStore(context).getOrComputeIfAbsent(EXCEPTION_WAS_HANDLED, key -> FALSE, Boolean.class); + if (handled != null && !handled) { this.support.afterEach(context); } } diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java index f424126d6fdd..a749d1f825a0 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java @@ -11,6 +11,7 @@ package org.junit.jupiter.migrationsupport.rules; import static java.util.Collections.unmodifiableList; +import static java.util.Objects.requireNonNull; import static org.junit.platform.commons.support.AnnotationSupport.findPublicAnnotatedFields; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import static org.junit.platform.commons.support.HierarchyTraversalMode.TOP_DOWN; @@ -146,8 +147,8 @@ private List getRuleAnnotatedMembers(ExtensionContext c Object testInstance = context.getRequiredTestInstance(); Namespace namespace = Namespace.create(TestRuleSupport.class, context.getRequiredTestClass()); // @formatter:off - return new ArrayList<>(context.getStore(namespace) - .getOrComputeIfAbsent("rule-annotated-members", key -> findRuleAnnotatedMembers(testInstance), List.class)); + return new ArrayList(requireNonNull(context.getStore(namespace) + .getOrComputeIfAbsent("rule-annotated-members", key -> findRuleAnnotatedMembers(testInstance), List.class))); // @formatter:on } diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java index d54bdaf1fc52..871f646e66aa 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/AbstractTestRuleAdapter.java @@ -17,6 +17,7 @@ import java.lang.reflect.Method; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.migrationsupport.rules.member.TestRuleAnnotatedMember; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ClassUtils; @@ -37,10 +38,12 @@ public AbstractTestRuleAdapter(TestRuleAnnotatedMember annotatedMember, Class adapteeClass + " is not assignable from " + this.target.getClass()); } + @Nullable protected Object executeMethod(String name) { return executeMethod(name, new Class[0]); } + @Nullable protected Object executeMethod(String methodName, Class[] parameterTypes, Object... arguments) { Method method = findMethod(this.target.getClass(), methodName, parameterTypes).orElseThrow( () -> new JUnitException("Failed to find method %s(%s) in class %s".formatted(methodName, diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java index d69bee9757cc..8353b255297f 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java @@ -2,4 +2,7 @@ * Simple wrappers for JUnit 4 rules to overcome visibility limitations of the JUnit 4 implementations. */ +@NullMarked package org.junit.jupiter.migrationsupport.rules.adapter; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/AbstractTestRuleAnnotatedMember.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/AbstractTestRuleAnnotatedMember.java index be6ea055b87d..7e3557a0a085 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/AbstractTestRuleAnnotatedMember.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/AbstractTestRuleAnnotatedMember.java @@ -10,6 +10,8 @@ package org.junit.jupiter.migrationsupport.rules.member; +import org.jspecify.annotations.Nullable; +import org.junit.platform.commons.util.Preconditions; import org.junit.rules.TestRule; /** @@ -19,8 +21,8 @@ abstract class AbstractTestRuleAnnotatedMember implements TestRuleAnnotatedMembe private final TestRule testRule; - AbstractTestRuleAnnotatedMember(TestRule testRule) { - this.testRule = testRule; + AbstractTestRuleAnnotatedMember(@Nullable TestRule testRule) { + this.testRule = Preconditions.notNull(testRule, "TestRule must not be null"); } @Override diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java index 85ce964ae4f6..d60c3221db07 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java @@ -2,4 +2,7 @@ * Abstractions for members which can be targets of JUnit 4 rule annotations. */ +@NullMarked package org.junit.jupiter.migrationsupport.rules.member; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java index 752ebb7e1e08..6532d84fcb78 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java @@ -2,4 +2,7 @@ * Extensions which provide (limited) support for JUnit 4 rules within JUnit Jupiter. */ +@NullMarked package org.junit.jupiter.migrationsupport.rules; + +import org.jspecify.annotations.NullMarked; diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index 5084568fc44a..4ff6591def9d 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -84,7 +84,6 @@ class ArchUnitTests { void packagesShouldBeNullMarked(JavaClasses classes) { var exclusions = Stream.of( // "..shadow..", // - "org.junit.jupiter.migrationsupport..", // "org.junit.jupiter.params.." // ).map(PackageMatcher::of).toList(); From 59afddac36a4bfa89cabe939fa593f5187de5179 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 16:26:51 +0200 Subject: [PATCH 132/521] Enable NullAway in junit-jupiter-params --- .../junit-jupiter-params.gradle.kts | 2 + .../src/main/java/module-info.java | 3 ++ ...ClassInvocationLifecycleMethodInvoker.java | 6 ++- .../params/ArgumentCountValidator.java | 6 ++- .../params/ArgumentSetLifecycleMethod.java | 2 + .../jupiter/params/EvaluatedArgumentSet.java | 25 +++++++--- .../params/ParameterizedClassExtension.java | 5 +- .../ParameterizedInvocationContext.java | 2 + .../ParameterizedInvocationNameFormatter.java | 15 ++++-- ...ameterizedInvocationParameterResolver.java | 2 + .../params/ParameterizedTestExtension.java | 5 +- .../junit/jupiter/params/ResolutionCache.java | 4 +- .../junit/jupiter/params/ResolverFacade.java | 18 +++++++- .../params/aggregator/ArgumentsAccessor.java | 15 +++++- .../aggregator/ArgumentsAggregator.java | 3 ++ .../aggregator/DefaultArgumentsAccessor.java | 30 ++++++++---- .../aggregator/SimpleArgumentsAggregator.java | 7 +-- .../params/aggregator/package-info.java | 3 ++ .../AnnotationBasedArgumentConverter.java | 24 ++++++---- .../ArgumentConversionException.java | 5 +- .../params/converter/ArgumentConverter.java | 6 ++- .../converter/DefaultArgumentConverter.java | 12 +++-- .../converter/JavaTimeArgumentConverter.java | 6 ++- .../converter/SimpleArgumentConverter.java | 10 ++-- .../converter/TypedArgumentConverter.java | 15 ++++-- .../params/converter/package-info.java | 3 ++ .../junit/jupiter/params/package-info.java | 3 ++ .../jupiter/params/provider/Arguments.java | 22 +++++---- .../params/provider/CsvArgumentsProvider.java | 46 +++++++++++-------- .../provider/CsvFileArgumentsProvider.java | 29 ++++++------ .../provider/FieldArgumentsProvider.java | 11 +++-- .../provider/MethodArgumentsProvider.java | 5 +- .../jupiter/params/provider/package-info.java | 3 ++ .../jupiter/params/support/ParameterInfo.java | 2 + .../jupiter/params/support/package-info.java | 3 ++ .../params/aggregator/ArgumentsAccessor.kt | 2 +- .../ParameterInfoIntegrationTests.java | 2 +- .../junit-jupiter-params.expected.txt | 1 + .../tooling/support/tests/ArchUnitTests.java | 3 +- 39 files changed, 250 insertions(+), 116 deletions(-) diff --git a/junit-jupiter-params/junit-jupiter-params.gradle.kts b/junit-jupiter-params/junit-jupiter-params.gradle.kts index 6bf26d8c4581..0f585b5d097d 100644 --- a/junit-jupiter-params/junit-jupiter-params.gradle.kts +++ b/junit-jupiter-params/junit-jupiter-params.gradle.kts @@ -1,6 +1,7 @@ import junitbuild.extensions.javaModuleName plugins { + id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") id("junitbuild.shadow-conventions") id("junitbuild.jmh-conventions") @@ -15,6 +16,7 @@ dependencies { api(projects.junitJupiterApi) compileOnlyApi(libs.apiguardian) + compileOnly(libs.jspecify) shadowed(libs.univocity.parsers) diff --git a/junit-jupiter-params/src/main/java/module-info.java b/junit-jupiter-params/src/main/java/module-info.java index 35569b82dd9d..f7ef36172179 100644 --- a/junit-jupiter-params/src/main/java/module-info.java +++ b/junit-jupiter-params/src/main/java/module-info.java @@ -14,7 +14,10 @@ * @since 5.0 */ module org.junit.jupiter.params { + requires static transitive org.apiguardian.api; + requires static org.jspecify; + requires transitive org.junit.jupiter.api; requires transitive org.junit.platform.commons; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AbstractParameterizedClassInvocationLifecycleMethodInvoker.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AbstractParameterizedClassInvocationLifecycleMethodInvoker.java index 0d20faee725b..2b836b9aed46 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AbstractParameterizedClassInvocationLifecycleMethodInvoker.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/AbstractParameterizedClassInvocationLifecycleMethodInvoker.java @@ -10,6 +10,8 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; + import org.junit.jupiter.api.extension.ExecutableInvoker; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -52,9 +54,9 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { - return this.lifecycleMethod.parameterResolver // + return requireNonNull(this.lifecycleMethod.parameterResolver // .resolve(parameterContext, extensionContext, this.arguments, this.invocationIndex, - this.resolutionCache); + this.resolutionCache)); } protected void invoke(ExtensionContext context) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java index 706f33971cb5..4495eec648c0 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java @@ -10,6 +10,8 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; + import java.util.Arrays; import java.util.Optional; @@ -72,7 +74,7 @@ private ArgumentCountValidationMode getArgumentCountValidationModeConfiguration( String key = ARGUMENT_COUNT_VALIDATION_KEY; ArgumentCountValidationMode fallback = ArgumentCountValidationMode.NONE; ExtensionContext.Store store = getStore(extensionContext); - return store.getOrComputeIfAbsent(key, __ -> { + return requireNonNull(store.getOrComputeIfAbsent(key, __ -> { Optional optionalConfigValue = extensionContext.getConfigurationParameter(key); if (optionalConfigValue.isPresent()) { String configValue = optionalConfigValue.get(); @@ -96,7 +98,7 @@ private ArgumentCountValidationMode getArgumentCountValidationModeConfiguration( else { return fallback; } - }, ArgumentCountValidationMode.class); + }, ArgumentCountValidationMode.class)); } private static String pluralize(int count, String singular, String plural) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentSetLifecycleMethod.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentSetLifecycleMethod.java index 13ed374ebf14..834cecb4fb2f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentSetLifecycleMethod.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentSetLifecycleMethod.java @@ -12,6 +12,7 @@ import java.lang.reflect.Method; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.platform.commons.JUnitException; @@ -51,6 +52,7 @@ public Object resolve(ParameterContext parameterContext, ExtensionContext extens boolean supports(ParameterContext parameterContext); + @Nullable Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, ResolutionCache resolutionCache); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java index 99c609d8969c..68a8bd2a368f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java @@ -15,6 +15,7 @@ import java.util.function.Function; import java.util.function.IntUnaryOperator; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Named; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments.ArgumentSet; @@ -32,25 +33,29 @@ class EvaluatedArgumentSet { static EvaluatedArgumentSet allOf(Arguments arguments) { + @Nullable Object[] all = arguments.get(); return create(all, all, arguments); } static EvaluatedArgumentSet of(Arguments arguments, IntUnaryOperator consumedLengthComputer) { + @Nullable Object[] all = arguments.get(); + @Nullable Object[] consumed = dropSurplus(all, consumedLengthComputer.applyAsInt(all.length)); return create(all, consumed, arguments); } - private static EvaluatedArgumentSet create(Object[] all, Object[] consumed, Arguments arguments) { + private static EvaluatedArgumentSet create(@Nullable Object[] all, @Nullable Object[] consumed, + Arguments arguments) { return new EvaluatedArgumentSet(all, consumed, determineName(arguments)); } - private final Object[] all; - private final Object[] consumed; + private final @Nullable Object[] all; + private final @Nullable Object[] consumed; private final Optional name; - private EvaluatedArgumentSet(Object[] all, Object[] consumed, Optional name) { + private EvaluatedArgumentSet(@Nullable Object[] all, @Nullable Object[] consumed, Optional name) { this.all = all; this.consumed = consumed; this.name = name; @@ -60,6 +65,7 @@ int getTotalLength() { return this.all.length; } + @Nullable Object[] getAllPayloads() { return extractFromNamed(this.all, Named::getPayload); } @@ -68,14 +74,17 @@ int getConsumedLength() { return this.consumed.length; } + @Nullable Object[] getConsumedNames() { return extractFromNamed(this.consumed, Named::getName); } + @Nullable Object[] getConsumedPayloads() { return extractFromNamed(this.consumed, Named::getPayload); } + @Nullable Object getConsumedPayload(int index) { return extractFromNamed(this.consumed[index], Named::getPayload); } @@ -84,7 +93,7 @@ Optional getName() { return this.name; } - private static Object[] dropSurplus(Object[] arguments, int newLength) { + private static @Nullable Object[] dropSurplus(@Nullable Object[] arguments, int newLength) { Preconditions.condition(newLength <= arguments.length, () -> "New length %d must be less than or equal to the total length %d".formatted(newLength, arguments.length)); @@ -98,13 +107,15 @@ private static Optional determineName(Arguments arguments) { return Optional.empty(); } - private static Object[] extractFromNamed(Object[] arguments, Function, Object> mapper) { + private static @Nullable Object[] extractFromNamed(@Nullable Object[] arguments, + Function, @Nullable Object> mapper) { return Arrays.stream(arguments) // .map(argument -> extractFromNamed(argument, mapper)) // .toArray(); } - private static Object extractFromNamed(Object argument, Function, Object> mapper) { + @Nullable + private static Object extractFromNamed(@Nullable Object argument, Function, @Nullable Object> mapper) { return argument instanceof Named named ? mapper.apply(named) : argument; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java index 2f45b6d7f606..3f134156eba6 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassExtension.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS; import static org.junit.jupiter.params.ParameterizedClassContext.InjectionType.CONSTRUCTOR; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; @@ -124,8 +125,8 @@ private static ParameterizedClassContext createClassContext(ExtensionContext ext } private ParameterizedClassContext getDeclarationContext(ExtensionContext extensionContext) { - return getStore(extensionContext)// - .get(DECLARATION_CONTEXT_KEY, ParameterizedClassContext.class); + return requireNonNull(getStore(extensionContext)// + .get(DECLARATION_CONTEXT_KEY, ParameterizedClassContext.class)); } private Store getStore(ExtensionContext context) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java index e310abb94843..62e198e0cf2a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java @@ -15,6 +15,7 @@ import java.util.Arrays; import java.util.concurrent.atomic.AtomicInteger; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.params.aggregator.ArgumentsAccessor; @@ -71,6 +72,7 @@ private void validateArgumentCount(ExtensionContext context) { private void storeParameterInfo(ExtensionContext context) { ParameterDeclarations declarations = this.declarationContext.getResolverFacade().getIndexedParameterDeclarations(); ClassLoader classLoader = getClassLoader(this.declarationContext.getTestClass()); + @Nullable Object[] arguments = this.arguments.getConsumedPayloads(); ArgumentsAccessor accessor = DefaultArgumentsAccessor.create(context, invocationIndex, classLoader, arguments); new DefaultParameterInfo(declarations, accessor).store(context); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java index ebaf50c536df..04d7111bcae7 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static org.junit.jupiter.params.ParameterizedInvocationConstants.ARGUMENTS_PLACEHOLDER; import static org.junit.jupiter.params.ParameterizedInvocationConstants.ARGUMENTS_WITH_NAMES_PLACEHOLDER; @@ -34,6 +35,7 @@ import java.util.function.Function; import java.util.stream.IntStream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.JUnitException; @@ -130,6 +132,7 @@ private PartialFormatter[] parse(String pattern, String displayName, return result.toArray(new PartialFormatter[0]); } + @Nullable private static PlaceholderPosition findFirstPlaceholder(PartialFormatters formatters, String segment) { if (segment.length() < formatters.minimumPlaceholderLength) { return null; @@ -210,10 +213,10 @@ private static class PlaceholderPosition { private static class ArgumentsContext { private final int invocationIndex; - private final Object[] consumedArguments; + private final @Nullable Object[] consumedArguments; private final Optional argumentSetName; - ArgumentsContext(int invocationIndex, Object[] consumedArguments, Optional argumentSetName) { + ArgumentsContext(int invocationIndex, @Nullable Object[] consumedArguments, Optional argumentSetName) { this.invocationIndex = invocationIndex; this.consumedArguments = consumedArguments; this.argumentSetName = argumentSetName; @@ -268,8 +271,9 @@ public synchronized void append(ArgumentsContext context, StringBuffer result) { this.messageFormat.format(makeReadable(context.consumedArguments), result, new FieldPosition(0)); } - private Object[] makeReadable(Object[] arguments) { + private @Nullable Object[] makeReadable(@Nullable Object[] arguments) { Format[] formats = messageFormat.getFormatsByArgumentIndex(); + @Nullable Object[] result = Arrays.copyOf(arguments, Math.min(arguments.length, formats.length), Object[].class); for (int i = 0; i < result.length; i++) { if (formats[i] == null) { @@ -279,7 +283,8 @@ private Object[] makeReadable(Object[] arguments) { return result; } - private String truncateIfExceedsMaxLength(String argument) { + @Nullable + private String truncateIfExceedsMaxLength(@Nullable String argument) { if (argument != null && argument.length() > this.argumentMaxLength) { return argument.substring(0, this.argumentMaxLength - 1) + ELLIPSIS; } @@ -316,7 +321,7 @@ void put(String placeholder, PartialFormatter formatter) { } PartialFormatter get(String placeholder) { - return formattersByPlaceholder.get(placeholder); + return requireNonNull(formattersByPlaceholder.get(placeholder)); } Set placeholders() { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java index 84faf1971d23..9d28206eeb0c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java @@ -12,6 +12,7 @@ import java.lang.reflect.Executable; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolutionException; @@ -50,6 +51,7 @@ public final boolean supportsParameter(ParameterContext parameterContext, Extens } @Override + @Nullable public final Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java index 1b4393d4f3a3..31de4ad836aa 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import java.util.Optional; @@ -56,8 +57,8 @@ public boolean mayReturnZeroTestTemplateInvocationContexts(ExtensionContext exte } private ParameterizedTestContext getDeclarationContext(ExtensionContext extensionContext) { - return getStore(extensionContext)// - .get(DECLARATION_CONTEXT_KEY, ParameterizedTestContext.class); + return requireNonNull(getStore(extensionContext)// + .get(DECLARATION_CONTEXT_KEY, ParameterizedTestContext.class)); } private ExtensionContext.Store getStore(ExtensionContext context) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java index eeec256dccd0..b692cb5a0e5d 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java @@ -14,6 +14,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.params.support.ParameterDeclaration; /** @@ -27,7 +28,8 @@ static ResolutionCache enabled() { ResolutionCache DISABLED = (__, resolver) -> resolver.get(); - Object resolve(ParameterDeclaration declaration, Supplier resolver); + @Nullable + Object resolve(ParameterDeclaration declaration, Supplier<@Nullable Object> resolver); class Concurrent implements ResolutionCache { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 54dc04b767f4..529f4db561fe 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -12,6 +12,7 @@ import static java.lang.System.lineSeparator; import static java.util.Collections.unmodifiableList; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; @@ -41,6 +42,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ExtensionConfigurationException; import org.junit.jupiter.api.extension.ExtensionContext; @@ -251,6 +253,7 @@ ArgumentSetLifecycleMethod.ParameterResolver createLifecycleMethodParameterResol * Resolve the parameter for the supplied context using the supplied * arguments. */ + @Nullable Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, ResolutionCache resolutionCache) { @@ -304,6 +307,7 @@ private void setField(Object testInstance, FieldParameterDeclaration declaration } } + @Nullable private Object resolve(ResolvableParameterDeclaration parameterDeclaration, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, Optional parameterContext) { Resolver resolver = getResolver(extensionContext, parameterDeclaration); @@ -465,9 +469,11 @@ private static ParameterResolutionException parameterResolutionException(String private interface Resolver { + @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex); + @Nullable Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex); @@ -486,6 +492,7 @@ private static Converter createDefault(ExtensionContext context) { } @Override + @Nullable public Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { Object argument = arguments.getConsumedPayload(parameterIndex); @@ -498,6 +505,7 @@ public Object resolve(ParameterContext parameterContext, int parameterIndex, Ext } @Override + @Nullable public Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { Object argument = arguments.getConsumedPayload(fieldContext.getParameterIndex()); @@ -527,9 +535,10 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT } @Override + @Nullable public Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { - ArgumentsAccessor accessor = ParameterInfo.get(extensionContext).getArguments(); + ArgumentsAccessor accessor = requireNonNull(ParameterInfo.get(extensionContext)).getArguments(); try { return this.argumentsAggregator.aggregateArguments(accessor, parameterContext); } @@ -540,9 +549,10 @@ public Object resolve(ParameterContext parameterContext, int parameterIndex, Ext } @Override + @Nullable public Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { - ArgumentsAccessor accessor = ParameterInfo.get(extensionContext).getArguments(); + ArgumentsAccessor accessor = requireNonNull(ParameterInfo.get(extensionContext)).getArguments(); try { return this.argumentsAggregator.aggregateArguments(accessor, fieldContext); } @@ -618,6 +628,7 @@ boolean isAggregator() { || isAnnotated(getAnnotatedElement(), AggregateWith.class); } + @Nullable protected abstract Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, Optional originalParameterContext); @@ -659,6 +670,7 @@ public Optional getParameterName() { } @Override + @Nullable public Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, Optional originalParameterContext) { return resolver.resolve(this, extensionContext, arguments, invocationIndex); @@ -698,6 +710,7 @@ public Optional getParameterName() { } @Override + @Nullable public Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, Optional originalParameterContext) { ParameterContext parameterContext = originalParameterContext // @@ -759,6 +772,7 @@ public boolean supports(ParameterContext parameterContext) { } @Override + @Nullable public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, ResolutionCache resolutionCache) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java index 5e31a35d288c..a098322c8643 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java @@ -15,6 +15,7 @@ import java.util.List; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; /** * {@code ArgumentsAccessor} defines the public API for accessing arguments provided @@ -52,6 +53,7 @@ public interface ArgumentsAccessor { * equal to zero and less than {@link #size} * @return the value at the given index, potentially {@code null} */ + @Nullable Object get(int index) throws ArgumentAccessException; /** @@ -63,6 +65,7 @@ public interface ArgumentsAccessor { * @param requiredType the required type of the value; never {@code null} * @return the value at the given index, potentially {@code null} */ + @Nullable T get(int index, Class requiredType) throws ArgumentAccessException; /** @@ -75,6 +78,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Character getCharacter(int index) throws ArgumentAccessException; /** @@ -87,6 +91,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Boolean getBoolean(int index) throws ArgumentAccessException; /** @@ -99,6 +104,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Byte getByte(int index) throws ArgumentAccessException; /** @@ -111,6 +117,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Short getShort(int index) throws ArgumentAccessException; /** @@ -123,6 +130,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Integer getInteger(int index) throws ArgumentAccessException; /** @@ -135,6 +143,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Long getLong(int index) throws ArgumentAccessException; /** @@ -147,6 +156,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Float getFloat(int index) throws ArgumentAccessException; /** @@ -159,6 +169,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable Double getDouble(int index) throws ArgumentAccessException; /** @@ -171,6 +182,7 @@ public interface ArgumentsAccessor { * @throws ArgumentAccessException if the value cannot be accessed * or converted to the desired type */ + @Nullable String getString(int index) throws ArgumentAccessException; /** @@ -181,12 +193,13 @@ public interface ArgumentsAccessor { /** * Get all arguments in this accessor as an array. */ + @Nullable Object[] toArray(); /** * Get all arguments in this accessor as an immutable list. */ - List toList(); + List<@Nullable Object> toList(); /** * Get the index of the current test invocation. 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..0e8ced7836b8 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 @@ -14,6 +14,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.params.support.FieldContext; @@ -65,6 +66,7 @@ public interface ArgumentsAggregator { * @throws ArgumentsAggregationException if an error occurs during the * aggregation */ + @Nullable Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException; @@ -82,6 +84,7 @@ Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) * aggregation * @since 5.13 */ + @Nullable @API(status = EXPERIMENTAL, since = "5.13") default Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) throws ArgumentsAggregationException { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java index 62750bbae9e8..8d9e5ace2ea4 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java @@ -18,6 +18,7 @@ import java.util.function.BiFunction; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.converter.DefaultArgumentConverter; import org.junit.platform.commons.util.ClassUtils; @@ -37,20 +38,21 @@ public class DefaultArgumentsAccessor implements ArgumentsAccessor { private final int invocationIndex; - private final Object[] arguments; - private final BiFunction, Object> converter; + private final @Nullable Object[] arguments; + private final BiFunction<@Nullable Object, Class, @Nullable Object> converter; public static DefaultArgumentsAccessor create(ExtensionContext context, int invocationIndex, - ClassLoader classLoader, Object[] arguments) { + ClassLoader classLoader, @Nullable Object[] arguments) { Preconditions.notNull(classLoader, "ClassLoader must not be null"); - BiFunction, Object> converter = (source, targetType) -> new DefaultArgumentConverter(context) // - .convert(source, targetType, classLoader); + BiFunction<@Nullable Object, Class, @Nullable Object> converter = (source, + targetType) -> new DefaultArgumentConverter(context) // + .convert(source, targetType, classLoader); return new DefaultArgumentsAccessor(converter, invocationIndex, arguments); } - private DefaultArgumentsAccessor(BiFunction, Object> converter, int invocationIndex, - Object... arguments) { + private DefaultArgumentsAccessor(BiFunction<@Nullable Object, Class, @Nullable Object> converter, + int invocationIndex, @Nullable Object... arguments) { Preconditions.condition(invocationIndex >= 1, () -> "Invocation index must be >= 1"); this.converter = Preconditions.notNull(converter, "Converter must not be null"); this.invocationIndex = invocationIndex; @@ -58,6 +60,7 @@ private DefaultArgumentsAccessor(BiFunction, Object> converter, } @Override + @Nullable public Object get(int index) { Preconditions.condition(index >= 0 && index < this.arguments.length, () -> "index must be >= 0 and < %d".formatted(this.arguments.length)); @@ -65,6 +68,7 @@ public Object get(int index) { } @Override + @Nullable public T get(int index, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); Object value = get(index); @@ -81,46 +85,55 @@ public T get(int index, Class requiredType) { } @Override + @Nullable public Character getCharacter(int index) { return get(index, Character.class); } @Override + @Nullable public Boolean getBoolean(int index) { return get(index, Boolean.class); } @Override + @Nullable public Byte getByte(int index) { return get(index, Byte.class); } @Override + @Nullable public Short getShort(int index) { return get(index, Short.class); } @Override + @Nullable public Integer getInteger(int index) { return get(index, Integer.class); } @Override + @Nullable public Long getLong(int index) { return get(index, Long.class); } @Override + @Nullable public Float getFloat(int index) { return get(index, Float.class); } @Override + @Nullable public Double getDouble(int index) { return get(index, Double.class); } @Override + @Nullable public String getString(int index) { return get(index, String.class); } @@ -131,12 +144,13 @@ public int size() { } @Override + @Nullable public Object[] toArray() { return Arrays.copyOf(this.arguments, this.arguments.length); } @Override - public List toList() { + public List<@Nullable Object> toList() { return Collections.unmodifiableList(Arrays.asList(this.arguments)); } 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..f46b842535ec 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 @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.AnnotatedElementContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.FieldContext; @@ -32,17 +33,17 @@ public SimpleArgumentsAggregator() { } @Override - public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) + public @Nullable Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) throws ArgumentsAggregationException { return aggregateArguments(accessor, context.getParameter().getType(), context, context.getIndex()); } @Override - public Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) + public @Nullable Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) throws ArgumentsAggregationException { return aggregateArguments(accessor, context.getField().getType(), context, context.getParameterIndex()); } - protected abstract Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, + protected abstract @Nullable Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, AnnotatedElementContext context, int parameterIndex) throws ArgumentsAggregationException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/package-info.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/package-info.java index e7129488d84f..a56f2a1280a1 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/package-info.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/package-info.java @@ -4,4 +4,7 @@ * {@link org.junit.jupiter.params.aggregator.AggregateWith} annotation. */ +@NullMarked package org.junit.jupiter.params.aggregator; + +import org.jspecify.annotations.NullMarked; 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..ade4018b17ba 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,11 +10,13 @@ package org.junit.jupiter.params.converter; +import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.lang.annotation.Annotation; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.AnnotationConsumer; import org.junit.jupiter.params.support.FieldContext; @@ -34,25 +36,28 @@ public abstract class AnnotationBasedArgumentConverter implements ArgumentConverter, AnnotationConsumer { + @Nullable + private A annotation; + public AnnotationBasedArgumentConverter() { } - private A annotation; - @Override public final void accept(A annotation) { - Preconditions.notNull(annotation, "annotation must not be null"); - this.annotation = annotation; + this.annotation = Preconditions.notNull(annotation, "annotation must not be null"); + ; } @Override - public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { - return convert(source, context.getParameter().getType(), this.annotation); + @Nullable + public final Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { + return convert(source, context.getParameter().getType(), requireNonNull(this.annotation)); } @Override - public final Object convert(Object source, FieldContext context) throws ArgumentConversionException { - return convert(source, context.getField().getType(), this.annotation); + @Nullable + public final Object convert(@Nullable Object source, FieldContext context) throws ArgumentConversionException { + return convert(source, context.getField().getType(), requireNonNull(this.annotation)); } /** @@ -68,7 +73,8 @@ public final Object convert(Object source, FieldContext context) throws Argument * @throws ArgumentConversionException in case an error occurs during the * conversion */ - protected abstract Object convert(Object source, Class targetType, A annotation) + @Nullable + protected abstract Object convert(@Nullable Object source, Class targetType, A annotation) throws ArgumentConversionException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java index 08a6228bd127..64d5b304aceb 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/ArgumentConversionException.java @@ -15,6 +15,7 @@ import java.io.Serial; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; /** @@ -31,11 +32,11 @@ public class ArgumentConversionException extends JUnitException { @Serial private static final long serialVersionUID = 1L; - public ArgumentConversionException(String message) { + public ArgumentConversionException(@Nullable String message) { super(message); } - public ArgumentConversionException(String message, Throwable cause) { + public ArgumentConversionException(@Nullable String message, @Nullable Throwable cause) { super(message, cause); } 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 eae935d66e75..86e9c17b656b 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 @@ -14,6 +14,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.params.support.FieldContext; @@ -64,7 +65,8 @@ public interface ArgumentConverter { * @throws ArgumentConversionException if an error occurs during the * conversion */ - Object convert(Object source, ParameterContext context) throws ArgumentConversionException; + @Nullable + Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException; /** * Convert the supplied {@code source} object according to the supplied @@ -80,7 +82,7 @@ public interface ArgumentConverter { * @since 5.13 */ @API(status = EXPERIMENTAL, since = "5.13") - default Object convert(Object source, FieldContext context) throws ArgumentConversionException { + default @Nullable Object convert(@Nullable Object source, FieldContext context) throws ArgumentConversionException { throw new JUnitException( String.format("ArgumentConverter does not override the convert(Object, FieldContext) method. " + "Please report this issue to the maintainers of %s.", diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java index 81e0bf1bc95d..46c29d6a9cc0 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/DefaultArgumentConverter.java @@ -24,6 +24,7 @@ import java.util.function.Function; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.FieldContext; @@ -80,20 +81,22 @@ public DefaultArgumentConverter(ExtensionContext context) { } @Override - public final Object convert(Object source, ParameterContext context) { + public final @Nullable Object convert(@Nullable Object source, ParameterContext context) { Class targetType = context.getParameter().getType(); ClassLoader classLoader = getClassLoader(context.getDeclaringExecutable().getDeclaringClass()); return convert(source, targetType, classLoader); } @Override - public final Object convert(Object source, FieldContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, FieldContext context) + throws ArgumentConversionException { + Class targetType = context.getField().getType(); ClassLoader classLoader = getClassLoader(context.getField().getDeclaringClass()); return convert(source, targetType, classLoader); } - public final Object convert(Object source, Class targetType, ClassLoader classLoader) { + public final @Nullable Object convert(@Nullable Object source, Class targetType, ClassLoader classLoader) { if (source == null) { if (targetType.isPrimitive()) { throw new ArgumentConversionException( @@ -128,7 +131,8 @@ private LocaleConversionFormat getLocaleConversionFormat() { .orElse(LocaleConversionFormat.BCP_47); } - Object convert(String source, Class targetType, ClassLoader classLoader) { + @Nullable + Object convert(@Nullable String source, Class targetType, ClassLoader classLoader) { return ConversionSupport.convert(source, targetType, classLoader); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java index 6684b472ff18..f91d22d0cf65 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverter.java @@ -27,6 +27,8 @@ import java.util.LinkedHashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + /** * @since 5.0 */ @@ -50,7 +52,9 @@ class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter targetClass, JavaTimeConversionPattern annotation) { + protected @Nullable Object convert(@Nullable Object input, Class targetClass, + JavaTimeConversionPattern annotation) { + if (input == null) { if (annotation.nullable()) { return null; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java index 2cb0f3f922a6..3203b0476966 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.FieldContext; @@ -33,12 +34,14 @@ public SimpleArgumentConverter() { } @Override - public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + @Nullable + public final Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { return convert(source, context.getParameter().getType()); } @Override - public final Object convert(Object source, FieldContext context) throws ArgumentConversionException { + @Nullable + public final Object convert(@Nullable Object source, FieldContext context) throws ArgumentConversionException { return convert(source, context.getField().getType()); } @@ -54,6 +57,7 @@ public final Object convert(Object source, FieldContext context) throws Argument * @throws ArgumentConversionException in case an error occurs during the * conversion */ - protected abstract Object convert(Object source, Class targetType) throws ArgumentConversionException; + @Nullable + protected abstract Object convert(@Nullable Object source, Class targetType) throws ArgumentConversionException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java index 79b7a42d1549..b2dda27b4639 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/TypedArgumentConverter.java @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ParameterContext; import org.junit.jupiter.params.support.FieldContext; import org.junit.platform.commons.util.Preconditions; @@ -30,7 +31,7 @@ * @see SimpleArgumentConverter */ @API(status = STABLE, since = "5.10") -public abstract class TypedArgumentConverter implements ArgumentConverter { +public abstract class TypedArgumentConverter implements ArgumentConverter { private final Class sourceType; private final Class targetType; @@ -48,16 +49,20 @@ protected TypedArgumentConverter(Class sourceType, Class targetType) { } @Override - public final Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { + return convert(source, context.getParameter().getType()); } @Override - public final Object convert(Object source, FieldContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, FieldContext context) + throws ArgumentConversionException { + return convert(source, context.getField().getType()); } - private T convert(Object source, Class actualTargetType) { + private T convert(@Nullable Object source, Class actualTargetType) { if (source == null) { return convert(null); } @@ -84,6 +89,6 @@ private T convert(Object source, Class actualTargetType) { * @throws ArgumentConversionException if an error occurs during the * conversion */ - protected abstract T convert(S source) throws ArgumentConversionException; + protected abstract T convert(@Nullable S source) throws ArgumentConversionException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/package-info.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/package-info.java index ff813c1864f7..6459e382e89f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/package-info.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/package-info.java @@ -4,4 +4,7 @@ * {@link org.junit.jupiter.params.converter.ConvertWith @ConvertWith} annotation. */ +@NullMarked package org.junit.jupiter.params.converter; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/package-info.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/package-info.java index aa0820df67a8..1261a4a90940 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/package-info.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/package-info.java @@ -2,4 +2,7 @@ * JUnit Jupiter extension for parameterized tests. */ +@NullMarked package org.junit.jupiter.params; + +import org.jspecify.annotations.NullMarked; 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 4a54fcbeb0a0..b1492ec95188 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 @@ -14,6 +14,7 @@ import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; /** @@ -60,8 +61,9 @@ public interface Arguments { * @apiNote If you need a type-safe way to access some or all of the arguments, * please read the {@linkplain Arguments class-level API note}. * - * @return the arguments; never {@code null} + * @return the arguments; never {@code null} but may contain {@code null} */ + @Nullable Object[] get(); /** @@ -69,12 +71,12 @@ public interface Arguments { * the supplied {@code arguments}. * * @param arguments the arguments to be used for an invocation of the test - * method; must not be {@code null} + * method; must not be {@code null} but may contain {@code null} * @return an instance of {@code Arguments}; never {@code null} * @see #arguments(Object...) * @see #argumentSet(String, Object...) */ - static Arguments of(Object... arguments) { + static Arguments of(@Nullable Object... arguments) { Preconditions.notNull(arguments, "arguments array must not be null"); return () -> arguments; } @@ -88,12 +90,12 @@ static Arguments of(Object... arguments) { * {@code import static org.junit.jupiter.params.provider.Arguments.arguments;} * * @param arguments the arguments to be used for an invocation of the test - * method; must not be {@code null} + * method; must not be {@code null} but may contain {@code null} * @return an instance of {@code Arguments}; never {@code null} * @since 5.3 * @see #argumentSet(String, Object...) */ - static Arguments arguments(Object... arguments) { + static Arguments arguments(@Nullable Object... arguments) { return of(arguments); } @@ -111,7 +113,7 @@ static Arguments arguments(Object... arguments) { * * @param name the name of the argument set; must not be {@code null} or blank * @param arguments the arguments to be used for an invocation of the test - * method; must not be {@code null} + * method; must not be {@code null} but may contain {@code null} * @return an {@code ArgumentSet}; never {@code null} * @since 5.11 * @see ArgumentSet @@ -119,7 +121,7 @@ static Arguments arguments(Object... arguments) { * @see org.junit.jupiter.params.ParameterizedTest#ARGUMENT_SET_NAME_OR_ARGUMENTS_WITH_NAMES_PLACEHOLDER */ @API(status = EXPERIMENTAL, since = "5.11") - static ArgumentSet argumentSet(String name, Object... arguments) { + static ArgumentSet argumentSet(String name, @Nullable Object... arguments) { return new ArgumentSet(name, arguments); } @@ -137,9 +139,9 @@ final class ArgumentSet implements Arguments { private final String name; - private final Object[] arguments; + private final @Nullable Object[] arguments; - private ArgumentSet(String name, Object[] arguments) { + private ArgumentSet(String name, @Nullable Object[] arguments) { Preconditions.notBlank(name, "name must not be null or blank"); Preconditions.notNull(arguments, "arguments array must not be null"); this.name = name; @@ -155,7 +157,7 @@ public String getName() { } @Override - public Object[] get() { + public @Nullable Object[] get() { return this.arguments; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index 86329b967638..3f961f83c718 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params.provider; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.params.provider.CsvParserFactory.createParserFor; import static org.junit.platform.commons.util.CollectionUtils.toSet; @@ -24,6 +25,7 @@ import com.univocity.parsers.csv.CsvParser; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Named; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.support.ParameterDeclarations; @@ -38,36 +40,34 @@ class CsvArgumentsProvider extends AnnotationBasedArgumentsProvider { private static final String LINE_SEPARATOR = "\n"; - private Set nullValues; - private CsvParser csvParser; - @Override protected Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context, CsvSource csvSource) { - this.nullValues = toSet(csvSource.nullValues()); - this.csvParser = createParserFor(csvSource); + Set nullValues = toSet(csvSource.nullValues()); + CsvParser csvParser = createParserFor(csvSource); final boolean textBlockDeclared = !csvSource.textBlock().isEmpty(); Preconditions.condition(csvSource.value().length > 0 ^ textBlockDeclared, () -> "@CsvSource must be declared with either `value` or `textBlock` but not both"); - return textBlockDeclared ? parseTextBlock(csvSource) : parseValueArray(csvSource); + return textBlockDeclared ? parseTextBlock(csvSource, csvParser, nullValues) + : parseValueArray(csvSource, csvParser, nullValues); } - private Stream parseTextBlock(CsvSource csvSource) { + private Stream parseTextBlock(CsvSource csvSource, CsvParser csvParser, Set nullValues) { String textBlock = csvSource.textBlock(); boolean useHeadersInDisplayName = csvSource.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); try { - List csvRecords = this.csvParser.parseAll(new StringReader(textBlock)); - String[] headers = useHeadersInDisplayName ? getHeaders(this.csvParser) : null; + List csvRecords = csvParser.parseAll(new StringReader(textBlock)); + String[] headers = useHeadersInDisplayName ? getHeaders(csvParser) : null; AtomicInteger index = new AtomicInteger(0); for (String[] csvRecord : csvRecords) { index.incrementAndGet(); Preconditions.notNull(csvRecord, () -> "Record at index " + index + " contains invalid CSV: \"\"\"\n" + textBlock + "\n\"\"\""); - argumentsList.add(processCsvRecord(csvRecord, this.nullValues, useHeadersInDisplayName, headers)); + argumentsList.add(processCsvRecord(csvRecord, nullValues, useHeadersInDisplayName, headers)); } } catch (Throwable throwable) { @@ -77,7 +77,7 @@ private Stream parseTextBlock(CsvSource csvSource) { return argumentsList.stream(); } - private Stream parseValueArray(CsvSource csvSource) { + private Stream parseValueArray(CsvSource csvSource, CsvParser csvParser, Set nullValues) { boolean useHeadersInDisplayName = csvSource.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); @@ -86,15 +86,15 @@ private Stream parseValueArray(CsvSource csvSource) { AtomicInteger index = new AtomicInteger(0); for (String input : csvSource.value()) { index.incrementAndGet(); - String[] csvRecord = this.csvParser.parseLine(input + LINE_SEPARATOR); + String[] csvRecord = csvParser.parseLine(input + LINE_SEPARATOR); // Lazily retrieve headers if necessary. if (useHeadersInDisplayName && headers == null) { - headers = getHeaders(this.csvParser); + headers = getHeaders(csvParser); continue; } Preconditions.notNull(csvRecord, () -> "Record at index " + index + " contains invalid CSV: \"" + input + "\""); - argumentsList.add(processCsvRecord(csvRecord, this.nullValues, useHeadersInDisplayName, headers)); + argumentsList.add(processCsvRecord(csvRecord, nullValues, useHeadersInDisplayName, headers)); } } catch (Throwable throwable) { @@ -116,18 +116,19 @@ static String[] getHeaders(CsvParser csvParser) { * {@link Named} if necessary (for CSV header support), and returns the * CSV record wrapped in an {@link Arguments} instance. */ - static Arguments processCsvRecord(Object[] csvRecord, Set nullValues, boolean useHeadersInDisplayName, - String[] headers) { + static Arguments processCsvRecord(String[] csvRecord, Set nullValues, boolean useHeadersInDisplayName, + String @Nullable [] headers) { // Nothing to process? if (nullValues.isEmpty() && !useHeadersInDisplayName) { - return Arguments.of(csvRecord); + return Arguments.of((Object[]) csvRecord); } - Preconditions.condition(!useHeadersInDisplayName || (csvRecord.length <= headers.length), + Preconditions.condition(!useHeadersInDisplayName || (csvRecord.length <= requireNonNull(headers).length), () -> "The number of columns (%d) exceeds the number of supplied headers (%d) in CSV record: %s".formatted( - csvRecord.length, headers.length, Arrays.toString(csvRecord))); + csvRecord.length, requireNonNull(headers).length, Arrays.toString(csvRecord))); + @Nullable Object[] arguments = new Object[csvRecord.length]; for (int i = 0; i < csvRecord.length; i++) { Object column = csvRecord[i]; @@ -135,13 +136,18 @@ static Arguments processCsvRecord(Object[] csvRecord, Set nullValues, bo column = null; } if (useHeadersInDisplayName) { - column = Named.of(headers[i] + " = " + column, column); + column = asNamed(requireNonNull(headers)[i] + " = " + column, column); } arguments[i] = column; } return Arguments.of(arguments); } + @SuppressWarnings("NullAway") + private static Named<@Nullable Object> asNamed(String name, @Nullable Object column) { + return Named.of(name, column); + } + /** * @return this method always throws an exception and therefore never * returns anything; the return type is merely present to allow this diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index 09635ced0b26..a56ec8270b3a 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params.provider; +import static java.util.Objects.requireNonNull; import static java.util.Spliterators.spliteratorUnknownSize; import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; @@ -33,6 +34,7 @@ import com.univocity.parsers.csv.CsvParser; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.support.ParameterDeclarations; import org.junit.platform.commons.JUnitException; @@ -46,10 +48,6 @@ class CsvFileArgumentsProvider extends AnnotationBasedArgumentsProvider provideArguments(ParameterDeclarations parameters, ExtensionContext context, CsvFileSource csvFileSource) { - this.charset = getCharsetFrom(csvFileSource); - this.numLinesToSkip = csvFileSource.numLinesToSkip(); - this.csvParser = createParserFor(csvFileSource); + Charset charset = getCharsetFrom(csvFileSource); + CsvParser csvParser = createParserFor(csvFileSource); Stream resources = Arrays.stream(csvFileSource.resources()).map(inputStreamProvider::classpathResource); Stream files = Arrays.stream(csvFileSource.files()).map(inputStreamProvider::file); @@ -73,7 +70,7 @@ protected Stream provideArguments(ParameterDeclarations par return Preconditions.notEmpty(sources, "Resources or files must not be empty") .stream() .map(source -> source.open(context)) - .map(inputStream -> beginParsing(inputStream, csvFileSource)) + .map(inputStream -> beginParsing(inputStream, csvFileSource, csvParser, charset)) .flatMap(parser -> toStream(parser, csvFileSource)); // @formatter:on } @@ -87,20 +84,21 @@ private Charset getCharsetFrom(CsvFileSource csvFileSource) { } } - private CsvParser beginParsing(InputStream inputStream, CsvFileSource csvFileSource) { + private CsvParser beginParsing(InputStream inputStream, CsvFileSource csvFileSource, CsvParser csvParser, + Charset charset) { try { - this.csvParser.beginParsing(inputStream, this.charset); + csvParser.beginParsing(inputStream, charset); } catch (Throwable throwable) { throw handleCsvException(throwable, csvFileSource); } - return this.csvParser; + return csvParser; } private Stream toStream(CsvParser csvParser, CsvFileSource csvFileSource) { CsvParserIterator iterator = new CsvParserIterator(csvParser, csvFileSource); return stream(spliteratorUnknownSize(iterator, Spliterator.ORDERED), false) // - .skip(this.numLinesToSkip) // + .skip(csvFileSource.numLinesToSkip()) // .onClose(() -> { try { csvParser.stopParsing(); @@ -117,8 +115,11 @@ private static class CsvParserIterator implements Iterator { private final CsvFileSource csvFileSource; private final boolean useHeadersInDisplayName; private final Set nullValues; + + @Nullable private Arguments nextArguments; - private String[] headers; + + private String @Nullable [] headers; CsvParserIterator(CsvParser csvParser, CsvFileSource csvFileSource) { this.csvParser = csvParser; @@ -137,7 +138,7 @@ public boolean hasNext() { public Arguments next() { Arguments result = this.nextArguments; advance(); - return result; + return requireNonNull(result); } private void advance() { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java index a0a4b137f4d7..3aaa3e8e7673 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java @@ -24,6 +24,7 @@ import java.util.stream.BaseStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.support.ParameterDeclarations; import org.junit.platform.commons.JUnitException; @@ -90,12 +91,12 @@ static Field findField(Class testClass, String fieldName) { .findFirst()// .orElse(null); - Preconditions.notNull(field, () -> "Could not find field named [%s] in class [%s]".formatted(resolvedFieldName, - resolvedClass.getName())); - return field; + return Preconditions.notNull(field, + () -> "Could not find field named [%s] in class [%s]".formatted(resolvedFieldName, + resolvedClass.getName())); } - private static Field validateField(Field field, Object testInstance) { + private static Field validateField(Field field, @Nullable Object testInstance) { Preconditions.condition(field.getDeclaringClass().isInstance(testInstance) || ModifierSupport.isStatic(field), () -> format("Field '%s' must be static: local @FieldSource fields must be static " + "unless the PER_CLASS @TestInstance lifecycle mode is used; " @@ -104,7 +105,7 @@ private static Field validateField(Field field, Object testInstance) { return field; } - private static Object readField(Field field, Object testInstance) { + private static Object readField(Field field, @Nullable Object testInstance) { Object value = ReflectionSupport.tryToReadFieldValue(field, testInstance).getOrThrow( cause -> new JUnitException("Could not read field [%s]".formatted(field.getName()), cause)); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java index 0c112eab5a66..d4af42cebd1f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java @@ -22,6 +22,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestTemplate; @@ -53,7 +54,7 @@ protected Stream provideArguments(ParameterDeclarations par return stream(methodNames) .map(factoryMethodName -> findFactoryMethod(testClass, testMethod, factoryMethodName)) .map(factoryMethod -> validateFactoryMethod(factoryMethod, testInstance)) - .map(factoryMethod -> context.getExecutableInvoker().invoke(factoryMethod, testInstance)) + .map(factoryMethod -> Preconditions.notNull(context.getExecutableInvoker().invoke(factoryMethod, testInstance), () -> "@MethodSource-referenced method [%s] must not return null".formatted(factoryMethod.toGenericString()))) .flatMap(CollectionUtils::toStream) .map(ArgumentsUtils::toArguments); // @formatter:on @@ -177,7 +178,7 @@ private static boolean isTestMethod(Method candidate) { || isAnnotated(candidate, TestFactory.class); } - private static Method validateFactoryMethod(Method factoryMethod, Object testInstance) { + private static Method validateFactoryMethod(Method factoryMethod, @Nullable Object testInstance) { Preconditions.condition( factoryMethod.getDeclaringClass().isInstance(testInstance) || ReflectionUtils.isStatic(factoryMethod), () -> format("Method '%s' must be static: local factory methods must be static " diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/package-info.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/package-info.java index a41697ab81e3..adb442e423e5 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/package-info.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/package-info.java @@ -5,4 +5,7 @@ * annotations. */ +@NullMarked package org.junit.jupiter.params.provider; + +import org.jspecify.annotations.NullMarked; 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..bc38c6ee223a 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 @@ -13,6 +13,7 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.extension.Extension; import org.junit.jupiter.api.extension.ExtensionContext; @@ -68,6 +69,7 @@ public interface ParameterInfo { * {@return the closest {@code ParameterInfo} instance for the supplied * {@code ExtensionContext}; potentially {@code null}} */ + @Nullable static ParameterInfo get(ExtensionContext context) { return context.getStore(NAMESPACE).get(KEY, ParameterInfo.class); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/package-info.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/package-info.java index 56772a43120d..866ac5d3c0df 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/package-info.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/package-info.java @@ -6,4 +6,7 @@ * for arguments. */ +@NullMarked package org.junit.jupiter.params.support; + +import org.jspecify.annotations.NullMarked; diff --git a/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/ArgumentsAccessor.kt b/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/ArgumentsAccessor.kt index 7d06dc0aa071..d8a791419aef 100644 --- a/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/ArgumentsAccessor.kt +++ b/junit-jupiter-params/src/main/kotlin/org/junit/jupiter/params/aggregator/ArgumentsAccessor.kt @@ -26,4 +26,4 @@ import org.apiguardian.api.API */ @Suppress("EXTENSION_SHADOWED_BY_MEMBER") // method is in fact not shadowed due to reified type inline fun ArgumentsAccessor.get(index: Int): T = - this.get(index, T::class.java) + this.get(index, T::class.java)!! diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java index 2b62f8d691e3..ffcc99878b8f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java @@ -34,7 +34,7 @@ class ParameterInfoIntegrationTests extends AbstractJupiterTestEngineTests { void storesParameterInfoInExtensionContextStoreOnDifferentLevels() { var results = executeTestsForClass(TestCase.class); - results.allEvents().assertStatistics(stats -> stats.started(7).succeeded(7)); + results.allEvents().debug().assertStatistics(stats -> stats.started(7).succeeded(7)); } @ParameterizedClass diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt index c23606354350..95e8e08ab7f7 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-params.expected.txt @@ -6,6 +6,7 @@ exports org.junit.jupiter.params.provider exports org.junit.jupiter.params.support requires java.base mandated requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.jupiter.api transitive requires org.junit.platform.commons transitive qualified opens org.junit.jupiter.params to org.junit.platform.commons diff --git a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java index 4ff6591def9d..47dad8ed873e 100644 --- a/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java +++ b/platform-tooling-support-tests/src/archUnit/java/platform/tooling/support/tests/ArchUnitTests.java @@ -83,8 +83,7 @@ class ArchUnitTests { @ArchTest void packagesShouldBeNullMarked(JavaClasses classes) { var exclusions = Stream.of( // - "..shadow..", // - "org.junit.jupiter.params.." // + "..shadow.." // ).map(PackageMatcher::of).toList(); var subpackages = Stream.of("org.junit.platform", "org.junit.jupiter", "org.junit.vintage") // From 332308e6b4bbf8fc10b21d12e8f4cdc37485faf3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 22 May 2025 16:27:16 +0200 Subject: [PATCH 133/521] Add JSpecify to all module descriptors --- junit-jupiter-api/src/main/java/module-info.java | 3 +++ junit-jupiter-engine/src/main/java/module-info.java | 3 +++ .../src/main/java/module-info.java | 5 ++++- junit-platform-console/src/main/java/module-info.java | 3 +++ junit-platform-engine/src/main/java/module-info.java | 2 +- junit-platform-jfr/src/main/java/module-info.java | 5 ++++- junit-platform-launcher/src/main/java/module-info.java | 5 ++++- junit-platform-reporting/src/main/java/module-info.java | 5 ++++- junit-platform-suite-api/src/main/java/module-info.java | 3 +++ junit-platform-suite-commons/src/main/java/module-info.java | 3 +++ junit-platform-suite-engine/src/main/java/module-info.java | 3 +++ junit-platform-testkit/src/main/java/module-info.java | 3 +++ junit-vintage-engine/src/main/java/module-info.java | 5 ++++- .../jar-describe-module/junit-jupiter-api.expected.txt | 1 + .../jar-describe-module/junit-jupiter-engine.expected.txt | 1 + .../junit-jupiter-migrationsupport.expected.txt | 1 + .../jar-describe-module/junit-platform-console.expected.txt | 1 + .../jar-describe-module/junit-platform-engine.expected.txt | 2 +- .../jar-describe-module/junit-platform-jfr.expected.txt | 1 + .../jar-describe-module/junit-platform-launcher.expected.txt | 1 + .../junit-platform-reporting.expected.txt | 1 + .../junit-platform-suite-api.expected.txt | 1 + .../junit-platform-suite-commons.expected.txt | 1 + .../junit-platform-suite-engine.expected.txt | 1 + .../jar-describe-module/junit-platform-testkit.expected.txt | 1 + .../jar-describe-module/junit-vintage-engine.expected.txt | 1 + 26 files changed, 55 insertions(+), 7 deletions(-) diff --git a/junit-jupiter-api/src/main/java/module-info.java b/junit-jupiter-api/src/main/java/module-info.java index afb8f4cd5e45..2660f24f0d87 100644 --- a/junit-jupiter-api/src/main/java/module-info.java +++ b/junit-jupiter-api/src/main/java/module-info.java @@ -14,7 +14,10 @@ * @since 5.0 */ module org.junit.jupiter.api { + requires static transitive org.apiguardian.api; + requires static org.jspecify; + requires transitive org.junit.platform.commons; requires transitive org.opentest4j; diff --git a/junit-jupiter-engine/src/main/java/module-info.java b/junit-jupiter-engine/src/main/java/module-info.java index e8e188aad477..ac95e98aeb2f 100644 --- a/junit-jupiter-engine/src/main/java/module-info.java +++ b/junit-jupiter-engine/src/main/java/module-info.java @@ -18,7 +18,10 @@ * runs Jupiter based tests on the platform. */ module org.junit.jupiter.engine { + requires static org.apiguardian.api; + requires static org.jspecify; + requires org.junit.jupiter.api; requires org.junit.platform.commons; requires org.junit.platform.engine; diff --git a/junit-jupiter-migrationsupport/src/main/java/module-info.java b/junit-jupiter-migrationsupport/src/main/java/module-info.java index ced462bec0db..e89e043930e3 100644 --- a/junit-jupiter-migrationsupport/src/main/java/module-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/module-info.java @@ -14,8 +14,11 @@ * @since 5.0 */ module org.junit.jupiter.migrationsupport { - requires transitive junit; // 4 + requires static transitive org.apiguardian.api; + requires static org.jspecify; + + requires transitive junit; // 4 requires transitive org.junit.jupiter.api; requires org.junit.platform.commons; diff --git a/junit-platform-console/src/main/java/module-info.java b/junit-platform-console/src/main/java/module-info.java index 166aff5ee795..0fe1a03f0cf7 100644 --- a/junit-platform-console/src/main/java/module-info.java +++ b/junit-platform-console/src/main/java/module-info.java @@ -15,7 +15,10 @@ * @provides java.util.spi.ToolProvider */ module org.junit.platform.console { + requires static org.apiguardian.api; + requires static org.jspecify; + requires org.junit.platform.commons; requires org.junit.platform.engine; requires org.junit.platform.launcher; diff --git a/junit-platform-engine/src/main/java/module-info.java b/junit-platform-engine/src/main/java/module-info.java index c81836121c9c..d23c9872dad9 100644 --- a/junit-platform-engine/src/main/java/module-info.java +++ b/junit-platform-engine/src/main/java/module-info.java @@ -19,7 +19,7 @@ module org.junit.platform.engine { requires static transitive org.apiguardian.api; - requires static transitive org.jspecify; + requires static org.jspecify; requires transitive org.junit.platform.commons; requires transitive org.opentest4j; diff --git a/junit-platform-jfr/src/main/java/module-info.java b/junit-platform-jfr/src/main/java/module-info.java index 6f38bf063cf7..3125840a2da4 100644 --- a/junit-platform-jfr/src/main/java/module-info.java +++ b/junit-platform-jfr/src/main/java/module-info.java @@ -20,8 +20,11 @@ * @since 1.7 */ module org.junit.platform.jfr { - requires jdk.jfr; + requires static org.apiguardian.api; + requires static org.jspecify; + + requires jdk.jfr; requires org.junit.platform.engine; requires org.junit.platform.launcher; diff --git a/junit-platform-launcher/src/main/java/module-info.java b/junit-platform-launcher/src/main/java/module-info.java index e4e492183f5a..4aa548b40565 100644 --- a/junit-platform-launcher/src/main/java/module-info.java +++ b/junit-platform-launcher/src/main/java/module-info.java @@ -22,8 +22,11 @@ * @uses org.junit.platform.launcher.TestExecutionListener */ module org.junit.platform.launcher { - requires transitive java.logging; + requires static transitive org.apiguardian.api; + requires static org.jspecify; + + requires transitive java.logging; requires transitive org.junit.platform.commons; requires transitive org.junit.platform.engine; diff --git a/junit-platform-reporting/src/main/java/module-info.java b/junit-platform-reporting/src/main/java/module-info.java index f1fe8cd51dca..11202c5829c3 100644 --- a/junit-platform-reporting/src/main/java/module-info.java +++ b/junit-platform-reporting/src/main/java/module-info.java @@ -14,8 +14,11 @@ * @since 1.4 */ module org.junit.platform.reporting { - requires java.xml; + requires static transitive org.apiguardian.api; + requires static org.jspecify; + + requires java.xml; requires org.junit.platform.commons; requires transitive org.junit.platform.engine; requires transitive org.junit.platform.launcher; diff --git a/junit-platform-suite-api/src/main/java/module-info.java b/junit-platform-suite-api/src/main/java/module-info.java index 9d8df8da3cf0..690db0fe2d21 100644 --- a/junit-platform-suite-api/src/main/java/module-info.java +++ b/junit-platform-suite-api/src/main/java/module-info.java @@ -14,7 +14,10 @@ * @since 1.0 */ module org.junit.platform.suite.api { + requires static transitive org.apiguardian.api; + requires static org.jspecify; + requires transitive org.junit.platform.commons; exports org.junit.platform.suite.api; diff --git a/junit-platform-suite-commons/src/main/java/module-info.java b/junit-platform-suite-commons/src/main/java/module-info.java index 52c508bdace7..f0514a14064d 100644 --- a/junit-platform-suite-commons/src/main/java/module-info.java +++ b/junit-platform-suite-commons/src/main/java/module-info.java @@ -14,7 +14,10 @@ * @since 1.8 */ module org.junit.platform.suite.commons { + requires static transitive org.apiguardian.api; + requires static org.jspecify; + requires org.junit.platform.suite.api; requires org.junit.platform.commons; requires org.junit.platform.engine; diff --git a/junit-platform-suite-engine/src/main/java/module-info.java b/junit-platform-suite-engine/src/main/java/module-info.java index e8a43bf80e1c..e7e15543dba2 100644 --- a/junit-platform-suite-engine/src/main/java/module-info.java +++ b/junit-platform-suite-engine/src/main/java/module-info.java @@ -16,7 +16,10 @@ * @provides org.junit.platform.engine.TestEngine */ module org.junit.platform.suite.engine { + requires static org.apiguardian.api; + requires static org.jspecify; + requires org.junit.platform.suite.api; requires org.junit.platform.suite.commons; requires org.junit.platform.commons; diff --git a/junit-platform-testkit/src/main/java/module-info.java b/junit-platform-testkit/src/main/java/module-info.java index 58f2033bcf62..cbfbd2a41393 100644 --- a/junit-platform-testkit/src/main/java/module-info.java +++ b/junit-platform-testkit/src/main/java/module-info.java @@ -15,7 +15,10 @@ * @uses org.junit.platform.engine.TestEngine */ module org.junit.platform.testkit { + requires static transitive org.apiguardian.api; + requires static org.jspecify; + requires transitive org.assertj.core; requires org.junit.platform.commons; requires transitive org.junit.platform.engine; diff --git a/junit-vintage-engine/src/main/java/module-info.java b/junit-vintage-engine/src/main/java/module-info.java index 6880a39df91d..9c982e4cfa62 100644 --- a/junit-vintage-engine/src/main/java/module-info.java +++ b/junit-vintage-engine/src/main/java/module-info.java @@ -17,8 +17,11 @@ * runs JUnit 3 and 4 based tests on the platform. */ module org.junit.vintage.engine { - requires junit; // 4 + requires static org.apiguardian.api; + requires static org.jspecify; + + requires junit; // 4 requires org.junit.platform.engine; provides org.junit.platform.engine.TestEngine diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt index 673304bda14d..7fa1fa9cf145 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-api.expected.txt @@ -9,6 +9,7 @@ exports org.junit.jupiter.api.parallel requires java.base mandated requires kotlin.stdlib static requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.platform.commons transitive requires org.opentest4j transitive qualified opens org.junit.jupiter.api.condition to org.junit.platform.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt index 699fe7363234..65a155299cf8 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-engine.expected.txt @@ -1,6 +1,7 @@ org.junit.jupiter.engine@${version} jar:file:.+/junit-jupiter-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static +requires org.jspecify static requires org.junit.jupiter.api requires org.junit.platform.commons requires org.junit.platform.engine diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt index 4012e4139344..933d05fecf74 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-jupiter-migrationsupport.expected.txt @@ -7,5 +7,6 @@ exports org.junit.jupiter.migrationsupport.rules.member requires java.base mandated requires junit transitive requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.jupiter.api transitive requires org.junit.platform.commons diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt index 031b331cc0b3..01086247b6b6 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-console.expected.txt @@ -1,6 +1,7 @@ org.junit.platform.console@${version} jar:file:.+/junit-platform-console-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static +requires org.jspecify static requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt index 4997294a0477..cc88b0d84c7e 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-engine.expected.txt @@ -9,7 +9,7 @@ exports org.junit.platform.engine.support.hierarchical exports org.junit.platform.engine.support.store requires java.base mandated requires org.apiguardian.api static transitive -requires org.jspecify static transitive +requires org.jspecify static requires org.junit.platform.commons transitive requires org.opentest4j transitive uses org.junit.platform.engine.discovery.DiscoverySelectorIdentifierParser diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt index bc727ca43cf6..b8f85f92a64e 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-jfr.expected.txt @@ -2,6 +2,7 @@ org.junit.platform.jfr@${version} jar:file:.+/junit-platform-jfr-\d.+\.jar..modu requires java.base mandated requires jdk.jfr requires org.apiguardian.api static +requires org.jspecify static requires org.junit.platform.engine requires org.junit.platform.launcher provides org.junit.platform.launcher.LauncherDiscoveryListener with org.junit.platform.jfr.FlightRecordingDiscoveryListener 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 e8f16dfa1f46..71aff5462347 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 @@ -6,6 +6,7 @@ exports org.junit.platform.launcher.listeners.discovery requires java.base mandated requires java.logging transitive requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.platform.commons transitive requires org.junit.platform.engine transitive uses org.junit.platform.engine.TestEngine diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt index 6bd9a8b227c3..c9f06e55f62b 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-reporting.expected.txt @@ -5,6 +5,7 @@ exports org.junit.platform.reporting.open.xml requires java.base mandated requires java.xml requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.platform.commons requires org.junit.platform.engine transitive requires org.junit.platform.launcher transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt index 77c942f97f87..5b5b0b36a9b3 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-api.expected.txt @@ -2,4 +2,5 @@ org.junit.platform.suite.api@${version} jar:file:.+/junit-platform-suite-api-\d. exports org.junit.platform.suite.api requires java.base mandated requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.platform.commons transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt index 0d25ab3dc62b..1d5c6b9f584c 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-commons.expected.txt @@ -1,6 +1,7 @@ org.junit.platform.suite.commons@${version} jar:file:.+/junit-platform-suite-commons-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static transitive +requires org.jspecify static requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt index cca1aba09043..d655ec351ed3 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-suite-engine.expected.txt @@ -1,6 +1,7 @@ org.junit.platform.suite.engine@${version} jar:file:.+/junit-platform-suite-engine-\d.+\.jar..module-info\.class requires java.base mandated requires org.apiguardian.api static +requires org.jspecify static requires org.junit.platform.commons requires org.junit.platform.engine requires org.junit.platform.launcher diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt index da43a9f5bd2c..008e2f1caf0a 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-platform-testkit.expected.txt @@ -3,6 +3,7 @@ exports org.junit.platform.testkit.engine requires java.base mandated requires org.apiguardian.api static transitive requires org.assertj.core transitive +requires org.jspecify static requires org.junit.platform.commons requires org.junit.platform.engine transitive requires org.junit.platform.launcher transitive diff --git a/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt b/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt index f3b130c0aa8d..79a358e40a59 100644 --- a/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt +++ b/platform-tooling-support-tests/projects/jar-describe-module/junit-vintage-engine.expected.txt @@ -2,6 +2,7 @@ org.junit.vintage.engine@${version} jar:file:.+/junit-vintage-engine-\d.+\.jar.. requires java.base mandated requires junit requires org.apiguardian.api static +requires org.jspecify static requires org.junit.platform.engine provides org.junit.platform.engine.TestEngine with org.junit.vintage.engine.VintageTestEngine contains org.junit.vintage.engine From ba0f0b181326e9a8cc989aa8c665b5ff08b1eeaa Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 15:33:28 +0200 Subject: [PATCH 134/521] Enable NullAway in tests --- ...ld.java-nullability-conventions.gradle.kts | 9 ++ jupiter-tests/jupiter-tests.gradle.kts | 1 + .../jupiter/api/AssertAllAssertionsTests.java | 6 + .../api/AssertInstanceOfAssertionsTests.java | 3 +- .../api/AssertLinesMatchAssertionsTests.java | 2 +- .../api/AssertNullAssertionsTests.java | 9 +- .../api/AssertThrowsAssertionsTests.java | 1 + .../AssertThrowsExactlyAssertionsTests.java | 1 + ...ertTimeoutPreemptivelyAssertionsTests.java | 24 ++-- .../junit/jupiter/api/AssertionTestUtils.java | 28 +++-- .../junit/jupiter/api/AssumptionsTests.java | 7 +- .../api/DisplayNameGenerationTests.java | 16 +-- .../junit/jupiter/api/DynamicTestTests.java | 11 +- .../jupiter/api/FailAssertionsTests.java | 1 + .../junit/jupiter/api/IterableFactory.java | 7 +- .../AbstractExecutionConditionTests.java | 11 +- ...edIfEnvironmentVariableConditionTests.java | 3 + ...edIfEnvironmentVariableConditionTests.java | 4 + .../api/extension/KitchenSinkExtension.java | 1 + .../jupiter/api/extension/MediaTypeTests.java | 1 + .../TypeBasedParameterResolverTests.java | 12 +- .../parallel/ResourceLocksProviderTests.java | 5 +- .../engine/ClassTemplateInvocationTests.java | 3 + .../engine/DefaultExecutionModeTests.java | 7 +- .../engine/NestedWithInheritanceTests.java | 2 + .../NestedWithSeparateInheritanceTests.java | 9 +- .../junit/jupiter/engine/ReportingTests.java | 1 + .../engine/TestInstanceLifecycleTests.java | 24 +++- .../engine/TestTemplateInvocationTests.java | 5 +- .../DefaultJupiterConfigurationTests.java | 4 +- .../descriptor/DisplayNameUtilsTests.java | 1 + .../descriptor/ExtensionContextTests.java | 82 ++++++++------ .../descriptor/LauncherStoreFacadeTest.java | 1 + .../descriptor/LifecycleMethodUtilsTests.java | 2 + .../descriptor/ResourceAutoClosingTests.java | 4 +- .../TestFactoryTestDescriptorTests.java | 2 +- .../TestInstanceLifecycleUtilsTests.java | 1 + .../DiscoverySelectorResolverTests.java | 107 +++++++++--------- .../AbstractExecutableInvokerTests.java | 7 +- .../DefaultExecutableInvokerTests.java | 8 +- .../InterceptingExecutableInvokerTests.java | 7 +- .../ParameterResolutionUtilsTests.java | 29 +++-- .../engine/extension/AutoCloseTests.java | 4 + .../extension/BeforeAndAfterAllTests.java | 2 + .../extension/BeforeAndAfterEachTests.java | 3 + ...oreAndAfterTestExecutionCallbackTests.java | 5 +- .../engine/extension/CloseablePathTests.java | 12 +- .../ExtensionContextExecutionTests.java | 8 +- ...gistrationViaParametersAndFieldsTests.java | 11 +- .../engine/extension/OrderedClassTests.java | 13 ++- .../engine/extension/OrderedMethodTests.java | 18 +-- ...rogrammaticExtensionRegistrationTests.java | 7 +- .../SeparateThreadTimeoutInvocationTests.java | 1 + .../extension/TempDirectoryCleanupTests.java | 4 + .../TempDirectoryMetaAnnotationTests.java | 2 + .../engine/extension/TempDirectoryTests.java | 17 ++- .../extension/TestInstanceFactoryTests.java | 1 + .../TestReporterParameterResolverTests.java | 3 +- .../engine/extension/TestWatcherTests.java | 11 +- .../TimeoutExceptionFactoryTests.java | 1 + .../extension/TimeoutExtensionTests.java | 5 +- .../TimeoutInvocationFactoryTests.java | 3 + ...igrationSupportWithBothRuleTypesTests.java | 4 +- .../ParameterizedClassIntegrationTests.java | 37 +++--- ...meterizedInvocationNameFormatterTests.java | 5 +- .../ParameterizedTestExtensionTests.java | 22 ++-- .../ParameterizedTestIntegrationTests.java | 15 +-- .../AggregatorIntegrationTests.java | 12 +- .../DefaultArgumentsAccessorTests.java | 11 +- .../DefaultArgumentConverterTests.java | 9 +- .../JavaTimeArgumentConverterTests.java | 17 ++- .../TypedArgumentConverterTests.java | 6 +- ...AnnotationBasedArgumentsProviderTests.java | 1 + .../provider/CsvArgumentsProviderTests.java | 3 +- .../CsvFileArgumentsProviderTests.java | 3 +- .../provider/FieldArgumentsProviderTests.java | 2 + .../MethodArgumentsProviderTests.java | 22 ++-- .../AnnotationConsumerInitializerTests.java | 6 +- .../ParameterInfoIntegrationTests.java | 2 + platform-tests/platform-tests.gradle.kts | 1 + .../platform/commons/function/TryTests.java | 2 + .../support/AnnotationSupportTests.java | 12 +- .../commons/support/ClassSupportTests.java | 1 + .../commons/support/ModifierSupportTests.java | 9 ++ .../support/ReflectionSupportTests.java | 19 ++++ .../conversion/ConversionSupportTests.java | 16 +-- .../DefaultClasspathScannerTests.java | 5 + .../commons/util/AnnotationUtilsTests.java | 12 ++ .../commons/util/ClassLoaderUtilsTests.java | 2 + .../commons/util/CollectionUtilsTests.java | 7 +- .../commons/util/ExceptionUtilsTests.java | 3 + .../commons/util/FunctionUtilsTests.java | 2 + .../commons/util/PackageUtilsTests.java | 7 +- .../commons/util/ReflectionUtilsTests.java | 24 +++- .../commons/util/StringUtilsTests.java | 6 + .../commons/util/ToStringBuilderTests.java | 5 + .../console/ConsoleLauncherWrapperResult.java | 47 ++++---- .../CommandLineOptionsParsingTests.java | 5 +- .../CompositeTestDescriptorVisitorTests.java | 1 + .../junit/platform/engine/TestTagTests.java | 2 + .../platform/engine/UniqueIdFormatTests.java | 4 +- .../junit/platform/engine/UniqueIdTests.java | 2 + .../discovery/ClassNameFilterTests.java | 2 + .../discovery/DiscoverySelectorsTests.java | 25 +++- .../discovery/PackageNameFilterTests.java | 2 + .../PrefixedConfigurationParametersTests.java | 1 + .../support/descriptor/ClassSourceTests.java | 1 + .../ClasspathResourceSourceTests.java | 1 + .../descriptor/CompositeTestSourceTests.java | 1 + .../descriptor/DefaultUriSourceTests.java | 1 + .../descriptor/FileSystemSourceTests.java | 1 + .../support/descriptor/MethodSourceTests.java | 3 + .../descriptor/PackageSourceTests.java | 2 + .../descriptor/TestDescriptorTests.java | 3 +- ...elExecutionConfigurationStrategyTests.java | 4 + ...lHierarchicalTestExecutorServiceTests.java | 9 +- .../NamespacedHierarchicalStoreTests.java | 3 + .../platform/launcher/MethodFilterTests.java | 2 + .../platform/launcher/TagFilterTests.java | 7 +- .../launcher/core/DefaultLauncherTests.java | 8 +- .../core/ExecutionListenerAdapterTests.java | 4 + .../launcher/core/LauncherConfigTests.java | 1 + .../LauncherConfigurationParametersTests.java | 2 + .../launcher/core/LauncherFactoryTests.java | 5 +- .../launcher/core/ListenerRegistryTests.java | 10 +- .../launcher/core/StreamInterceptorTests.java | 2 + ...queIdTrackingListenerIntegrationTests.java | 6 +- ...eLauncherDiscoveryRequestBuilderTests.java | 2 +- .../platform/testkit/engine/EventsTests.java | 10 +- .../NestedContainerEventConditionTests.java | 1 + .../platform-tooling-support-tests.gradle.kts | 1 + 131 files changed, 779 insertions(+), 312 deletions(-) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index 294ad34bf6f3..82c449a807e4 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -29,5 +29,14 @@ tasks.withType().configureEach { tasks.compileTestJava { options.errorprone.nullaway { handleTestAssertionLibraries = true + excludedFieldAnnotations.addAll( + "org.junit.jupiter.api.io.TempDir", + "org.junit.jupiter.params.Parameter", + "org.junit.runners.Parameterized.Parameter", + "org.mockito.Captor", + "org.mockito.InjectMocks", + "org.mockito.Mock", + "org.mockito.Spy", + ) } } diff --git a/jupiter-tests/jupiter-tests.gradle.kts b/jupiter-tests/jupiter-tests.gradle.kts index dadeecfea33b..8c4526753061 100644 --- a/jupiter-tests/jupiter-tests.gradle.kts +++ b/jupiter-tests/jupiter-tests.gradle.kts @@ -2,6 +2,7 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE plugins { id("junitbuild.code-generator") + id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java index dac3a628fb17..f87e109281cf 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java @@ -38,31 +38,37 @@ */ class AssertAllAssertionsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void assertAllWithNullExecutableArray() { assertPrecondition("executables array must not be null or empty", () -> assertAll((Executable[]) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void assertAllWithNullExecutableCollection() { assertPrecondition("executables collection must not be null", () -> assertAll((Collection) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void assertAllWithNullExecutableStream() { assertPrecondition("executables stream must not be null", () -> assertAll((Stream) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void assertAllWithNullInExecutableArray() { assertPrecondition("individual executables must not be null", () -> assertAll((Executable) null)); } + @SuppressWarnings({ "NullAway" }) @Test void assertAllWithNullInExecutableCollection() { assertPrecondition("individual executables must not be null", () -> assertAll(asList((Executable) null))); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void assertAllWithNullInExecutableStream() { assertPrecondition("individual executables must not be null", () -> assertAll(Stream.of((Executable) null))); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java index ff666a7ef0f5..1e3fa189b858 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertInstanceOfAssertionsTests.java @@ -17,6 +17,7 @@ import java.io.IOException; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.opentest4j.AssertionFailedError; @@ -91,7 +92,7 @@ private void assertInstanceOfSucceeds(Class expectedType, Object actualVa assertSame(res, actualValue); } - private void assertInstanceOfFails(Class expectedType, Object actualValue, String unexpectedSort) { + private void assertInstanceOfFails(Class expectedType, @Nullable Object actualValue, String unexpectedSort) { String valueType = actualValue == null ? "null" : actualValue.getClass().getCanonicalName(); String expectedMessage = "Unexpected %s, expected: <%s> but was: <%s>".formatted(unexpectedSort, expectedType.getCanonicalName(), valueType); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java index 273b75d11276..a1d9720c7cda 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java @@ -95,7 +95,7 @@ void assertLinesMatchUsingFastForwardMarkerWithLimit3() { } @Test - @SuppressWarnings({ "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes", "DataFlowIssue", "NullAway" }) void assertLinesMatchWithNullFails() { assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(null, (List) null)); assertThrows(PreconditionViolationException.class, () -> assertLinesMatch(null, Collections.emptyList())); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java index e960d250a993..7ec74ae92ee3 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java @@ -18,6 +18,8 @@ import java.util.function.Supplier; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.opentest4j.AssertionFailedError; /** @@ -63,7 +65,8 @@ void assertNullWithNonNullObjectWithNullStringReturnedFromToStringAndMessageSupp } @SuppressWarnings("unused") - private void assertNullWithNonNullObjectWithNullStringReturnedFromToString(Supplier messageSupplier) { + private void assertNullWithNonNullObjectWithNullStringReturnedFromToString( + @Nullable Supplier messageSupplier) { String actual = "null"; try { if (messageSupplier == null) { @@ -94,7 +97,8 @@ void assertNullWithNonNullObjectWithNullReferenceReturnedFromToStringAndMessageS } @SuppressWarnings("unused") - private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString(Supplier messageSupplier) { + private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString( + @Nullable Supplier messageSupplier) { Object actual = new NullToString(); try { if (messageSupplier == null) { @@ -141,6 +145,7 @@ void assertNullWithNonNullObjectAndMessageSupplier() { } } + @NullUnmarked private static class NullToString { @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java index c1f5a003cbc4..9f9e3edf4131 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsAssertionsTests.java @@ -47,6 +47,7 @@ void assertThrowsWithMethodReferenceForNonVoidReturnType() { future.run(); ExecutionException exception = assertThrows(ExecutionException.class, future::get); + assertNotNull(exception.getCause()); assertEquals("boom", exception.getCause().getMessage()); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsExactlyAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsExactlyAssertionsTests.java index d167f4f08e43..ea683191e03e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsExactlyAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertThrowsExactlyAssertionsTests.java @@ -87,6 +87,7 @@ void assertThrowsWithMethodReferenceForNonVoidReturnType() { future.run(); ExecutionException exception = assertThrowsExactly(ExecutionException.class, future::get); + assertNotNull(exception.getCause()); assertEquals("boom", exception.getCause().getMessage()); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertTimeoutPreemptivelyAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertTimeoutPreemptivelyAssertionsTests.java index 303bbb3124fe..b7fb03847676 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertTimeoutPreemptivelyAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertTimeoutPreemptivelyAssertionsTests.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; import static org.junit.jupiter.api.condition.OS.WINDOWS; @@ -28,6 +27,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.platform.commons.util.ExceptionUtils; import org.opentest4j.AssertionFailedError; @@ -81,7 +81,7 @@ void assertTimeoutPreemptivelyForExecutableThatCompletesAfterTheTimeout() { () -> assertTimeoutPreemptively(PREEMPTIVE_TIMEOUT, this::waitForInterrupt)); assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test @@ -91,7 +91,7 @@ void assertTimeoutPreemptivelyWithMessageForExecutableThatCompletesAfterTheTimeo assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test @@ -102,7 +102,7 @@ void assertTimeoutPreemptivelyWithMessageSupplierForExecutableThatCompletesAfter assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test @@ -156,7 +156,7 @@ void assertTimeoutPreemptivelyForSupplierThatCompletesAfterTheTimeout() { assertMessageEquals(error, "execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test @@ -171,7 +171,7 @@ void assertTimeoutPreemptivelyWithMessageForSupplierThatCompletesAfterTheTimeout assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test @@ -186,15 +186,16 @@ void assertTimeoutPreemptivelyWithMessageSupplierForSupplierThatCompletesAfterTh assertMessageEquals(error, "Tempus Fugit ==> execution timed out after " + PREEMPTIVE_TIMEOUT.toMillis() + " ms"); assertMessageStartsWith(error.getCause(), "Execution timed out in "); - assertStackTraceContains(error.getCause().getStackTrace(), "CountDownLatch", "await"); + assertStackTraceContains(error.getCause(), "CountDownLatch", "await"); } @Test void assertTimeoutPreemptivelyUsesThreadsWithSpecificNamePrefix() { AtomicReference threadName = new AtomicReference<>(""); assertTimeoutPreemptively(ofMillis(1000), () -> threadName.set(Thread.currentThread().getName())); - assertTrue(threadName.get().startsWith("junit-timeout-thread-"), - "Thread name does not match the expected prefix"); + assertThat(threadName.get()) // + .withFailMessage("Thread name does not match the expected prefix") // + .startsWith("junit-timeout-thread-"); } @Test @@ -244,8 +245,9 @@ private void waitForInterrupt() { /** * Assert the given stack trace elements contain an element with the given class name and method name. */ - private static void assertStackTraceContains(StackTraceElement[] stackTrace, String className, String methodName) { - assertThat(stackTrace).anySatisfy(element -> { + private static void assertStackTraceContains(@Nullable Throwable throwable, String className, String methodName) { + assertThat(throwable).isNotNull(); + assertThat(throwable.getStackTrace()).anySatisfy(element -> { assertThat(element.getClassName()).endsWith(className); assertThat(element.getMethodName()).isEqualTo(methodName); }); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java index d961acd53496..a5bb7c0886a0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertionTestUtils.java @@ -13,6 +13,8 @@ import java.io.Serializable; import java.util.Objects; +import org.apache.groovy.parser.antlr4.util.StringUtils; +import org.jspecify.annotations.Nullable; import org.opentest4j.AssertionFailedError; import org.opentest4j.ValueWrapper; @@ -27,7 +29,7 @@ static void expectAssertionFailedError() { } static void assertEmptyMessage(Throwable ex) throws AssertionError { - if (!ex.getMessage().isEmpty()) { + if (!StringUtils.isEmpty(ex.getMessage())) { throw new AssertionError("Exception message should be empty, but was [" + ex.getMessage() + "]."); } } @@ -39,35 +41,41 @@ static void assertMessageEquals(Throwable ex, String msg) throws AssertionError } static void assertMessageMatches(Throwable ex, String regex) throws AssertionError { - if (!ex.getMessage().matches(regex)) { + if (ex.getMessage() == null || !ex.getMessage().matches(regex)) { throw new AssertionError("Exception message should match regular expression [" + regex + "], but was [" + ex.getMessage() + "]."); } } - static void assertMessageStartsWith(Throwable ex, String msg) throws AssertionError { - if (!ex.getMessage().startsWith(msg)) { + static void assertMessageStartsWith(@Nullable Throwable ex, String msg) throws AssertionError { + if (ex == null) { + throw new AssertionError("Cause should not have been null"); + } + if (ex.getMessage() == null || !ex.getMessage().startsWith(msg)) { throw new AssertionError( "Exception message should start with [" + msg + "], but was [" + ex.getMessage() + "]."); } } static void assertMessageEndsWith(Throwable ex, String msg) throws AssertionError { - if (!ex.getMessage().endsWith(msg)) { + if (ex.getMessage() == null || !ex.getMessage().endsWith(msg)) { throw new AssertionError( "Exception message should end with [" + msg + "], but was [" + ex.getMessage() + "]."); } } - static void assertMessageContains(Throwable ex, String msg) throws AssertionError { - if (!ex.getMessage().contains(msg)) { + static void assertMessageContains(@Nullable Throwable ex, String msg) throws AssertionError { + if (ex == null) { + throw new AssertionError("Cause should not have been null"); + } + if (ex.getMessage() == null || !ex.getMessage().contains(msg)) { throw new AssertionError( "Exception message should contain [" + msg + "], but was [" + ex.getMessage() + "]."); } } - static void assertExpectedAndActualValues(AssertionFailedError ex, Object expected, Object actual) - throws AssertionError { + static void assertExpectedAndActualValues(AssertionFailedError ex, @Nullable Object expected, + @Nullable Object actual) throws AssertionError { if (!wrapsEqualValue(ex.getExpected(), expected)) { throw new AssertionError("Expected value in AssertionFailedError should equal [" + ValueWrapper.create(expected) + "], but was [" + ex.getExpected() + "]."); @@ -78,7 +86,7 @@ static void assertExpectedAndActualValues(AssertionFailedError ex, Object expect } } - static boolean wrapsEqualValue(ValueWrapper wrapper, Object value) { + static boolean wrapsEqualValue(ValueWrapper wrapper, @Nullable Object value) { if (value == null || value instanceof Serializable) { return Objects.equals(value, wrapper.getValue()); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssumptionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssumptionsTests.java index 7aa35c56b634..499704bf6604 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssumptionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssumptionsTests.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Objects; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.opentest4j.TestAbortedException; @@ -216,11 +217,11 @@ void abortWithStringSupplier() { // ------------------------------------------------------------------- - private static void assertAssumptionFailure(String msg, Executable executable) { + private static void assertAssumptionFailure(@Nullable String msg, Executable executable) { assertTestAbortedException(msg == null ? "Assumption failed" : "Assumption failed: " + msg, executable); } - private static void assertTestAbortedException(String expectedMessage, Executable executable) { + private static void assertTestAbortedException(@Nullable String expectedMessage, Executable executable) { try { executable.execute(); expectTestAbortedException(); @@ -235,7 +236,7 @@ private static void expectTestAbortedException() { throw new AssertionError("Should have thrown a " + TestAbortedException.class.getName()); } - private static void assertMessageEquals(Throwable t, String expectedMessage) throws AssertionError { + private static void assertMessageEquals(Throwable t, @Nullable String expectedMessage) throws AssertionError { if (!Objects.equals(expectedMessage, t.getMessage())) { throw new AssertionError("Message in TestAbortedException should be [" + expectedMessage + "], but was [" + t.getMessage() + "]."); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/DisplayNameGenerationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/DisplayNameGenerationTests.java index 323470e59556..bf356db5d3ca 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/DisplayNameGenerationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/DisplayNameGenerationTests.java @@ -397,8 +397,6 @@ static class UnderscoreStyleInheritedFromSuperClassTestCase extends UnderscoreSt @DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) static class StackTestCase { - Stack stack; - @Test void is_instantiated_using_its_noarg_constructor() { new Stack<>(); @@ -407,6 +405,8 @@ void is_instantiated_using_its_noarg_constructor() { @Nested class A_new_stack { + Stack stack; + @BeforeEach void createNewStack() { stack = new Stack<>(); @@ -464,8 +464,6 @@ void peek_returns_that_element_without_removing_it_from_the_stack() { @IndicativeSentencesGeneration(generator = DisplayNameGenerator.ReplaceUnderscores.class) static class IndicativeGeneratorTestCase { - Stack stack; - @Test void is_instantiated_with_its_constructor() { new Stack<>(); @@ -474,6 +472,8 @@ void is_instantiated_with_its_constructor() { @Nested class when_new { + Stack stack; + @BeforeEach void create_with_new_stack() { stack = new Stack<>(); @@ -509,8 +509,6 @@ void is_no_longer_empty() { @IndicativeSentencesGeneration(separator = " >> ", generator = DisplayNameGenerator.ReplaceUnderscores.class) static class IndicativeGeneratorWithCustomSeparatorTestCase { - Stack stack; - @Test void is_instantiated_with_its_constructor() { new Stack<>(); @@ -519,6 +517,8 @@ void is_instantiated_with_its_constructor() { @Nested class when_new { + Stack stack; + @BeforeEach void create_with_new_stack() { stack = new Stack<>(); @@ -554,8 +554,6 @@ void is_no_longer_empty() { @IndicativeSentencesGeneration static class IndicativeGeneratorWithCustomSentenceFragmentsTestCase { - Stack stack; - @SentenceFragment("is instantiated with its constructor") @Test void instantiateViaConstructor() { @@ -566,6 +564,8 @@ void instantiateViaConstructor() { @Nested class NewStackTestCase { + Stack stack; + @BeforeEach void createNewStack() { stack = new Stack<>(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java index 073678ad4088..5f33ded5be82 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java @@ -27,6 +27,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.api.function.ThrowingConsumer; import org.junit.platform.commons.PreconditionViolationException; @@ -41,8 +42,9 @@ class DynamicTestTests { private static final Executable nix = () -> { }; - private final List assertedValues = new ArrayList<>(); + private final List<@Nullable String> assertedValues = new ArrayList<>(); + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromStreamPreconditions() { ThrowingConsumer testExecutor = input -> { @@ -57,6 +59,7 @@ void streamFromStreamPreconditions() { () -> DynamicTest.stream(Stream.empty(), displayNameGenerator, null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromIteratorPreconditions() { ThrowingConsumer testExecutor = input -> { @@ -71,6 +74,7 @@ void streamFromIteratorPreconditions() { () -> DynamicTest.stream(emptyIterator(), displayNameGenerator, null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromStreamWithNamesPreconditions() { ThrowingConsumer testExecutor = input -> { @@ -81,6 +85,7 @@ void streamFromStreamWithNamesPreconditions() { assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(Stream.empty(), null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromIteratorWithNamesPreconditions() { ThrowingConsumer testExecutor = input -> { @@ -91,12 +96,14 @@ void streamFromIteratorWithNamesPreconditions() { assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream(emptyIterator(), null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromStreamWithNamedExecutablesPreconditions() { assertThrows(PreconditionViolationException.class, () -> DynamicTest.stream((Stream) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamFromIteratorWithNamedExecutablesPreconditions() { assertThrows(PreconditionViolationException.class, @@ -170,7 +177,7 @@ private void assertStream(Stream stream) throws Throwable { assertThat(assertedValues).containsExactly("foo", "bar"); } - private void throwingConsumer(String str) throws Throwable { + private void throwingConsumer(@Nullable String str) throws Throwable { if ("baz".equals(str)) { throw new Throwable("Baz!"); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java index d549bbbed364..252a7974ba95 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java @@ -73,6 +73,7 @@ void failWithNullString() { } } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void failWithNullMessageSupplier() { try { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/IterableFactory.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/IterableFactory.java index 0dcb9c312037..ae363fe49c04 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/IterableFactory.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/IterableFactory.java @@ -15,13 +15,16 @@ import java.util.List; import java.util.Set; +import org.jspecify.annotations.Nullable; + final class IterableFactory { - static List listOf(Object... objects) { + @SuppressWarnings("NullableProblems") + static List listOf(@Nullable Object... objects) { return Arrays.asList(objects); } - static Set setOf(Object... objects) { + static Set setOf(@Nullable Object... objects) { return new LinkedHashSet<>(listOf(objects)); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java index bff8050468de..4b213419aad0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java @@ -12,6 +12,7 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.commons.support.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.support.ReflectionSupport.findMethod; @@ -27,6 +28,7 @@ import java.util.Optional; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -53,6 +55,7 @@ abstract class AbstractExecutionConditionTests { private final ExtensionContext context = mock(); + @Nullable private ConditionEvaluationResult result; @BeforeAll @@ -84,18 +87,22 @@ protected void evaluateCondition() { } protected void assertEnabled() { + assertNotNull(this.result); assertFalse(this.result.isDisabled(), "Should be enabled"); } protected void assertDisabled() { + assertNotNull(this.result); assertTrue(this.result.isDisabled(), "Should be disabled"); } protected void assertReasonContains(String text) { + assertNotNull(this.result); assertThat(this.result.getReason()).hasValueSatisfying(reason -> assertThat(reason).contains(text)); } protected void assertCustomDisabledReasonIs(String text) { + assertNotNull(this.result); if (this.result.isDisabled()) { assertThat(this.result.getReason()).hasValueSatisfying( reason -> assertThat(reason).contains(" ==> " + text)); @@ -103,11 +110,11 @@ protected void assertCustomDisabledReasonIs(String text) { } private Optional method(TestInfo testInfo) { - return method(getTestClass(), testInfo.getTestMethod().get().getName()); + return method(getTestClass(), testInfo.getTestMethod().orElseThrow().getName()); } private Optional method(Class testClass, String methodName) { - return Optional.of(findMethod(testClass, methodName).get()); + return Optional.of(findMethod(testClass, methodName).orElseThrow()); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java index c9c7434a5bea..68da1e4ea32e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java @@ -16,6 +16,7 @@ import static org.junit.jupiter.api.condition.DisabledIfEnvironmentVariableIntegrationTests.KEY1; import static org.junit.jupiter.api.condition.DisabledIfEnvironmentVariableIntegrationTests.KEY2; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; @@ -36,6 +37,7 @@ class DisabledIfEnvironmentVariableConditionTests extends AbstractExecutionCondi private ExecutionCondition condition = new DisabledIfEnvironmentVariableCondition() { @Override + @Nullable protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } @@ -99,6 +101,7 @@ void disabledBecauseEnvironmentVariableForComposedAnnotationMatchesExactly() { this.condition = new DisabledIfEnvironmentVariableCondition() { @Override + @Nullable protected String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java index db0116e38695..29fb1a913f76 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.KEY1; import static org.junit.jupiter.api.condition.EnabledIfEnvironmentVariableIntegrationTests.KEY2; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExecutionCondition; import org.junit.platform.commons.PreconditionViolationException; @@ -37,6 +38,7 @@ class EnabledIfEnvironmentVariableConditionTests extends AbstractExecutionCondit private ExecutionCondition condition = new EnabledIfEnvironmentVariableCondition() { @Override + @Nullable protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } @@ -100,6 +102,7 @@ void enabledBecauseBothEnvironmentVariablesMatchExactly() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override + @Nullable protected String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } @@ -141,6 +144,7 @@ void disabledBecauseEnvironmentVariableForComposedAnnotationDoesNotMatch() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override + @Nullable protected String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : KEY2.equals(name) ? BOGUS : null; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java index ada59dbdda55..ee8d1dba0729 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java @@ -30,6 +30,7 @@ * @since 5.0 * @see ExtensionComposabilityTests */ +@SuppressWarnings({ "DataFlowIssue", "NullAway" }) // @formatter:off public class KitchenSinkExtension implements diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/MediaTypeTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/MediaTypeTests.java index b1d06036b6fc..7e1bea151e7c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/MediaTypeTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/MediaTypeTests.java @@ -45,6 +45,7 @@ void parseWithInvalidMediaType() { assertEquals("Invalid media type: 'invalid'", exception.getMessage()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void parseWithNullMediaType() { var exception = assertThrows(PreconditionViolationException.class, () -> MediaType.parse(null)); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java index fb8c6b0ed0b2..a8b06d75f34b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolverTests.java @@ -56,20 +56,20 @@ void missingTypeTypeBasedParameterResolver() { @Test void supportsParameterForBasicTypes() { Parameter parameter1 = findParameterOfMethod("methodWithBasicTypeParameter", String.class); - assertTrue(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); - assertTrue(subClassedBasicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); + assertTrue(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), mock())); + assertTrue(subClassedBasicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), mock())); Parameter parameter2 = findParameterOfMethod("methodWithObjectParameter", Object.class); - assertFalse(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter2), null)); + assertFalse(basicTypeBasedParameterResolver.supportsParameter(parameterContext(parameter2), mock())); } @Test void supportsParameterForParameterizedTypes() { Parameter parameter1 = findParameterOfMethod("methodWithParameterizedTypeParameter", Map.class); - assertTrue(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), null)); + assertTrue(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter1), mock())); Parameter parameter3 = findParameterOfMethod("methodWithAnotherParameterizedTypeParameter", Map.class); - assertFalse(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter3), null)); + assertFalse(parametrizedTypeBasedParameterResolver.supportsParameter(parameterContext(parameter3), mock())); } @Test @@ -98,7 +98,7 @@ private static ExtensionContext extensionContext() { } private Parameter findParameterOfMethod(String methodName, Class... parameterTypes) { - Method method = ReflectionSupport.findMethod(Sample.class, methodName, parameterTypes).get(); + Method method = ReflectionSupport.findMethod(Sample.class, methodName, parameterTypes).orElseThrow(); return method.getParameters()[0]; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLocksProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLocksProviderTests.java index f5bc7a17b77b..750c886f429c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLocksProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLocksProviderTests.java @@ -11,6 +11,7 @@ package org.junit.jupiter.api.parallel; import static java.util.Collections.emptySet; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -24,6 +25,7 @@ import java.util.Set; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -115,6 +117,7 @@ static class Provider implements ResourceLocksProvider { private static boolean isProvideForNestedClassCalled = false; private static boolean isProvideForNestedTestMethodCalled = false; + @Nullable private Class testClass; @Override @@ -128,7 +131,7 @@ public Set provideForClass(Class testClass) { @Override public Set provideForNestedClass(List> enclosingInstanceTypes, Class testClass) { isProvideForNestedClassCalled = true; - assertEquals(List.of(this.testClass), enclosingInstanceTypes); + assertEquals(List.of(requireNonNull(this.testClass)), enclosingInstanceTypes); assertEquals(ClassLevelProviderTestCase.NestedClass.class, testClass); return emptySet(); } 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..3e3151b3155a 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 @@ -50,6 +50,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -1168,6 +1169,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override + @Nullable public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(Namespace.GLOBAL).get("someResource"); @@ -1431,6 +1433,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override + @Nullable public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(PreparingClassTemplateInvocationContextProvider.NAMESPACE).get("resource"); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/DefaultExecutionModeTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/DefaultExecutionModeTests.java index c67182cd7283..4857345b6cef 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/DefaultExecutionModeTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/DefaultExecutionModeTests.java @@ -19,6 +19,7 @@ import static org.junit.platform.engine.support.hierarchical.Node.ExecutionMode.SAME_THREAD; import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance; @@ -41,7 +42,7 @@ void defaultExecutionModeIsReadFromConfigurationParameter() { assertUsesExpectedExecutionMode(CONCURRENT, CONCURRENT); } - private void assertUsesExpectedExecutionMode(ExecutionMode defaultExecutionMode, + private void assertUsesExpectedExecutionMode(@Nullable ExecutionMode defaultExecutionMode, ExecutionMode expectedExecutionMode) { var engineDescriptor = discoverTestsWithDefaultExecutionMode(TestCase.class, defaultExecutionMode); assertExecutionModeRecursively(engineDescriptor, expectedExecutionMode); @@ -63,7 +64,7 @@ void annotationOverridesDefaultExecutionModeToSameThreadForAllDescendants() { } private void assertUsesExpectedExecutionModeForTestClassAndItsDescendants(Class testClass, - ExecutionMode defaultExecutionMode, ExecutionMode expectedExecutionMode) { + @Nullable ExecutionMode defaultExecutionMode, ExecutionMode expectedExecutionMode) { var engineDescriptor = discoverTestsWithDefaultExecutionMode(testClass, defaultExecutionMode); engineDescriptor.getChildren().forEach(child -> assertExecutionModeRecursively(child, expectedExecutionMode)); } @@ -104,7 +105,7 @@ void methodsInNestedTestClassesWithInstancePerClassInHierarchyHaveExecutionModeS } private JupiterEngineDescriptor discoverTestsWithDefaultExecutionMode(Class testClass, - ExecutionMode executionMode) { + @Nullable ExecutionMode executionMode) { LauncherDiscoveryRequestBuilder request = request().selectors(selectClass(testClass)); if (executionMode != null) { request.configurationParameter(Constants.DEFAULT_PARALLEL_EXECUTION_MODE, executionMode.name()); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithInheritanceTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithInheritanceTests.java index 3b3602e09fb8..64a75e51e58f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithInheritanceTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithInheritanceTests.java @@ -15,11 +15,13 @@ import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +@NullUnmarked class NestedWithInheritanceTests extends SuperClass { static List lifecycleInvokingClassNames; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java index b73cee268861..360bf5ae3f99 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java @@ -10,11 +10,13 @@ package org.junit.jupiter.engine; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -22,6 +24,7 @@ class NestedWithSeparateInheritanceTests extends SuperClass1 { + @Nullable static List lifecycleInvokingClassNames; static String OUTER = NestedWithSeparateInheritanceTests.class.getSimpleName(); @@ -59,7 +62,7 @@ static void setup() { @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); - NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); + requireNonNull(NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames).add(invokingClass); } } @@ -74,7 +77,7 @@ static void setup() { @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); - NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); + requireNonNull(NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames).add(invokingClass); } } @@ -89,7 +92,7 @@ static void setup() { @BeforeEach public void beforeEach() { String invokingClass = this.getClass().getSimpleName(); - NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames.add(invokingClass); + requireNonNull(NestedWithSeparateInheritanceTests.lifecycleInvokingClassNames).add(invokingClass); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ReportingTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ReportingTests.java index 7d69e5d8c932..7c9f0f9d035f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/ReportingTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/ReportingTests.java @@ -115,6 +115,7 @@ void succeedingTest(TestReporter reporter) { file -> Files.writeString(file, "succeedingTest")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void invalidReportData(TestReporter reporter) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestInstanceLifecycleTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestInstanceLifecycleTests.java index a360f0c8306e..185f903dc785 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestInstanceLifecycleTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestInstanceLifecycleTests.java @@ -34,6 +34,7 @@ import java.util.Objects; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -96,6 +97,7 @@ void init() { afterEachCount = 0; } + @SuppressWarnings("NullAway") @Test void instancePerMethod() { Class testClass = InstancePerMethodTestCase.class; @@ -181,6 +183,7 @@ void instancePerClassWithInheritedLifecycleMode() { instanceCounts(entry(SubInstancePerClassTestCase.class, 1))); } + @SuppressWarnings("NullAway") private void instancePerClass(Class testClass, Map.Entry, Integer>[] instances) { int containers = 3; int tests = 3; @@ -248,6 +251,7 @@ private void instancePerClass(Class testClass, Map.Entry, Integer>[] assertThat(lifecyclesMap.get(testClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); } + @SuppressWarnings("NullAway") @Test void instancePerMethodWithNestedTestClass() { Class testClass = InstancePerMethodOuterTestCase.class; @@ -370,6 +374,7 @@ void instancePerMethodWithNestedTestClass() { assertThat(lifecyclesMap.get(nestedTestClass).stream()).allMatch(Lifecycle.PER_METHOD::equals); } + @SuppressWarnings("NullAway") @Test void instancePerClassWithNestedTestClass() { Class testClass = InstancePerClassOuterTestCase.class; @@ -490,6 +495,7 @@ void instancePerClassWithNestedTestClass() { assertThat(lifecyclesMap.get(nestedTestClass).stream()).allMatch(Lifecycle.PER_CLASS::equals); } + @SuppressWarnings("NullAway") @Test void instancePerMethodOnOuterTestClassWithInstancePerClassOnNestedTestClass() { Class testClass = MixedLifecyclesOuterTestCase.class; @@ -676,7 +682,7 @@ private static void incrementInstanceCount(Class testClass) { instanceCount.compute(testClass, (key, value) -> value == null ? 1 : value + 1); } - private static String executionConditionKey(Class testClass, String testMethod) { + private static String executionConditionKey(Class testClass, @Nullable String testMethod) { return concat(ExecutionCondition.class, testClass, testMethod); } @@ -708,7 +714,7 @@ private static String testTemplateKey(Class testClass, String testMethod) { return concat(TestTemplateInvocationContextProvider.class, testClass, testMethod); } - private static String concat(Class c1, Class c2, String str) { + private static String concat(Class c1, Class c2, @Nullable String str) { return concat(c1.getSimpleName(), c2.getSimpleName(), str); } @@ -716,7 +722,7 @@ private static String concat(Class c1, Class c2) { return concat(c1.getSimpleName(), c2.getSimpleName()); } - private static String concat(String... args) { + private static String concat(@Nullable String... args) { return join(".", args); } @@ -814,6 +820,7 @@ static void beforeAll(TestInfo testInfo) { beforeAllCount++; } + @SuppressWarnings("NullAway") @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); @@ -839,18 +846,21 @@ void beforeEach() { beforeEachCount++; } + @SuppressWarnings("NullAway") @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); @@ -879,6 +889,7 @@ static void beforeAll(TestInfo testInfo) { beforeAllCount++; } + @SuppressWarnings("NullAway") @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); @@ -909,18 +920,21 @@ void beforeEach() { beforeEachCount++; } + @SuppressWarnings("NullAway") @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); @@ -955,6 +969,7 @@ void beforeEach() { beforeEachCount++; } + @SuppressWarnings("NullAway") @Test void outerTest() { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); @@ -984,18 +999,21 @@ void beforeEach() { beforeEachCount++; } + @SuppressWarnings("NullAway") @Test void test1(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @Test void test2(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); testsInvoked.add(testInfo.getTestMethod().get().getName()); } + @SuppressWarnings("NullAway") @SingletonTest void singletonTest(TestInfo testInfo) { assertSame(this, instanceMap.get(postProcessTestInstanceKey(getClass())).getInnermostInstance()); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java index 5cb6dba4dd82..ca3f839721d1 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java @@ -44,6 +44,7 @@ import java.util.stream.Stream; import org.assertj.core.api.Condition; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -499,6 +500,7 @@ void templateWithWrongParameterType(int parameter) { fail("never called: " + parameter); } + @Nullable String parameterInstanceVariable; @ExtendWith(StringParameterInjectingInvocationContextProvider.class) @@ -549,7 +551,7 @@ void template(String parameter) { static class TestTemplateTestClassWithBeforeAndAfterEach { - private static List lifecycleEvents = new ArrayList<>(); + private static final List lifecycleEvents = new ArrayList<>(); @BeforeAll static void beforeAll(TestInfo testInfo) { @@ -916,6 +918,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override + @Nullable public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(PreparingTestTemplateInvocationContextProvider.NAMESPACE).get("resource"); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java index ef7a98337044..af5fc8088059 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/config/DefaultJupiterConfigurationTests.java @@ -25,6 +25,7 @@ import java.util.Optional; import java.util.function.Supplier; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Test; @@ -42,6 +43,7 @@ class DefaultJupiterConfigurationTests { private static final String KEY = DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getDefaultTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, @@ -153,7 +155,7 @@ void shouldGetStandardAsDefaultTempDirFactorySupplierWithoutConfigParamSet() { assertThat(supplier.get()).isSameAs(TempDirFactory.Standard.INSTANCE); } - private void assertDefaultConfigParam(String configValue, Lifecycle expected) { + private void assertDefaultConfigParam(@Nullable String configValue, Lifecycle expected) { ConfigurationParameters configParams = mock(); when(configParams.get(KEY)).thenReturn(Optional.ofNullable(configValue)); Lifecycle lifecycle = new DefaultJupiterConfiguration(configParams, dummyOutputDirectoryProvider(), diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/DisplayNameUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/DisplayNameUtilsTests.java index ee7aa76cd0cd..b6252bb58ee2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/DisplayNameUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/DisplayNameUtilsTests.java @@ -227,6 +227,7 @@ class NestedTestCase { } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) static class NullDisplayNameGenerator implements DisplayNameGenerator { @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index 1d41630c244f..f48979ec7dff 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -37,6 +37,7 @@ import java.util.Set; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayNameGenerator; import org.junit.jupiter.api.Named; @@ -94,7 +95,7 @@ void setUp() { void fromJupiterEngineDescriptor() { var engineTestDescriptor = new JupiterEngineDescriptor(UniqueId.root("engine", "junit-jupiter"), configuration); - try (var engineContext = new JupiterEngineExtensionContext(null, engineTestDescriptor, configuration, + try (var engineContext = new JupiterEngineExtensionContext(mock(), engineTestDescriptor, configuration, extensionRegistry, launcherStoreFacade)) { // @formatter:off assertAll("engineContext", @@ -125,8 +126,10 @@ void fromClassTestDescriptor() { nestedClassDescriptor.addChild(doublyNestedClassDescriptor); nestedClassDescriptor.addChild(methodTestDescriptor); - var outerExtensionContext = new ClassExtensionContext(null, null, outerClassDescriptor, PER_METHOD, - configuration, extensionRegistry, launcherStoreFacade, null); + var parentExtensionContext = mock(AbstractExtensionContext.class); + + var outerExtensionContext = new ClassExtensionContext(parentExtensionContext, mock(), outerClassDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); // @formatter:off assertAll("outerContext", @@ -138,15 +141,15 @@ void fromClassTestDescriptor() { () -> assertThrows(PreconditionViolationException.class, outerExtensionContext::getRequiredTestInstance), () -> assertThrows(PreconditionViolationException.class, outerExtensionContext::getRequiredTestMethod), () -> assertThat(outerExtensionContext.getDisplayName()).isEqualTo(outerClassDescriptor.getDisplayName()), - () -> assertThat(outerExtensionContext.getParent()).isEmpty(), + () -> assertThat(outerExtensionContext.getParent()).containsSame(parentExtensionContext), () -> assertThat(outerExtensionContext.getExecutionMode()).isEqualTo(ExecutionMode.SAME_THREAD), () -> assertThat(outerExtensionContext.getExtensions(PreInterruptCallback.class)).isEmpty(), () -> assertThat(outerExtensionContext.getEnclosingTestClasses()).isEmpty() ); // @formatter:on - var nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, null, nestedClassDescriptor, - PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, null); + var nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, mock(), nestedClassDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); // @formatter:off assertAll("nestedContext", () -> assertThat(nestedExtensionContext.getParent()).containsSame(outerExtensionContext), @@ -155,8 +158,8 @@ void fromClassTestDescriptor() { ); // @formatter:on - var doublyNestedExtensionContext = new ClassExtensionContext(nestedExtensionContext, null, - doublyNestedClassDescriptor, PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, null); + var doublyNestedExtensionContext = new ClassExtensionContext(nestedExtensionContext, mock(), + doublyNestedClassDescriptor, PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); // @formatter:off assertAll("doublyNestedContext", () -> assertThat(doublyNestedExtensionContext.getParent()).containsSame(nestedExtensionContext), @@ -165,7 +168,7 @@ void fromClassTestDescriptor() { ); // @formatter:on - var methodExtensionContext = new MethodExtensionContext(nestedExtensionContext, null, methodTestDescriptor, + var methodExtensionContext = new MethodExtensionContext(nestedExtensionContext, mock(), methodTestDescriptor, configuration, extensionRegistry, launcherStoreFacade, new OpenTest4JAwareThrowableCollector()); // @formatter:off assertAll("methodContext", @@ -179,8 +182,8 @@ void fromClassTestDescriptor() { @Test void ExtensionContext_With_ExtensionRegistry_getExtensions() { var classTestDescriptor = nestedClassDescriptor(); - try (var ctx = new ClassExtensionContext(null, null, classTestDescriptor, PER_METHOD, configuration, - extensionRegistry, launcherStoreFacade, null)) { + try (var ctx = new ClassExtensionContext(mock(AbstractExtensionContext.class), mock(), classTestDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock())) { Extension ext = mock(); when(extensionRegistry.getExtensions(Extension.class)).thenReturn(List.of(ext)); @@ -197,22 +200,26 @@ void tagsCanBeRetrievedInExtensionContext() { var methodTestDescriptor = methodDescriptor(); outerClassDescriptor.addChild(methodTestDescriptor); - var outerExtensionContext = new ClassExtensionContext(null, null, outerClassDescriptor, PER_METHOD, - configuration, extensionRegistry, launcherStoreFacade, null); + var rootExtensionContext = new JupiterEngineExtensionContext(mock(), mock(), configuration, extensionRegistry, + launcherStoreFacade); + assertThat(rootExtensionContext.getRoot()).isSameAs(rootExtensionContext); + + var outerExtensionContext = new ClassExtensionContext(rootExtensionContext, mock(), outerClassDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); assertThat(outerExtensionContext.getTags()).containsExactly("outer-tag"); - assertThat(outerExtensionContext.getRoot()).isSameAs(outerExtensionContext); + assertThat(outerExtensionContext.getRoot()).isSameAs(rootExtensionContext); - var nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, null, nestedClassDescriptor, - PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, null); + var nestedExtensionContext = new ClassExtensionContext(outerExtensionContext, mock(), nestedClassDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); assertThat(nestedExtensionContext.getTags()).containsExactlyInAnyOrder("outer-tag", "nested-tag"); - assertThat(nestedExtensionContext.getRoot()).isSameAs(outerExtensionContext); + assertThat(nestedExtensionContext.getRoot()).isSameAs(rootExtensionContext); - var methodExtensionContext = new MethodExtensionContext(outerExtensionContext, null, methodTestDescriptor, + var methodExtensionContext = new MethodExtensionContext(outerExtensionContext, mock(), methodTestDescriptor, configuration, extensionRegistry, launcherStoreFacade, new OpenTest4JAwareThrowableCollector()); methodExtensionContext.setTestInstances(DefaultTestInstances.of(new OuterClassTestCase())); assertThat(methodExtensionContext.getTags()).containsExactlyInAnyOrder("outer-tag", "method-tag"); - assertThat(methodExtensionContext.getRoot()).isSameAs(outerExtensionContext); + assertThat(methodExtensionContext.getRoot()).isSameAs(rootExtensionContext); } @Test @@ -226,11 +233,11 @@ void fromMethodTestDescriptor() { Object testInstance = new OuterClassTestCase(); var testMethod = methodTestDescriptor.getTestMethod(); - var engineExtensionContext = new JupiterEngineExtensionContext(null, engineDescriptor, configuration, + var engineExtensionContext = new JupiterEngineExtensionContext(mock(), engineDescriptor, configuration, extensionRegistry, launcherStoreFacade); - var classExtensionContext = new ClassExtensionContext(engineExtensionContext, null, classTestDescriptor, - PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, null); - var methodExtensionContext = new MethodExtensionContext(classExtensionContext, null, methodTestDescriptor, + var classExtensionContext = new ClassExtensionContext(engineExtensionContext, mock(), classTestDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); + var methodExtensionContext = new MethodExtensionContext(classExtensionContext, mock(), methodTestDescriptor, configuration, extensionRegistry, launcherStoreFacade, new OpenTest4JAwareThrowableCollector()); methodExtensionContext.setTestInstances(DefaultTestInstances.of(testInstance)); @@ -255,10 +262,11 @@ void fromMethodTestDescriptor() { @Test @SuppressWarnings("resource") void reportEntriesArePublishedToExecutionListener() { - var classTestDescriptor = outerClassDescriptor(null); + var classTestDescriptor = outerClassDescriptor(mock()); var engineExecutionListener = spy(EngineExecutionListener.class); - ExtensionContext extensionContext = new ClassExtensionContext(null, engineExecutionListener, - classTestDescriptor, PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, null); + ExtensionContext extensionContext = new ClassExtensionContext(mock(AbstractExtensionContext.class), + engineExecutionListener, classTestDescriptor, PER_METHOD, configuration, extensionRegistry, + launcherStoreFacade, mock()); var map1 = Collections.singletonMap("key", "value"); var map2 = Collections.singletonMap("other key", "other value"); @@ -383,8 +391,8 @@ private ExtensionContext createExtensionContextForFilePublishing(Path tempDir, EngineExecutionListener engineExecutionListener, ClassTestDescriptor classTestDescriptor) { when(configuration.getOutputDirectoryProvider()) // .thenReturn(hierarchicalOutputDirectoryProvider(tempDir)); - return new ClassExtensionContext(null, engineExecutionListener, classTestDescriptor, PER_METHOD, configuration, - extensionRegistry, launcherStoreFacade, null); + return new ClassExtensionContext(mock(AbstractExtensionContext.class), engineExecutionListener, + classTestDescriptor, PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); } @Test @@ -392,9 +400,9 @@ private ExtensionContext createExtensionContextForFilePublishing(Path tempDir, void usingStore() { var methodTestDescriptor = methodDescriptor(); var classTestDescriptor = outerClassDescriptor(methodTestDescriptor); - ExtensionContext parentContext = new ClassExtensionContext(null, null, classTestDescriptor, PER_METHOD, - configuration, extensionRegistry, launcherStoreFacade, null); - var childContext = new MethodExtensionContext(parentContext, null, methodTestDescriptor, configuration, + ExtensionContext parentContext = new ClassExtensionContext(mock(AbstractExtensionContext.class), mock(), + classTestDescriptor, PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); + var childContext = new MethodExtensionContext(parentContext, mock(), methodTestDescriptor, configuration, extensionRegistry, launcherStoreFacade, new OpenTest4JAwareThrowableCollector()); childContext.setTestInstances(DefaultTestInstances.of(new OuterClassTestCase())); @@ -448,22 +456,22 @@ void configurationParameter(Function { var engineUniqueId = UniqueId.parse("[engine:junit-jupiter]"); var engineDescriptor = new JupiterEngineDescriptor(engineUniqueId, configuration); - return new JupiterEngineExtensionContext(null, engineDescriptor, configuration, extensionRegistry, + return new JupiterEngineExtensionContext(mock(), engineDescriptor, configuration, extensionRegistry, launcherStoreFacade); }), // named("class", (JupiterConfiguration configuration) -> { var classUniqueId = UniqueId.parse("[engine:junit-jupiter]/[class:MyClass]"); var classTestDescriptor = new ClassTestDescriptor(classUniqueId, testClass, configuration); - return new ClassExtensionContext(null, null, classTestDescriptor, PER_METHOD, configuration, - extensionRegistry, launcherStoreFacade, null); + return new ClassExtensionContext(mock(AbstractExtensionContext.class), mock(), classTestDescriptor, + PER_METHOD, configuration, extensionRegistry, launcherStoreFacade, mock()); }), // named("method", (JupiterConfiguration configuration) -> { var method = ReflectionSupport.findMethod(testClass, "extensionContextFactories").orElseThrow(); var methodUniqueId = UniqueId.parse("[engine:junit-jupiter]/[class:MyClass]/[method:myMethod]"); var methodTestDescriptor = new TestMethodTestDescriptor(methodUniqueId, testClass, method, List::of, configuration); - return new MethodExtensionContext(null, null, methodTestDescriptor, configuration, extensionRegistry, - launcherStoreFacade, null); + return new MethodExtensionContext(mock(AbstractExtensionContext.class), mock(), methodTestDescriptor, + configuration, extensionRegistry, launcherStoreFacade, mock()); }) // ); } @@ -478,7 +486,7 @@ private NestedClassTestDescriptor doublyNestedClassDescriptor() { OuterClassTestCase.NestedClass.DoublyNestedClass.class, List::of, configuration); } - private ClassTestDescriptor outerClassDescriptor(TestDescriptor child) { + private ClassTestDescriptor outerClassDescriptor(@Nullable TestDescriptor child) { var classTestDescriptor = new ClassTestDescriptor(UniqueId.root("class", "OuterClass"), OuterClassTestCase.class, configuration); if (child != null) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LauncherStoreFacadeTest.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LauncherStoreFacadeTest.java index e140cb7329d5..ae6d12135362 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LauncherStoreFacadeTest.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LauncherStoreFacadeTest.java @@ -79,6 +79,7 @@ void returnsNamespaceAwareStore() { assertNotNull(adapter); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void throwsExceptionWhenNamespaceIsNull() { LauncherStoreFacade facade = new LauncherStoreFacade(requestLevelStore); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtilsTests.java index d4f56b9b684f..44f67c95609f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtilsTests.java @@ -22,6 +22,7 @@ import java.util.ArrayList; import java.util.List; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -251,6 +252,7 @@ void eight() { } @SuppressWarnings("JUnitMalformedDeclaration") +@NullUnmarked class TestCaseWithInvalidLifecycleMethods { @BeforeEach diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java index ce217f3b838f..717c40b9e5f6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java @@ -39,7 +39,7 @@ void shouldCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsTrue() th AutoCloseableResource resource = new AutoCloseableResource(); when(configuration.isClosingStoredAutoCloseablesEnabled()).thenReturn(true); - ExtensionContext extensionContext = new JupiterEngineExtensionContext(null, testDescriptor, configuration, + ExtensionContext extensionContext = new JupiterEngineExtensionContext(mock(), testDescriptor, configuration, extensionRegistry, launcherStoreFacade); ExtensionContext.Store store = extensionContext.getStore(ExtensionContext.Namespace.GLOBAL); store.put("resource", resource); @@ -54,7 +54,7 @@ void shouldNotCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsFalse( AutoCloseableResource resource = new AutoCloseableResource(); when(configuration.isClosingStoredAutoCloseablesEnabled()).thenReturn(false); - ExtensionContext extensionContext = new JupiterEngineExtensionContext(null, testDescriptor, configuration, + ExtensionContext extensionContext = new JupiterEngineExtensionContext(mock(), testDescriptor, configuration, extensionRegistry, launcherStoreFacade); ExtensionContext.Store store = extensionContext.getStore(ExtensionContext.Namespace.GLOBAL); store.put("resource", resource); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java index d072738824d9..da14c6c3ae6c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java @@ -163,7 +163,7 @@ void before() throws Exception { extensionContext = mock(); isClosed = false; - context = new JupiterEngineExecutionContext(null, null, null) // + context = new JupiterEngineExecutionContext(mock(), mock(), mock()) // .extend() // .withThrowableCollector(new OpenTest4JAwareThrowableCollector()) // .withExtensionContext(extensionContext) // diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java index f16710ad35f7..2617a5153215 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestInstanceLifecycleUtilsTests.java @@ -48,6 +48,7 @@ class TestInstanceLifecycleUtilsTests { private static final String KEY = DEFAULT_TEST_INSTANCE_LIFECYCLE_PROPERTY_NAME; + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getTestInstanceLifecyclePreconditions() { PreconditionViolationException exception = assertThrows(PreconditionViolationException.class, diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java index 9833fa18cb43..7f6053f76105 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java @@ -54,6 +54,7 @@ import java.util.function.Predicate; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassTemplate; import org.junit.jupiter.api.DisplayNameGenerator; @@ -98,6 +99,8 @@ class DiscoverySelectorResolverTests extends AbstractJupiterTestEngineTests { private final JupiterConfiguration configuration = mock(); private final LauncherDiscoveryListener discoveryListener = mock(); + + @Nullable private TestDescriptor engineDescriptor; @BeforeEach @@ -111,7 +114,7 @@ void setUp() { void nonTestClassResolution() { resolve(request().selectors(selectClass(NonTestClass.class))); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); } @Test @@ -119,7 +122,7 @@ void doesNotAttemptToResolveMethodsForNonTestClasses() { var methodSelector = selectMethod(NonTestClass.class, "doesNotExist"); resolve(request().selectors(methodSelector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); assertUnresolved(methodSelector); } @@ -127,7 +130,7 @@ void doesNotAttemptToResolveMethodsForNonTestClasses() { void abstractClassResolution() { resolve(request().selectors(selectClass(AbstractTestClass.class))); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); assertUnresolved(selectClass(AbstractTestClass.class)); } @@ -137,7 +140,7 @@ void singleClassResolution() { resolve(request().selectors(selector)); - assertEquals(4, engineDescriptor.getDescendants().size()); + assertEquals(4, requireNonNull(engineDescriptor).getDescendants().size()); assertUniqueIdsForMyTestClass(uniqueIds()); } @@ -147,7 +150,7 @@ void classResolutionForNonexistentClass() { resolve(request().selectors(selector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow()).hasMessageContaining("Could not load class with name"); @@ -160,7 +163,7 @@ void duplicateClassSelectorOnlyResolvesOnce() { selectClass(MyTestClass.class) // )); - assertEquals(4, engineDescriptor.getDescendants().size()); + assertEquals(4, requireNonNull(engineDescriptor).getDescendants().size()); assertUniqueIdsForMyTestClass(uniqueIds()); } @@ -171,7 +174,7 @@ void twoClassesResolution() { resolve(request().selectors(selector1, selector2)); - assertEquals(7, engineDescriptor.getDescendants().size()); + assertEquals(7, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertUniqueIdsForMyTestClass(uniqueIds); assertThat(uniqueIds).contains(uniqueIdForClass(YourTestClass.class)); @@ -192,7 +195,7 @@ void classResolutionOfStaticNestedClass() { resolve(request().selectors(selector)); - assertEquals(3, engineDescriptor.getDescendants().size()); + assertEquals(3, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); @@ -217,7 +220,7 @@ void classResolutionOfClassTemplate() { assertThat(verified.get()).describedAs("filter can see descendants").isTrue(); - TestDescriptor classTemplateDescriptor = getOnlyElement(engineDescriptor.getChildren()); + TestDescriptor classTemplateDescriptor = getOnlyElement(requireNonNull(engineDescriptor).getChildren()); assertThat(classTemplateDescriptor.mayRegisterTests()).isTrue(); assertThat(classTemplateDescriptor.getDescendants()).isEmpty(); @@ -233,17 +236,17 @@ void uniqueIdResolutionOfClassTemplateInvocation() { resolve(request().selectors(selector)); - assertThat(engineDescriptor.getChildren()).hasSize(1); + assertThat(requireNonNull(engineDescriptor).getChildren()).hasSize(1); - TestDescriptor classTemplateDescriptor = getOnlyElement(engineDescriptor.getChildren()); + TestDescriptor classTemplateDescriptor = getOnlyElement(requireNonNull(engineDescriptor).getChildren()); classTemplateDescriptor.prune(); - assertThat(engineDescriptor.getChildren()).hasSize(1); + assertThat(requireNonNull(engineDescriptor).getChildren()).hasSize(1); assertThat(classTemplateDescriptor.mayRegisterTests()).isTrue(); assertThat(classTemplateDescriptor.getDescendants()).isEmpty(); classTemplateDescriptor.prune(); - assertThat(engineDescriptor.getChildren()).hasSize(1); + assertThat(requireNonNull(engineDescriptor).getChildren()).hasSize(1); assertThat(classTemplateDescriptor.mayRegisterTests()).isTrue(); assertThat(classTemplateDescriptor.getDescendants()).isEmpty(); } @@ -255,7 +258,7 @@ void methodResolution() throws NoSuchMethodException { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); @@ -267,7 +270,7 @@ void methodResolutionFromInheritedMethod() throws NoSuchMethodException { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(HerTestClass.class, "test1()")); @@ -280,7 +283,7 @@ void resolvingSelectorOfNonTestMethodResolvesNothing() throws NoSuchMethodExcept resolve(request().selectors(selector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); } @Test @@ -291,7 +294,7 @@ void methodResolutionForNonexistentClass() { resolve(request().selectors(selector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow())// @@ -305,7 +308,7 @@ void methodResolutionForNonexistentMethod() { resolve(request().selectors(selector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); var result = verifySelectorProcessed(selector); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow()).hasMessageContaining("Could not find method"); @@ -317,7 +320,7 @@ void classResolutionByUniqueId() { resolve(request().selectors(selector)); - assertEquals(4, engineDescriptor.getDescendants().size()); + assertEquals(4, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertUniqueIdsForMyTestClass(uniqueIds); } @@ -328,7 +331,7 @@ void staticNestedClassResolutionByUniqueId() { resolve(request().selectors(selector)); - assertEquals(3, engineDescriptor.getDescendants().size()); + assertEquals(3, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); @@ -342,7 +345,7 @@ void methodOfInnerClassByUniqueId() { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(OtherTestClass.NestedTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(OtherTestClass.NestedTestClass.class, "test5()")); @@ -355,7 +358,7 @@ void resolvingUniqueIdWithUnknownSegmentTypeResolvesNothing() { resolve(request().selectors(selector)); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); assertUnresolved(selector); } @@ -365,7 +368,7 @@ void resolvingUniqueIdOfNonTestMethodResolvesNothing() { resolve(request().selectors(selector)); - assertThat(engineDescriptor.getDescendants()).isEmpty(); + assertThat(requireNonNull(engineDescriptor).getDescendants()).isEmpty(); assertUnresolved(selector); } @@ -375,7 +378,7 @@ void methodResolutionByUniqueIdWithMissingMethodName() { resolve(request().selectors(selectUniqueId(uniqueId))); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow())// @@ -389,7 +392,7 @@ void methodResolutionByUniqueIdWithMissingParameters() { resolve(request().selectors(selectUniqueId(uniqueId))); - assertThat(engineDescriptor.getDescendants()).isEmpty(); + assertThat(requireNonNull(engineDescriptor).getDescendants()).isEmpty(); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow())// @@ -403,7 +406,7 @@ void methodResolutionByUniqueIdWithBogusParameters() { resolve(request().selectors(selectUniqueId(uniqueId))); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); var result = verifySelectorProcessed(selectUniqueId(uniqueId)); assertThat(result.getStatus()).isEqualTo(FAILED); assertThat(result.getThrowable().orElseThrow())// @@ -418,7 +421,7 @@ void methodResolutionByUniqueId() { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); @@ -430,7 +433,7 @@ void methodResolutionByUniqueIdFromInheritedClass() { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); @@ -444,7 +447,7 @@ void methodResolutionByUniqueIdWithParams() { resolve(request().selectors(selector)); - assertEquals(2, engineDescriptor.getDescendants().size()); + assertEquals(2, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(HerTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(HerTestClass.class, "test7(java.lang.String)")); @@ -457,7 +460,7 @@ void resolvingUniqueIdWithWrongParamsResolvesNothing() { resolve(request().selectors(selectUniqueId(uniqueId))); - assertTrue(engineDescriptor.getDescendants().isEmpty()); + assertTrue(requireNonNull(engineDescriptor).getDescendants().isEmpty()); assertUnresolved(selectUniqueId(uniqueId)); } @@ -469,7 +472,7 @@ void twoMethodResolutionsByUniqueId() { // adding same selector twice should have no effect resolve(request().selectors(selector1, selector2, selector2)); - assertEquals(3, engineDescriptor.getDescendants().size()); + assertEquals(3, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(MyTestClass.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(MyTestClass.class, "test1()")); @@ -490,7 +493,7 @@ void packageResolutionUsingExplicitBasePackage() { resolve(request().selectors(selector)); - assertEquals(6, engineDescriptor.getDescendants().size()); + assertEquals(6, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(Class1WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class1WithTestCases.class, "test1()")); @@ -505,7 +508,7 @@ void packageResolutionUsingDefaultPackage() throws Exception { resolve(request().selectors(selectPackage(""))); // 150 is completely arbitrary. The actual number is likely much higher. - assertThat(engineDescriptor.getDescendants())// + assertThat(requireNonNull(engineDescriptor).getDescendants())// .describedAs("Too few test descriptors in classpath")// .hasSizeGreaterThan(150); @@ -529,14 +532,14 @@ void classpathResolution() throws Exception { resolve(request().selectors(selectors)); // 150 is completely arbitrary. The actual number is likely much higher. - assertThat(engineDescriptor.getDescendants())// + assertThat(requireNonNull(engineDescriptor).getDescendants())// .describedAs("Too few test descriptors in classpath")// .hasSizeGreaterThan(150); List uniqueIds = uniqueIds(); assertThat(uniqueIds)// .describedAs("Failed to pick up DefaultPackageTestCase via classpath scanning")// - .contains(uniqueIdForClass(ReflectionSupport.tryToLoadClass("DefaultPackageTestCase").get())); + .contains(uniqueIdForClass(ReflectionSupport.tryToLoadClass("DefaultPackageTestCase").getNonNull())); assertThat(uniqueIds).contains(uniqueIdForClass(Class1WithTestCases.class)); assertThat(uniqueIds).contains(uniqueIdForMethod(Class1WithTestCases.class, "test1()")); assertThat(uniqueIds).contains(uniqueIdForClass(Class2WithTestCases.class)); @@ -641,7 +644,7 @@ void methodResolutionInDoubleNestedTestClass() throws NoSuchMethodException { resolve(request().selectors(selector)); - assertEquals(4, engineDescriptor.getDescendants().size()); + assertEquals(4, requireNonNull(engineDescriptor).getDescendants().size()); List uniqueIds = uniqueIds(); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.class)); assertThat(uniqueIds).contains(uniqueIdForClass(TestCaseWithNesting.NestedTestCase.class)); @@ -671,7 +674,7 @@ void testFactoryMethodResolutionByUniqueId() { resolve(request().selectors(selectUniqueId(factoryUid))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); } @@ -682,7 +685,7 @@ void testTemplateMethodResolutionByUniqueId() { resolve(request().selectors(selectUniqueId(templateUid))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), templateUid); } @@ -695,9 +698,9 @@ void resolvingDynamicTestByUniqueIdResolvesUpToParentTestFactory() { resolve(request().selectors(selectUniqueId(dynamicTestUid))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); - TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); + TestDescriptor testClassDescriptor = getOnlyElement(requireNonNull(engineDescriptor).getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); @@ -718,9 +721,9 @@ void resolvingDynamicContainerByUniqueIdResolvesUpToParentTestFactory() { resolve(request().selectors(selectUniqueId(dynamicTestUid))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); - TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); + TestDescriptor testClassDescriptor = getOnlyElement(requireNonNull(engineDescriptor).getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); @@ -739,9 +742,9 @@ void resolvingDynamicTestByUniqueIdAndTestFactoryByMethodSelectorResolvesTestFac resolve(request().selectors(selectUniqueId(dynamicTestUid), selectMethod(clazz, "dynamicTest"))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), factoryUid); - TestDescriptor testClassDescriptor = getOnlyElement(engineDescriptor.getChildren()); + TestDescriptor testClassDescriptor = getOnlyElement(requireNonNull(engineDescriptor).getChildren()); TestDescriptor testFactoryDescriptor = getOnlyElement(testClassDescriptor.getChildren()); DynamicDescendantFilter dynamicDescendantFilter = getDynamicDescendantFilter(testFactoryDescriptor); assertThat(dynamicDescendantFilter.test(UniqueId.root("foo", "bar"), 42)).isTrue(); @@ -760,7 +763,7 @@ void resolvingTestTemplateInvocationByUniqueIdResolvesOnlyUpToParentTestTemplate resolve(request().selectors(selectUniqueId(invocationUid))); - assertThat(engineDescriptor.getDescendants()).hasSize(2); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(2); assertThat(uniqueIds()).containsSequence(uniqueIdForClass(clazz), templateUid); } @@ -769,7 +772,7 @@ void includingPackageNameFilterExcludesClassesInNonMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( includePackageNames("org.junit.jupiter.engine.unknown"))); - assertThat(engineDescriptor.getDescendants()).isEmpty(); + assertThat(requireNonNull(engineDescriptor).getDescendants()).isEmpty(); } @Test @@ -777,7 +780,7 @@ void includingPackageNameFilterIncludesClassesInMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( includePackageNames("org.junit.jupiter.engine"))); - assertThat(engineDescriptor.getDescendants()).hasSize(3); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(3); } @Test @@ -785,7 +788,7 @@ void excludingPackageNameFilterExcludesClassesInMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( excludePackageNames("org.junit.jupiter.engine"))); - assertThat(engineDescriptor.getDescendants()).isEmpty(); + assertThat(requireNonNull(engineDescriptor).getDescendants()).isEmpty(); } @Test @@ -793,7 +796,7 @@ void excludingPackageNameFilterIncludesClassesInNonMatchingPackages() { resolve(request().selectors(selectClass(MatchingClass.class)).filters( excludePackageNames("org.junit.jupiter.engine.unknown"))); - assertThat(engineDescriptor.getDescendants()).hasSize(3); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(3); } @Test @@ -801,7 +804,7 @@ void classNamePatternFilterExcludesNonMatchingClasses() { resolve(request().selectors(selectClass(MatchingClass.class), selectClass(OtherClass.class)).filters( includeClassNamePatterns(".*MatchingClass"))); - assertThat(engineDescriptor.getDescendants()).hasSize(3); + assertThat(requireNonNull(engineDescriptor).getDescendants()).hasSize(3); } private void resolve(LauncherDiscoveryRequestBuilder builder) { @@ -809,12 +812,12 @@ private void resolve(LauncherDiscoveryRequestBuilder builder) { } private TestDescriptor descriptorByUniqueId(UniqueId uniqueId) { - return engineDescriptor.getDescendants().stream().filter( + return requireNonNull(engineDescriptor).getDescendants().stream().filter( d -> d.getUniqueId().equals(uniqueId)).findFirst().orElseThrow(); } private List uniqueIds() { - return engineDescriptor.getDescendants().stream().map(TestDescriptor::getUniqueId).toList(); + return requireNonNull(engineDescriptor).getDescendants().stream().map(TestDescriptor::getUniqueId).toList(); } private LauncherDiscoveryRequestBuilder request() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java index c054f3ec1220..18291aefb8d6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java @@ -23,6 +23,7 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Method; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolver; @@ -39,6 +40,8 @@ abstract class AbstractExecutableInvokerTests { private static final String ENIGMA = "enigma"; protected final MethodSource instance = mock(); + + @Nullable protected Method method; protected final ExtensionContext extensionContext = mock(); @@ -84,7 +87,7 @@ private void thereIsAParameterResolverThatResolvesTheParameterTo(Object argument private void testMethodWithASingleStringParameter() { this.method = ReflectionSupport.findMethod(this.instance.getClass(), "singleStringParameter", - String.class).get(); + String.class).orElseThrow(); } private void register(ParameterResolver... resolvers) { @@ -95,6 +98,6 @@ private void register(ParameterResolver... resolvers) { abstract void invokeMethod(); - abstract T invokeConstructor(Constructor constructor, Object outerInstance); + abstract T invokeConstructor(Constructor constructor, @Nullable Object outerInstance); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/DefaultExecutableInvokerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/DefaultExecutableInvokerTests.java index c9db82e0dd9c..27cc736eb43d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/DefaultExecutableInvokerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/DefaultExecutableInvokerTests.java @@ -10,8 +10,12 @@ package org.junit.jupiter.engine.execution; +import static java.util.Objects.requireNonNull; + import java.lang.reflect.Constructor; +import org.jspecify.annotations.Nullable; + /** * Unit tests for {@link DefaultExecutableInvoker}. * @@ -21,11 +25,11 @@ class DefaultExecutableInvokerTests extends AbstractExecutableInvokerTests { @Override void invokeMethod() { - newInvoker().invoke(this.method, this.instance); + newInvoker().invoke(requireNonNull(this.method), this.instance); } @Override - T invokeConstructor(Constructor constructor, Object outerInstance) { + T invokeConstructor(Constructor constructor, @Nullable Object outerInstance) { return newInvoker().invoke(constructor, outerInstance); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvokerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvokerTests.java index 58d96e0ecce1..a3abef9708e2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvokerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvokerTests.java @@ -10,10 +10,13 @@ package org.junit.jupiter.engine.execution; +import static java.util.Objects.requireNonNull; + import java.lang.reflect.Constructor; import java.lang.reflect.Executable; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; /** @@ -25,12 +28,12 @@ class InterceptingExecutableInvokerTests extends AbstractExecutableInvokerTests @Override void invokeMethod() { - newInvoker().invoke(this.method, this.instance, this.extensionContext, this.extensionRegistry, + newInvoker().invoke(requireNonNull(this.method), this.instance, this.extensionContext, this.extensionRegistry, passthroughInterceptor()); } @Override - T invokeConstructor(Constructor constructor, Object outerInstance) { + T invokeConstructor(Constructor constructor, @Nullable Object outerInstance) { return newInvoker().invoke(constructor, Optional.ofNullable(outerInstance), __ -> extensionContext, extensionRegistry, passthroughInterceptor()); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index 54e175b8bc6f..ab46ed9da2f4 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -10,6 +10,7 @@ package org.junit.jupiter.engine.execution; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -25,6 +26,7 @@ import java.util.function.Predicate; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -45,6 +47,8 @@ class ParameterResolutionUtilsTests { private static final String ENIGMA = "enigma"; private final MethodSource instance = mock(); + + @Nullable private Method method; private final ExtensionContext extensionContext = mock(); @@ -142,6 +146,7 @@ void onlyConsiderParameterResolversThatSupportAParticularParameter() { assertThat(arguments).containsExactly("something"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void passContextInformationToParameterResolverMethods() { anyTestMethodWithAtLeastOneParameter(); @@ -152,10 +157,10 @@ void passContextInformationToParameterResolverMethods() { assertSame(extensionContext, extension.supportsArguments.extensionContext); assertEquals(0, extension.supportsArguments.parameterContext.getIndex()); - assertSame(instance, extension.supportsArguments.parameterContext.getTarget().get()); + assertSame(instance, extension.supportsArguments.parameterContext.getTarget().orElseThrow()); assertSame(extensionContext, extension.resolveArguments.extensionContext); assertEquals(0, extension.resolveArguments.parameterContext.getIndex()); - assertSame(instance, extension.resolveArguments.parameterContext.getTarget().get()); + assertSame(instance, extension.resolveArguments.parameterContext.getTarget().orElseThrow()); assertThat(extension.resolveArguments.parameterContext.toString())// .contains("parameter", String.class.getTypeName(), "index", "0", "target", "Mock"); } @@ -289,7 +294,7 @@ private void throwDuringParameterResolution(RuntimeException parameterResolution register(ConfigurableParameterResolver.onAnyCallThrow(parameterResolutionException)); } - private void thereIsAParameterResolverThatResolvesTheParameterTo(Object argument) { + private void thereIsAParameterResolverThatResolvesTheParameterTo(@Nullable Object argument) { register(ConfigurableParameterResolver.supportsAndResolvesTo(parameterContext -> argument)); } @@ -323,14 +328,14 @@ private void register(ParameterResolver... resolvers) { } } - private Object[] resolveConstructorParameters(Class clazz, Object outerInstance) { + private @Nullable Object[] resolveConstructorParameters(Class clazz, @Nullable Object outerInstance) { Constructor constructor = ReflectionUtils.getDeclaredConstructor(clazz); return ParameterResolutionUtils.resolveParameters(constructor, Optional.empty(), Optional.ofNullable(outerInstance), extensionContext, extensionRegistry); } - private Object[] resolveMethodParameters() { - return ParameterResolutionUtils.resolveParameters(this.method, Optional.of(this.instance), + private @Nullable Object[] resolveMethodParameters() { + return ParameterResolutionUtils.resolveParameters(requireNonNull(this.method), Optional.of(this.instance), this.extensionContext, this.extensionRegistry); } @@ -338,8 +343,8 @@ private Object[] resolveMethodParameters() { static class ArgumentRecordingParameterResolver implements ParameterResolver { - ArgumentRecordingParameterResolver.Arguments supportsArguments; - ArgumentRecordingParameterResolver.Arguments resolveArguments; + ArgumentRecordingParameterResolver.@Nullable Arguments supportsArguments; + ArgumentRecordingParameterResolver.@Nullable Arguments resolveArguments; static class Arguments { @@ -359,6 +364,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override + @Nullable public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { resolveArguments = new ArgumentRecordingParameterResolver.Arguments(parameterContext, extensionContext); return null; @@ -375,7 +381,7 @@ static ParameterResolver onAnyCallThrow(RuntimeException runtimeException) { }); } - static ParameterResolver supportsAndResolvesTo(Function resolve) { + static ParameterResolver supportsAndResolvesTo(Function resolve) { return new ConfigurableParameterResolver(parameterContext -> true, resolve); } @@ -386,10 +392,10 @@ static ParameterResolver withoutSupport() { } private final Predicate supports; - private final Function resolve; + private final Function resolve; private ConfigurableParameterResolver(Predicate supports, - Function resolve) { + Function resolve) { this.supports = supports; this.resolve = resolve; } @@ -399,6 +405,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon return supports.test(parameterContext); } + @Nullable @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return resolve.apply(parameterContext); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java index 53b754d8b99b..2c2fc7476e13 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/AutoCloseTests.java @@ -28,6 +28,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AutoClose; import org.junit.jupiter.api.BeforeAll; @@ -422,6 +423,7 @@ static class ArrayFieldTestCase implements TestInterface { final int[] x = {}; } + @NullUnmarked static class NullCloseableFieldTestCase implements TestInterface { @AutoClose @@ -456,6 +458,7 @@ static class CloseMethodMustBeInvokedViaInterfaceTestCase implements TestInterfa @TestInstance(PER_METHOD) @SuppressWarnings("JUnitMalformedDeclaration") + @NullUnmarked static class InstancePerMethodTestCase { @AutoClose @@ -694,6 +697,7 @@ void nestedTest() { } } + @NullUnmarked static class AutoCloseSpy implements AutoCloseable, Runnable { private final String prefix; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java index 34ebef190656..0075ace93ab2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -38,6 +39,7 @@ class BeforeAndAfterAllTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); + @Nullable private static Optional actualExceptionInAfterAllCallback; @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java index 0b320af3dbb4..372f8199ff8b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java @@ -18,6 +18,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -42,8 +43,10 @@ class BeforeAndAfterEachTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); private static final List beforeEachMethodCallSequence = new ArrayList<>(); + @Nullable private static Optional actualExceptionInAfterEachCallback; + @SuppressWarnings("OptionalAssignedToNull") @BeforeEach void resetCallSequence() { callSequence.clear(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java index 119b2ecb6909..dd13d741e1ea 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java @@ -20,6 +20,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; @@ -42,10 +43,12 @@ */ class BeforeAndAfterTestExecutionCallbackTests extends AbstractJupiterTestEngineTests { - private static List callSequence = new ArrayList<>(); + private static final List callSequence = new ArrayList<>(); + @Nullable private static Optional actualExceptionInAfterTestExecution; + @SuppressWarnings("OptionalAssignedToNull") @BeforeEach void resetCallSequence() { callSequence.clear(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java index 5c66048d03f6..ad86b2cf460a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java @@ -52,6 +52,8 @@ import com.google.common.jimfs.Jimfs; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; @@ -68,6 +70,7 @@ import org.junit.jupiter.api.io.TempDirFactory; import org.junit.jupiter.engine.AbstractJupiterTestEngineTests; import org.junit.jupiter.engine.execution.NamespaceAwareStore; +import org.junit.jupiter.engine.extension.TempDirectory.CloseablePath; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; import org.junit.platform.commons.PreconditionViolationException; @@ -86,7 +89,8 @@ class CloseablePathTests extends AbstractJupiterTestEngineTests { private final AnnotatedElementContext elementContext = mock(); private final ExtensionContext extensionContext = mock(); - private TempDirectory.CloseablePath closeablePath; + @Nullable + private CloseablePath closeablePath; @Target(METHOD) @Retention(RUNTIME) @@ -164,6 +168,7 @@ void factoryReturnsDirectoryOnNonDefaultFileSystemWithPath() throws IOException delete(closeablePath.get()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @DisplayName("fails if the factory returns null") @ParameterizedTest @ElementTypeSource @@ -276,7 +281,9 @@ class Cleanup { @AfterEach void cleanupTempDirectory() throws IOException { - deleteIfExists(closeablePath.get()); + if (closeablePath != null) { + deleteIfExists(closeablePath.get()); + } } @DisplayName("is done for a cleanup mode of ALWAYS") @@ -457,6 +464,7 @@ void deletesSymbolicLinksTargetingDirOutsideTempDir(Class elementType, } } + @NullUnmarked static class TestCase { Path tempDir; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionContextExecutionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionContextExecutionTests.java index c3214cf18aad..5f3281917664 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionContextExecutionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionContextExecutionTests.java @@ -34,13 +34,13 @@ void extensionContextHierarchy(ExtensionContext methodExtensionContext) { Optional classExtensionContext = methodExtensionContext.getParent(); assertThat(classExtensionContext).isNotEmpty(); - assertThat(classExtensionContext.orElse(null).getElement()).contains(ExtensionContextExecutionTests.class); + assertThat(classExtensionContext.orElseThrow().getElement()).contains(ExtensionContextExecutionTests.class); - Optional engineExtensionContext = classExtensionContext.orElse(null).getParent(); + Optional engineExtensionContext = classExtensionContext.orElseThrow().getParent(); assertThat(engineExtensionContext).isNotEmpty(); - assertThat(engineExtensionContext.orElse(null).getElement()).isEmpty(); + assertThat(engineExtensionContext.orElseThrow().getElement()).isEmpty(); - assertThat(engineExtensionContext.orElse(null).getParent()).isEmpty(); + assertThat(engineExtensionContext.orElseThrow().getParent()).isEmpty(); } @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java index 0a72e2dd4212..7be354083dfc 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ExtensionRegistrationViaParametersAndFieldsTests.java @@ -40,6 +40,8 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -596,6 +598,7 @@ void test(Long number) { } } + @NullUnmarked static class MultipleExtendWithRegistrationsViaFieldTestCase { @SuppressWarnings("unused") @@ -623,6 +626,7 @@ void test() { /** * The {@link MagicField.Extension} is registered via a static field. */ + @NullUnmarked static class StaticFieldTestCase { @SuppressWarnings("unused") @@ -648,6 +652,7 @@ void test() { /** * The {@link MagicField.Extension} is registered via an instance field. */ + @NullUnmarked static class InstanceFieldTestCase { @MagicField @@ -667,6 +672,7 @@ void test() { * The {@link MagicField.Extension} is registered via a static field and * an instance field. */ + @NullUnmarked @TestInstance(Lifecycle.PER_CLASS) static class TestInstancePerClassFieldTestCase { @@ -689,6 +695,7 @@ void test() { } } + @NullUnmarked @TestInstance(Lifecycle.PER_METHOD) static class AllInOneWithTestInstancePerMethodTestCase { @@ -779,6 +786,7 @@ static class AllInOneWithTestInstancePerClassTestCase extends AllInOneWithTestIn } } + @NullUnmarked static class ProgrammaticTestInstancePostProcessorTestCase { @RegisterExtension @@ -954,7 +962,8 @@ public final void postProcessTestInstance(Object testInstance, ExtensionContext ModifierSupport::isNotStatic); } - private void injectFields(String trigger, Class testClass, Object instance, Predicate predicate) { + private void injectFields(String trigger, Class testClass, @Nullable Object instance, + Predicate predicate) { findAnnotatedFields(testClass, this.annotationType, predicate).forEach(field -> { try { makeAccessible(field).set(instance, trigger + " - " + field.getName()); 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..1954b93d35e0 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 @@ -23,6 +23,7 @@ import java.util.logging.LogRecord; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.ClassOrderer; @@ -209,12 +210,12 @@ private static void assertIneffectiveOrderAnnotationIssues(List .containsExactlyInAnyOrder(ClassSource.from(A_TestCase.class), ClassSource.from(C_TestCase.class)); } - private Events executeTests(Class classOrderer) { + private Events executeTests(@Nullable Class classOrderer) { return executeTests(classOrderer, selectClass(A_TestCase.class), selectClass(B_TestCase.class), selectClass(C_TestCase.class)); } - private Events executeTests(Class classOrderer, DiscoverySelector... selectors) { + private Events executeTests(@Nullable Class classOrderer, DiscoverySelector... selectors) { // @formatter:off return testKit(classOrderer, selectors) .execute() @@ -222,17 +223,17 @@ private Events executeTests(Class classOrderer, Discover // @formatter:on } - private EngineDiscoveryResults discoverTests(Class classOrderer) { + private EngineDiscoveryResults discoverTests(@Nullable Class classOrderer) { return discoverTests(classOrderer, selectClass(A_TestCase.class), selectClass(B_TestCase.class), selectClass(C_TestCase.class)); } - private EngineDiscoveryResults discoverTests(Class classOrderer, + private EngineDiscoveryResults discoverTests(@Nullable Class classOrderer, DiscoverySelector... selectors) { return testKit(classOrderer, selectors).discover(); } - private static EngineTestKit.Builder testKit(Class classOrderer, + private static EngineTestKit.Builder testKit(@Nullable Class classOrderer, DiscoverySelector[] selectors) { var testKit = EngineTestKit.engine("junit-jupiter"); @@ -246,7 +247,7 @@ static abstract class BaseTestCase { @BeforeEach void trackInvocations(TestInfo testInfo) { - var testClass = testInfo.getTestClass().get(); + var testClass = testInfo.getTestClass().orElseThrow(); callSequence.add(testClass.getSimpleName()); } 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 3085d59cb66c..bd1b61c9446b 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 @@ -34,6 +34,7 @@ import java.util.logging.LogRecord; import java.util.regex.Pattern; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DynamicTest; @@ -323,23 +324,24 @@ void misbehavingMethodOrdererThatRemovesElements() { .containsSubsequence("test2()", "test4()");// removed item is re-added before ordered item } - private EngineDiscoveryResults discoverTests(Class testClass, Class defaultOrderer) { + private EngineDiscoveryResults discoverTests(Class testClass, + @Nullable Class defaultOrderer) { return testKit(testClass, defaultOrderer, Severity.INFO).discover(); } - private Events executeTestsInParallel(Class testClass, Class defaultOrderer) { + private Events executeTestsInParallel(Class testClass, @Nullable Class defaultOrderer) { return executeTestsInParallel(testClass, defaultOrderer, Severity.INFO); } - private Events executeTestsInParallel(Class testClass, Class defaultOrderer, + private Events executeTestsInParallel(Class testClass, @Nullable Class defaultOrderer, Severity criticalSeverity) { return testKit(testClass, defaultOrderer, criticalSeverity) // .execute() // .testEvents(); } - private static EngineTestKit.Builder testKit(Class testClass, Class defaultOrderer, - Severity criticalSeverity) { + private static EngineTestKit.Builder testKit(Class testClass, + @Nullable Class defaultOrderer, Severity criticalSeverity) { var testKit = EngineTestKit.engine("junit-jupiter") // .configurationParameter(PARALLEL_EXECUTION_ENABLED_PROPERTY_NAME, "true") // .configurationParameter(DEFAULT_PARALLEL_EXECUTION_MODE, "concurrent") // @@ -740,7 +742,7 @@ public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().set(1, createMethodDescriptorImpersonator(method2)); } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "DataFlowIssue", "NullAway" }) static T createMethodDescriptorImpersonator(MethodDescriptor method) { MethodDescriptor stub = new MethodDescriptor() { @Override @@ -760,12 +762,12 @@ public boolean isAnnotated(Class annotationType) { @Override public Optional findAnnotation(Class annotationType) { - return null; + return Optional.empty(); } @Override public List findRepeatableAnnotations(Class annotationType) { - return null; + return List.of(); } @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java index e168d58cc974..49519b77b131 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java @@ -29,6 +29,8 @@ import java.util.function.Predicate; import org.assertj.core.api.Condition; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -221,7 +223,7 @@ void classLevelWithNonExtensionFieldValue() { instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, String.class)))); } - private String expectedMessage(Class testClass, Class valueType) { + private String expectedMessage(Class testClass, @Nullable Class valueType) { return "Failed to register extension via @RegisterExtension field [" + field(testClass) + "]: field value's type [" + (valueType != null ? valueType.getName() : null) + "] must implement an [" + Extension.class.getName() + "] API."; @@ -324,6 +326,7 @@ void afterEach(String wisdom) { @SuppressWarnings("JUnitMalformedDeclaration") @ExtendWith(ExtensionInjector.class) + @NullUnmarked static class InstanceLevelExtensionRegistrationWithInjectedExtensionTestCase { @RegisterExtension @@ -629,6 +632,7 @@ static class ClassLevelExtensionRegistrationWithPrivateFieldTestCase extends Abs } + @NullUnmarked static class InstanceLevelExtensionRegistrationWithNullFieldTestCase extends AbstractTestCase { @RegisterExtension @@ -636,6 +640,7 @@ static class InstanceLevelExtensionRegistrationWithNullFieldTestCase extends Abs } + @NullUnmarked static class ClassLevelExtensionRegistrationWithNullFieldTestCase extends AbstractTestCase { @RegisterExtension diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java index 04e2735f4805..b74afe95b6ec 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java @@ -36,6 +36,7 @@ class SeparateThreadTimeoutInvocationTests { private static final long PREEMPTIVE_TIMEOUT_MILLIS = WINDOWS.isCurrentOs() ? 1000 : 100; + @SuppressWarnings("NullAway") @Test @DisplayName("throws timeout exception when timeout duration is exceeded") void throwsTimeoutException() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java index b8d0b90468aa..5619832335ba 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryCleanupTests.java @@ -27,6 +27,7 @@ import java.util.logging.Level; import java.util.logging.LogRecord; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Nested; @@ -53,6 +54,7 @@ class TempDirectoryCleanupTests extends AbstractJupiterTestEngineTests { @Nested + @NullUnmarked class TempDirFieldTests { private static Path defaultFieldDir; @@ -315,6 +317,7 @@ void passingTest(@TempDir(cleanup = ON_SUCCESS) Path tempDir) { } @Nested + @NullUnmarked class TempDirParameterTests { private static Path defaultParameterDir; @@ -539,6 +542,7 @@ void doesNotFollowJunctions(@TempDir Path tempDir, @TrackLogRecords LogRecordLis } @SuppressWarnings("JUnitMalformedDeclaration") + @NullUnmarked static class JunctionTestCase { public static Path target; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryMetaAnnotationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryMetaAnnotationTests.java index 338ba7dd286a..7e93ae45728f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryMetaAnnotationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryMetaAnnotationTests.java @@ -19,6 +19,7 @@ import java.nio.file.Files; import java.nio.file.Path; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -45,6 +46,7 @@ void annotationOnParameter() { } @SuppressWarnings("JUnitMalformedDeclaration") + @NullUnmarked static class AnnotationOnFieldTestCase { @CustomTempDir diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java index 394f7005e298..ea21ce0abe14 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TempDirectoryTests.java @@ -14,6 +14,7 @@ import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -51,6 +52,8 @@ import com.google.common.jimfs.Jimfs; import org.assertj.core.api.Condition; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -110,6 +113,7 @@ void resetStaticVariables() { AllPossibleDeclarationLocationsTestCase.tempDirs.clear(); } + @SuppressWarnings("NullAway") @ParameterizedTest(name = "{0}") @EnumSource(TestInstance.Lifecycle.class) @DisplayName("resolves separate temp dirs for each annotation declaration") @@ -352,6 +356,7 @@ void doesNotSupportCustomDefaultTempDirFactoryNotReturningDirectory() { private static class FactoryNotReturningDirectory implements TempDirFactory { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) { return null; @@ -1112,6 +1117,7 @@ void deeplyNested() { } @SuppressWarnings("JUnitMalformedDeclaration") + @NullUnmarked static class StaticTempDirUsageInsideNestedClassTestCase { @TempDir @@ -1308,6 +1314,7 @@ void test(@TempDir(factory = Factory.class) Path tempDir) { private static class Factory implements TempDirFactory { + @Nullable private static Path parent; private Factory() throws IOException { @@ -1317,7 +1324,7 @@ private Factory() throws IOException { @Override public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) throws Exception { - return Files.createTempDirectory(parent, "prefix"); + return Files.createTempDirectory(requireNonNull(parent), "prefix"); } } @@ -1334,6 +1341,7 @@ void test(@TempDir(factory = Factory.class) Path tempDir) { private static class Factory implements TempDirFactory { + @Nullable private static FileSystem fileSystem; @Override @@ -1345,7 +1353,7 @@ public Path createTempDirectory(AnnotatedElementContext elementContext, Extensio @Override public void close() throws IOException { - fileSystem.close(); + requireNonNull(fileSystem).close(); fileSystem = null; } } @@ -1363,6 +1371,7 @@ void test(@TempDir(factory = Factory.class) Path tempDir) { private static class Factory implements TempDirFactory { + @Nullable private static FileSystem fileSystem; @Override @@ -1374,7 +1383,7 @@ public Path createTempDirectory(AnnotatedElementContext elementContext, Extensio @Override public void close() throws IOException { - fileSystem.close(); + requireNonNull(fileSystem).close(); fileSystem = null; } } @@ -1410,6 +1419,7 @@ private static String getName(AnnotatedElement element) { } @SuppressWarnings("JUnitMalformedDeclaration") + @NullUnmarked static class FactoryWithCustomMetaAnnotationTestCase { @TempDirForField @@ -1464,6 +1474,7 @@ void test(@SuppressWarnings("unused") @TempDir(factory = Factory.class) Path tem // never called } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) private static class Factory implements TempDirFactory { @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstanceFactoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstanceFactoryTests.java index 8433ad7f5824..ac92484ef037 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstanceFactoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestInstanceFactoryTests.java @@ -775,6 +775,7 @@ private static class LegacyInstanceFactory extends AbstractTestInstanceFactory { */ private static class NullTestInstanceFactory implements TestInstanceFactory { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { return null; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestReporterParameterResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestReporterParameterResolverTests.java index f785fb791744..c6b811a1d684 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestReporterParameterResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestReporterParameterResolverTests.java @@ -31,6 +31,7 @@ class TestReporterParameterResolverTests { TestReporterParameterResolver resolver = new TestReporterParameterResolver(); + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void supports() { Parameter parameter1 = findParameterOfMethod("methodWithTestReporterParameter", TestReporter.class); @@ -49,7 +50,7 @@ void resolve() { } private Parameter findParameterOfMethod(String methodName, Class... parameterTypes) { - Method method = ReflectionSupport.findMethod(Sample.class, methodName, parameterTypes).get(); + Method method = ReflectionSupport.findMethod(Sample.class, methodName, parameterTypes).orElseThrow(); return method.getParameters()[0]; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java index 05d318c12418..49a3bb073554 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java @@ -30,6 +30,7 @@ import java.util.logging.LogRecord; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; @@ -385,12 +386,12 @@ public void testSuccessful(ExtensionContext context) { } @Override - public void testAborted(ExtensionContext context, Throwable cause) { + public void testAborted(ExtensionContext context, @Nullable Throwable cause) { trackResult("testAborted", context); } @Override - public void testFailed(ExtensionContext context, Throwable cause) { + public void testFailed(ExtensionContext context, @Nullable Throwable cause) { trackResult("testFailed", context); } @@ -419,12 +420,12 @@ public void testDisabled(ExtensionContext context, Optional reason) { } @Override - public void testAborted(ExtensionContext context, Throwable cause) { + public void testAborted(ExtensionContext context, @Nullable Throwable cause) { throw new JUnitException("Exception in testAborted()"); } @Override - public void testFailed(ExtensionContext context, Throwable cause) { + public void testFailed(ExtensionContext context, @Nullable Throwable cause) { throw new JUnitException("Exception in testFailed()"); } @@ -440,7 +441,7 @@ static class DataRetrievingTestWatcher implements BeforeTestExecutionCallback, T private static final String KEY = "key"; - private static final Map results = new HashMap<>(); + private static final Map results = new HashMap<>(); @Override public void beforeTestExecution(ExtensionContext context) throws Exception { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java index 3c5c5a29602e..5e0ef939dd0a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java @@ -51,6 +51,7 @@ void createExceptionWithMethodSignatureTimeoutAndThrowable() { .hasSuppressedException(suppressedException); } + @SuppressWarnings({ "DataFlowIssue", "NullAway", "ThrowableNotThrown" }) @Nested @DisplayName("throws exception when") class ThrowException { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExtensionTests.java index 8cfd1f1c24d3..b88fcfac4343 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExtensionTests.java @@ -37,6 +37,7 @@ import java.util.concurrent.TimeoutException; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -340,7 +341,8 @@ void reportsIllegalTimeoutDurations() { private static Execution findExecution(Events events, String displayName) { return events.executions()// .filter(execution -> execution.getTestDescriptor().getDisplayName().contains(displayName))// - .findFirst().get(); + .findFirst() // + .orElseThrow(); } @Nested @@ -618,6 +620,7 @@ void methodThatDoesNotThrowInterruptedException() { @SuppressWarnings("JUnitMalformedDeclaration") static class PlainTestCase { + @Nullable public static String slowMethod; @BeforeAll 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..87a1b0358298 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 @@ -61,6 +61,7 @@ void setUp() { timeoutInvocationFactory = new TimeoutInvocationFactory(store); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("throws exception when null store is provided on create") void shouldThrowExceptionWhenInstantiatingWithNullStore() { @@ -68,6 +69,7 @@ void shouldThrowExceptionWhenInstantiatingWithNullStore() { .hasMessage("store must not be null"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("throws exception when null timeout thread mode is provided on create") void shouldThrowExceptionWhenNullTimeoutThreadModeIsProvidedWhenCreate() { @@ -75,6 +77,7 @@ void shouldThrowExceptionWhenNullTimeoutThreadModeIsProvidedWhenCreate() { .hasMessage("thread mode must not be null"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("throws exception when null timeout invocation parameters is provided on create") void shouldThrowExceptionWhenNullTimeoutInvocationParametersIsProvidedWhenCreate() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java index ba149cdf0e1b..1ad5ee93778d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java @@ -16,6 +16,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.migrationsupport.rules.FailAfterAllHelper.fail; +import org.jspecify.annotations.Nullable; import org.junit.Rule; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; @@ -52,6 +53,7 @@ public ExternalResource getResource2() { numberOfRule2InstancesCreated++; } + @Nullable private Object instance; @Override @@ -63,7 +65,7 @@ protected void before() { @Override protected void after() { assertNotNull(instance); - assertSame(instance, this); + assertSame(this, instance); afterOfRule2WasExecuted = true; } }; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java index 7d7946553b5e..f8dc13677f1f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedClassIntegrationTests.java @@ -11,6 +11,7 @@ package org.junit.jupiter.params; import static java.util.Comparator.comparing; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.tuple; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -56,6 +57,7 @@ import java.util.stream.Stream; import org.assertj.core.api.Condition; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -944,11 +946,13 @@ static class FieldInjectionWithRegisteredConversionTestCase { @Test void test1() { + assertNotNull(value); assertTrue(value.startsWith("minus"), "negative"); } @Test void test2() { + assertNotNull(value); assertTrue(value.startsWith("minus"), "negative"); } } @@ -960,8 +964,8 @@ private static class CustomIntegerToStringConverter extends TypedArgumentConvert } @Override - protected String convert(Integer source) throws ArgumentConversionException { - return switch (source) { + protected String convert(@Nullable Integer source) throws ArgumentConversionException { + return switch (requireNonNull(source)) { case -1 -> "minus one"; case +1 -> "plus one"; default -> throw new IllegalArgumentException("Unsupported value: " + source); @@ -976,12 +980,12 @@ record RecordWithBuiltInAggregatorTestCase(ArgumentsAccessor accessor) { @Test void test1() { - assertTrue(accessor.getInteger(0) < 0, "negative"); + assertTrue(requireNonNull(accessor.getInteger(0)) < 0, "negative"); } @Test void test2() { - assertTrue(accessor.getInteger(0) < 0, "negative"); + assertTrue(requireNonNull(accessor.getInteger(0)) < 0, "negative"); } } @@ -996,12 +1000,12 @@ static class FieldInjectionWithBuiltInAggregatorTestCase { @Test void test1() { - assertTrue(accessor.getInteger(0) < 0, "negative"); + assertTrue(requireNonNull(accessor.getInteger(0)) < 0, "negative"); } @Test void test2() { - assertTrue(accessor.getInteger(0) < 0, "negative"); + assertTrue(requireNonNull(accessor.getInteger(0)) < 0, "negative"); } } @@ -1056,7 +1060,7 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT AnnotatedElementContext context, int parameterIndex) throws ArgumentsAggregationException { assertThat(targetType).isEqualTo(int.class); - return accessor.getInteger(0) * 2; + return requireNonNull(accessor.getInteger(0)) * 2; } } @@ -1713,6 +1717,7 @@ void test(TestReporter reporter) { record ArgumentConversionPerInvocationConstructorInjectionTestCase( @ConvertWith(Wrapper.Converter.class) Wrapper wrapper) { + @Nullable static Wrapper instance; @BeforeAll @@ -1745,6 +1750,7 @@ private void setOrCheckWrapper() { @ValueSource(ints = 1) static class ArgumentConversionPerInvocationFieldInjectionTestCase { + @Nullable static Wrapper instance; @BeforeAll @@ -1780,8 +1786,8 @@ private void setOrCheckWrapper() { record Wrapper(int value) { static class Converter extends SimpleArgumentConverter { @Override - protected Object convert(Object source, Class targetType) { - return new Wrapper((Integer) source); + protected Object convert(@Nullable Object source, Class targetType) { + return new Wrapper((Integer) requireNonNull(source)); } } } @@ -1972,8 +1978,8 @@ void test2() { static class AtomicIntegerConverter extends SimpleArgumentConverter { @Override - protected Object convert(Object source, Class targetType) { - return new AtomicInteger((Integer) source); + protected Object convert(@Nullable Object source, Class targetType) { + return new AtomicInteger((Integer) requireNonNull(source)); } } @@ -2019,13 +2025,15 @@ void test() { class Converter implements ArgumentConverter { @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public @Nullable Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { assertNotNull(context.getParameter().getAnnotation(CustomConversion.class)); return source; } @Override - public Object convert(Object source, FieldContext context) throws ArgumentConversionException { + public @Nullable Object convert(@Nullable Object source, FieldContext context) + throws ArgumentConversionException { assertNotNull(context.getField().getAnnotation(CustomConversion.class)); return source; } @@ -2201,7 +2209,8 @@ void test() { static class ToStringConverter extends SimpleArgumentConverter { @Override - protected Object convert(Object source, Class targetType) throws ArgumentConversionException { + protected @Nullable Object convert(@Nullable Object source, Class targetType) + throws ArgumentConversionException { return source == null ? null : String.valueOf(source); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterTests.java index 7d48e198dfb2..82865ea6dfc4 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterTests.java @@ -37,6 +37,8 @@ import java.util.Arrays; import java.util.Locale; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -346,6 +348,7 @@ private static String format(ParameterizedInvocationNameFormatter formatter, int return formatter.format(invocationIndex, EvaluatedArgumentSet.allOf(arguments)); } + @NullUnmarked private static class ToStringReturnsNull { @Override @@ -386,7 +389,7 @@ void processFruits(String fruit1, String fruit2) { private static class CustomAggregator extends SimpleArgumentsAggregator { @Override - protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, + protected @Nullable Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, AnnotatedElementContext context, int parameterIndex) { return accessor.get(0); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java index 741a392c4caf..e6e49f6488ae 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java @@ -17,6 +17,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.params.ParameterizedInvocationContextProvider.arguments; import static org.junit.jupiter.params.ParameterizedTestExtension.DECLARATION_CONTEXT_KEY; +import static org.mockito.Mockito.mock; import java.io.FileNotFoundException; import java.lang.reflect.AnnotatedElement; @@ -31,6 +32,7 @@ import java.util.function.Function; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; import org.junit.jupiter.api.extension.ExecutableInvoker; @@ -47,6 +49,7 @@ import org.junit.jupiter.params.support.ParameterDeclarations; import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.PreconditionViolationException; +import org.junit.platform.commons.support.AnnotationSupport; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; @@ -133,7 +136,7 @@ public Stream provideArguments(ParameterDeclarations parame } }; - var exception = assertThrows(FileNotFoundException.class, () -> arguments(failingProvider, null, null)); + var exception = assertThrows(FileNotFoundException.class, () -> arguments(failingProvider, mock(), mock())); assertEquals("a message", exception.getMessage()); } @@ -236,17 +239,17 @@ public ExtensionContext getRoot() { @Override public String getUniqueId() { - return null; + throw new UnsupportedOperationException(); } @Override public String getDisplayName() { - return null; + return "display-name"; } @Override public Set getTags() { - return null; + throw new UnsupportedOperationException(); } @Override @@ -312,7 +315,7 @@ public Store getStore(Namespace namespace) { org.junit.platform.engine.support.store.Namespace.create(namespace.getParts())); method // .map(it -> new ParameterizedTestContext(testClass, it, - it.getAnnotation(ParameterizedTest.class))) // + AnnotationSupport.findAnnotation(it, ParameterizedTest.class).orElseThrow())) // .ifPresent(ctx -> store.put(DECLARATION_CONTEXT_KEY, ctx)); return store; } @@ -331,12 +334,12 @@ public ExecutionMode getExecutionMode() { public ExecutableInvoker getExecutableInvoker() { return new ExecutableInvoker() { @Override - public Object invoke(Method method, Object target) { - return null; + public Object invoke(Method method, @Nullable Object target) { + throw new UnsupportedOperationException(); } @Override - public T invoke(Constructor constructor, Object outerInstance) { + public T invoke(Constructor constructor, @Nullable Object outerInstance) { return ReflectionUtils.newInstance(constructor); } }; @@ -414,6 +417,7 @@ void method() { class NonStaticArgumentsProvider implements ArgumentsProvider { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) { @@ -456,7 +460,7 @@ static class AmbiguousConstructorArgumentsProvider implements ArgumentsProvider @Override public Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) { - return null; + throw new UnsupportedOperationException(); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index 515f7eb87d6f..bf6653dce499 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -63,6 +63,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assumptions; @@ -928,8 +929,7 @@ void streamOfTwoDimensionalObjectArrays() { void reportsContainerWithAssumptionFailureInMethodSourceAsAborted() { execute("assumptionFailureInMethodSourceFactoryMethod", String.class).allEvents().assertThatEvents() // .haveExactly(1, event(container("test-template:assumptionFailureInMethodSourceFactoryMethod"), // - abortedWithReason(instanceOf(TestAbortedException.class), - message("Assumption failed: nothing to test")))); + abortedWithReason(instanceOf(TestAbortedException.class), message("nothing to test")))); } @Test @@ -1928,8 +1928,8 @@ void assumptionFailureInMethodSourceFactoryMethod(String test) { } static List assumptionFailureInMethodSourceFactoryMethod() { - Assumptions.assumeFalse(true, "nothing to test"); - return null; + Assumptions.abort("nothing to test"); + return List.of(); } } @@ -2508,7 +2508,8 @@ public Stream provideArguments(ParameterDeclarations parame record ArgumentConverterWithConstructorParameter(String value) implements ArgumentConverter { @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { return value; } } @@ -2593,7 +2594,7 @@ public Stream provideArguments(ParameterDeclarations parame private static class StringLengthConverter implements ArgumentConverter { @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { return String.valueOf(source).length(); } } @@ -2610,7 +2611,7 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT private static class ErroneousConverter implements ArgumentConverter { @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { throw new ArgumentConversionException("something went horribly wrong"); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java index 999a101abd21..b90fe9521334 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params.aggregator; +import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toMap; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; @@ -35,6 +36,8 @@ import java.util.Map; import java.util.stream.IntStream; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.AnnotatedElementContext; @@ -225,6 +228,7 @@ private EngineExecutionResults execute(DiscoverySelector... selectors) { // ------------------------------------------------------------------------- + @NullUnmarked public static class Person { final String firstName; @@ -248,6 +252,7 @@ enum Gender { F, M } + @NullUnmarked static class Address { final String street; @@ -308,7 +313,7 @@ public Address aggregateArguments(ArgumentsAccessor arguments, Class targetTy return new Address( arguments.getString(startIndex + 0), arguments.getString(startIndex + 1), - arguments.getInteger(startIndex + 2) + requireNonNull(arguments.getInteger(startIndex + 2)) ); // @formatter:on } @@ -332,7 +337,7 @@ protected Map aggregateArguments(ArgumentsAccessor arguments, C static class NullAggregator extends SimpleArgumentsAggregator { @Override - protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, + protected @Nullable Object aggregateArguments(ArgumentsAccessor accessor, Class targetType, AnnotatedElementContext context, int parameterIndex) { Preconditions.condition(!targetType.isPrimitive(), () -> "only supports reference types"); return null; @@ -391,7 +396,8 @@ static class InstanceCountingConverter implements ArgumentConverter { } @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public @Nullable Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { return source; } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java index b5f6e941bc6e..8bad1f29d436 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessorTests.java @@ -20,6 +20,7 @@ import java.util.Arrays; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.platform.commons.PreconditionViolationException; @@ -31,6 +32,7 @@ */ class DefaultArgumentsAccessorTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void argumentsMustNotBeNull() { assertThrows(PreconditionViolationException.class, () -> defaultArgumentsAccessor(1, (Object[]) null)); @@ -52,12 +54,12 @@ void indexMustBeSmallerThanLength() { @Test void getNull() { - assertNull(defaultArgumentsAccessor(1, new Object[] { null }).get(0)); + assertNull(defaultArgumentsAccessor(1, new @Nullable Object[] { null }).get(0)); } @Test void getWithNullCastToWrapperType() { - assertNull(defaultArgumentsAccessor(1, (Object[]) new Integer[] { null }).get(0, Integer.class)); + assertNull(defaultArgumentsAccessor(1, (Object[]) new @Nullable Integer[] { null }).get(0, Integer.class)); } @Test @@ -79,7 +81,7 @@ void getWithCastToPrimitiveType() { "Argument at index [0] with value [1] and type [java.lang.Integer] could not be converted or cast to type [int]."); exception = assertThrows(ArgumentAccessException.class, - () -> defaultArgumentsAccessor(1, new Object[] { null }).get(0, int.class)); + () -> defaultArgumentsAccessor(1, new @Nullable Object[] { null }).get(0, int.class)); assertThat(exception.getMessage()).isEqualTo( "Argument at index [0] with value [null] and type [null] could not be converted or cast to type [int]."); } @@ -165,7 +167,8 @@ void size() { assertEquals(5, defaultArgumentsAccessor(1, 'a', 'b', 'c', 'd', 'e').size()); } - private static DefaultArgumentsAccessor defaultArgumentsAccessor(int invocationIndex, Object... arguments) { + private static DefaultArgumentsAccessor defaultArgumentsAccessor(int invocationIndex, + @Nullable Object... arguments) { var context = mock(ExtensionContext.class); var classLoader = DefaultArgumentsAccessorTests.class.getClassLoader(); return DefaultArgumentsAccessor.create(context, invocationIndex, classLoader, arguments); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/DefaultArgumentConverterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/DefaultArgumentConverterTests.java index 501f4c09a40c..405828e97fbb 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/DefaultArgumentConverterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/DefaultArgumentConverterTests.java @@ -29,6 +29,7 @@ import java.util.Locale; import java.util.Optional; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; @@ -168,7 +169,7 @@ void delegatesStringToClassWithCustomTypeFromDifferentClassLoaderConversion() th var clazz = (Class) convert(customTypeName, Class.class, testClassLoader); assertThat(clazz).isNotEqualTo(Enigma.class); - assertThat(clazz).isEqualTo(customType); + assertThat(clazz).isNotNull().isEqualTo(customType); assertThat(clazz.getClassLoader()).isSameAs(testClassLoader); verify(underTest).convert(customTypeName, Class.class, testClassLoader); @@ -177,7 +178,7 @@ void delegatesStringToClassWithCustomTypeFromDifferentClassLoaderConversion() th // ------------------------------------------------------------------------- - private void assertConverts(Object input, Class targetClass, Object expectedOutput) { + private void assertConverts(@Nullable Object input, Class targetClass, @Nullable Object expectedOutput) { var result = convert(input, targetClass); assertThat(result) // @@ -187,11 +188,11 @@ private void assertConverts(Object input, Class targetClass, Object expectedO verify(underTest, never()).convert(any(), any(), any(ClassLoader.class)); } - private Object convert(Object input, Class targetClass) { + private @Nullable Object convert(@Nullable Object input, Class targetClass) { return convert(input, targetClass, ClassLoaderUtils.getClassLoader(getClass())); } - private Object convert(Object input, Class targetClass, ClassLoader classLoader) { + private @Nullable Object convert(@Nullable Object input, Class targetClass, ClassLoader classLoader) { return underTest.convert(input, targetClass, classLoader); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java index 2cee9d79f7c9..f2bb6db3f720 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/JavaTimeArgumentConverterTests.java @@ -30,6 +30,7 @@ import java.time.chrono.ChronoLocalDateTime; import java.time.chrono.ChronoZonedDateTime; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; /** @@ -37,66 +38,77 @@ */ class JavaTimeArgumentConverterTests { + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToChronoLocalDate() { assertThat(convert("01.02.2017", "dd.MM.yyyy", ChronoLocalDate.class)) // .isEqualTo(LocalDate.of(2017, 2, 1)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToChronoLocalDateTime() { assertThat(convert("01.02.2017 12:34:56.789", "dd.MM.yyyy HH:mm:ss.SSS", ChronoLocalDateTime.class)) // .isEqualTo(LocalDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToChronoZonedDateTime() { assertThat(convert("01.02.2017 12:34:56.789 Z", "dd.MM.yyyy HH:mm:ss.SSS X", ChronoZonedDateTime.class)) // .isEqualTo(ZonedDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000, UTC)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToLocalDate() { assertThat(convert("01.02.2017", "dd.MM.yyyy", LocalDate.class)) // .isEqualTo(LocalDate.of(2017, 2, 1)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToLocalDateTime() { assertThat(convert("01.02.2017 12:34:56.789", "dd.MM.yyyy HH:mm:ss.SSS", LocalDateTime.class)) // .isEqualTo(LocalDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToLocalTime() { assertThat(convert("12:34:56.789", "HH:mm:ss.SSS", LocalTime.class)) // .isEqualTo(LocalTime.of(12, 34, 56, 789_000_000)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToOffsetDateTime() { assertThat(convert("01.02.2017 12:34:56.789 +02", "dd.MM.yyyy HH:mm:ss.SSS X", OffsetDateTime.class)) // .isEqualTo(OffsetDateTime.of(2017, 2, 1, 12, 34, 56, 789_000_000, ZoneOffset.ofHours(2))); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToOffsetTime() { assertThat(convert("12:34:56.789 -02", "HH:mm:ss.SSS X", OffsetTime.class)) // .isEqualTo(OffsetTime.of(12, 34, 56, 789_000_000, ZoneOffset.ofHours(-2))); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToYear() { assertThat(convert("2017", "yyyy", Year.class)) // .isEqualTo(Year.of(2017)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToYearMonth() { assertThat(convert("03/2017", "MM/yyyy", YearMonth.class)) // .isEqualTo(YearMonth.of(2017, 3)); } + @SuppressWarnings("DataFlowIssue") @Test void convertsStringToZonedDateTime() { assertThat(convert("01.02.2017 12:34:56.789 Europe/Berlin", "dd.MM.yyyy HH:mm:ss.SSS VV", ZonedDateTime.class)) // @@ -125,16 +137,17 @@ void throwsExceptionOnNullParameterWithoutNullable() { /** * @since 5.12 */ + @SuppressWarnings("DataFlowIssue") @Test void convertsNullableParameter() { assertThat(convert(null, "dd.MM.yyyy", true, LocalDate.class)).isNull(); } - private Object convert(Object input, String pattern, Class targetClass) { + private @Nullable Object convert(@Nullable Object input, String pattern, Class targetClass) { return convert(input, pattern, false, targetClass); } - private Object convert(Object input, String pattern, boolean nullable, Class targetClass) { + private @Nullable Object convert(@Nullable Object input, String pattern, boolean nullable, Class targetClass) { var converter = new JavaTimeArgumentConverter(); var annotation = mock(JavaTimeConversionPattern.class); when(annotation.value()).thenReturn(pattern); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/TypedArgumentConverterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/TypedArgumentConverterTests.java index 599f3d2e9163..dc93874d7d32 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/TypedArgumentConverterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/converter/TypedArgumentConverterTests.java @@ -23,6 +23,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Parameter; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ParameterContext; @@ -47,6 +48,7 @@ class UnitTests { /** * @since 5.8 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// @@ -67,7 +69,7 @@ void convertsSourceToTarget() { ); } - private void assertConverts(String input, int expected) { + private void assertConverts(@Nullable String input, int expected) { assertThat(this.converter.convert(input)).isEqualTo(expected); } @@ -168,7 +170,7 @@ private static class StringLengthArgumentConverter extends TypedArgumentConverte } @Override - protected Integer convert(String source) throws ArgumentConversionException { + protected Integer convert(@Nullable String source) throws ArgumentConversionException { return (source != null ? source.length() : 0); } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java index 885ba7a77591..4e75630c5d39 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/AnnotationBasedArgumentsProviderTests.java @@ -38,6 +38,7 @@ protected Stream provideArguments( } }; + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("should throw exception when null annotation is provided to accept method") void shouldThrowExceptionWhenNullAnnotationIsProvidedToAccept() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java index bc479af1a62b..6cc030cf447f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvArgumentsProviderTests.java @@ -17,6 +17,7 @@ import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedTest; @@ -387,7 +388,7 @@ private Stream provideArguments(CsvSource annotation) { } @SuppressWarnings("unchecked") - private static T[] array(T... elements) { + private static @Nullable T[] array(@Nullable T... elements) { return elements; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvFileArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvFileArgumentsProviderTests.java index 3a7269f4ee0f..06d27ddf5ae7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvFileArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/CsvFileArgumentsProviderTests.java @@ -26,6 +26,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.io.TempDir; @@ -548,7 +549,7 @@ private Stream provideArguments(CsvFileArgumentsProvider provider, Csv } @SuppressWarnings("unchecked") - private static T[] array(T... elements) { + private static @Nullable T[] array(@Nullable T... elements) { return elements; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/FieldArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/FieldArgumentsProviderTests.java index f8a9a9c6c299..9271b3a97141 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/FieldArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/FieldArgumentsProviderTests.java @@ -28,6 +28,7 @@ import java.util.stream.LongStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInstance.Lifecycle; @@ -519,6 +520,7 @@ void test() { // --- Invalid --------------------------------------------------------- + @Nullable static List nullList = null; static Object object = -1; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java index da3a2994bb8e..14e2b6fb9ace 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java @@ -29,6 +29,8 @@ import java.util.stream.LongStream; import java.util.stream.Stream; +import org.jspecify.annotations.NullUnmarked; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -49,6 +51,7 @@ */ class MethodArgumentsProviderTests { + @Nullable private MutableExtensionRegistry extensionRegistry; @Test @@ -729,15 +732,15 @@ private static Object[] array(Object... objects) { return objects; } - private Stream provideArguments(String... factoryMethodNames) { + private Stream<@Nullable Object[]> provideArguments(String... factoryMethodNames) { return provideArguments(TestCase.class, false, factoryMethodNames); } - private Stream provideArguments(Method testMethod, String factoryMethodName) { + private Stream<@Nullable Object[]> provideArguments(Method testMethod, String factoryMethodName) { return provideArguments(TestCase.class, testMethod, false, factoryMethodName); } - private Stream provideArguments(Class testClass, boolean allowNonStaticMethod, + private Stream<@Nullable Object[]> provideArguments(Class testClass, boolean allowNonStaticMethod, String... factoryMethodNames) { // Ensure we have a non-null test method, even if it's not a real test method. @@ -746,8 +749,8 @@ private Stream provideArguments(Class testClass, boolean allowNonSt return provideArguments(testClass, testMethod, allowNonStaticMethod, factoryMethodNames); } - private Stream provideArguments(Class testClass, Method testMethod, boolean allowNonStaticMethod, - String... factoryMethodNames) { + private Stream<@Nullable Object[]> provideArguments(Class testClass, Method testMethod, + boolean allowNonStaticMethod, String... factoryMethodNames) { var methodSource = mock(MethodSource.class); @@ -756,8 +759,7 @@ private Stream provideArguments(Class testClass, Method testMethod, var extensionContext = mock(ExtensionContext.class); when(extensionContext.getTestClass()).thenReturn(Optional.of(testClass)); when(extensionContext.getTestMethod()).thenReturn(Optional.of(testMethod)); - when(extensionContext.getExecutableInvoker()).thenReturn( - new DefaultExecutableInvoker(extensionContext, extensionRegistry)); + when(extensionContext.getExecutableInvoker()).thenReturn(getExecutableInvoker(extensionContext)); doCallRealMethod().when(extensionContext).getRequiredTestClass(); @@ -772,6 +774,11 @@ private Stream provideArguments(Class testClass, Method testMethod, return provider.provideArguments(mock(), extensionContext).map(Arguments::get); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + private DefaultExecutableInvoker getExecutableInvoker(ExtensionContext extensionContext) { + return new DefaultExecutableInvoker(extensionContext, extensionRegistry); + } + // ------------------------------------------------------------------------- static class DefaultFactoryMethodNameTestCase { @@ -803,6 +810,7 @@ static Stream test(int num) { } } + @NullUnmarked static class MultipleInvalidDefaultFactoriesTestCase { // Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java index 16306451bca4..4d4ea67ecf24 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java @@ -25,6 +25,7 @@ import java.util.List; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; @@ -126,10 +127,12 @@ protected Stream provideArguments(ParameterDeclarations par private static class SomeAnnotationBasedArgumentConverter extends AnnotationBasedArgumentConverter { + @Nullable JavaTimeConversionPattern annotation; @Override - protected Object convert(Object source, Class targetType, JavaTimeConversionPattern annotation) { + protected @Nullable Object convert(@Nullable Object source, Class targetType, + JavaTimeConversionPattern annotation) { this.annotation = annotation; return null; } @@ -137,6 +140,7 @@ protected Object convert(Object source, Class targetType, JavaTimeConversionP private static class SomeAnnotationConsumer implements AnnotationConsumer { + @Nullable CsvSource annotation; @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java index ffcc99878b8f..c1990a02aa4e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/ParameterInfoIntegrationTests.java @@ -11,6 +11,7 @@ package org.junit.jupiter.params.support; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import org.junit.jupiter.api.Nested; @@ -102,6 +103,7 @@ public void beforeEach(ExtensionContext parameterizedTestInvocationContext) { private static void assertParameterInfo(ExtensionContext context, String parameterName, int argumentValue) { var parameterInfo = ParameterInfo.get(context); + assertNotNull(parameterInfo); var declaration = parameterInfo.getDeclarations().get(0).orElseThrow(); assertEquals(parameterName, declaration.getParameterName().orElseThrow()); assertEquals(int.class, declaration.getParameterType()); diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index dc66c0e7a4dc..629b68107c0b 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -5,6 +5,7 @@ import org.gradle.internal.os.OperatingSystem plugins { id("junitbuild.java-library-conventions") + id("junitbuild.java-nullability-conventions") id("junitbuild.junit4-compatibility") id("junitbuild.testing-conventions") id("junitbuild.jmh-conventions") diff --git a/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java b/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java index 7fabe5b52440..d7901d7aac7d 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/function/TryTests.java @@ -72,6 +72,7 @@ void failedTriesCanBeTransformed() throws Exception { assertThat(exception.get()).isSameAs(cause); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void successfulTriesCanStoreNull() throws Exception { var success = Try.success(null); @@ -100,6 +101,7 @@ void triesWithSameContentAreEqual() { assertThat(failure).isEqualTo(Try.failure(cause)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void methodPreconditionsAreChecked() { assertThrows(JUnitException.class, () -> Try.call(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/AnnotationSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/AnnotationSupportTests.java index b882977606a1..67c36c8a7c12 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/AnnotationSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/AnnotationSupportTests.java @@ -23,6 +23,7 @@ import java.util.List; import java.util.Optional; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; @@ -34,6 +35,7 @@ */ class AnnotationSupportTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isAnnotatedPreconditions() { var optional = Optional.of(Probe.class); @@ -57,6 +59,7 @@ void isAnnotatedDelegates() { AnnotationSupport.isAnnotated(element, Override.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotationOnElementPreconditions() { var optional = Optional.of(Probe.class); @@ -81,7 +84,7 @@ void findAnnotationOnElementDelegates() { AnnotationSupport.findAnnotation(element, Override.class)); } - @SuppressWarnings("deprecation") + @SuppressWarnings({ "deprecation", "DataFlowIssue", "NullAway" }) @Test void findAnnotationOnClassWithSearchModePreconditions() { assertPreconditionViolationException("annotationType", @@ -90,6 +93,7 @@ void findAnnotationOnClassWithSearchModePreconditions() { () -> AnnotationSupport.findAnnotation(Probe.class, Override.class, (SearchOption) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotationOnClassWithEnclosingInstanceTypesPreconditions() { assertPreconditionViolationException("enclosingInstanceTypes", @@ -120,6 +124,7 @@ void findAnnotationOnClassWithSearchModeDelegates() { AnnotationSupport.findAnnotation(clazz, Override.class, SearchOption.INCLUDE_ENCLOSING_CLASSES)); } + @NullUnmarked @Test void findAnnotationOnClassWithEnclosingInstanceTypes() { assertThat(AnnotationSupport.findAnnotation(Probe.class, Tag.class, List.of())) // @@ -130,6 +135,7 @@ void findAnnotationOnClassWithEnclosingInstanceTypes() { .contains(Probe.class.getDeclaredAnnotation(Tag.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findPublicAnnotatedFieldsPreconditions() { assertPreconditionViolationException("Class", @@ -148,6 +154,7 @@ void findPublicAnnotatedFieldsDelegates() { AnnotationSupport.findPublicAnnotatedFields(Probe.class, Throwable.class, Override.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedMethodsPreconditions() { assertPreconditionViolationException("Class", @@ -192,6 +199,7 @@ void findRepeatableAnnotationsDelegates() throws Throwable { assertEquals(expected.toString(), actual.toString(), "expected equal exception toString representation"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findRepeatableAnnotationsPreconditions() { assertPreconditionViolationException("annotationType", @@ -217,6 +225,7 @@ void findAnnotatedFieldsDelegates() { HierarchyTraversalMode.TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedFieldsPreconditions() { assertPreconditionViolationException("Class", @@ -268,6 +277,7 @@ void findAnnotatedFieldValuesForStaticFieldsByType() { .containsExactlyInAnyOrder("s1", "s2"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedFieldValuesPreconditions() { assertPreconditionViolationException("instance", diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/ClassSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/ClassSupportTests.java index e2b972348253..98e90a516900 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/ClassSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/ClassSupportTests.java @@ -24,6 +24,7 @@ */ class ClassSupportTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullSafeToStringPreconditions() { Function, ? extends String> mapper = null; diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/ModifierSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/ModifierSupportTests.java index 18332317aa51..bf9957b9a2d6 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/ModifierSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/ModifierSupportTests.java @@ -34,6 +34,7 @@ */ class ModifierSupportTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isPublicPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isPublic((Class) null)); @@ -51,6 +52,7 @@ void isPublicDelegates(Method method) { assertEquals(ReflectionUtils.isPublic(method), ModifierSupport.isPublic(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isPrivatePreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isPrivate((Class) null)); @@ -68,6 +70,7 @@ void isPrivateDelegates(Method method) { assertEquals(ReflectionUtils.isPrivate(method), ModifierSupport.isPrivate(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isNotPrivatePreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotPrivate((Class) null)); @@ -85,6 +88,7 @@ void isNotPrivateDelegates(Method method) { assertEquals(ReflectionUtils.isNotPrivate(method), ModifierSupport.isNotPrivate(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isAbstractPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isAbstract((Class) null)); @@ -102,6 +106,7 @@ void isAbstractDelegates(Method method) { assertEquals(ReflectionUtils.isAbstract(method), ModifierSupport.isAbstract(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isNotAbstractPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotAbstract((Class) null)); @@ -119,6 +124,7 @@ void isNotAbstractDelegates(Method method) { assertEquals(ReflectionUtils.isNotAbstract(method), ModifierSupport.isNotAbstract(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isStaticPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isStatic((Class) null)); @@ -136,6 +142,7 @@ void isStaticDelegates(Method method) { assertEquals(ReflectionUtils.isStatic(method), ModifierSupport.isStatic(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isNotStaticPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotStatic((Class) null)); @@ -153,6 +160,7 @@ void isNotStaticDelegates(Method method) { assertEquals(ReflectionUtils.isNotStatic(method), ModifierSupport.isNotStatic(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isFinalPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isFinal((Class) null)); @@ -170,6 +178,7 @@ void isFinalDelegates(Method method) { assertEquals(ReflectionUtils.isFinal(method), ModifierSupport.isFinal(method)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isNotFinalPreconditions() { assertPreconditionViolationException("Class", () -> ModifierSupport.isNotFinal((Class) null)); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java index 11134ab5608e..4aea6556942f 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/ReflectionSupportTests.java @@ -56,6 +56,7 @@ void tryToLoadClassDelegates() { ReflectionSupport.tryToLoadClass("java.nio.Bits")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToLoadClassPreconditions() { assertPreconditionViolationExceptionForString("Class name", () -> ReflectionSupport.tryToLoadClass(null)); @@ -80,6 +81,7 @@ void tryToLoadClassWithExplicitClassLoaderDelegates() { /** * @since 1.10 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToLoadClassWithExplicitClassLoaderPreconditions() { var cl = getClass().getClassLoader(); @@ -108,6 +110,7 @@ List findAllClassesInClasspathRootDelegates() throws Throwable { /** * @since 1.12 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToGetResourcesPreconditions() { assertPreconditionViolationExceptionForString("Resource name", () -> ReflectionSupport.tryToGetResources(null)); @@ -130,6 +133,7 @@ void tryToGetResources() { ReflectionSupport.tryToGetResources("default-package.resource", getDefaultClassLoader()).toOptional()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllClassesInClasspathRootPreconditions() { var path = Path.of(".").toUri(); @@ -163,6 +167,7 @@ List findAllResourcesInClasspathRootDelegates() throws Throwable { /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllResourcesInClasspathRootPreconditions() { var path = Path.of(".").toUri(); @@ -194,6 +199,7 @@ List streamAllResourcesInClasspathRootDelegates() throws Throwable /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamAllResourcesInClasspathRootPreconditions() { var path = Path.of(".").toUri(); @@ -210,6 +216,7 @@ void findAllClassesInPackageDelegates() { ReflectionSupport.findAllClassesInPackage("org.junit", allTypes, allNames)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllClassesInPackagePreconditions() { assertPreconditionViolationExceptionForString("basePackageName", @@ -234,6 +241,7 @@ void findAllResourcesInPackageDelegates() { /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllResourcesInPackagePreconditions() { assertPreconditionViolationExceptionForString("basePackageName", @@ -256,6 +264,7 @@ void streamAllResourcesInPackageDelegates() { /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamAllResourcesInPackagePreconditions() { assertPreconditionViolationExceptionForString("basePackageName", @@ -270,6 +279,7 @@ void findAllClassesInModuleDelegates() { ReflectionSupport.findAllClassesInModule("org.junit.platform.commons", allTypes, allNames)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllClassesInModulePreconditions() { var exception = assertThrows(PreconditionViolationException.class, @@ -293,6 +303,7 @@ void findAllResourcesInModuleDelegates() { /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllResourcesInModulePreconditions() { var exception = assertThrows(PreconditionViolationException.class, @@ -314,6 +325,7 @@ void streamAllResourcesInModuleDelegates() { /** * @since 1.11 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void streamAllResourcesInModulePreconditions() { var exception = assertThrows(PreconditionViolationException.class, @@ -329,6 +341,7 @@ void newInstanceDelegates() { ReflectionSupport.newInstance(String.class, "foo")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void newInstancePreconditions() { assertPreconditionViolationException("Class", () -> ReflectionSupport.newInstance(null)); @@ -345,6 +358,7 @@ void invokeMethodDelegates() throws Exception { ReflectionSupport.invokeMethod(method, null, "true")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void invokeMethodPreconditions() throws Exception { assertPreconditionViolationException("Method", () -> ReflectionSupport.invokeMethod(null, null, "true")); @@ -368,6 +382,7 @@ void findFieldsDelegates() { ReflectionSupport.findFields(ReflectionSupportTests.class, allFields, HierarchyTraversalMode.TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findFieldsPreconditions() { assertPreconditionViolationException("Class", @@ -393,6 +408,7 @@ void tryToReadFieldValueDelegates() throws Exception { ReflectionSupport.tryToReadFieldValue(instanceField, this)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToReadFieldValuePreconditions() throws Exception { assertPreconditionViolationException("Field", () -> ReflectionSupport.tryToReadFieldValue(null, this)); @@ -414,6 +430,7 @@ void findMethodDelegates() { ReflectionSupport.findMethod(Boolean.class, "valueOf", String.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findMethodPreconditions() { assertPreconditionViolationException("Class", @@ -447,6 +464,7 @@ void findMethodsDelegates() { ReflectionSupport.findMethods(ReflectionSupportTests.class, allMethods, HierarchyTraversalMode.TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findMethodsPreconditions() { assertPreconditionViolationException("Class", @@ -467,6 +485,7 @@ void findNestedClassesDelegates() { ReflectionSupport.findNestedClasses(ClassWithNestedClasses.class, ReflectionUtils::isStatic)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findNestedClassesPreconditions() { assertPreconditionViolationException("Class", diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java index 626fbe117939..9e87f62ea62d 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java @@ -41,6 +41,7 @@ import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; @@ -228,12 +229,11 @@ void convertsStringToClassWithCustomTypeFromDifferentClassLoader() throws Except var customType = testClassLoader.loadClass(customTypeName); assertThat(customType.getClassLoader()).isSameAs(testClassLoader); - var declaringExecutable = ReflectionSupport.findMethod(customType, "foo").get(); + var declaringExecutable = ReflectionSupport.findMethod(customType, "foo").orElseThrow(); assertThat(declaringExecutable.getDeclaringClass().getClassLoader()).isSameAs(testClassLoader); var clazz = (Class) convert(customTypeName, Class.class, classLoader(declaringExecutable)); - assertThat(clazz).isNotEqualTo(Enigma.class); - assertThat(clazz).isEqualTo(customType); + assertThat(clazz).isNotNull().isNotEqualTo(Enigma.class).isEqualTo(customType); assertThat(clazz.getClassLoader()).isSameAs(testClassLoader); } } @@ -308,7 +308,7 @@ void convertsStringToUUID() { // ------------------------------------------------------------------------- - private void assertConverts(String input, Class targetClass, Object expectedOutput) { + private void assertConverts(@Nullable String input, Class targetClass, @Nullable Object expectedOutput) { var result = convert(input, targetClass); assertThat(result) // @@ -316,16 +316,18 @@ private void assertConverts(String input, Class targetClass, Object expectedO .isEqualTo(expectedOutput); } - private Object convert(String input, Class targetClass) { + @Nullable + private Object convert(@Nullable String input, Class targetClass) { return convert(input, targetClass, classLoader()); } - private Object convert(String input, Class targetClass, ClassLoader classLoader) { + @Nullable + private Object convert(@Nullable String input, Class targetClass, ClassLoader classLoader) { return ConversionSupport.convert(input, targetClass, classLoader); } private static ClassLoader classLoader() { - Method declaringExecutable = ReflectionSupport.findMethod(ConversionSupportTests.class, "foo").get(); + Method declaringExecutable = ReflectionSupport.findMethod(ConversionSupportTests.class, "foo").orElseThrow(); return classLoader(declaringExecutable); } 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 26a2fa53ad98..8f40d780c8a5 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 @@ -441,12 +441,14 @@ void resourcesCanBeRead() throws IOException { } } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void scanForClassesInPackageForNullBasePackage() { assertThrows(PreconditionViolationException.class, () -> classpathScanner.scanForClassesInPackage(null, allClasses)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void scanForResourcesInPackageForNullBasePackage() { assertThrows(PreconditionViolationException.class, @@ -465,6 +467,7 @@ void scanForResourcesInPackageForWhitespaceBasePackage() { () -> classpathScanner.scanForResourcesInPackage(" ", allResources)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void scanForClassesInPackageForNullClassFilter() { assertThrows(PreconditionViolationException.class, @@ -548,6 +551,7 @@ void findAllClassesInClasspathRootWithFilter() throws Exception { assertTrue(classes.contains(DefaultClasspathScannerTests.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllClassesInClasspathRootForNullRoot() { assertThrows(PreconditionViolationException.class, @@ -560,6 +564,7 @@ void findAllClassesInClasspathRootForNonExistingRoot() { () -> classpathScanner.scanForClassesInClasspathRoot(Path.of("does_not_exist").toUri(), allClasses)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAllClassesInClasspathRootForNullClassFilter() { assertThrows(PreconditionViolationException.class, 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 20a282e723bf..31c65511af00 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 @@ -41,6 +41,7 @@ import java.util.Optional; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -334,12 +335,14 @@ private void assertExtensionsFound(Class clazz, String... tags) { () -> "Extensions found for class " + clazz.getName()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedMethodsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedMethods(null, Annotation1.class, TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedMethodsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, @@ -420,18 +423,21 @@ void findAnnotatedMethodsForAnnotationUsedInInterface() throws Exception { // === findAnnotatedFields() =============================================== + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedFieldsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedFields(null, Annotation1.class, isStringField, TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedFieldsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, () -> findAnnotatedFields(ClassWithAnnotatedFields.class, null, isStringField, TOP_DOWN)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findAnnotatedFieldsForNullPredicate() { assertThrows(PreconditionViolationException.class, @@ -545,18 +551,21 @@ void findAnnotatedFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exce // === findPublicAnnotatedFields() ========================================= + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findPublicAnnotatedFieldsForNullClass() { assertThrows(PreconditionViolationException.class, () -> findPublicAnnotatedFields(null, String.class, Annotation1.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findPublicAnnotatedFieldsForNullFieldType() { assertThrows(PreconditionViolationException.class, () -> findPublicAnnotatedFields(getClass(), null, Annotation1.class)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findPublicAnnotatedFieldsForNullAnnotationType() { assertThrows(PreconditionViolationException.class, @@ -1004,12 +1013,15 @@ static class ClassWithShadowedAnnotatedFields extends ClassWithAnnotatedFields { // ------------------------------------------------------------------------- @Annotation1 + @Nullable private Boolean privateDirectlyAnnotatedField; @Annotation1 + @Nullable public String directlyAnnotatedField; @ComposedAnnotation + @Nullable public Integer metaAnnotatedField; interface InterfaceWithAnnotatedFields { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/ClassLoaderUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/ClassLoaderUtilsTests.java index 3d8a72df921a..562a0fea2499 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/ClassLoaderUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/ClassLoaderUtilsTests.java @@ -29,6 +29,7 @@ */ class ClassLoaderUtilsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getClassLoaderPreconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// @@ -100,6 +101,7 @@ void getDefaultClassLoaderWithNullContextClassLoader() { } } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getLocationFromNullFails() { var exception = assertThrows(PreconditionViolationException.class, () -> ClassLoaderUtils.getLocation(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java index 749f62161073..12ef9107f8ce 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java @@ -32,6 +32,7 @@ import java.util.stream.LongStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -57,6 +58,7 @@ class CollectionUtilsTests { @Nested class OnlyElement { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullCollection() { var exception = assertThrows(PreconditionViolationException.class, @@ -89,6 +91,7 @@ void multiElementCollection() { @Nested class FirstElement { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullCollection() { var exception = assertThrows(PreconditionViolationException.class, @@ -191,6 +194,7 @@ void isConvertibleToStreamForNull() { assertThat(CollectionUtils.isConvertibleToStream(null)).isFalse(); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void toStreamWithNull() { Exception exception = assertThrows(PreconditionViolationException.class, @@ -368,7 +372,8 @@ void iteratesListElementsInReverseOrder(@ConvertWith(CommaSeparator.class) List< private static class CommaSeparator implements ArgumentConverter { @Override - public Object convert(Object source, ParameterContext context) throws ArgumentConversionException { + public Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { return source == null ? List.of() : List.of(((String) source).split(",")); } } diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java index 798185711c3c..cc30b382ceac 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/ExceptionUtilsTests.java @@ -31,8 +31,10 @@ * * @since 1.0 */ +@SuppressWarnings("ThrowableNotThrown") class ExceptionUtilsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void throwAsUncheckedExceptionWithNullException() { assertThrows(PreconditionViolationException.class, () -> throwAsUncheckedException(null)); @@ -48,6 +50,7 @@ void throwAsUncheckedExceptionWithUncheckedException() { assertThrows(RuntimeException.class, () -> throwAsUncheckedException(new NumberFormatException())); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void readStackTraceForNullThrowable() { assertThrows(PreconditionViolationException.class, () -> readStackTrace(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/FunctionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/FunctionUtilsTests.java index ee74043ceb39..42d9938ff5af 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/FunctionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/FunctionUtilsTests.java @@ -26,12 +26,14 @@ */ class FunctionUtilsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void whereWithNullFunction() { var exception = assertThrows(PreconditionViolationException.class, () -> FunctionUtils.where(null, o -> true)); assertEquals("function must not be null", exception.getMessage()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void whereWithNullPredicate() { var exception = assertThrows(PreconditionViolationException.class, () -> FunctionUtils.where(o -> o, null)); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/PackageUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/PackageUtilsTests.java index 801500ccede9..de415b7c4467 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/PackageUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/PackageUtilsTests.java @@ -33,6 +33,7 @@ */ class PackageUtilsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAttributeWithNullType() { var exception = assertThrows(PreconditionViolationException.class, @@ -40,6 +41,7 @@ void getAttributeWithNullType() { assertEquals("type must not be null", exception.getMessage()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAttributeWithNullFunction() { var exception = assertThrows(PreconditionViolationException.class, @@ -47,6 +49,7 @@ void getAttributeWithNullFunction() { assertEquals("function must not be null", exception.getMessage()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAttributeWithFunctionReturningNullIsEmpty() { assertFalse(PackageUtils.getAttribute(ValueWrapper.class, p -> null).isPresent()); @@ -54,7 +57,7 @@ void getAttributeWithFunctionReturningNullIsEmpty() { @Test void getAttributeFromDefaultPackageMemberIsEmpty() throws Exception { - var classInDefaultPackage = ReflectionUtils.tryToLoadClass("DefaultPackageTestCase").get(); + var classInDefaultPackage = ReflectionUtils.tryToLoadClass("DefaultPackageTestCase").getNonNull(); assertFalse(PackageUtils.getAttribute(classInDefaultPackage, Package::getSpecificationTitle).isPresent()); } @@ -75,6 +78,7 @@ private Executable isPresent(Function function) { return () -> assertTrue(PackageUtils.getAttribute(ValueWrapper.class, function).isPresent()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAttributeWithNullTypeAndName() { var exception = assertThrows(PreconditionViolationException.class, @@ -82,6 +86,7 @@ void getAttributeWithNullTypeAndName() { assertEquals("type must not be null", exception.getMessage()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAttributeWithNullName() { var exception = assertThrows(PreconditionViolationException.class, 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 1c391226562b..90a4fd60a4a7 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 @@ -59,6 +59,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; @@ -113,6 +114,7 @@ void returnsPrimitiveVoid() throws Exception { assertFalse(ReflectionUtils.returnsPrimitiveVoid(clazz.getDeclaredMethod("methodReturningPrimitive"))); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getAllAssignmentCompatibleClassesWithNullClass() { assertThrows(PreconditionViolationException.class, @@ -127,6 +129,7 @@ void getAllAssignmentCompatibleClasses() { assertTrue(superclasses.stream().allMatch(clazz -> clazz.isAssignableFrom(B.class))); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void newInstance() { // @formatter:off @@ -233,6 +236,7 @@ private static void createDirectories(Path... paths) throws IOException { } } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getDeclaredConstructorPreconditions() { // @formatter:off @@ -531,6 +535,7 @@ static void staticMethod() { @Nested class IsClassAssignableToClassTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isAssignableToForNullSourceType() { assertThatExceptionOfType(PreconditionViolationException.class)// @@ -545,6 +550,7 @@ void isAssignableToForPrimitiveSourceType() { .withMessage("source type must not be a primitive type"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isAssignableToForNullTargetType() { assertThatExceptionOfType(PreconditionViolationException.class)// @@ -601,6 +607,7 @@ void isAssignableTo() { @Nested class IsObjectAssignableToClassTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isAssignableToForNullClass() { assertThrows(PreconditionViolationException.class, @@ -666,6 +673,7 @@ void isAssignableToForNullObjectAndPrimitive() { @Nested class MethodInvocationTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void invokeMethodPreconditions() { // @formatter:off @@ -732,6 +740,7 @@ private void privateMethod() { @Nested class ResourceLoadingTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToGetResourcePreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToGetResources("")); @@ -773,6 +782,7 @@ void tryToGetResourceWhenResourceNotFound() { @Nested class ClassLoadingTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToLoadClassPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToLoadClass(null)); @@ -939,6 +949,7 @@ private static void assertTryToLoadClass(String name, Class type) { @Nested class FullyQualifiedMethodNameTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getFullyQualifiedMethodNamePreconditions() { // @formatter:off @@ -974,6 +985,7 @@ void getFullyQualifiedMethodNameForMethodWithMultipleParameters() { // @formatter:on } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void parseFullyQualifiedMethodNamePreconditions() { // @formatter:off @@ -1013,6 +1025,7 @@ void parseFullyQualifiedMethodNameForMethodWithMultipleParameters() { @Nested class NestedClassTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findNestedClassesPreconditions() { // @formatter:off @@ -1022,6 +1035,7 @@ void findNestedClassesPreconditions() { // @formatter:on } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isNestedClassPresentPreconditions() { // @formatter:off @@ -1199,6 +1213,7 @@ static class ClassExtendingClassWithNestedClasses extends ClassWithNestedClasses @Nested class MethodUtilitiesTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToGetMethodPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.tryToGetMethod(null, null)); @@ -1223,6 +1238,7 @@ void tryToGetMethod() throws Exception { assertThat(ReflectionUtils.tryToGetMethod(Object.class, "clone", int.class).toOptional()).isEmpty(); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void isMethodPresentPreconditions() { assertThrows(PreconditionViolationException.class, () -> ReflectionUtils.isMethodPresent(null, m -> true)); @@ -1244,6 +1260,7 @@ void isMethodPresent() { @Nested class FindMethodTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findMethodByParameterTypesPreconditions() { // @formatter:off @@ -1432,6 +1449,7 @@ void methodWithParameterizedMap(Map map) { @Nested class FindMethodsTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void findMethodsPreconditions() { // @formatter:off @@ -1907,6 +1925,7 @@ String specialBaz() { @Nested class ReadFieldTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToReadFieldValueOfNonexistentStaticField() { assertThrows(NoSuchFieldException.class, @@ -1923,6 +1942,7 @@ void tryToReadFieldValueOfNonexistentInstanceField() { () -> tryToReadFieldValue(MyClass.class, "doesNotExist", new MySubClass(42)).get()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToReadFieldValueOfExistingStaticField() throws Exception { assertThat(tryToReadFieldValue(MyClass.class, "staticField", null).get()).isEqualTo(42); @@ -1938,7 +1958,7 @@ void tryToReadFieldValueOfExistingInstanceField() throws Exception { assertThat(tryToReadFieldValue(MyClass.class, "instanceField", instance).get()).isEqualTo(42); var field = MyClass.class.getDeclaredField("instanceField"); - assertThat(tryToReadFieldValue(field, instance).get()).isEqualTo(42); + assertThat(tryToReadFieldValue(field, instance).getNonNull()).isEqualTo(42); var exception = assertThrows(PreconditionViolationException.class, () -> tryToReadFieldValue(field, null).get()); @@ -1974,6 +1994,7 @@ void findFieldsDoesNotAllowInstanceFieldToHideStaticField() throws Exception { assertThat(fields).containsExactly(nonStaticField); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void readFieldValuesPreconditions() { List fields = new ArrayList<>(); @@ -2090,6 +2111,7 @@ public static class ClassWithFields { @SuppressWarnings("unused") private final String privateStringField = "enigma"; + @Nullable final String nullStringField = null; public final int integerField = 42; diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java index 4707b9d91a95..315fdb472500 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/StringUtilsTests.java @@ -27,6 +27,7 @@ import static org.junit.platform.commons.util.StringUtils.replaceIsoControlCharacters; import static org.junit.platform.commons.util.StringUtils.replaceWhitespaceCharacters; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; @@ -49,6 +50,7 @@ void blankness() { // @formatter:on } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void whitespace() { // @formatter:off @@ -72,6 +74,7 @@ void whitespace() { // @formatter:on } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void controlCharacters() { // @formatter:off @@ -95,6 +98,7 @@ void controlCharacters() { // @formatter:on } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void replaceControlCharacters() { assertNull(replaceIsoControlCharacters(null, "")); @@ -108,6 +112,7 @@ void replaceControlCharacters() { assertThrows(PreconditionViolationException.class, () -> replaceIsoControlCharacters("", null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void replaceWhitespaces() { assertNull(replaceWhitespaceCharacters(null, "")); @@ -172,6 +177,7 @@ private void shouldNotContainIsoControlCharacter(String str) { () -> "'%s' should not contain ISO control character".formatted(str)); } + @NullUnmarked private static class ToStringReturnsNull { @Override diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/ToStringBuilderTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/ToStringBuilderTests.java index c030ba8673de..10d268699f55 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/ToStringBuilderTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/ToStringBuilderTests.java @@ -16,6 +16,7 @@ import java.util.LinkedHashMap; import java.util.Map; +import org.jspecify.annotations.NullUnmarked; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; @@ -26,16 +27,19 @@ */ class ToStringBuilderTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void withNullObject() { assertThrows(PreconditionViolationException.class, () -> new ToStringBuilder((Object) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void withNullClass() { assertThrows(PreconditionViolationException.class, () -> new ToStringBuilder((Class) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void appendWithIllegalName() { var builder = new ToStringBuilder(""); @@ -141,6 +145,7 @@ void withDemoImplementation() { assertEquals("RoleModel [name = 'Dilbert', age = 42]", roleModel.toString()); } + @NullUnmarked static class RoleModel { String name; diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java index f7fd34632fe5..972496c23fa6 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java @@ -10,9 +10,12 @@ package org.junit.platform.console; +import static java.util.Objects.requireNonNull; + import java.io.PrintWriter; import java.util.List; +import org.jspecify.annotations.Nullable; import org.junit.platform.console.options.CommandResult; import org.junit.platform.launcher.listeners.TestExecutionSummary; @@ -25,6 +28,8 @@ class ConsoleLauncherWrapperResult implements TestExecutionSummary { final String out; final String err; final int code; + + @Nullable private final TestExecutionSummary summary; ConsoleLauncherWrapperResult(String[] args, String out, String err, CommandResult result) { @@ -46,114 +51,118 @@ private void checkTestExecutionSummaryState() { @Override public long getTimeStarted() { checkTestExecutionSummaryState(); - return summary.getTimeStarted(); + return requiredSummary().getTimeStarted(); } @Override public long getTimeFinished() { checkTestExecutionSummaryState(); - return summary.getTimeFinished(); + return requiredSummary().getTimeFinished(); } @Override public long getTotalFailureCount() { checkTestExecutionSummaryState(); - return summary.getTotalFailureCount(); + return requiredSummary().getTotalFailureCount(); } @Override public long getContainersFoundCount() { checkTestExecutionSummaryState(); - return summary.getContainersFoundCount(); + return requiredSummary().getContainersFoundCount(); } @Override public long getContainersStartedCount() { checkTestExecutionSummaryState(); - return summary.getContainersStartedCount(); + return requiredSummary().getContainersStartedCount(); } @Override public long getContainersSkippedCount() { checkTestExecutionSummaryState(); - return summary.getContainersSkippedCount(); + return requiredSummary().getContainersSkippedCount(); } @Override public long getContainersAbortedCount() { checkTestExecutionSummaryState(); - return summary.getContainersAbortedCount(); + return requiredSummary().getContainersAbortedCount(); } @Override public long getContainersSucceededCount() { checkTestExecutionSummaryState(); - return summary.getContainersSucceededCount(); + return requiredSummary().getContainersSucceededCount(); } @Override public long getContainersFailedCount() { checkTestExecutionSummaryState(); - return summary.getContainersFailedCount(); + return requiredSummary().getContainersFailedCount(); } @Override public long getTestsFoundCount() { checkTestExecutionSummaryState(); - return summary.getTestsFoundCount(); + return requiredSummary().getTestsFoundCount(); } @Override public long getTestsStartedCount() { checkTestExecutionSummaryState(); - return summary.getTestsStartedCount(); + return requiredSummary().getTestsStartedCount(); } @Override public long getTestsSkippedCount() { checkTestExecutionSummaryState(); - return summary.getTestsSkippedCount(); + return requiredSummary().getTestsSkippedCount(); } @Override public long getTestsAbortedCount() { checkTestExecutionSummaryState(); - return summary.getTestsAbortedCount(); + return requiredSummary().getTestsAbortedCount(); } @Override public long getTestsSucceededCount() { checkTestExecutionSummaryState(); - return summary.getTestsSucceededCount(); + return requiredSummary().getTestsSucceededCount(); } @Override public long getTestsFailedCount() { checkTestExecutionSummaryState(); - return summary.getTestsFailedCount(); + return requiredSummary().getTestsFailedCount(); } @Override public void printTo(PrintWriter writer) { checkTestExecutionSummaryState(); - summary.printTo(writer); + requiredSummary().printTo(writer); } @Override public void printFailuresTo(PrintWriter writer) { checkTestExecutionSummaryState(); - summary.printFailuresTo(writer); + requiredSummary().printFailuresTo(writer); } @Override public void printFailuresTo(PrintWriter writer, int maxStackTraceLines) { checkTestExecutionSummaryState(); - summary.printFailuresTo(writer, maxStackTraceLines); + requiredSummary().printFailuresTo(writer, maxStackTraceLines); } @Override public List getFailures() { checkTestExecutionSummaryState(); - return summary.getFailures(); + return requiredSummary().getFailures(); + } + + private TestExecutionSummary requiredSummary() { + return requireNonNull(summary); } } diff --git a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java index f6852850705b..0bb925ef8bb1 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/options/CommandLineOptionsParsingTests.java @@ -29,6 +29,7 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; +import static org.mockito.Mockito.mock; import java.io.File; import java.io.IOException; @@ -708,12 +709,12 @@ Result parseArgLine(String argLine) throws IOException { abstract Result parseArgLine(String argLine) throws IOException; private static String[] split(String argLine) { - return "".equals(argLine) ? new String[0] : argLine.split("\\s+"); + return argLine.isEmpty() ? new String[0] : argLine.split("\\s+"); } } private static Result parse(String... args) { - ExecuteTestsCommand command = new ExecuteTestsCommand((__, ___) -> null); + ExecuteTestsCommand command = new ExecuteTestsCommand((__, ___) -> mock()); command.parseArgs(args); return new Result(command.toTestDiscoveryOptions(), command.toTestConsoleOutputOptions()); } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/CompositeTestDescriptorVisitorTests.java b/platform-tests/src/test/java/org/junit/platform/engine/CompositeTestDescriptorVisitorTests.java index 88ee3f0ed7aa..675de2bd7002 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/CompositeTestDescriptorVisitorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/CompositeTestDescriptorVisitorTests.java @@ -22,6 +22,7 @@ class CompositeTestDescriptorVisitorTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void checksPreconditions() { assertThrows(PreconditionViolationException.class, Visitor::composite); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java b/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java index 1152290acd19..0a8bf6fae4cf 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/TestTagTests.java @@ -28,6 +28,7 @@ */ class TestTagTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void validSyntax() { // @formatter:off @@ -65,6 +66,7 @@ void factory() { assertEquals("foo-tag", TestTag.create("\t foo-tag \n").getName()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void factoryPreconditions() { assertSyntaxViolation(null); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdFormatTests.java b/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdFormatTests.java index 47d1913f19e2..bedc9014524f 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdFormatTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdFormatTests.java @@ -10,9 +10,9 @@ package org.junit.platform.engine; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -115,7 +115,7 @@ interface ParsingTestTrait { @Test default void parseMalformedUid() { Throwable throwable = assertThrows(JUnitException.class, () -> getFormat().parse("malformed UID")); - assertTrue(throwable.getMessage().contains("malformed UID")); + assertThat(throwable).hasMessageContaining("malformed UID"); } @Test diff --git a/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdTests.java b/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdTests.java index 60a907427d34..4a18ec05cf05 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/UniqueIdTests.java @@ -123,6 +123,7 @@ void appendingSegmentInstance() { assertSegment(uniqueId.getSegments().get(2), "t2", "v2"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void appendingNullIsNotAllowed() { var uniqueId = UniqueId.forEngine(ENGINE_ID); @@ -229,6 +230,7 @@ void additionalSegmentMakesItNotEqual() { @Nested class Prefixing { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullIsNotAPrefix() { var id = UniqueId.forEngine(ENGINE_ID); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/ClassNameFilterTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/ClassNameFilterTests.java index fd14be421e26..158f086fae47 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/ClassNameFilterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/ClassNameFilterTests.java @@ -23,6 +23,7 @@ */ class ClassNameFilterTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void includeClassNamePatternsChecksPreconditions() { assertThatThrownBy(() -> ClassNameFilter.includeClassNamePatterns((String[]) null)) // @@ -85,6 +86,7 @@ void includeClassNamePatternsWithMultiplePatterns() { + secondRegex + "'"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void excludeClassNamePatternsChecksPreconditions() { assertThatThrownBy(() -> ClassNameFilter.excludeClassNamePatterns((String[]) null)) // diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index 7d649513deaf..fdc03244c95a 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -70,6 +70,7 @@ class DiscoverySelectorsTests { @Nested class SelectUriTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectUriByName() { assertViolatesPrecondition(() -> selectUri((String) null)); @@ -82,6 +83,7 @@ void selectUriByName() { assertEquals(uri, selector.getUri().toString()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectUriByURI() { assertViolatesPrecondition(() -> selectUri((URI) null)); @@ -107,6 +109,7 @@ void parseUriSelector() { .isEqualTo(URI.create("https://junit.org")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectFileByName() { assertViolatesPrecondition(() -> selectFile((String) null)); @@ -120,6 +123,7 @@ void selectFileByName() { assertEquals(Path.of(path), selector.getPath()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectFileByNameAndPosition() { var filePosition = FilePosition.from(12, 34); @@ -135,6 +139,7 @@ void selectFileByNameAndPosition() { assertEquals(filePosition, selector.getPosition().orElseThrow()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectFileByFileReference() throws Exception { assertViolatesPrecondition(() -> selectFile((File) null)); @@ -151,6 +156,7 @@ void selectFileByFileReference() throws Exception { assertEquals(Path.of(path), selector.getPath()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectFileByFileReferenceAndPosition() throws Exception { var filePosition = FilePosition.from(12, 34); @@ -227,6 +233,7 @@ void parseFileSelectorWithAbsolutePathAndFilePosition() { Optional.of(filePosition)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectDirectoryByName() { assertViolatesPrecondition(() -> selectDirectory((String) null)); @@ -240,6 +247,7 @@ void selectDirectoryByName() { assertEquals(Path.of(path), selector.getPath()); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectDirectoryByFileReference() throws Exception { assertViolatesPrecondition(() -> selectDirectory((File) null)); @@ -287,6 +295,7 @@ void parseDirectorySelectorWithAbsolutePath() { .containsExactly(path, new File(path), Path.of(path)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectClasspathResourcesPreconditions() { assertViolatesPrecondition(() -> selectClasspathResource((String) null)); @@ -330,6 +339,7 @@ void getMissingClasspathResources() { assertViolatesPrecondition(selector::getClasspathResources); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectClasspathResourcesWithFilePosition() { var filePosition = FilePosition.from(12, 34); @@ -397,7 +407,7 @@ public String getName() { @Override public URI getUri() { - return null; + throw new UnsupportedOperationException(); } } } @@ -420,6 +430,7 @@ void parseModuleByName() { .isEqualTo("java.base"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectModuleByNamePreconditions() { assertViolatesPrecondition(() -> selectModule(null)); @@ -434,6 +445,7 @@ void selectModulesByNames() { assertThat(names).containsExactlyInAnyOrder("b", "a"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectModulesByNamesPreconditions() { assertViolatesPrecondition(() -> selectModules(null)); @@ -533,6 +545,7 @@ void selectClassByNameWithExplicitClassLoader() throws Exception { @Nested class SelectMethodTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(className, methodName)") void selectMethodByClassNameAndMethodNamePreconditions() { @@ -544,6 +557,7 @@ void selectMethodByClassNameAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectMethod(" ", "method")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(className, methodName, parameterTypeNames)") void selectMethodByClassNameMethodNameAndParameterTypeNamesPreconditions() { @@ -556,6 +570,7 @@ void selectMethodByClassNameMethodNameAndParameterTypeNamesPreconditions() { assertViolatesPrecondition(() -> selectMethod("TestClass", "method", (String) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(className, methodName, parameterTypes)") void selectMethodByClassNameMethodNameAndParameterTypesPreconditions() { @@ -569,6 +584,7 @@ void selectMethodByClassNameMethodNameAndParameterTypesPreconditions() { assertViolatesPrecondition(() -> selectMethod("TestClass", "method", new Class[] { int.class, null })); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(class, methodName)") void selectMethodByClassAndMethodNamePreconditions() { @@ -578,6 +594,7 @@ void selectMethodByClassAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectMethod((Class) null, "method")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(class, methodName, parameterTypeNames)") void selectMethodByClassMethodNameAndParameterTypeNamesPreconditions() { @@ -588,6 +605,7 @@ void selectMethodByClassMethodNameAndParameterTypeNamesPreconditions() { assertViolatesPrecondition(() -> selectMethod(testClass(), "method", (String) null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectMethod(class, method)") void selectMethodByClassAndMethodPreconditions() { @@ -1131,6 +1149,7 @@ void selectDoubleNestedClassByClassNames() { assertThat(parseIdentifier(selector)).isEqualTo(selector); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void selectNestedClassPreconditions() { assertViolatesPrecondition(() -> selectNestedClass(null, "ClassName")); @@ -1298,6 +1317,7 @@ void selectDoubleNestedMethodByEnclosingClassNamesAndMethodName() throws Excepti assertThat(parseIdentifier(selector)).isEqualTo(selector); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName)") void selectNestedMethodByEnclosingClassNamesAndMethodNamePreconditions() { @@ -1309,6 +1329,7 @@ void selectNestedMethodByEnclosingClassNamesAndMethodNamePreconditions() { assertViolatesPrecondition(() -> selectNestedMethod(List.of("ClassName"), "ClassName", " ")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName, parameterTypeNames)") void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypeNamesPreconditions() { @@ -1325,6 +1346,7 @@ void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypeNamesPreco /** * @since 1.10 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClassNames, nestedClassName, methodName, parameterTypes)") void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypesPreconditions() { @@ -1343,6 +1365,7 @@ void selectNestedMethodByEnclosingClassNamesMethodNameAndParameterTypesPrecondit /** * @since 1.10 */ + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test @DisplayName("Preconditions: selectNestedMethod(enclosingClasses, nestedClass, methodName, parameterTypes)") void selectNestedMethodByEnclosingClassesClassMethodNameAndParameterTypesPreconditions() { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/PackageNameFilterTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/PackageNameFilterTests.java index b93ba77a34c9..fb52e9c9858b 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/PackageNameFilterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/PackageNameFilterTests.java @@ -23,6 +23,7 @@ */ class PackageNameFilterTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void includePackageChecksPreconditions() { assertThatThrownBy(() -> PackageNameFilter.includePackageNames((String[]) null)) // @@ -74,6 +75,7 @@ void includePackageWithMultiplePackages() { + includedPackage2 + "'"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void excludePackageChecksPreconditions() { assertThatThrownBy(() -> PackageNameFilter.excludePackageNames((String[]) null)) // diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java index fe064e60e58b..c2f4fa7f0fb2 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/config/PrefixedConfigurationParametersTests.java @@ -37,6 +37,7 @@ class PrefixedConfigurationParametersTests { @Mock private ConfigurationParameters delegate; + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> new PrefixedConfigurationParameters(null, "example.")); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClassSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClassSourceTests.java index 078c9f629c76..e1ee9cd4e0e3 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClassSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClassSourceTests.java @@ -39,6 +39,7 @@ Stream createSerializableInstances() { ); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> ClassSource.from((String) null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSourceTests.java index 9141a47fd5bb..a84a471d9b92 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSourceTests.java @@ -38,6 +38,7 @@ Stream createSerializableInstances() { return Stream.of(ClasspathResourceSource.from(FOO_RESOURCE)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> ClasspathResourceSource.from((String) null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/CompositeTestSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/CompositeTestSourceTests.java index 2702e480ae33..f09f0efbcaa3 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/CompositeTestSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/CompositeTestSourceTests.java @@ -37,6 +37,7 @@ Stream createSerializableInstances() { return Stream.of(CompositeTestSource.from(sources)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void createCompositeTestSourceFromNullList() { assertThrows(PreconditionViolationException.class, () -> CompositeTestSource.from(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DefaultUriSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DefaultUriSourceTests.java index 03f5edd70f6b..f68fc5e6d8c3 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DefaultUriSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/DefaultUriSourceTests.java @@ -33,6 +33,7 @@ Stream createSerializableInstances() { return Stream.of(new DefaultUriSource(URI.create("sample://instance"))); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullSourceUriYieldsException() { assertThrows(PreconditionViolationException.class, () -> new DefaultUriSource(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/FileSystemSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/FileSystemSourceTests.java index 307193a02774..9f6723b85e31 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/FileSystemSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/FileSystemSourceTests.java @@ -34,6 +34,7 @@ Stream createSerializableInstances() { FileSource.from(new File("file.and.position"), FilePosition.from(42, 23))); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void nullSourceFileOrDirectoryYieldsException() { assertThrows(PreconditionViolationException.class, () -> FileSource.from(null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/MethodSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/MethodSourceTests.java index 4f97624c7ce6..df9106349d16 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/MethodSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/MethodSourceTests.java @@ -57,6 +57,7 @@ void equalsAndHashCodeForMethodSource() throws Exception { assertEqualsAndHashCode(MethodSource.from(method1), MethodSource.from(method1), MethodSource.from(method2)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void instantiatingWithNullNamesShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from("foo", null)); @@ -75,11 +76,13 @@ void instantiatingWithBlankNamesShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from(" ", "foo")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void instantiationWithNullMethodShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, () -> MethodSource.from(null)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void instantiationWithNullClassOrMethodShouldThrowPreconditionViolationException() { assertThrows(PreconditionViolationException.class, diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/PackageSourceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/PackageSourceTests.java index 8da7f16a8545..f964343c4c2d 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/PackageSourceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/PackageSourceTests.java @@ -32,6 +32,7 @@ Stream createSerializableInstances() { return Stream.of(PackageSource.from("package.source")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void packageSourceFromNullPackageName() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from((String) null)); @@ -42,6 +43,7 @@ void packageSourceFromEmptyPackageName() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from(" ")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void packageSourceFromNullPackageReference() { assertThrows(PreconditionViolationException.class, () -> PackageSource.from((Package) null)); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorTests.java index 2d7d96308ecd..b1b0591d5b3a 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorTests.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.Set; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestSource; import org.junit.platform.engine.TestTag; @@ -57,7 +58,7 @@ public Optional getParent() { } @Override - public void setParent(TestDescriptor parent) { + public void setParent(@Nullable TestDescriptor parent) { throw new UnsupportedOperationException("Not implemented"); } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategyTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategyTests.java index 9a55301ab6af..d4683aad6d7b 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategyTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/DefaultParallelExecutionConfigurationStrategyTests.java @@ -49,6 +49,7 @@ void fixedStrategyCreatesValidConfiguration() { assertThat(configuration.getMinimumRunnable()).isEqualTo(42); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + 42); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); + assertThat(configuration.getSaturatePredicate()).isNotNull(); assertThat(configuration.getSaturatePredicate().test(null)).isTrue(); } @@ -62,6 +63,7 @@ void fixedSaturateStrategyCreatesValidConfiguration() { var configuration = strategy.createConfiguration(configParams); assertThat(configuration.getParallelism()).isEqualTo(42); assertThat(configuration.getMaxPoolSize()).isEqualTo(42); + assertThat(configuration.getSaturatePredicate()).isNotNull(); assertThat(configuration.getSaturatePredicate().test(null)).isFalse(); } @@ -78,6 +80,7 @@ void dynamicStrategyCreatesValidConfiguration() { assertThat(configuration.getMinimumRunnable()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMaxPoolSize()).isEqualTo(256 + (availableProcessors * 2)); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); + assertThat(configuration.getSaturatePredicate()).isNotNull(); assertThat(configuration.getSaturatePredicate().test(null)).isTrue(); } @@ -96,6 +99,7 @@ void dynamicSaturateStrategyCreatesValidConfiguration() { assertThat(configuration.getMinimumRunnable()).isEqualTo(availableProcessors * 2); assertThat(configuration.getMaxPoolSize()).isEqualTo(availableProcessors * 6); assertThat(configuration.getKeepAliveSeconds()).isEqualTo(30); + assertThat(configuration.getSaturatePredicate()).isNotNull(); assertThat(configuration.getSaturatePredicate().test(null)).isFalse(); } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorServiceTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorServiceTests.java index 59dfbba0f789..a31f31598a4a 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorServiceTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorServiceTests.java @@ -33,6 +33,7 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicReference; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.junit.jupiter.api.function.Executable; @@ -105,6 +106,7 @@ static List incompatibleLockCombinations() { ); } + @SuppressWarnings("NullAway") @ParameterizedTest @MethodSource("incompatibleLockCombinations") void defersTasksWithIncompatibleLocks(Set initialResources, @@ -166,6 +168,7 @@ static List compatibleLockCombinations() { ); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @ParameterizedTest @MethodSource("compatibleLockCombinations") void canWorkStealTaskWithCompatibleLocks(Set initialResources, @@ -198,6 +201,8 @@ void defersTasksWithIncompatibleLocksOnMultipleLevels() throws Throwable { var deferred = new ConcurrentHashMap(); var deferredTasks = new CopyOnWriteArrayList(); + + @SuppressWarnings("NullAway") TaskEventListener taskEventListener = testTask -> { deferredTasks.add(testTask); deferred.get(testTask).countDown(); @@ -305,9 +310,11 @@ static final class DummyTestTask implements TestTask { private final ResourceLock resourceLock; private final Executable action; + @Nullable private volatile String threadName; + private final CountDownLatch started = new CountDownLatch(1); - private final CompletableFuture completion = new CompletableFuture<>(); + private final CompletableFuture<@Nullable Void> completion = new CompletableFuture<>(); DummyTestTask(String identifier, ResourceLock resourceLock, Executable action) { this.identifier = identifier; diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java index 81b1797c8b2b..cf5b418d2a52 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java @@ -189,6 +189,7 @@ void getWithTypeSafety() { assertEquals(value, requiredTypeValue); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; @@ -239,6 +240,7 @@ void getOrComputeIfAbsentWithTypeSafety() { assertEquals(value, computedValue); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getOrComputeIfAbsentWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; @@ -285,6 +287,7 @@ void removeWithTypeSafety() { assertNull(store.get(namespace, key)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void removeWithTypeSafetyAndPrimitiveValueType() { String key = "enigma"; diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java index 57f716bb0e5e..af47b9fabd3d 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/MethodFilterTests.java @@ -39,6 +39,7 @@ class MethodFilterTests { private static final TestDescriptor CLASS2_TEST1 = methodTestDescriptor("class2", Class2.class, "test1"); private static final TestDescriptor CLASS2_TEST2 = methodTestDescriptor("class2", Class2.class, "test2"); + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void includeMethodNamePatternsChecksPreconditions() { assertThatThrownBy(() -> includeMethodNamePatterns((String[]) null)) // @@ -86,6 +87,7 @@ void includeMultipleMethodNamePatterns() { firstRegex, secondRegex)); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void excludeMethodNamePatternsChecksPreconditions() { assertThatThrownBy(() -> excludeMethodNamePatterns((String[]) null)) // diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/TagFilterTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/TagFilterTests.java index d81e7879ef0b..734bbcdb0a34 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/TagFilterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/TagFilterTests.java @@ -20,6 +20,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Tag; import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; @@ -60,7 +61,8 @@ void includeTagsWithInvalidSyntax() { // @formatter:on } - private void assertSyntaxViolationForIncludes(String tag) { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + private void assertSyntaxViolationForIncludes(@Nullable String tag) { var exception = assertThrows(PreconditionViolationException.class, () -> includeTags(tag)); assertThat(exception).hasMessageStartingWith("Unable to parse tag expression"); } @@ -77,7 +79,8 @@ void excludeTagsWithInvalidSyntax() { // @formatter:on } - private void assertSyntaxViolationForExcludes(String tag) { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + private void assertSyntaxViolationForExcludes(@Nullable String tag) { var exception = assertThrows(PreconditionViolationException.class, () -> excludeTags(tag)); assertThat(exception).hasMessageStartingWith("Unable to parse tag expression"); } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java index cc530eed7924..adf70020ca02 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/DefaultLauncherTests.java @@ -129,6 +129,7 @@ void discoverEmptyTestPlanWithEngineWithoutAnyTests() { void discoverTestPlanForEngineThatReturnsNullForItsRootDescriptor() { TestEngine engine = new TestEngineStub("some-engine-id") { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { return null; @@ -149,6 +150,7 @@ public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId void discoverErrorTestDescriptorForEngineThatThrowsInDiscoveryPhase(Class throwableClass) { TestEngine engine = new TestEngineStub("my-engine-id") { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId uniqueId) { try { @@ -427,7 +429,7 @@ void withoutConfigurationParameters_LauncherPassesEmptyConfigurationParametersIn var launcher = createLauncher(engine); launcher.execute(request().build()); - var configurationParameters = engine.requestForExecution.getConfigurationParameters(); + var configurationParameters = requireNonNull(engine.requestForExecution).getConfigurationParameters(); assertThat(configurationParameters.get("key")).isNotPresent(); } @@ -438,7 +440,7 @@ void withConfigurationParameters_LauncherPassesPopulatedConfigurationParametersI var launcher = createLauncher(engine); launcher.execute(request().configurationParameter("key", "value").build()); - var configurationParameters = engine.requestForExecution.getConfigurationParameters(); + var configurationParameters = requireNonNull(engine.requestForExecution).getConfigurationParameters(); assertThat(configurationParameters.get("key")).isPresent(); assertThat(configurationParameters.get("key")).contains("value"); } @@ -453,7 +455,7 @@ void withoutConfigurationParameters_LookupFallsBackToSystemProperty() { var launcher = createLauncher(engine); launcher.execute(request().build()); - var configurationParameters = engine.requestForExecution.getConfigurationParameters(); + var configurationParameters = requireNonNull(engine.requestForExecution).getConfigurationParameters(); var optionalFoo = configurationParameters.get(FOO); assertTrue(optionalFoo.isPresent(), "foo should have been picked up via system property"); assertEquals(BAR, optionalFoo.get(), "foo property"); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/ExecutionListenerAdapterTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/ExecutionListenerAdapterTests.java index d8a29dc6e105..f1c05f80fc37 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/ExecutionListenerAdapterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/ExecutionListenerAdapterTests.java @@ -16,6 +16,7 @@ import java.util.Map; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.TestDescriptor; @@ -65,7 +66,10 @@ void nothing() { static class MockTestExecutionListener implements TestExecutionListener { + @Nullable public TestIdentifier testIdentifier; + + @Nullable public ReportEntry entry; @Override diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigTests.java index c3b518dcd3b2..7b3a92d90e5b 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigTests.java @@ -30,6 +30,7 @@ */ class LauncherConfigTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThrows(PreconditionViolationException.class, diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java index b2608e60fcba..05a74b2bb9ee 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java @@ -59,6 +59,7 @@ void reset() { System.clearProperty(KEY); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void constructorPreconditions() { assertThrows(PreconditionViolationException.class, () -> fromMap(null)); @@ -67,6 +68,7 @@ void constructorPreconditions() { assertThrows(PreconditionViolationException.class, () -> fromMapAndFile(Map.of(), " ")); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void getPreconditions() { ConfigurationParameters configParams = fromMap(Map.of()); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index c6f4a74cd64c..99c2f2ecc599 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.core; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -62,6 +63,7 @@ */ class LauncherFactoryTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThrows(PreconditionViolationException.class, () -> LauncherFactory.create(null)); @@ -328,7 +330,7 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult } }); - assertThat(result.get().getThrowable().orElseThrow()) // + assertThat(requireNonNull(result.get()).getThrowable().orElseThrow()) // .hasRootCauseMessage("from execution") // .hasStackTraceContaining(TestLauncherInterceptor1.class.getName() + ".intercept(") // .hasStackTraceContaining(TestLauncherInterceptor2.class.getName() + ".intercept("); @@ -577,6 +579,7 @@ public void launcherSessionClosed(LauncherSession session) { .getStore() // .get(Namespace.GLOBAL, "sessionResource", CloseTrackingResource.class); + assertThat(sessionResource).isNotNull(); assertThat(sessionResource.isClosed()).isFalse(); } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/ListenerRegistryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/ListenerRegistryTests.java index 1c3a08783764..9f7052c2fd06 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/ListenerRegistryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/ListenerRegistryTests.java @@ -13,14 +13,17 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertThrows; +import java.util.List; + import org.junit.jupiter.api.Test; import org.junit.platform.commons.PreconditionViolationException; public class ListenerRegistryTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void registerWithNullArray() { - var registry = ListenerRegistry.create(l -> l.getFirst()); + var registry = ListenerRegistry.create(List::getFirst); var exception = assertThrows(PreconditionViolationException.class, () -> registry.addAll((Object[]) null)); @@ -29,16 +32,17 @@ void registerWithNullArray() { @Test void registerWithEmptyArray() { - var registry = ListenerRegistry.create(l -> l.getFirst()); + var registry = ListenerRegistry.create(List::getFirst); var exception = assertThrows(PreconditionViolationException.class, registry::addAll); assertThat(exception).hasMessageContaining("listeners array must not be null or empty"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void registerWithArrayContainingNullElements() { - var registry = ListenerRegistry.create(l -> l.getFirst()); + var registry = ListenerRegistry.create(List::getFirst); var exception = assertThrows(PreconditionViolationException.class, () -> registry.addAll(new Object[] { null })); diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/StreamInterceptorTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/StreamInterceptorTests.java index 2b5f35ca86bb..cb8aa8856663 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/StreamInterceptorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/StreamInterceptorTests.java @@ -20,6 +20,7 @@ import java.io.PrintStream; import java.util.stream.IntStream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AutoClose; import org.junit.jupiter.api.Test; @@ -32,6 +33,7 @@ class StreamInterceptorTests { PrintStream targetStream = new PrintStream(originalOut); @AutoClose + @Nullable StreamInterceptor streamInterceptor; @Test diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java index dd916c324636..35fd8cc2692d 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListenerIntegrationTests.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.listeners; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; @@ -44,6 +45,7 @@ import java.util.stream.Stream; import org.assertj.core.api.Condition; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; @@ -214,6 +216,7 @@ private List executeTests(Map configurationParameters, C .build(); LauncherFactory.create().execute(request, new TestExecutionListener() { + @Nullable private TestPlan testPlan; @Override @@ -227,7 +230,8 @@ public void executionSkipped(TestIdentifier testIdentifier, String reason) { uniqueIds.add(testIdentifier.getUniqueId()); } else { - this.testPlan.getChildren(testIdentifier).forEach(child -> executionSkipped(child, reason)); + requireNonNull(this.testPlan).getChildren(testIdentifier).forEach( + child -> executionSkipped(child, reason)); } } diff --git a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java index 125a8c2a8e81..efa86382c9bc 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilderTests.java @@ -691,7 +691,7 @@ public Optional getBoolean(String key) { @Override public Set keySet() { - return null; + return Set.of(); } } diff --git a/platform-tests/src/test/java/org/junit/platform/testkit/engine/EventsTests.java b/platform-tests/src/test/java/org/junit/platform/testkit/engine/EventsTests.java index 2d519bede3b6..bd8009c8f4ff 100644 --- a/platform-tests/src/test/java/org/junit/platform/testkit/engine/EventsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/testkit/engine/EventsTests.java @@ -10,9 +10,9 @@ package org.junit.platform.testkit.engine; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.platform.testkit.engine.EventConditions.engine; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; @@ -171,7 +171,7 @@ void assertEventsMatchLooselyInOrderWithAllEventsInWrongOrderFails() { ); var error = assertThrows(AssertionFailedError.class, willFail); - assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); + assertThat(error).hasMessageContaining("Conditions are not in the correct order."); } @Test @@ -201,7 +201,7 @@ void assertEventsMatchLooselyInOrderWithASubsetInWrongOrderFails() { ); var error = assertThrows(AssertionFailedError.class, willFail); - assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); + assertThat(error).hasMessageContaining("Conditions are not in the correct order."); } @Test @@ -266,7 +266,7 @@ void assertEventsMatchLooselyInOrderWithSecondAndLastEventInBadOrderFails() { ); var error = assertThrows(AssertionFailedError.class, willFail); - assertTrue(error.getMessage().contains("Conditions are not in the correct order.")); + assertThat(error).hasMessageContaining("Conditions are not in the correct order."); } @Test @@ -281,7 +281,7 @@ void assertEventsMatchLooselyInOrderWithTooManyEventsFails() { event(engine(), finishedSuccessfully())); var error = assertThrows(AssertionError.class, willFail); - assertTrue(error.getMessage().endsWith("to be less than or equal to 4 but was 6")); + assertThat(error).hasMessageEndingWith("to be less than or equal to 4 but was 6"); } } diff --git a/platform-tests/src/test/java/org/junit/platform/testkit/engine/NestedContainerEventConditionTests.java b/platform-tests/src/test/java/org/junit/platform/testkit/engine/NestedContainerEventConditionTests.java index d109969008b1..dcece1a3a020 100644 --- a/platform-tests/src/test/java/org/junit/platform/testkit/engine/NestedContainerEventConditionTests.java +++ b/platform-tests/src/test/java/org/junit/platform/testkit/engine/NestedContainerEventConditionTests.java @@ -41,6 +41,7 @@ */ class NestedContainerEventConditionTests { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void preconditions() { assertThatExceptionOfType(PreconditionViolationException.class)// diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index a88d8b140243..b321d09be1da 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -7,6 +7,7 @@ import java.time.Duration plugins { id("junitbuild.build-parameters") + id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") } From 0a0d7ece816b1bcff0244274de5e7c502a2921ba Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 15:33:15 +0200 Subject: [PATCH 135/521] Enable NullAway in documentation --- documentation/documentation.gradle.kts | 1 + .../src/test/java/example/ClassTemplateDemo.java | 4 ++++ .../src/test/java/example/DynamicTestsDemo.java | 2 +- .../src/test/java/example/FirstCustomEngine.java | 4 ++++ .../src/test/java/example/ParameterizedTestDemo.java | 2 ++ .../src/test/java/example/SecondCustomEngine.java | 4 ++++ .../src/test/java/example/TestingAStackDemo.java | 4 ++-- .../src/test/java/example/callbacks/package-info.java | 5 +++++ .../test/java/example/defaultmethods/package-info.java | 5 +++++ .../src/test/java/example/exception/package-info.java | 5 +++++ .../java/example/extensions/HttpServerExtension.java | 5 ++++- .../test/java/example/extensions/RandomNumberDemo.java | 4 ++++ .../java/example/extensions/RandomNumberExtension.java | 3 ++- .../src/test/java/example/extensions/package-info.java | 5 +++++ .../test/java/example/interceptor/package-info.java | 5 +++++ documentation/src/test/java/example/package-info.java | 5 +++++ .../java/example/registration/DocumentationDemo.java | 10 +++++++--- .../test/java/example/registration/package-info.java | 5 +++++ .../src/test/java/example/session/HttpTests.java | 3 +++ .../src/test/java/example/session/package-info.java | 5 +++++ .../example/sharedresources/SharedResourceDemo.java | 1 + .../java/example/sharedresources/package-info.java | 5 +++++ .../test/java/example/testinterface/package-info.java | 5 +++++ .../src/test/java/example/testkit/package-info.java | 5 +++++ .../src/test/java/example/timing/TimingExtension.java | 7 +++++-- .../src/test/java/example/timing/package-info.java | 5 +++++ .../src/test/java/extensions/package-info.java | 5 +++++ .../java21/example/ParameterizedLifecycleDemo.java | 10 ++++++++++ .../src/test/java21/example/package-info.java | 5 +++++ .../junitbuild.java-nullability-conventions.gradle.kts | 2 +- 30 files changed, 125 insertions(+), 11 deletions(-) create mode 100644 documentation/src/test/java/example/callbacks/package-info.java create mode 100644 documentation/src/test/java/example/defaultmethods/package-info.java create mode 100644 documentation/src/test/java/example/exception/package-info.java create mode 100644 documentation/src/test/java/example/extensions/package-info.java create mode 100644 documentation/src/test/java/example/interceptor/package-info.java create mode 100644 documentation/src/test/java/example/package-info.java create mode 100644 documentation/src/test/java/example/registration/package-info.java create mode 100644 documentation/src/test/java/example/session/package-info.java create mode 100644 documentation/src/test/java/example/sharedresources/package-info.java create mode 100644 documentation/src/test/java/example/testinterface/package-info.java create mode 100644 documentation/src/test/java/example/testkit/package-info.java create mode 100644 documentation/src/test/java/example/timing/package-info.java create mode 100644 documentation/src/test/java/extensions/package-info.java create mode 100644 documentation/src/test/java21/example/package-info.java diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index e079ac81867e..2c34e5fda5e5 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -18,6 +18,7 @@ plugins { alias(libs.plugins.plantuml) id("junitbuild.build-parameters") id("junitbuild.java-multi-release-test-sources") + id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") } diff --git a/documentation/src/test/java/example/ClassTemplateDemo.java b/documentation/src/test/java/example/ClassTemplateDemo.java index d0291dedfbdf..d1035b434348 100644 --- a/documentation/src/test/java/example/ClassTemplateDemo.java +++ b/documentation/src/test/java/example/ClassTemplateDemo.java @@ -19,6 +19,7 @@ import java.util.List; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.ClassTemplate; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ClassTemplateInvocationContext; @@ -37,6 +38,9 @@ class ClassTemplateDemo { // tag::custom_line_break[] = unmodifiableList(Arrays.asList("apple", "banana", "lemon")); + //end::user_guide[] + @Nullable + //tag::user_guide[] private String fruit; @Test diff --git a/documentation/src/test/java/example/DynamicTestsDemo.java b/documentation/src/test/java/example/DynamicTestsDemo.java index c5643890b2d3..f6adb6b2117b 100644 --- a/documentation/src/test/java/example/DynamicTestsDemo.java +++ b/documentation/src/test/java/example/DynamicTestsDemo.java @@ -47,7 +47,7 @@ class DynamicTestsDemo { @TestFactory // end::user_guide[] @Tag("exclude") - DynamicTest dummy() { return null; } + DynamicTest dummy() { return dynamicTest("dummy", () -> {}); } // tag::user_guide[] List dynamicTestsWithInvalidReturnType() { return Arrays.asList("Hello"); diff --git a/documentation/src/test/java/example/FirstCustomEngine.java b/documentation/src/test/java/example/FirstCustomEngine.java index efd9b14a7f0c..5fd886fd65e8 100644 --- a/documentation/src/test/java/example/FirstCustomEngine.java +++ b/documentation/src/test/java/example/FirstCustomEngine.java @@ -18,6 +18,7 @@ import java.io.UncheckedIOException; import java.net.ServerSocket; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -32,6 +33,9 @@ */ public class FirstCustomEngine implements TestEngine { + //end::user_guide[] + @Nullable + //tag::user_guide[] public ServerSocket socket; @Override diff --git a/documentation/src/test/java/example/ParameterizedTestDemo.java b/documentation/src/test/java/example/ParameterizedTestDemo.java index b76647dc6861..a7312f584cc5 100644 --- a/documentation/src/test/java/example/ParameterizedTestDemo.java +++ b/documentation/src/test/java/example/ParameterizedTestDemo.java @@ -459,6 +459,7 @@ void testWithExplicitArgumentConversion( // end::explicit_conversion_example[] static + @SuppressWarnings({ "NullableProblems", "NullAway" }) // tag::explicit_conversion_example_ToStringArgumentConverter[] public class ToStringArgumentConverter extends SimpleArgumentConverter { @@ -474,6 +475,7 @@ protected Object convert(Object source, Class targetType) { // end::explicit_conversion_example_ToStringArgumentConverter[] static + @SuppressWarnings({ "NullableProblems", "NullAway", "ConstantValue" }) // tag::explicit_conversion_example_TypedArgumentConverter[] public class ToLengthArgumentConverter extends TypedArgumentConverter { diff --git a/documentation/src/test/java/example/SecondCustomEngine.java b/documentation/src/test/java/example/SecondCustomEngine.java index 3d11c13ac18d..ff90dfa8b983 100644 --- a/documentation/src/test/java/example/SecondCustomEngine.java +++ b/documentation/src/test/java/example/SecondCustomEngine.java @@ -17,6 +17,7 @@ import java.io.UncheckedIOException; import java.net.ServerSocket; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -32,6 +33,9 @@ */ public class SecondCustomEngine implements TestEngine { + //end::user_guide[] + @Nullable + //tag::user_guide[] public ServerSocket socket; @Override diff --git a/documentation/src/test/java/example/TestingAStackDemo.java b/documentation/src/test/java/example/TestingAStackDemo.java index 80b1ec495d83..c4ef3a5640dc 100644 --- a/documentation/src/test/java/example/TestingAStackDemo.java +++ b/documentation/src/test/java/example/TestingAStackDemo.java @@ -27,8 +27,6 @@ @DisplayName("A stack") class TestingAStackDemo { - Stack stack; - @Test @DisplayName("is instantiated with new Stack()") void isInstantiatedWithNew() { @@ -39,6 +37,8 @@ void isInstantiatedWithNew() { @DisplayName("when new") class WhenNew { + Stack stack; + @BeforeEach void createNewStack() { stack = new Stack<>(); diff --git a/documentation/src/test/java/example/callbacks/package-info.java b/documentation/src/test/java/example/callbacks/package-info.java new file mode 100644 index 000000000000..a58f6d3a9a52 --- /dev/null +++ b/documentation/src/test/java/example/callbacks/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.callbacks; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/defaultmethods/package-info.java b/documentation/src/test/java/example/defaultmethods/package-info.java new file mode 100644 index 000000000000..851eeadc2f84 --- /dev/null +++ b/documentation/src/test/java/example/defaultmethods/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.defaultmethods; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/exception/package-info.java b/documentation/src/test/java/example/exception/package-info.java new file mode 100644 index 000000000000..5c758dfba6c9 --- /dev/null +++ b/documentation/src/test/java/example/exception/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.exception; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/extensions/HttpServerExtension.java b/documentation/src/test/java/example/extensions/HttpServerExtension.java index 5ba23509d964..33a447468790 100644 --- a/documentation/src/test/java/example/extensions/HttpServerExtension.java +++ b/documentation/src/test/java/example/extensions/HttpServerExtension.java @@ -28,12 +28,15 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon return HttpServer.class.equals(parameterContext.getParameter().getType()); } + //end::user_guide[] + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + //tag::user_guide[] @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { ExtensionContext rootContext = extensionContext.getRoot(); ExtensionContext.Store store = rootContext.getStore(Namespace.GLOBAL); - String key = HttpServerResource.class.getName(); + Class key = HttpServerResource.class; HttpServerResource resource = store.getOrComputeIfAbsent(key, __ -> { try { HttpServerResource serverResource = new HttpServerResource(0); diff --git a/documentation/src/test/java/example/extensions/RandomNumberDemo.java b/documentation/src/test/java/example/extensions/RandomNumberDemo.java index e11b87ce5b52..6cdbb7cdb87b 100644 --- a/documentation/src/test/java/example/extensions/RandomNumberDemo.java +++ b/documentation/src/test/java/example/extensions/RandomNumberDemo.java @@ -10,6 +10,7 @@ package example.extensions; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -19,6 +20,9 @@ class RandomNumberDemo { // Use static randomNumber0 field anywhere in the test class, // including @BeforeAll or @AfterEach lifecycle methods. @Random + // end::user_guide[] + @Nullable + // tag::user_guide[] private static Integer randomNumber0; // Use randomNumber1 field in test methods and @BeforeEach diff --git a/documentation/src/test/java/example/extensions/RandomNumberExtension.java b/documentation/src/test/java/example/extensions/RandomNumberExtension.java index 666e6ffe9ae5..c3386b0972f1 100644 --- a/documentation/src/test/java/example/extensions/RandomNumberExtension.java +++ b/documentation/src/test/java/example/extensions/RandomNumberExtension.java @@ -17,6 +17,7 @@ import java.lang.reflect.Field; import java.util.function.Predicate; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; @@ -69,7 +70,7 @@ public Integer resolveParameter(ParameterContext pc, ExtensionContext ec) { return this.random.nextInt(); } - private void injectFields(Class testClass, Object testInstance, + private void injectFields(Class testClass, @Nullable Object testInstance, Predicate predicate) { predicate = predicate.and(field -> isInteger(field.getType())); diff --git a/documentation/src/test/java/example/extensions/package-info.java b/documentation/src/test/java/example/extensions/package-info.java new file mode 100644 index 000000000000..df450c1a5811 --- /dev/null +++ b/documentation/src/test/java/example/extensions/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.extensions; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/interceptor/package-info.java b/documentation/src/test/java/example/interceptor/package-info.java new file mode 100644 index 000000000000..ece161c1da00 --- /dev/null +++ b/documentation/src/test/java/example/interceptor/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.interceptor; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/package-info.java b/documentation/src/test/java/example/package-info.java new file mode 100644 index 000000000000..a2bcf4a4db17 --- /dev/null +++ b/documentation/src/test/java/example/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/registration/DocumentationDemo.java b/documentation/src/test/java/example/registration/DocumentationDemo.java index 59571061d7de..7512235d9dc3 100644 --- a/documentation/src/test/java/example/registration/DocumentationDemo.java +++ b/documentation/src/test/java/example/registration/DocumentationDemo.java @@ -12,6 +12,7 @@ import java.nio.file.Path; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterEachCallback; import org.junit.jupiter.api.extension.ExtensionContext; @@ -20,6 +21,9 @@ //tag::user_guide[] class DocumentationDemo { + //end::user_guide[] + @Nullable + //tag::user_guide[] static Path lookUpDocsDir() { // return path to docs dir // end::user_guide[] @@ -40,13 +44,13 @@ void generateDocumentation() { class DocumentationExtension implements AfterEachCallback { @SuppressWarnings("unused") - private final Path path; + private final @Nullable Path path; - private DocumentationExtension(Path path) { + private DocumentationExtension(@Nullable Path path) { this.path = path; } - static DocumentationExtension forPath(Path path) { + static DocumentationExtension forPath(@Nullable Path path) { return new DocumentationExtension(path); } diff --git a/documentation/src/test/java/example/registration/package-info.java b/documentation/src/test/java/example/registration/package-info.java new file mode 100644 index 000000000000..ceb3eb919fc2 --- /dev/null +++ b/documentation/src/test/java/example/registration/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.registration; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/session/HttpTests.java b/documentation/src/test/java/example/session/HttpTests.java index 97a13439a3e4..ed68c283380f 100644 --- a/documentation/src/test/java/example/session/HttpTests.java +++ b/documentation/src/test/java/example/session/HttpTests.java @@ -49,6 +49,9 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon return HttpServer.class.equals(parameterContext.getParameter().getType()); } + //end::user_guide[] + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + //tag::user_guide[] @Override public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return extensionContext diff --git a/documentation/src/test/java/example/session/package-info.java b/documentation/src/test/java/example/session/package-info.java new file mode 100644 index 000000000000..7f7249dfecf0 --- /dev/null +++ b/documentation/src/test/java/example/session/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.session; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/sharedresources/SharedResourceDemo.java b/documentation/src/test/java/example/sharedresources/SharedResourceDemo.java index 52b00c624471..4ca8e4a11efb 100644 --- a/documentation/src/test/java/example/sharedresources/SharedResourceDemo.java +++ b/documentation/src/test/java/example/sharedresources/SharedResourceDemo.java @@ -24,6 +24,7 @@ class SharedResourceDemo { + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) //tag::user_guide[] @Test void runBothCustomEnginesTest() { diff --git a/documentation/src/test/java/example/sharedresources/package-info.java b/documentation/src/test/java/example/sharedresources/package-info.java new file mode 100644 index 000000000000..02e87d295042 --- /dev/null +++ b/documentation/src/test/java/example/sharedresources/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.sharedresources; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/testinterface/package-info.java b/documentation/src/test/java/example/testinterface/package-info.java new file mode 100644 index 000000000000..3c0a7b9e0712 --- /dev/null +++ b/documentation/src/test/java/example/testinterface/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.testinterface; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/testkit/package-info.java b/documentation/src/test/java/example/testkit/package-info.java new file mode 100644 index 000000000000..bb644c62acd1 --- /dev/null +++ b/documentation/src/test/java/example/testkit/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.testkit; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/example/timing/TimingExtension.java b/documentation/src/test/java/example/timing/TimingExtension.java index 1426e42629f1..f07abe049c3e 100644 --- a/documentation/src/test/java/example/timing/TimingExtension.java +++ b/documentation/src/test/java/example/timing/TimingExtension.java @@ -36,12 +36,15 @@ public class TimingExtension implements BeforeTestExecutionCallback, AfterTestEx private static final String START_TIME = "start time"; @Override - public void beforeTestExecution(ExtensionContext context) throws Exception { + public void beforeTestExecution(ExtensionContext context) { getStore(context).put(START_TIME, System.currentTimeMillis()); } + //end::user_guide[] + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + //tag::user_guide[] @Override - public void afterTestExecution(ExtensionContext context) throws Exception { + public void afterTestExecution(ExtensionContext context) { Method testMethod = context.getRequiredTestMethod(); long startTime = getStore(context).remove(START_TIME, long.class); long duration = System.currentTimeMillis() - startTime; diff --git a/documentation/src/test/java/example/timing/package-info.java b/documentation/src/test/java/example/timing/package-info.java new file mode 100644 index 000000000000..545aa617da23 --- /dev/null +++ b/documentation/src/test/java/example/timing/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example.timing; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java/extensions/package-info.java b/documentation/src/test/java/extensions/package-info.java new file mode 100644 index 000000000000..edd479f63275 --- /dev/null +++ b/documentation/src/test/java/extensions/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package extensions; + +import org.jspecify.annotations.NullMarked; diff --git a/documentation/src/test/java21/example/ParameterizedLifecycleDemo.java b/documentation/src/test/java21/example/ParameterizedLifecycleDemo.java index c55f121cfb3f..c9c3375367d1 100644 --- a/documentation/src/test/java21/example/ParameterizedLifecycleDemo.java +++ b/documentation/src/test/java21/example/ParameterizedLifecycleDemo.java @@ -17,6 +17,7 @@ import java.nio.file.Path; import java.util.List; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -53,6 +54,9 @@ static void beforeInvocation(TextFile textFile, @TempDir Path tempDir) throws Ex textFile.path = Files.writeString(filePath, textFile.content); } + //end::user_guide[] + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + //tag::user_guide[] @AfterParameterizedClassInvocation static void afterInvocation(TextFile textFile) throws Exception { var actualContent = Files.readString(textFile.path); // <3> @@ -61,6 +65,9 @@ static void afterInvocation(TextFile textFile) throws Exception { // File will be deleted automatically by @TempDir support } + //end::user_guide[] + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + //tag::user_guide[] @Test void test() { assertTrue(Files.exists(textFile.path)); // <2> @@ -75,6 +82,9 @@ static class TextFile { final String fileName; final String content; + // end::example[] + @Nullable + // tag::example[] Path path; TextFile(String fileName, String content) { diff --git a/documentation/src/test/java21/example/package-info.java b/documentation/src/test/java21/example/package-info.java new file mode 100644 index 000000000000..a2bcf4a4db17 --- /dev/null +++ b/documentation/src/test/java21/example/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package example; + +import org.jspecify.annotations.NullMarked; diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index 82c449a807e4..75f0c6e70ab5 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -26,7 +26,7 @@ tasks.withType().configureEach { } } -tasks.compileTestJava { +tasks.withType().named { it.startsWith("compileTest") }.configureEach { options.errorprone.nullaway { handleTestAssertionLibraries = true excludedFieldAnnotations.addAll( From 286ac34b524a2d953fa2b6788317dfac310e0af3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 15:35:34 +0200 Subject: [PATCH 136/521] Annotate nullability in `org.junit.platform.commons.test` --- .../junit/platform/commons/test/ConcurrencyTestingUtils.java | 4 +++- .../java/org/junit/platform/commons/test/package-info.java | 5 +++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/package-info.java diff --git a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java index e0ae6d6c762e..ca1474c2e372 100644 --- a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java +++ b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java @@ -21,6 +21,8 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import org.jspecify.annotations.Nullable; + public class ConcurrencyTestingUtils { public static void executeConcurrently(int threads, Runnable action) throws Exception { @@ -30,7 +32,7 @@ public static void executeConcurrently(int threads, Runnable action) throws Exce }); } - public static List executeConcurrently(int threads, Callable action) throws Exception { + public static List executeConcurrently(int threads, Callable<@Nullable T> action) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(threads); try { CountDownLatch latch = new CountDownLatch(threads); diff --git a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/package-info.java b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/package-info.java new file mode 100644 index 000000000000..72143b56db41 --- /dev/null +++ b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/package-info.java @@ -0,0 +1,5 @@ + +@NullMarked +package org.junit.platform.commons.test; + +import org.jspecify.annotations.NullMarked; From 43f0a0d570c859ec968e7a0c4b80bd4fdb08bac6 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 15:55:11 +0200 Subject: [PATCH 137/521] Treat compiler warnings as errors for all source sets --- ...tbuild.java-library-conventions.gradle.kts | 21 +++++-------------- 1 file changed, 5 insertions(+), 16 deletions(-) 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 9c8b4ba5b31a..63bf6e8eb36b 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 @@ -208,22 +208,16 @@ tasks.withType().configureEach { tasks.withType().configureEach { options.encoding = "UTF-8" -} - -tasks.compileJava { options.compilerArgs.addAll(listOf( - "-Xlint:all", // Enables all recommended warnings. - "-Werror", // Terminates compilation when warnings occur. - "-parameters", // Generates metadata for reflection on method parameters. - "--module-version", "${project.version}" + "-Xlint:all", // Enables all recommended warnings. + "-Werror", // Terminates compilation when warnings occur. + "-parameters", // Generates metadata for reflection on method parameters. )) } -tasks.compileTestJava { +tasks.compileJava { options.compilerArgs.addAll(listOf( - "-Xlint:all", // Enables all recommended warnings. - "-Werror", // Terminates compilation when warnings occur. - "-parameters" // Generates metadata for reflection on method parameters. + "--module-version", "${project.version}" )) } @@ -279,10 +273,5 @@ pluginManager.withPlugin("java-test-fixtures") { } tasks.named("compileTestFixturesJava") { options.release = extension.testJavaVersion.map { it.majorVersion.toInt() } - options.compilerArgs.addAll(listOf( - "-Xlint:all", // Enables all recommended warnings. - "-Werror", // Terminates compilation when warnings occur. - "-parameters" // Generates metadata for reflection on method parameters. - )) } } From 1754400c9f127897982e0a981f2258c7d7cab5b5 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 15:55:33 +0200 Subject: [PATCH 138/521] Fix compilation of JMH benchmarks --- junit-jupiter-params/junit-jupiter-params.gradle.kts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/junit-jupiter-params/junit-jupiter-params.gradle.kts b/junit-jupiter-params/junit-jupiter-params.gradle.kts index 0f585b5d097d..45b9b56127bb 100644 --- a/junit-jupiter-params/junit-jupiter-params.gradle.kts +++ b/junit-jupiter-params/junit-jupiter-params.gradle.kts @@ -1,4 +1,6 @@ import junitbuild.extensions.javaModuleName +import net.ltgt.gradle.errorprone.errorprone +import net.ltgt.gradle.nullaway.nullaway plugins { id("junitbuild.java-nullability-conventions") @@ -56,6 +58,14 @@ tasks { "--add-reads", "${javaModuleName}=univocity.parsers" )) } + compileJmhJava { + options.compilerArgs.add("-Xlint:-processing") + options.errorprone.nullaway { + customInitializerAnnotations.add( + "org.openjdk.jmh.annotations.Setup", + ) + } + } javadoc { (options as StandardJavadocDocletOptions).apply { addStringOption("-add-modules", "univocity.parsers") From a8229d8f31729bb8e01680782cba4c3fe0c1e967 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 16:17:49 +0200 Subject: [PATCH 139/521] Move `@Nullable` to return type for methods --- .../jupiter/api/AssertionFailureBuilder.java | 3 +- .../org/junit/jupiter/api/AssertionUtils.java | 3 +- .../jupiter/api/DisplayNameGenerator.java | 3 +- ...isabledIfEnvironmentVariableCondition.java | 3 +- ...EnabledIfEnvironmentVariableCondition.java | 3 +- .../org/junit/jupiter/api/condition/OS.java | 9 ++-- .../api/extension/ExecutableInvoker.java | 3 +- .../api/extension/ExtensionContext.java | 12 ++---- .../api/extension/InvocationInterceptor.java | 1 - .../support/TypeBasedParameterResolver.java | 3 +- .../descriptor/ClassBasedTestDescriptor.java | 3 +- .../execution/DefaultExecutableInvoker.java | 3 +- .../engine/execution/NamespaceAwareStore.java | 21 ++++------ .../execution/ParameterResolutionUtils.java | 3 +- .../extension/TestInfoParameterResolver.java | 3 +- .../engine/extension/TimeoutExtension.java | 6 +-- .../engine/support/MethodReflectionUtils.java | 3 +- .../adapter/AbstractTestRuleAdapter.java | 6 +-- .../jupiter/params/EvaluatedArgumentSet.java | 4 +- .../ParameterizedInvocationNameFormatter.java | 6 +-- ...ameterizedInvocationParameterResolver.java | 3 +- .../junit/jupiter/params/ResolverFacade.java | 40 ++++++++---------- .../params/aggregator/ArgumentsAccessor.java | 3 +- .../aggregator/ArgumentsAggregator.java | 3 +- .../aggregator/DefaultArgumentsAccessor.java | 33 +++++---------- .../AnnotationBasedArgumentConverter.java | 11 +++-- .../converter/SimpleArgumentConverter.java | 12 +++--- .../jupiter/params/support/ParameterInfo.java | 3 +- .../commons/support/ReflectionSupport.java | 3 +- .../support/conversion/ConversionSupport.java | 4 +- .../FallbackStringToObjectConverter.java | 6 +-- .../conversion/StringToClassConverter.java | 3 +- .../conversion/StringToObjectConverter.java | 3 +- .../support/scanning/CloseablePath.java | 3 +- .../commons/util/AnnotationUtils.java | 3 +- .../commons/util/KotlinReflectionUtils.java | 3 +- .../commons/util/ReflectionUtils.java | 6 +-- .../options/TestConsoleOutputOptions.java | 9 ++-- .../console/options/TestDiscoveryOptions.java | 3 +- .../engine/discovery/ClassSelector.java | 3 +- .../engine/discovery/MethodSelector.java | 3 +- .../engine/discovery/NestedClassSelector.java | 3 +- .../discovery/NestedMethodSelector.java | 3 +- .../support/descriptor/MethodSource.java | 3 +- .../ParallelExecutionConfiguration.java | 3 +- .../hierarchical/ThrowableCollector.java | 3 +- .../store/NamespacedHierarchicalStore.java | 42 +++++++------------ .../launcher/AbstractMethodFilter.java | 3 +- .../core/DiscoveryIssueCollector.java | 3 +- .../core/LauncherConfigurationParameters.java | 12 ++---- .../launcher/core/StreamInterceptor.java | 3 +- .../legacy/LegacyReportingUtils.java | 6 +-- .../suite/engine/SuiteTestDescriptor.java | 3 +- .../junit/platform/testkit/engine/Events.java | 4 +- .../testkit/engine/TerminationInfo.java | 3 +- .../engine/descriptor/DescriptionUtils.java | 3 +- .../engine/descriptor/TestSourceProvider.java | 6 +-- ...fensiveAllDefaultPossibilitiesBuilder.java | 9 ++-- ...edIfEnvironmentVariableConditionTests.java | 6 +-- ...edIfEnvironmentVariableConditionTests.java | 9 ++-- .../engine/ClassTemplateInvocationTests.java | 8 ++-- .../engine/TestTemplateInvocationTests.java | 3 +- .../ParameterResolutionUtilsTests.java | 6 +-- .../conversion/ConversionSupportTests.java | 6 +-- .../tagexpression/ParserErrorTests.java | 3 +- 65 files changed, 149 insertions(+), 265 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java index 13008d802204..fdb5cdd68d52 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -164,8 +164,7 @@ public AssertionFailedError build() { : new AssertionFailedError(message, cause); } - @Nullable - private static String nullSafeGet(@Nullable Object messageOrSupplier) { + private static @Nullable String nullSafeGet(@Nullable Object messageOrSupplier) { if (messageOrSupplier == null) { return null; } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java index 3d64dc32c5dd..1d18b446f2f9 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionUtils.java @@ -51,8 +51,7 @@ static void fail(Supplier<@Nullable String> messageSupplier) { throw new AssertionFailedError(nullSafeGet(messageSupplier)); } - @Nullable - static String nullSafeGet(@Nullable Supplier<@Nullable String> messageSupplier) { + static @Nullable String nullSafeGet(@Nullable Supplier<@Nullable String> messageSupplier) { return (messageSupplier != null ? messageSupplier.get() : null); } 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 f3e65a73436b..ec6bf3e18ebc 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 @@ -501,8 +501,7 @@ private static Optional findIndicativeSentencesGe return findAnnotation(testClass, IndicativeSentencesGeneration.class, enclosingInstanceTypes); } - @Nullable - private static String getSentenceFragment(AnnotatedElement element) { + private static @Nullable String getSentenceFragment(AnnotatedElement element) { return findAnnotation(element, SentenceFragment.class) // .map(SentenceFragment::value) // .map(sentenceFragment -> { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java index df55d472b802..968eca1a4e28 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableCondition.java @@ -68,8 +68,7 @@ protected ConditionEvaluationResult evaluate(DisabledIfEnvironmentVariable annot * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return System.getenv(name); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java index 984066484e2b..1885aa9c8a39 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableCondition.java @@ -67,8 +67,7 @@ protected ConditionEvaluationResult evaluate(EnabledIfEnvironmentVariable annota * {@link System#getenv(String)}. Can be overridden in a subclass for * testing purposes. */ - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return System.getenv(name); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java index f1e1c2b1592d..8b6f4a348241 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java @@ -104,18 +104,15 @@ public enum OS { * @since 5.9 */ @API(status = STABLE, since = "5.10") - @Nullable - public static OS current() { + public static @Nullable OS current() { return CURRENT_OS; } - @Nullable - private static OS determineCurrentOs() { + private static @Nullable OS determineCurrentOs() { return parse(System.getProperty("os.name")); } - @Nullable - static OS parse(String osName) { + static @Nullable OS parse(String osName) { if (StringUtils.isBlank(osName)) { logger.debug( () -> "JVM system property 'os.name' is undefined. It is therefore not possible to detect the current OS."); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java index 9365c05dffc2..6defd08748ac 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExecutableInvoker.java @@ -34,8 +34,7 @@ public interface ExecutableInvoker { * @param method the method to invoke and resolve parameters for * @see #invoke(Method, Object) */ - @Nullable - default Object invoke(Method method) { + default @Nullable Object invoke(Method method) { return invoke(method, null); } 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 5cdc8e48c48e..e8e5133baa9e 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 @@ -555,8 +555,7 @@ interface CloseableResource { * @see #get(Object) * @see #getOrDefault(Object, Class, Object) */ - @Nullable - V get(Object key, Class requiredType); + @Nullable V get(Object key, Class requiredType); /** * Get the value of the specified required type that is stored under @@ -653,8 +652,7 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - @Nullable - Object getOrComputeIfAbsent(K key, Function defaultCreator); + @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the @@ -685,8 +683,7 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - @Nullable - V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); + @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. @@ -742,8 +739,7 @@ default V getOrComputeIfAbsent(Class type) { * for the specified key * @see #remove(Object) */ - @Nullable - V remove(Object key, Class requiredType); + @Nullable V remove(Object key, Class requiredType); } diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java index 933ce4588ef5..89ee85a7735d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/InvocationInterceptor.java @@ -143,7 +143,6 @@ default void interceptTestMethod(Invocation<@Nullable Void> invocation, * @return the result of the invocation; potentially {@code null} * @throws Throwable in case of failures */ - @Nullable default T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { return invocation.proceed(); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java index b7746e962622..be80ed5c3a0a 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/support/TypeBasedParameterResolver.java @@ -61,8 +61,7 @@ private Type enclosedTypeOfParameterResolver() { return typeBasedParameterResolverSuperclass.getActualTypeArguments()[0]; } - @Nullable - private ParameterizedType findTypeBasedParameterResolverSuperclass(Class clazz) { + private @Nullable ParameterizedType findTypeBasedParameterResolverSuperclass(Class clazz) { Class superclass = clazz.getSuperclass(); // Abort? diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index 3a6c2e1637b4..5151d5c686a7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -295,8 +295,7 @@ public void cleanUp(JupiterEngineExecutionContext context) throws Exception { this.testInstanceFactory = null; } - @Nullable - private TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) { + private @Nullable TestInstanceFactory resolveTestInstanceFactory(ExtensionRegistry registry) { List factories = registry.getExtensions(TestInstanceFactory.class); if (factories.size() == 1) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java index 109593b6fc5b..37a663ebb0b8 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultExecutableInvoker.java @@ -48,8 +48,7 @@ public T invoke(Constructor constructor, @Nullable Object outerInstance) } @Override - @Nullable - public Object invoke(Method method, @Nullable Object target) { + public @Nullable Object invoke(Method method, @Nullable Object target) { @Nullable Object[] arguments = resolveParameters(method, Optional.ofNullable(target), extensionContext, extensionRegistry); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java index 24cd4a985436..59897452d19d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java @@ -39,31 +39,27 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override - @Nullable - public Object get(Object key) { + public @Nullable Object get(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.get(this.namespace, key)); } @Override - @Nullable - public T get(Object key, Class requiredType) { + public @Nullable T get(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore(() -> this.valuesStore.get(this.namespace, key, requiredType)); } @Override - @Nullable - public Object getOrComputeIfAbsent(K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); return accessStore(() -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator)); } @Override - @Nullable - public V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { + public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); @@ -78,22 +74,19 @@ public void put(Object key, @Nullable Object value) { } @Override - @Nullable - public Object remove(Object key) { + public @Nullable Object remove(Object key) { Preconditions.notNull(key, "key must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key)); } @Override - @Nullable - public T remove(Object key, Class requiredType) { + public @Nullable T remove(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); return accessStore(() -> this.valuesStore.remove(this.namespace, key, requiredType)); } - @Nullable - private T accessStore(Supplier<@Nullable T> action) { + private @Nullable T accessStore(Supplier<@Nullable T> action) { try { return action.get(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java index 07d9cdb4b589..c83032af3ac8 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java @@ -125,8 +125,7 @@ public class ParameterResolutionUtils { return values; } - @Nullable - private static Object resolveParameter(ParameterContext parameterContext, Executable executable, + private static @Nullable Object resolveParameter(ParameterContext parameterContext, Executable executable, ExtensionContextSupplier extensionContext, ExtensionRegistry extensionRegistry) { try { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java index dcf6d43d4f1f..c956ee43a956 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TestInfoParameterResolver.java @@ -91,8 +91,7 @@ public String toString() { } @SuppressWarnings("OptionalAssignedToNull") - @Nullable - private static Object nullSafeGet(@Nullable Optional optional) { + private static @Nullable Object nullSafeGet(@Nullable Optional optional) { return optional != null ? optional.orElse(null) : null; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java index 1c8deceef80f..46c6a502e2bc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java @@ -163,8 +163,7 @@ private T intercept(Invocation invocation, ReflectiveInvocationContext adapteeClass + " is not assignable from " + this.target.getClass()); } - @Nullable - protected Object executeMethod(String name) { + protected @Nullable Object executeMethod(String name) { return executeMethod(name, new Class[0]); } - @Nullable - protected Object executeMethod(String methodName, Class[] parameterTypes, Object... arguments) { + protected @Nullable Object executeMethod(String methodName, Class[] parameterTypes, Object... arguments) { Method method = findMethod(this.target.getClass(), methodName, parameterTypes).orElseThrow( () -> new JUnitException("Failed to find method %s(%s) in class %s".formatted(methodName, ClassUtils.nullSafeToString(parameterTypes), this.target.getClass().getName()))); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java index 68a8bd2a368f..de8573073b55 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/EvaluatedArgumentSet.java @@ -114,8 +114,8 @@ private static Optional determineName(Arguments arguments) { .toArray(); } - @Nullable - private static Object extractFromNamed(@Nullable Object argument, Function, @Nullable Object> mapper) { + private static @Nullable Object extractFromNamed(@Nullable Object argument, + Function, @Nullable Object> mapper) { return argument instanceof Named named ? mapper.apply(named) : argument; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java index 04d7111bcae7..22eb77dc327f 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java @@ -132,8 +132,7 @@ private PartialFormatter[] parse(String pattern, String displayName, return result.toArray(new PartialFormatter[0]); } - @Nullable - private static PlaceholderPosition findFirstPlaceholder(PartialFormatters formatters, String segment) { + private static @Nullable PlaceholderPosition findFirstPlaceholder(PartialFormatters formatters, String segment) { if (segment.length() < formatters.minimumPlaceholderLength) { return null; } @@ -283,8 +282,7 @@ public synchronized void append(ArgumentsContext context, StringBuffer result) { return result; } - @Nullable - private String truncateIfExceedsMaxLength(@Nullable String argument) { + private @Nullable String truncateIfExceedsMaxLength(@Nullable String argument) { if (argument != null && argument.length() > this.argumentMaxLength) { return argument.substring(0, this.argumentMaxLength - 1) + ELLIPSIS; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java index 9d28206eeb0c..193aff285e76 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationParameterResolver.java @@ -51,8 +51,7 @@ public final boolean supportsParameter(ParameterContext parameterContext, Extens } @Override - @Nullable - public final Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + public final @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return this.resolverFacade.resolve(parameterContext, extensionContext, this.arguments, this.invocationIndex, diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 529f4db561fe..aa81b1d92c34 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -307,9 +307,9 @@ private void setField(Object testInstance, FieldParameterDeclaration declaration } } - @Nullable - private Object resolve(ResolvableParameterDeclaration parameterDeclaration, ExtensionContext extensionContext, - EvaluatedArgumentSet arguments, int invocationIndex, Optional parameterContext) { + private @Nullable Object resolve(ResolvableParameterDeclaration parameterDeclaration, + ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, + Optional parameterContext) { Resolver resolver = getResolver(extensionContext, parameterDeclaration); return parameterDeclaration.resolve(resolver, extensionContext, arguments, invocationIndex, parameterContext); } @@ -492,9 +492,8 @@ private static Converter createDefault(ExtensionContext context) { } @Override - @Nullable - public Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, - EvaluatedArgumentSet arguments, int invocationIndex) { + public @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex, + ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { Object argument = arguments.getConsumedPayload(parameterIndex); try { return this.argumentConverter.convert(argument, parameterContext); @@ -505,8 +504,7 @@ public Object resolve(ParameterContext parameterContext, int parameterIndex, Ext } @Override - @Nullable - public Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, + public @Nullable Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { Object argument = arguments.getConsumedPayload(fieldContext.getParameterIndex()); try { @@ -535,9 +533,8 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT } @Override - @Nullable - public Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, - EvaluatedArgumentSet arguments, int invocationIndex) { + public @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex, + ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { ArgumentsAccessor accessor = requireNonNull(ParameterInfo.get(extensionContext)).getArguments(); try { return this.argumentsAggregator.aggregateArguments(accessor, parameterContext); @@ -549,8 +546,7 @@ public Object resolve(ParameterContext parameterContext, int parameterIndex, Ext } @Override - @Nullable - public Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, + public @Nullable Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { ArgumentsAccessor accessor = requireNonNull(ParameterInfo.get(extensionContext)).getArguments(); try { @@ -628,8 +624,7 @@ boolean isAggregator() { || isAnnotated(getAnnotatedElement(), AggregateWith.class); } - @Nullable - protected abstract Object resolve(Resolver resolver, ExtensionContext extensionContext, + protected abstract @Nullable Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, Optional originalParameterContext); } @@ -670,9 +665,9 @@ public Optional getParameterName() { } @Override - @Nullable - public Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, - int invocationIndex, Optional originalParameterContext) { + public @Nullable Object resolve(Resolver resolver, ExtensionContext extensionContext, + EvaluatedArgumentSet arguments, int invocationIndex, + Optional originalParameterContext) { return resolver.resolve(this, extensionContext, arguments, invocationIndex); } } @@ -710,9 +705,9 @@ public Optional getParameterName() { } @Override - @Nullable - public Object resolve(Resolver resolver, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, - int invocationIndex, Optional originalParameterContext) { + public @Nullable Object resolve(Resolver resolver, ExtensionContext extensionContext, + EvaluatedArgumentSet arguments, int invocationIndex, + Optional originalParameterContext) { ParameterContext parameterContext = originalParameterContext // .filter(it -> it.getParameter().equals(this.parameter)) // .orElseGet(() -> toParameterContext(extensionContext, originalParameterContext)); @@ -772,8 +767,7 @@ public boolean supports(ParameterContext parameterContext) { } @Override - @Nullable - public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext, + public @Nullable Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex, ResolutionCache resolutionCache) { ResolvableParameterDeclaration actualDeclaration = this.lifecycleMethodResolverFacade // diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java index a098322c8643..536c19db6a19 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/ArgumentsAccessor.java @@ -65,8 +65,7 @@ public interface ArgumentsAccessor { * @param requiredType the required type of the value; never {@code null} * @return the value at the given index, potentially {@code null} */ - @Nullable - T get(int index, Class requiredType) throws ArgumentAccessException; + @Nullable T get(int index, Class requiredType) throws ArgumentAccessException; /** * Get the value of the argument at the given index as a {@link Character}, 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 0e8ced7836b8..8a6ada359a1a 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 @@ -84,9 +84,8 @@ Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context) * aggregation * @since 5.13 */ - @Nullable @API(status = EXPERIMENTAL, since = "5.13") - default Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) + default @Nullable Object aggregateArguments(ArgumentsAccessor accessor, FieldContext context) throws ArgumentsAggregationException { throw new JUnitException( String.format("ArgumentsAggregator does not override the convert(ArgumentsAccessor, FieldContext) method. " diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java index 8d9e5ace2ea4..f33ac3dbdf0e 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java @@ -68,8 +68,7 @@ public Object get(int index) { } @Override - @Nullable - public T get(int index, Class requiredType) { + public @Nullable T get(int index, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); Object value = get(index); try { @@ -85,56 +84,47 @@ public T get(int index, Class requiredType) { } @Override - @Nullable - public Character getCharacter(int index) { + public @Nullable Character getCharacter(int index) { return get(index, Character.class); } @Override - @Nullable - public Boolean getBoolean(int index) { + public @Nullable Boolean getBoolean(int index) { return get(index, Boolean.class); } @Override - @Nullable - public Byte getByte(int index) { + public @Nullable Byte getByte(int index) { return get(index, Byte.class); } @Override - @Nullable - public Short getShort(int index) { + public @Nullable Short getShort(int index) { return get(index, Short.class); } @Override - @Nullable - public Integer getInteger(int index) { + public @Nullable Integer getInteger(int index) { return get(index, Integer.class); } @Override - @Nullable - public Long getLong(int index) { + public @Nullable Long getLong(int index) { return get(index, Long.class); } @Override - @Nullable - public Float getFloat(int index) { + public @Nullable Float getFloat(int index) { return get(index, Float.class); } @Override - @Nullable - public Double getDouble(int index) { + public @Nullable Double getDouble(int index) { return get(index, Double.class); } @Override - @Nullable - public String getString(int index) { + public @Nullable String getString(int index) { return get(index, String.class); } @@ -144,8 +134,7 @@ public int size() { } @Override - @Nullable - public Object[] toArray() { + public @Nullable Object[] toArray() { return Arrays.copyOf(this.arguments, this.arguments.length); } 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 ade4018b17ba..b36a604e86e7 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 @@ -49,14 +49,14 @@ public final void accept(A annotation) { } @Override - @Nullable - public final Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { return convert(source, context.getParameter().getType(), requireNonNull(this.annotation)); } @Override - @Nullable - public final Object convert(@Nullable Object source, FieldContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, FieldContext context) + throws ArgumentConversionException { return convert(source, context.getField().getType(), requireNonNull(this.annotation)); } @@ -73,8 +73,7 @@ public final Object convert(@Nullable Object source, FieldContext context) throw * @throws ArgumentConversionException in case an error occurs during the * conversion */ - @Nullable - protected abstract Object convert(@Nullable Object source, Class targetType, A annotation) + protected abstract @Nullable Object convert(@Nullable Object source, Class targetType, A annotation) throws ArgumentConversionException; } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java index 3203b0476966..8ef7a6235104 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/converter/SimpleArgumentConverter.java @@ -34,14 +34,14 @@ public SimpleArgumentConverter() { } @Override - @Nullable - public final Object convert(@Nullable Object source, ParameterContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, ParameterContext context) + throws ArgumentConversionException { return convert(source, context.getParameter().getType()); } @Override - @Nullable - public final Object convert(@Nullable Object source, FieldContext context) throws ArgumentConversionException { + public final @Nullable Object convert(@Nullable Object source, FieldContext context) + throws ArgumentConversionException { return convert(source, context.getField().getType()); } @@ -57,7 +57,7 @@ public final Object convert(@Nullable Object source, FieldContext context) throw * @throws ArgumentConversionException in case an error occurs during the * conversion */ - @Nullable - protected abstract Object convert(@Nullable Object source, Class targetType) throws ArgumentConversionException; + protected abstract @Nullable Object convert(@Nullable Object source, Class targetType) + throws ArgumentConversionException; } 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 bc38c6ee223a..296a688f2545 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 @@ -69,8 +69,7 @@ public interface ParameterInfo { * {@return the closest {@code ParameterInfo} instance for the supplied * {@code ExtensionContext}; potentially {@code null}} */ - @Nullable - static ParameterInfo get(ExtensionContext context) { + static @Nullable ParameterInfo get(ExtensionContext context) { return context.getStore(NAMESPACE).get(KEY, ParameterInfo.class); } 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 634853f49403..4d8b6e2e81e7 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 @@ -453,8 +453,7 @@ public static T newInstance(Class clazz, Object... args) { * if the return type is {@code void} * @see ExceptionUtils#throwAsUncheckedException(Throwable) */ - @Nullable - public static Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { + public static @Nullable Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { return ReflectionUtils.invokeMethod(method, target, args); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java index a9a09540997b..007ee26b07bf 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java @@ -100,8 +100,8 @@ private ConversionSupport() { * @since 1.11 */ @SuppressWarnings("unchecked") - @Nullable - public static T convert(@Nullable String source, Class targetType, @Nullable ClassLoader classLoader) { + public static @Nullable T convert(@Nullable String source, Class targetType, + @Nullable ClassLoader classLoader) { if (source == null) { if (targetType.isPrimitive()) { throw new ConversionException( diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java index ef8191beae75..33ae2321c596 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java @@ -98,8 +98,7 @@ private static Function findFactoryExecutable(Class targetTyp }); } - @Nullable - private static Method findFactoryMethod(Class targetType) { + private static @Nullable Method findFactoryMethod(Class targetType) { List factoryMethods = findMethods(targetType, new IsFactoryMethod(targetType), BOTTOM_UP); if (factoryMethods.size() == 1) { return factoryMethods.get(0); @@ -107,8 +106,7 @@ private static Method findFactoryMethod(Class targetType) { return null; } - @Nullable - private static Constructor findFactoryConstructor(Class targetType) { + private static @Nullable Constructor findFactoryConstructor(Class targetType) { List> constructors = findConstructors(targetType, new IsFactoryConstructor(targetType)); if (constructors.size() == 1) { return constructors.get(0); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java index 1e1cd0e832b4..a2d5cbb9322e 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToClassConverter.java @@ -26,8 +26,7 @@ public Object convert(String source, Class targetType) throws Exception { } @Override - @Nullable - public Object convert(String className, Class targetType, ClassLoader classLoader) throws Exception { + public @Nullable Object convert(String className, Class targetType, ClassLoader classLoader) throws Exception { // @formatter:off return ReflectionSupport.tryToLoadClass(className, classLoader) .getOrThrow(cause -> new ConversionException( diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java index 378a7bad5ed8..6c3bfffae363 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToObjectConverter.java @@ -48,8 +48,7 @@ interface StringToObjectConverter { * Can be overridden by concrete implementations of this interface that need * access to the supplied {@link ClassLoader}. */ - @Nullable - default Object convert(String source, Class targetType, ClassLoader classLoader) throws Exception { + default @Nullable Object convert(String source, Class targetType, ClassLoader classLoader) throws Exception { return convert(source, targetType); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java index cbe5c17ec01d..aa18d1b587de 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/CloseablePath.java @@ -115,8 +115,7 @@ private ManagedFileSystem retain() { return this; } - @Nullable - private ManagedFileSystem release() { + private @Nullable ManagedFileSystem release() { if (referenceCount.decrementAndGet() == 0) { close(); return null; diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index 271a1085f0be..11b657a3fcb0 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -425,8 +425,7 @@ private static boolean isRepeatableAnnotationContainer(Class[] getKotlinSuspendingFunctionParameterTypes(Method method return KotlinReflectionUtilsKt.getParameterTypes(method); } - @Nullable - public static Object invokeKotlinSuspendingFunction(Method method, @Nullable Object target, + public static @Nullable Object invokeKotlinSuspendingFunction(Method method, @Nullable Object target, @Nullable Object[] args) { requireKotlinReflect(method); requireKotlinxCoroutines(method); 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 0e34e0fdeee4..4291635ebecb 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 @@ -566,8 +566,7 @@ static boolean isWideningConversion(Class sourceType, Class targetType) { * @return the corresponding wrapper type or {@code null} if the * supplied type is {@code null} or not a primitive type */ - @Nullable - public static Class getWrapperType(Class type) { + public static @Nullable Class getWrapperType(Class type) { return primitiveToWrapperMap.get(type); } @@ -715,8 +714,7 @@ public static List readFieldValues(List fields, @Nullable Object /** * @see org.junit.platform.commons.support.ReflectionSupport#invokeMethod(Method, Object, Object...) */ - @Nullable - public static Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { + public static @Nullable Object invokeMethod(Method method, @Nullable Object target, @Nullable Object... args) { Preconditions.notNull(method, "Method must not be null"); Preconditions.condition((target != null || isStatic(method)), () -> String.format("Cannot invoke non-static method [%s] on a null target.", method.toGenericString())); diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java index e157715be6a6..235588768f12 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java @@ -51,8 +51,7 @@ public void setAnsiColorOutputDisabled(boolean ansiColorOutputDisabled) { this.ansiColorOutputDisabled = ansiColorOutputDisabled; } - @Nullable - public Path getColorPalettePath() { + public @Nullable Path getColorPalettePath() { return colorPalettePath; } @@ -85,8 +84,7 @@ public void setTheme(Theme theme) { } @API(status = INTERNAL, since = "1.13") - @Nullable - public Path getStdoutPath() { + public @Nullable Path getStdoutPath() { return this.stdoutPath; } @@ -96,8 +94,7 @@ public void setStdoutPath(@Nullable Path stdoutPath) { } @API(status = INTERNAL, since = "1.13") - @Nullable - public Path getStderrPath() { + public @Nullable Path getStderrPath() { return this.stderrPath; } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java index 449a436acbc0..030cc1475b2f 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java @@ -107,8 +107,7 @@ public void setAdditionalClasspathEntries(List additionalClasspathEntries) this.additionalClasspathEntries = additionalClasspathEntries; } - @Nullable - public List getSelectedClasspathEntries() { + public @Nullable List getSelectedClasspathEntries() { return this.selectedClasspathEntries; } 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 a2ec7a37801a..06e5d605a249 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 @@ -74,8 +74,7 @@ public class ClassSelector implements DiscoverySelector { * @since 1.10 */ @API(status = EXPERIMENTAL, since = "1.10") - @Nullable - public ClassLoader getClassLoader() { + public @Nullable ClassLoader getClassLoader() { return this.classLoader; } 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 22c3343dab73..ac5579cba6ae 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 @@ -131,9 +131,8 @@ public class MethodSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ - @Nullable @API(status = EXPERIMENTAL, since = "1.10") - public ClassLoader getClassLoader() { + public @Nullable ClassLoader getClassLoader() { return this.classLoader; } 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 46901b7c06f0..8c2b67753525 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 @@ -81,9 +81,8 @@ public class NestedClassSelector implements DiscoverySelector { * @return the {@code ClassLoader}; potentially {@code null} * @since 1.10 */ - @Nullable @API(status = EXPERIMENTAL, since = "1.10") - public ClassLoader getClassLoader() { + public @Nullable 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 bd0353b1a5bb..8298167f3fb8 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 @@ -101,9 +101,8 @@ public class NestedMethodSelector implements DiscoverySelector { * * @since 1.10 */ - @Nullable @API(status = EXPERIMENTAL, since = "1.10") - public ClassLoader getClassLoader() { + public @Nullable ClassLoader getClassLoader() { return this.nestedClassSelector.getClassLoader(); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java index 3ffc0ceae2ea..b3c95915dd52 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java @@ -165,8 +165,7 @@ public final String getMethodName() { /** * Get the method parameter types of this source. */ - @Nullable - public final String getMethodParameterTypes() { + public final @Nullable String getMethodParameterTypes() { return this.methodParameterTypes; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java index 6a953cbbd9da..b7cd9cb64ffe 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ParallelExecutionConfiguration.java @@ -70,8 +70,7 @@ public interface ParallelExecutionConfiguration { * boolean, int, int, int, Predicate, long, java.util.concurrent.TimeUnit) */ @API(status = STABLE, since = "1.11") - @Nullable - default Predicate getSaturatePredicate() { + default @Nullable Predicate getSaturatePredicate() { return null; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java index 7cfe656b926b..f322178a62fa 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java @@ -123,8 +123,7 @@ else if (throwable != t) { * @see #isEmpty() * @see #assertEmpty() */ - @Nullable - public Throwable getThrowable() { + public @Nullable Throwable getThrowable() { return this.throwable; } 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 08f5727ed8e9..3f3c46278352 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 @@ -157,8 +157,7 @@ public void close() { * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ - @Nullable - public Object get(N namespace, Object key) { + public @Nullable Object get(N namespace, Object key) { StoredValue storedValue = getStoredValue(new CompositeKey<>(namespace, key)); return StoredValue.evaluateIfNotNull(storedValue); } @@ -174,8 +173,8 @@ public Object get(N namespace, Object key) { * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ - @Nullable - public T get(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { + public @Nullable T get(N namespace, Object key, Class requiredType) + throws NamespacedHierarchicalStoreException { Object value = get(namespace, key); return castToRequiredType(key, value, requiredType); } @@ -192,8 +191,7 @@ public T get(N namespace, Object key, Class requiredType) throws Namespac * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ - @Nullable - public Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); CompositeKey compositeKey = new CompositeKey<>(namespace, key); StoredValue storedValue = getStoredValue(compositeKey); @@ -221,8 +219,7 @@ public Object getOrComputeIfAbsent(N namespace, K key, Function V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, + public @Nullable V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); @@ -243,8 +240,8 @@ public V getOrComputeIfAbsent(N namespace, K key, Function(namespace, key), newStoredValue(() -> value)); return StoredValue.evaluateIfNotNull(oldValue); @@ -263,8 +260,7 @@ public Object put(N namespace, Object key, @Nullable Object value) throws Namesp * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ - @Nullable - public Object remove(N namespace, Object key) { + public @Nullable Object remove(N namespace, Object key) { rejectIfClosed(); StoredValue previous = this.storedValues.remove(new CompositeKey<>(namespace, key)); return StoredValue.evaluateIfNotNull(previous); @@ -284,8 +280,8 @@ public Object remove(N namespace, Object key) { * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ - @Nullable - public T remove(N namespace, Object key, Class requiredType) throws NamespacedHierarchicalStoreException { + public @Nullable T remove(N namespace, Object key, Class requiredType) + throws NamespacedHierarchicalStoreException { rejectIfClosed(); Object value = remove(namespace, key); return castToRequiredType(key, value, requiredType); @@ -295,8 +291,7 @@ private StoredValue newStoredValue(Supplier<@Nullable Object> value) { return new StoredValue(this.insertOrderSequence.getAndIncrement(), value); } - @Nullable - private StoredValue getStoredValue(CompositeKey compositeKey) { + private @Nullable StoredValue getStoredValue(CompositeKey compositeKey) { StoredValue storedValue = this.storedValues.get(compositeKey); if (storedValue != null) { return storedValue; @@ -307,9 +302,8 @@ private StoredValue getStoredValue(CompositeKey compositeKey) { return null; } - @Nullable @SuppressWarnings("unchecked") - private T castToRequiredType(Object key, @Nullable Object value, Class requiredType) { + private @Nullable T castToRequiredType(Object key, @Nullable Object value, Class requiredType) { Preconditions.notNull(requiredType, "requiredType must not be null"); if (value == null) { return null; @@ -372,8 +366,7 @@ private static class StoredValue { this.supplier = supplier; } - @Nullable - private EvaluatedValue evaluateSafely(CompositeKey compositeKey) { + private @Nullable EvaluatedValue evaluateSafely(CompositeKey compositeKey) { try { return new EvaluatedValue<>(compositeKey, this.order, evaluate()); } @@ -383,13 +376,11 @@ private EvaluatedValue evaluateSafely(CompositeKey compositeKey) { } } - @Nullable - private Object evaluate() { + private @Nullable Object evaluate() { return this.supplier.get(); } - @Nullable - static Object evaluateIfNotNull(@Nullable StoredValue value) { + static @Nullable Object evaluateIfNotNull(@Nullable StoredValue value) { return value != null ? value.evaluate() : null; } @@ -443,8 +434,7 @@ private MemoizingSupplier(Supplier<@Nullable Object> delegate) { } @Override - @Nullable - public Object get() { + public @Nullable Object get() { if (this.value == NO_VALUE_SET) { computeValue(); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java index 9b60eecb1c6a..6c2eb66988da 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java @@ -50,8 +50,7 @@ protected Optional findMatchingPattern(@Nullable String methodName) { return this.patterns.stream().filter(pattern -> pattern.matcher(methodName).matches()).findAny(); } - @Nullable - protected String getFullyQualifiedMethodNameFromDescriptor(TestDescriptor descriptor) { + protected @Nullable String getFullyQualifiedMethodNameFromDescriptor(TestDescriptor descriptor) { return descriptor.getSource() // .filter(source -> source instanceof MethodSource) // .map(methodSource -> getFullyQualifiedMethodNameWithoutParameters(((MethodSource) methodSource))) // diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java index 573b4032bd99..7714d3fb7618 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueCollector.java @@ -78,8 +78,7 @@ else if (result.getStatus() == UNRESOLVED && selector instanceof UniqueIdSelecto } } - @Nullable - static TestSource toSource(DiscoverySelector selector) { + static @Nullable TestSource toSource(DiscoverySelector selector) { if (selector instanceof ClassSelector classSelector) { return ClassSource.from(classSelector.getClassName()); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java index 1d4f797a4c61..ebb0f19a3df4 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java @@ -71,8 +71,7 @@ public Set keySet() { Collectors.toSet()); } - @Nullable - private String getProperty(String key) { + private @Nullable String getProperty(String key) { Preconditions.notBlank(key, "key must not be null or blank"); return providers.stream() // .map(parameterProvider -> parameterProvider.getValue(key)) // @@ -165,8 +164,7 @@ default int size() { static ParameterProvider explicit(Map configParams) { return new ParameterProvider() { @Override - @Nullable - public String getValue(String key) { + public @Nullable String getValue(String key) { return configParams.get(key); } @@ -192,8 +190,7 @@ public String toString() { static ParameterProvider systemProperties() { return new ParameterProvider() { @Override - @Nullable - public String getValue(String key) { + public @Nullable String getValue(String key) { try { return System.getProperty(key); } @@ -240,8 +237,7 @@ public String toString() { static ParameterProvider inherited(ConfigurationParameters configParams) { return new ParameterProvider() { @Override - @Nullable - public String getValue(String key) { + public @Nullable String getValue(String key) { return configParams.get(key).orElse(null); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java index 430c961688df..60a3d6a8cc9a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StreamInterceptor.java @@ -114,8 +114,7 @@ private void pushToTop(RewindableByteArrayOutputStream out) { } } - @Nullable - private RewindableByteArrayOutputStream getOutput() { + private @Nullable RewindableByteArrayOutputStream getOutput() { RewindableByteArrayOutputStream out = output.get(); return out.isMarked() ? out : mostRecentOutputs.peek(); } diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java index eb6580723431..b82ac7c9f1a8 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/LegacyReportingUtils.java @@ -63,13 +63,11 @@ public static String getClassName(TestPlan testPlan, TestIdentifier testIdentifi return getParentLegacyReportingName(testPlan, testIdentifier); } - @Nullable - private static TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { + private static @Nullable TestIdentifier getParent(TestPlan testPlan, TestIdentifier testIdentifier) { return testPlan.getParent(testIdentifier).orElse(null); } - @Nullable - private static ClassSource getClassSource(TestIdentifier current) { + private static @Nullable ClassSource getClassSource(TestIdentifier current) { // @formatter:off return current.getSource() .filter(ClassSource.class::isInstance) diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index 79ba4a9630de..d5e474519108 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -179,8 +179,7 @@ private void executeBeforeSuiteMethods(ThrowableCollector throwableCollector) { } } - @Nullable - private TestExecutionSummary executeTests(EngineExecutionListener parentEngineExecutionListener, + private @Nullable TestExecutionSummary executeTests(EngineExecutionListener parentEngineExecutionListener, NamespacedHierarchicalStore requestLevelStore, ThrowableCollector throwableCollector) { if (throwableCollector.isNotEmpty()) { return null; 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 5c7960434c35..ff1f6ae4af51 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 @@ -470,8 +470,8 @@ private static void checkCondition(List events, SoftAssertions softly, Co } } - @Nullable - private static Event findEvent(List events, SoftAssertions softly, Condition condition) { + private static @Nullable Event findEvent(List events, SoftAssertions softly, + Condition condition) { // @formatter:off Optional matchedEvent = events.stream() .filter(condition::matches) diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java index fdc425c1955f..fa579b75cafa 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/TerminationInfo.java @@ -115,8 +115,7 @@ public boolean executed() { * @throws UnsupportedOperationException if this {@code TerminationInfo} * does not represent a skipped execution */ - @Nullable - public String getSkipReason() throws UnsupportedOperationException { + public @Nullable String getSkipReason() throws UnsupportedOperationException { if (skipped()) { return this.skipReason; } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java index 23f50a48387c..915e3c18d713 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/DescriptionUtils.java @@ -20,8 +20,7 @@ public class DescriptionUtils { private DescriptionUtils() { } - @Nullable - public static String getMethodName(Description description) { + public static @Nullable String getMethodName(Description description) { String displayName = description.getDisplayName(); int i = displayName.indexOf('('); if (i >= 0) { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java index a8973bf6a0d8..78fd2afbb585 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java @@ -45,8 +45,7 @@ public class TestSourceProvider { private final Map testSourceCache = new ConcurrentHashMap<>(); private final Map, List> methodsCache = synchronizedMap(new LruCache<>(31)); - @Nullable - public TestSource findTestSource(Description description) { + public @Nullable TestSource findTestSource(Description description) { TestSource testSource = testSourceCache.computeIfAbsent(description, this::computeTestSource); return testSource == NULL_SOURCE ? null : testSource; } @@ -74,8 +73,7 @@ private String sanitizeMethodName(String methodName) { return methodName; } - @Nullable - private Method findMethod(Class testClass, String methodName) { + private @Nullable Method findMethod(Class testClass, String methodName) { List methods = methodsCache.computeIfAbsent(testClass, clazz -> findMethods(clazz, m -> true, TOP_DOWN)).stream() // .filter(where(Method::getName, isEqual(methodName))) // diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java index dceb9cce4461..c858e3c06b5e 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/DefensiveAllDefaultPossibilitiesBuilder.java @@ -109,9 +109,8 @@ private static class DefensiveAnnotatedBuilder extends AnnotatedBuilder { super(suiteBuilder); } - @Nullable @Override - public Runner buildRunner(Class runnerClass, Class testClass) throws Exception { + public @Nullable Runner buildRunner(Class runnerClass, Class testClass) throws Exception { // Referenced by name because it might not be available at runtime. if ("org.junit.platform.runner.JUnitPlatform".equals(runnerClass.getName())) { logger.warn(() -> "Ignoring test class using JUnitPlatform runner: " + testClass.getName()); @@ -129,9 +128,8 @@ private static class DefensiveJUnit4Builder extends JUnit4Builder { private static final Predicate isPotentialJUnit4TestMethod = new IsPotentialJUnit4TestMethod(); - @Nullable @Override - public Runner runnerForClass(Class testClass) throws Throwable { + public @Nullable Runner runnerForClass(Class testClass) throws Throwable { if (containsTestMethods(testClass)) { return super.runnerForClass(testClass); } @@ -149,9 +147,8 @@ private boolean containsTestMethods(Class testClass) { * @since 5.1 */ private static class NullIgnoredBuilder extends IgnoredBuilder { - @Nullable @Override - public Runner runnerForClass(Class testClass) { + public @Nullable Runner runnerForClass(Class testClass) { // don't ignore entire test classes just yet return null; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java index 68da1e4ea32e..921f5d173e4e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/DisabledIfEnvironmentVariableConditionTests.java @@ -37,8 +37,7 @@ class DisabledIfEnvironmentVariableConditionTests extends AbstractExecutionCondi private ExecutionCondition condition = new DisabledIfEnvironmentVariableCondition() { @Override - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } }; @@ -101,8 +100,7 @@ void disabledBecauseEnvironmentVariableForComposedAnnotationMatchesExactly() { this.condition = new DisabledIfEnvironmentVariableCondition() { @Override - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } }; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java index 29fb1a913f76..7410b433c1eb 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledIfEnvironmentVariableConditionTests.java @@ -38,8 +38,7 @@ class EnabledIfEnvironmentVariableConditionTests extends AbstractExecutionCondit private ExecutionCondition condition = new EnabledIfEnvironmentVariableCondition() { @Override - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : null; } }; @@ -102,8 +101,7 @@ void enabledBecauseBothEnvironmentVariablesMatchExactly() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return KEY1.equals(name) || KEY2.equals(name) ? ENIGMA : null; } }; @@ -144,8 +142,7 @@ void disabledBecauseEnvironmentVariableForComposedAnnotationDoesNotMatch() { this.condition = new EnabledIfEnvironmentVariableCondition() { @Override - @Nullable - protected String getEnvironmentVariable(String name) { + protected @Nullable String getEnvironmentVariable(String name) { return KEY1.equals(name) ? ENIGMA : KEY2.equals(name) ? BOGUS : null; } }; 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 3e3151b3155a..c39bc60b5fb7 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 @@ -1169,9 +1169,8 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override - @Nullable - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) - throws ParameterResolutionException { + public @Nullable Object resolveParameter(ParameterContext parameterContext, + ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(Namespace.GLOBAL).get("someResource"); } } @@ -1433,8 +1432,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override - @Nullable - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(PreparingClassTemplateInvocationContextProvider.NAMESPACE).get("resource"); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java index ca3f839721d1..9e5a7f9fe050 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/TestTemplateInvocationTests.java @@ -918,8 +918,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override - @Nullable - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { return extensionContext.getStore(PreparingTestTemplateInvocationContextProvider.NAMESPACE).get("resource"); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index ab46ed9da2f4..cd68a46daf63 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -364,8 +364,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override - @Nullable - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { + public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { resolveArguments = new ArgumentRecordingParameterResolver.Arguments(parameterContext, extensionContext); return null; } @@ -405,9 +404,8 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon return supports.test(parameterContext); } - @Nullable @Override - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { + public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return resolve.apply(parameterContext); } } diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java index 9e87f62ea62d..594cbe9f118f 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/ConversionSupportTests.java @@ -316,13 +316,11 @@ private void assertConverts(@Nullable String input, Class targetClass, @Nulla .isEqualTo(expectedOutput); } - @Nullable - private Object convert(@Nullable String input, Class targetClass) { + private @Nullable Object convert(@Nullable String input, Class targetClass) { return convert(input, targetClass, classLoader()); } - @Nullable - private Object convert(@Nullable String input, Class targetClass, ClassLoader classLoader) { + private @Nullable Object convert(@Nullable String input, Class targetClass, ClassLoader classLoader) { return ConversionSupport.convert(input, targetClass, classLoader); } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java index 71a3b70779fe..1d5bcd3cb0dc 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserErrorTests.java @@ -90,8 +90,7 @@ private static Stream data() { // @formatter:on } - @Nullable - private String parseErrorFromParsing(String tagExpression) { + private @Nullable String parseErrorFromParsing(String tagExpression) { try { var parseResult = parser.parse(tagExpression); parseResult.tagExpressionOrThrow(RuntimeException::new); From 788eff6ce4a4cf51b2b88de525f501411964a200 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 16:30:11 +0200 Subject: [PATCH 140/521] Fix IDEA-detected nullability problems in main source sets --- .../main/java/example/util/StringUtils.java | 8 +++-- .../api/condition/MethodBasedCondition.java | 2 +- ...izedInvocationNameFormatterBenchmarks.java | 5 +++- .../provider/NullArgumentsProvider.java | 3 +- .../FallbackStringToObjectConverter.java | 7 +++-- .../platform/commons/util/ModuleUtils.java | 5 ++-- .../engine/discovery/MethodSelector.java | 30 +++++++++++-------- .../HierarchicalOutputDirectoryProvider.java | 8 +++-- .../discovery/ClassSelectorResolver.java | 2 +- .../engine/execution/RunListenerAdapter.java | 3 +- 10 files changed, 46 insertions(+), 27 deletions(-) diff --git a/documentation/src/main/java/example/util/StringUtils.java b/documentation/src/main/java/example/util/StringUtils.java index a48d72e3d3ad..b0eee5e142f8 100644 --- a/documentation/src/main/java/example/util/StringUtils.java +++ b/documentation/src/main/java/example/util/StringUtils.java @@ -10,10 +10,14 @@ package example.util; +import static java.util.Objects.requireNonNull; + +import org.jspecify.annotations.Nullable; + public class StringUtils { - public static boolean isPalindrome(String candidate) { - int length = candidate.length(); + public static boolean isPalindrome(@Nullable String candidate) { + int length = requireNonNull(candidate).length(); for (int i = 0; i < length / 2; i++) { if (candidate.charAt(i) != candidate.charAt(length - (i + 1))) { return false; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java index b7103c4898f6..157a75dadd57 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/MethodBasedCondition.java @@ -68,7 +68,7 @@ Method getConditionMethod(String fullyQualifiedMethodName, ExtensionContext cont String className = methodParts[0]; String methodName = methodParts[1]; ClassLoader classLoader = ClassLoaderUtils.getClassLoader(testClass); - Class clazz = ReflectionSupport.tryToLoadClass(className, classLoader).getOrThrow( + Class clazz = ReflectionSupport.tryToLoadClass(className, classLoader).getNonNullOrThrow( cause -> new JUnitException("Could not load class [%s]".formatted(className), cause)); return findMethod(clazz, methodName); } diff --git a/junit-jupiter-params/src/jmh/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterBenchmarks.java b/junit-jupiter-params/src/jmh/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterBenchmarks.java index 592be9f94445..0d57127007e1 100644 --- a/junit-jupiter-params/src/jmh/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterBenchmarks.java +++ b/junit-jupiter-params/src/jmh/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatterBenchmarks.java @@ -10,6 +10,7 @@ package org.junit.jupiter.params; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.params.ParameterizedInvocationConstants.DEFAULT_DISPLAY_NAME; import static org.junit.jupiter.params.ParameterizedInvocationConstants.DISPLAY_NAME_PLACEHOLDER; @@ -50,7 +51,9 @@ public void formatTestNames(Blackhole blackhole) throws Exception { var method = TestCase.class.getDeclaredMethod("parameterizedTest", int.class); var formatter = new ParameterizedInvocationNameFormatter( DISPLAY_NAME_PLACEHOLDER + " " + DEFAULT_DISPLAY_NAME + " ({0})", "displayName", - new ParameterizedTestContext(TestCase.class, method, method.getAnnotation(ParameterizedTest.class)), 512); + new ParameterizedTestContext(TestCase.class, method, + requireNonNull(method.getAnnotation(ParameterizedTest.class))), + 512); for (int i = 0; i < argumentsList.size(); i++) { Arguments arguments = argumentsList.get(i); blackhole.consume(formatter.format(i, EvaluatedArgumentSet.allOf(arguments))); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java index e6fb99f84074..87ffaf0a38f2 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/NullArgumentsProvider.java @@ -14,6 +14,7 @@ import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.support.ParameterDeclarations; import org.junit.platform.commons.util.Preconditions; @@ -24,7 +25,7 @@ */ class NullArgumentsProvider implements ArgumentsProvider { - private static final Arguments nullArguments = arguments(new Object[] { null }); + private static final Arguments nullArguments = arguments(new @Nullable Object[] { null }); @Override public Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java index 33ae2321c596..b7f96707a52e 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java @@ -67,7 +67,7 @@ class FallbackStringToObjectConverter implements StringToObjectConverter { * This prevents the framework from repeatedly searching for things which * are already known not to exist. */ - private static final ConcurrentHashMap, Function> factoryExecutableCache // + private static final ConcurrentHashMap, Function> factoryExecutableCache // = new ConcurrentHashMap<>(64); @Override @@ -76,15 +76,16 @@ public boolean canConvertTo(Class targetType) { } @Override + @Nullable public Object convert(String source, Class targetType) throws Exception { - Function executable = findFactoryExecutable(targetType); + Function executable = findFactoryExecutable(targetType); Preconditions.condition(executable != NULL_EXECUTABLE, "Illegal state: convert() must not be called if canConvert() returned false"); return executable.apply(source); } - private static Function findFactoryExecutable(Class targetType) { + private static Function findFactoryExecutable(Class targetType) { return factoryExecutableCache.computeIfAbsent(targetType, type -> { Method factoryMethod = findFactoryMethod(type); if (factoryMethod != null) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index 9f20d964f471..9b069eef54d8 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -10,6 +10,7 @@ package org.junit.platform.commons.util; +import static java.util.Objects.requireNonNull; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toSet; @@ -298,10 +299,10 @@ List scan(ModuleReference reference) { private Resource loadResourceUnchecked(String binaryName) { try { - URI uri = classLoader.getResource(binaryName).toURI(); + URI uri = requireNonNull(classLoader.getResource(binaryName)).toURI(); return new DefaultResource(binaryName, uri); } - catch (URISyntaxException e) { + catch (NullPointerException | URISyntaxException e) { throw new JUnitException("Failed to load resource with name '" + binaryName + "'.", e); } } 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 ac5579cba6ae..41c400874314 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 @@ -219,44 +219,50 @@ public Class[] getParameterTypes() { } private Class lazyLoadJavaClass() { - // @formatter:off - if (this.javaClass == null) { + Class value = this.javaClass; + if (value == null) { + // @formatter:off Try> tryToLoadClass = this.classLoader == null ? ReflectionSupport.tryToLoadClass(this.className) : ReflectionSupport.tryToLoadClass(this.className, this.classLoader); - this.javaClass = tryToLoadClass.getNonNullOrThrow(cause -> + value = tryToLoadClass.getNonNullOrThrow(cause -> new PreconditionViolationException("Could not load class with name: " + this.className, cause)); + // @formatter:on + this.javaClass = value; } - // @formatter:on - return this.javaClass; + return value; } private Method lazyLoadJavaMethod() { - if (this.javaMethod == null) { + var value = this.javaMethod; + if (value == null) { Class javaClass = lazyLoadJavaClass(); var parameterTypes = lazyLoadParameterTypes(); if (parameterTypes.length > 0) { - this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName, parameterTypes).orElseThrow( + value = ReflectionSupport.findMethod(javaClass, this.methodName, parameterTypes).orElseThrow( () -> new PreconditionViolationException( "Could not find method with name [%s] and parameter types [%s] in class [%s].".formatted( this.methodName, this.parameterTypeNames, javaClass.getName()))); } else { - this.javaMethod = ReflectionSupport.findMethod(javaClass, this.methodName).orElseThrow( + value = ReflectionSupport.findMethod(javaClass, this.methodName).orElseThrow( () -> new PreconditionViolationException( "Could not find method with name [%s] in class [%s].".formatted(this.methodName, javaClass.getName()))); } + this.javaMethod = value; } - return this.javaMethod; + return value; } private Class[] lazyLoadParameterTypes() { - if (this.parameterTypes == null) { - this.parameterTypes = ReflectionUtils.resolveParameterTypes(lazyLoadJavaClass(), this.methodName, + var value = this.parameterTypes; + if (value == null) { + value = ReflectionUtils.resolveParameterTypes(lazyLoadJavaClass(), this.methodName, this.parameterTypeNames); + this.parameterTypes = value; } - return this.parameterTypes; + return value; } /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java index 0012a5add088..b836d2ca5b3c 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java @@ -57,10 +57,12 @@ public Path createOutputDirectory(TestDescriptor testDescriptor) throws IOExcept @Override public synchronized Path getRootDirectory() { - if (rootDir == null) { - rootDir = rootDirSupplier.get(); + var currentRootDir = rootDir; + if (currentRootDir == null) { + currentRootDir = rootDirSupplier.get(); + rootDir = currentRootDir; } - return rootDir; + return currentRootDir; } private static Path toSanitizedPath(Segment segment) { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/ClassSelectorResolver.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/ClassSelectorResolver.java index e8a005591a40..5a2741d42ecc 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/ClassSelectorResolver.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/ClassSelectorResolver.java @@ -56,7 +56,7 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { String testClassName = lastSegment.getValue(); if (classFilter.match(testClassName)) { Class testClass = ReflectionSupport.tryToLoadClass(testClassName)// - .getOrThrow(cause -> new JUnitException("Unknown class: " + testClassName, cause)); + .getNonNullOrThrow(cause -> new JUnitException("Unknown class: " + testClassName, cause)); return resolveTestClassThatPassedNameFilter(testClass, context); } } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java index 8aec956c3af3..6a0b4756f7fd 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/RunListenerAdapter.java @@ -15,6 +15,7 @@ import java.util.Optional; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.Ignore; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.TestDescriptor; @@ -192,7 +193,7 @@ private Optional determineReasonForIgnoredTest(TestDescriptor testDescri .flatMap(testClass -> getReason(testClass.getAnnotation(Ignore.class))); } - private static Optional getReason(Ignore annotation) { + private static Optional getReason(@Nullable Ignore annotation) { return Optional.ofNullable(annotation).map(Ignore::value); } From 261c2f5a1576ea29add753b92499e7cf29342f23 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 16:44:32 +0200 Subject: [PATCH 141/521] Add to release notes --- .../docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index f8a932f61913..28e79fd1e8b7 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -27,7 +27,8 @@ repository on GitHub. [[release-notes-6.0.0-M1-overall-new-features-and-improvements]] ==== New Features and Improvements -* ❓ +* All JUnit modules now use https://jspecify.dev/[JSpecify]'s nullability annotations to + indicate which method parameters, return types, etc. can be `null`. [[release-notes-6.0.0-M1-junit-platform]] From 1f5d97ed3383931374bde5b195515553b5dff189 Mon Sep 17 00:00:00 2001 From: Stefano Cordio Date: Sat, 24 May 2025 11:21:43 +0200 Subject: [PATCH 142/521] Remove `null` support from `getWrapperType` input, add test coverage --- .../platform/commons/util/ReflectionUtils.java | 4 ++-- .../commons/util/ReflectionUtilsTests.java | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) 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 4291635ebecb..d85f942009c0 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 @@ -238,7 +238,7 @@ public enum HierarchyTraversalMode { classNameToTypeMap = Collections.unmodifiableMap(classNamesToTypes); - Map, Class> primitivesToWrappers = new IdentityHashMap<>(9); + Map, Class> primitivesToWrappers = new IdentityHashMap<>(8); primitivesToWrappers.put(boolean.class, Boolean.class); primitivesToWrappers.put(byte.class, Byte.class); @@ -564,7 +564,7 @@ static boolean isWideningConversion(Class sourceType, Class targetType) { * * @param type the primitive type for which to retrieve the wrapper type * @return the corresponding wrapper type or {@code null} if the - * supplied type is {@code null} or not a primitive type + * supplied type is not a primitive type */ public static @Nullable Class getWrapperType(Class type) { return primitiveToWrapperMap.get(type); 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 90a4fd60a4a7..9738a86ef7a6 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 @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -213,6 +214,19 @@ void wideningConversion() { assertFalse(isWideningConversion(String.class, int.class)); // neither a primitive nor a wrapper } + @Test + void getWrapperType() { + assertEquals(Boolean.class, ReflectionUtils.getWrapperType(boolean.class)); + assertEquals(Byte.class, ReflectionUtils.getWrapperType(byte.class)); + assertEquals(Character.class, ReflectionUtils.getWrapperType(char.class)); + assertEquals(Short.class, ReflectionUtils.getWrapperType(short.class)); + assertEquals(Integer.class, ReflectionUtils.getWrapperType(int.class)); + assertEquals(Long.class, ReflectionUtils.getWrapperType(long.class)); + assertEquals(Float.class, ReflectionUtils.getWrapperType(float.class)); + assertEquals(Double.class, ReflectionUtils.getWrapperType(double.class)); + assertNull(ReflectionUtils.getWrapperType(Object.class)); + } + @Test void getAllClasspathRootDirectories(@TempDir Path tempDirectory) throws Exception { var root1 = tempDirectory.resolve("root1").toAbsolutePath(); From 86c9ff534314ee5aca0a679dbaf70eb363a72b05 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:31:23 +0200 Subject: [PATCH 143/521] Use enhanced switch expressions --- .../descriptor/AbstractExtensionContext.java | 26 ++++------ .../ExclusiveResourceCollector.java | 12 ++--- .../descriptor/JupiterTestDescriptor.java | 12 ++--- .../discovery/ClassSelectorResolver.java | 48 +++++++++---------- .../engine/extension/TimeoutDuration.java | 28 ++++------- .../engine/extension/TimeoutExtension.java | 16 +++---- .../ParameterizedClassInvocationContext.java | 27 ++++------- .../junit/platform/console/options/Theme.java | 15 ++---- .../console/tasks/ConsoleTestExecutor.java | 25 ++++------ .../junit/platform/console/tasks/Style.java | 15 ++---- .../support/hierarchical/LockManager.java | 13 ++--- .../platform/launcher/TestIdentifier.java | 13 ++--- .../launcher/core/DiscoveryIssueNotifier.java | 16 ++----- .../launcher/core/EngineIdValidator.java | 19 ++++---- .../xml/OpenTestReportGeneratingListener.java | 14 ++---- 15 files changed, 115 insertions(+), 184 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index 8a9129bc5136..b35768ca74a6 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -221,16 +221,11 @@ public Store getStore(Namespace namespace) { @Override public Store getStore(StoreScope scope, Namespace namespace) { - // TODO [#4246] Use switch expression - switch (scope) { - case LAUNCHER_SESSION: - return launcherStoreFacade.getSessionLevelStore(namespace); - case EXECUTION_REQUEST: - return launcherStoreFacade.getRequestLevelStore(namespace); - case EXTENSION_CONTEXT: - return getStore(namespace); - } - throw new JUnitException("Unknown StoreScope: " + scope); + return switch (scope) { + case LAUNCHER_SESSION -> launcherStoreFacade.getSessionLevelStore(namespace); + case EXECUTION_REQUEST -> launcherStoreFacade.getRequestLevelStore(namespace); + case EXTENSION_CONTEXT -> getStore(namespace); + }; } @Override @@ -267,12 +262,9 @@ public List getExtensions(Class extensionType) { protected abstract Node.ExecutionMode getPlatformExecutionMode(); private ExecutionMode toJupiterExecutionMode(Node.ExecutionMode mode) { - switch (mode) { - case CONCURRENT: - return ExecutionMode.CONCURRENT; - case SAME_THREAD: - return ExecutionMode.SAME_THREAD; - } - throw new JUnitException("Unknown ExecutionMode: " + mode); + return switch (mode) { + case CONCURRENT -> ExecutionMode.CONCURRENT; + case SAME_THREAD -> ExecutionMode.SAME_THREAD; + }; } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java index 9e3dde197bbe..a7c49e9b14c7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java @@ -26,7 +26,6 @@ import org.junit.jupiter.api.parallel.ResourceLock; import org.junit.jupiter.api.parallel.ResourceLockTarget; import org.junit.jupiter.api.parallel.ResourceLocksProvider; -import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.commons.util.StringUtils; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; @@ -113,13 +112,10 @@ private List getProviders() { } private static ExclusiveResource.LockMode toLockMode(ResourceAccessMode mode) { - switch (mode) { - case READ: - return ExclusiveResource.LockMode.READ; - case READ_WRITE: - return ExclusiveResource.LockMode.READ_WRITE; - } - throw new JUnitException("Unknown ResourceAccessMode: " + mode); + return switch (mode) { + case READ -> ExclusiveResource.LockMode.READ; + case READ_WRITE -> ExclusiveResource.LockMode.READ_WRITE; + }; } } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index 893234e8f017..ceebc08fe2c7 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -41,7 +41,6 @@ import org.junit.jupiter.engine.execution.ConditionEvaluator; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; -import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.UnrecoverableExceptions; import org.junit.platform.engine.DiscoveryIssue; @@ -171,13 +170,10 @@ Optional getExecutionModeFromAnnotation(AnnotatedElement element) } public static ExecutionMode toExecutionMode(org.junit.jupiter.api.parallel.ExecutionMode mode) { - switch (mode) { - case CONCURRENT: - return ExecutionMode.CONCURRENT; - case SAME_THREAD: - return ExecutionMode.SAME_THREAD; - } - throw new JUnitException("Unknown ExecutionMode: " + mode); + return switch (mode) { + case CONCURRENT -> ExecutionMode.CONCURRENT; + case SAME_THREAD -> ExecutionMode.SAME_THREAD; + }; } @Override 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 b47e8434c009..4470da5a543e 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 @@ -125,31 +125,29 @@ else if (isInnerClass(nestedClass) && predicates.looksLikeIntendedTestClass(nest public Resolution resolve(UniqueIdSelector selector, Context context) { UniqueId uniqueId = selector.getUniqueId(); UniqueId.Segment lastSegment = uniqueId.getLastSegment(); - if (ClassTestDescriptor.SEGMENT_TYPE.equals(lastSegment.getType())) { - return resolveStandaloneClassUniqueId(context, lastSegment, __ -> true, this::newClassTestDescriptor); - } - if (ClassTemplateTestDescriptor.STANDALONE_CLASS_SEGMENT_TYPE.equals(lastSegment.getType())) { - return resolveStandaloneClassUniqueId(context, lastSegment, this.predicates.isAnnotatedWithClassTemplate, - this::newClassTemplateTestDescriptor); - } - if (NestedClassTestDescriptor.SEGMENT_TYPE.equals(lastSegment.getType())) { - return resolveNestedClassUniqueId(context, uniqueId, __ -> true, this::newNestedClassTestDescriptor); - } - if (ClassTemplateTestDescriptor.NESTED_CLASS_SEGMENT_TYPE.equals(lastSegment.getType())) { - return resolveNestedClassUniqueId(context, uniqueId, this.predicates.isAnnotatedWithClassTemplate, - this::newNestedClassTemplateTestDescriptor); - } - if (ClassTemplateInvocationTestDescriptor.SEGMENT_TYPE.equals(lastSegment.getType())) { - Optional testDescriptor = context.addToParent( - () -> selectUniqueId(uniqueId.removeLastSegment()), parent -> { - int index = Integer.parseInt(lastSegment.getValue().substring(1)); - return Optional.of(newDummyClassTemplateInvocationTestDescriptor(parent, index)); - }); - return toInvocationMatch(testDescriptor) // - .map(Resolution::match) // - .orElse(unresolved()); - } - return unresolved(); + return switch (lastSegment.getType()) { + case ClassTestDescriptor.SEGMENT_TYPE -> // + resolveStandaloneClassUniqueId(context, lastSegment, __ -> true, this::newClassTestDescriptor); + case ClassTemplateTestDescriptor.STANDALONE_CLASS_SEGMENT_TYPE -> // + resolveStandaloneClassUniqueId(context, lastSegment, this.predicates.isAnnotatedWithClassTemplate, + this::newClassTemplateTestDescriptor); + case NestedClassTestDescriptor.SEGMENT_TYPE -> // + resolveNestedClassUniqueId(context, uniqueId, __ -> true, this::newNestedClassTestDescriptor); + case ClassTemplateTestDescriptor.NESTED_CLASS_SEGMENT_TYPE -> // + resolveNestedClassUniqueId(context, uniqueId, this.predicates.isAnnotatedWithClassTemplate, + this::newNestedClassTemplateTestDescriptor); + case ClassTemplateInvocationTestDescriptor.SEGMENT_TYPE -> { + Optional testDescriptor = context.addToParent( + () -> selectUniqueId(uniqueId.removeLastSegment()), parent -> { + int index = Integer.parseInt(lastSegment.getValue().substring(1)); + return Optional.of(newDummyClassTemplateInvocationTestDescriptor(parent, index)); + }); + yield toInvocationMatch(testDescriptor) // + .map(Resolution::match) // + .orElse(unresolved()); + } + default -> unresolved(); + }; } @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java index ac99448af8a9..80b7f28e72e9 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java @@ -76,23 +76,15 @@ public Duration toDuration() { } private ChronoUnit toChronoUnit() { - switch (unit) { - case NANOSECONDS: - return ChronoUnit.NANOS; - case MICROSECONDS: - return ChronoUnit.MICROS; - case MILLISECONDS: - return ChronoUnit.MILLIS; - case SECONDS: - return ChronoUnit.SECONDS; - case MINUTES: - return ChronoUnit.MINUTES; - case HOURS: - return ChronoUnit.HOURS; - case DAYS: - return ChronoUnit.DAYS; - default: - throw new JUnitException("Could not map TimeUnit " + unit + " to ChronoUnit"); - } + return switch (unit) { + case NANOSECONDS -> ChronoUnit.NANOS; + case MICROSECONDS -> ChronoUnit.MICROS; + case MILLISECONDS -> ChronoUnit.MILLIS; + case SECONDS -> ChronoUnit.SECONDS; + case MINUTES -> ChronoUnit.MINUTES; + case HOURS -> ChronoUnit.HOURS; + case DAYS -> ChronoUnit.DAYS; + default -> throw new JUnitException("Could not map TimeUnit " + unit + " to ChronoUnit"); + }; } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java index 46c6a502e2bc..c0b32bf4303d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java @@ -221,16 +221,12 @@ private boolean isTimeoutDisabled(ExtensionContext extensionContext) { * Determine if timeouts are disabled for the supplied mode. */ private boolean isTimeoutDisabled(String mode) { - switch (mode) { - case ENABLED_MODE_VALUE: - return false; - case DISABLED_MODE_VALUE: - return true; - case DISABLED_ON_DEBUG_MODE_VALUE: - return RuntimeUtils.isDebugMode(); - default: - throw new ExtensionConfigurationException("Unsupported timeout mode: " + mode); - } + return switch (mode) { + case ENABLED_MODE_VALUE -> false; + case DISABLED_MODE_VALUE -> true; + case DISABLED_ON_DEBUG_MODE_VALUE -> RuntimeUtils.isDebugMode(); + default -> throw new ExtensionConfigurationException("Unsupported timeout mode: " + mode); + }; } @FunctionalInterface diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java index 51f74401b29c..0344bb9abca5 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java @@ -22,7 +22,6 @@ import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.params.ParameterizedClassContext.InjectionType; import org.junit.jupiter.params.provider.Arguments; -import org.junit.platform.commons.JUnitException; import org.junit.platform.commons.util.Preconditions; class ParameterizedClassInvocationContext extends ParameterizedInvocationContext @@ -53,13 +52,10 @@ public void prepareInvocation(ExtensionContext context) { private Extension createParameterInjector() { InjectionType injectionType = this.declarationContext.getInjectionType(); - switch (injectionType) { - case CONSTRUCTOR: - return createExtensionForConstructorInjection(); - case FIELDS: - return createExtensionForFieldInjection(); - } - throw new JUnitException("Unsupported injection type: " + injectionType); + return switch (injectionType) { + case CONSTRUCTOR -> createExtensionForConstructorInjection(); + case FIELDS -> createExtensionForFieldInjection(); + }; } private ClassTemplateConstructorParameterResolver createExtensionForConstructorInjection() { @@ -72,15 +68,12 @@ private ClassTemplateConstructorParameterResolver createExtensionForConstructorI private Extension createExtensionForFieldInjection() { ResolverFacade resolverFacade = this.declarationContext.getResolverFacade(); TestInstance.Lifecycle lifecycle = this.declarationContext.getTestInstanceLifecycle(); - switch (lifecycle) { - case PER_CLASS: - return new BeforeClassTemplateInvocationFieldInjector(resolverFacade, this.arguments, - this.invocationIndex, this.resolutionCache); - case PER_METHOD: - return new InstancePostProcessingClassTemplateFieldInjector(resolverFacade, this.arguments, - this.invocationIndex, this.resolutionCache); - } - throw new JUnitException("Unsupported lifecycle: " + lifecycle); + return switch (lifecycle) { + case PER_CLASS -> new BeforeClassTemplateInvocationFieldInjector(resolverFacade, this.arguments, + this.invocationIndex, this.resolutionCache); + case PER_METHOD -> new InstancePostProcessingClassTemplateFieldInjector(resolverFacade, this.arguments, + this.invocationIndex, this.resolutionCache); + }; } private Stream createLifecycleMethodInvokers() { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/Theme.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/Theme.java index 83d75d08fc8f..1abf7f8e0084 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/Theme.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/Theme.java @@ -116,16 +116,11 @@ public final String skipped() { } public final String status(TestExecutionResult result) { - switch (result.getStatus()) { - case SUCCESSFUL: - return successful(); - case ABORTED: - return aborted(); - case FAILED: - return failed(); - default: - return result.getStatus().name(); - } + return switch (result.getStatus()) { + case SUCCESSFUL -> successful(); + case ABORTED -> aborted(); + case FAILED -> failed(); + }; } /** diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java index eb0f3874a8e3..4c001b4d806f 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/ConsoleTestExecutor.java @@ -180,21 +180,16 @@ private SummaryGeneratingListener registerListeners(PrintWriter out, Optional createDetailsPrintingListener(PrintWriter out) { ColorPalette colorPalette = getColorPalette(); Theme theme = outputOptions.getTheme(); - switch (outputOptions.getDetails()) { - case SUMMARY: - // summary listener is always created and registered - return Optional.empty(); - case FLAT: - return Optional.of(new FlatPrintingListener(out, colorPalette)); - case TREE: - return Optional.of(new TreePrintingListener(out, colorPalette, theme)); - case VERBOSE: - return Optional.of(new VerboseTreePrintingListener(out, colorPalette, 16, theme)); - case TESTFEED: - return Optional.of(new TestFeedPrintingListener(out, colorPalette)); - default: - return Optional.empty(); - } + return switch (outputOptions.getDetails()) { + case SUMMARY -> + // summary listener is always created and registered + Optional.empty(); + case FLAT -> Optional.of(new FlatPrintingListener(out, colorPalette)); + case TREE -> Optional.of(new TreePrintingListener(out, colorPalette, theme)); + case VERBOSE -> Optional.of(new VerboseTreePrintingListener(out, colorPalette, 16, theme)); + case TESTFEED -> Optional.of(new TestFeedPrintingListener(out, colorPalette)); + case NONE -> Optional.empty(); + }; } private ColorPalette getColorPalette() { diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/Style.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/Style.java index 72b2dc83ff22..5a74c39738be 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/Style.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/Style.java @@ -21,16 +21,11 @@ enum Style { NONE, SUCCESSFUL, ABORTED, FAILED, SKIPPED, CONTAINER, TEST, DYNAMIC, REPORTED; static Style valueOf(TestExecutionResult result) { - switch (result.getStatus()) { - case SUCCESSFUL: - return Style.SUCCESSFUL; - case ABORTED: - return Style.ABORTED; - case FAILED: - return Style.FAILED; - default: - return Style.NONE; - } + return switch (result.getStatus()) { + case SUCCESSFUL -> Style.SUCCESSFUL; + case ABORTED -> Style.ABORTED; + case FAILED -> Style.FAILED; + }; } static Style valueOf(TestIdentifier testIdentifier) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java index 988d52efb69e..c8e236341726 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java @@ -71,14 +71,11 @@ private List toDistinctSortedResources(Collection resources) { - switch (resources.size()) { - case 0: - return NopLock.INSTANCE; - case 1: - return toSingleLock(getOnlyElement(resources)); - default: - return new CompositeLock(resources, toLocks(resources)); - } + return switch (resources.size()) { + case 0 -> NopLock.INSTANCE; + case 1 -> toSingleLock(getOnlyElement(resources)); + default -> new CompositeLock(resources, toLocks(resources)); + }; } private SingleLock toSingleLock(ExclusiveResource resource) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index bd4329d26afc..4e96c47cb659 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -98,14 +98,11 @@ private TestIdentifier(UniqueId uniqueId, String displayName, @Nullable TestSour } private Set copyOf(Set tags) { - switch (tags.size()) { - case 0: - return emptySet(); - case 1: - return singleton(getOnlyElement(tags)); - default: - return new LinkedHashSet<>(tags); - } + return switch (tags.size()) { + case 0 -> emptySet(); + case 1 -> singleton(getOnlyElement(tags)); + default -> new LinkedHashSet<>(tags); + }; } /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java index 6dbae69407c3..0d7e8d901a61 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java @@ -98,17 +98,11 @@ private void logIssues(TestEngine testEngine, List issues, Strin } private static Consumer> logger(Severity severity) { - // TODO [#4246] Use switch expression - switch (severity) { - case INFO: - return logger::info; - case WARNING: - return logger::warn; - case ERROR: - return logger::error; - default: - throw new IllegalArgumentException("Unknown severity: " + severity); - } + return switch (severity) { + case INFO -> logger::info; + case WARNING -> logger::warn; + case ERROR -> logger::error; + }; } private static String formatMessage(TestEngine testEngine, List issues, String adjective) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java index 80df2561c5e5..7aa014de4179 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineIdValidator.java @@ -58,22 +58,21 @@ private static boolean validateReservedIds(TestEngine testEngine) { if (!engineId.startsWith("junit-")) { return true; } - switch (engineId) { - case "junit-jupiter": { + return switch (engineId) { + case "junit-jupiter" -> { validateWellKnownClassName(testEngine, "org.junit.jupiter.engine.JupiterTestEngine"); - return true; + yield true; } - case "junit-vintage": { + case "junit-vintage" -> { validateWellKnownClassName(testEngine, "org.junit.vintage.engine.VintageTestEngine"); - return true; + yield true; } - case "junit-platform-suite": { + case "junit-platform-suite" -> { validateWellKnownClassName(testEngine, "org.junit.platform.suite.engine.SuiteTestEngine"); - return true; + yield true; } - default: - return false; - } + default -> false; + }; } private static void validateWellKnownClassName(TestEngine testEngine, String expectedClassName) { 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 4726702e5a30..46f41fa50f64 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 @@ -393,15 +393,11 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult } private Result.Status convertStatus(TestExecutionResult.Status status) { - switch (status) { - case FAILED: - return Result.Status.FAILED; - case SUCCESSFUL: - return Result.Status.SUCCESSFUL; - case ABORTED: - return Result.Status.ABORTED; - } - throw new JUnitException("Unhandled status: " + status); + return switch (status) { + case FAILED -> Result.Status.FAILED; + case SUCCESSFUL -> Result.Status.SUCCESSFUL; + case ABORTED -> Result.Status.ABORTED; + }; } } From 64de9f0bbe97f5fbdc878eb75bf4c54e244abfb4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:43:36 +0200 Subject: [PATCH 144/521] Use immutable collection factory methods --- .../extension/MutableExtensionRegistry.java | 7 ++-- .../extension/TimeoutDurationParser.java | 23 +++++------ .../junit/jupiter/params/ResolverFacade.java | 3 +- .../support/conversion/ConversionSupport.java | 6 +-- .../StringToCommonJavaTypesConverter.java | 29 +++++--------- .../conversion/StringToJavaTimeConverter.java | 38 +++++++++---------- .../conversion/StringToNumberConverter.java | 26 +++++-------- .../commons/util/AnnotationUtils.java | 3 +- .../platform/commons/util/ExceptionUtils.java | 2 +- .../commons/util/ReflectionUtils.java | 2 +- .../org/junit/platform/engine/TestTag.java | 6 +-- .../descriptor/CompositeTestSource.java | 4 +- .../core/ClasspathAlignmentChecker.java | 6 +-- .../CompositeLauncherDiscoveryListener.java | 4 +- .../CompositeLauncherSessionListener.java | 4 +- .../reporting/legacy/xml/XmlReportWriter.java | 15 +++----- 16 files changed, 66 insertions(+), 112 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index 654d52995004..9ca2552765ec 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -18,8 +18,6 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -53,13 +51,14 @@ public class MutableExtensionRegistry implements ExtensionRegistry, ExtensionReg private static final Logger logger = LoggerFactory.getLogger(MutableExtensionRegistry.class); - private static final List DEFAULT_STATELESS_EXTENSIONS = Collections.unmodifiableList(Arrays.asList(// + private static final List DEFAULT_STATELESS_EXTENSIONS = List.of( // new DisabledCondition(), // new AutoCloseExtension(), // new TimeoutExtension(), // new RepeatedTestExtension(), // new TestInfoParameterResolver(), // - new TestReporterParameterResolver())); + new TestReporterParameterResolver() // + ); /** * Factory for creating and populating a new root registry with the default diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java index a0f01842181e..cba8abbc873e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDurationParser.java @@ -22,8 +22,6 @@ import static java.util.regex.Pattern.UNICODE_CASE; import java.time.format.DateTimeParseException; -import java.util.Collections; -import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -37,19 +35,16 @@ class TimeoutDurationParser { private static final Pattern PATTERN = Pattern.compile("([1-9]\\d*) ?((?:[nμm]?s)|m|h|d)?", CASE_INSENSITIVE | UNICODE_CASE); - private static final Map UNITS_BY_ABBREVIATION; - static { - Map unitsByAbbreviation = new HashMap<>(); - unitsByAbbreviation.put("ns", NANOSECONDS); - unitsByAbbreviation.put("μs", MICROSECONDS); - unitsByAbbreviation.put("ms", MILLISECONDS); - unitsByAbbreviation.put("s", SECONDS); - unitsByAbbreviation.put("m", MINUTES); - unitsByAbbreviation.put("h", HOURS); - unitsByAbbreviation.put("d", DAYS); - UNITS_BY_ABBREVIATION = Collections.unmodifiableMap(unitsByAbbreviation); - } + private static final Map UNITS_BY_ABBREVIATION = Map.of( // + "ns", NANOSECONDS, // + "μs", MICROSECONDS, // + "ms", MILLISECONDS, // + "s", SECONDS, // + "m", MINUTES, // + "h", HOURS, // + "d", DAYS // + ); TimeoutDuration parse(CharSequence text) throws DateTimeParseException { Matcher matcher = PATTERN.matcher(text); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index aa81b1d92c34..6972c72d9ada 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -11,7 +11,6 @@ package org.junit.jupiter.params; import static java.lang.System.lineSeparator; -import static java.util.Collections.unmodifiableList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toList; @@ -584,7 +583,7 @@ public Optional getFirst() { @Override public List getAll() { - return unmodifiableList(new ArrayList<>(this.declarationsByIndex.values())); + return List.copyOf(this.declarationsByIndex.values()); } @Override diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java index 007ee26b07bf..fe3923f9cb4d 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/ConversionSupport.java @@ -10,8 +10,6 @@ package org.junit.platform.commons.support.conversion; -import static java.util.Arrays.asList; -import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.junit.platform.commons.util.ReflectionUtils.getWrapperType; @@ -31,7 +29,7 @@ @API(status = EXPERIMENTAL, since = "1.11") public final class ConversionSupport { - private static final List stringToObjectConverters = unmodifiableList(asList( // + private static final List stringToObjectConverters = List.of( // new StringToBooleanConverter(), // new StringToCharacterConverter(), // new StringToNumberConverter(), // @@ -40,7 +38,7 @@ public final class ConversionSupport { new StringToJavaTimeConverter(), // new StringToCommonJavaTypesConverter(), // new FallbackStringToObjectConverter() // - )); + ); private ConversionSupport() { /* no-op */ diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java index ceeca4d05e09..5d0d3db7fd3b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java @@ -10,8 +10,6 @@ package org.junit.platform.commons.support.conversion; -import static java.util.Collections.unmodifiableMap; - import java.io.File; import java.net.MalformedURLException; import java.net.URI; @@ -20,7 +18,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Currency; -import java.util.HashMap; import java.util.Locale; import java.util.Map; import java.util.UUID; @@ -30,25 +27,19 @@ class StringToCommonJavaTypesConverter implements StringToObjectConverter { - private static final Map, Function> CONVERTERS; - - static { - Map, Function> converters = new HashMap<>(); - + private static final Map, Function> CONVERTERS = Map.of( // // java.io and java.nio - converters.put(File.class, File::new); - converters.put(Charset.class, Charset::forName); - converters.put(Path.class, Paths::get); + File.class, File::new, // + Charset.class, Charset::forName, // + Path.class, Paths::get, // java.net - converters.put(URI.class, URI::create); - converters.put(URL.class, StringToCommonJavaTypesConverter::toURL); + URI.class, URI::create, // + URL.class, StringToCommonJavaTypesConverter::toURL, // java.util - converters.put(Currency.class, Currency::getInstance); - converters.put(Locale.class, Locale::new); - converters.put(UUID.class, UUID::fromString); - - CONVERTERS = unmodifiableMap(converters); - } + Currency.class, Currency::getInstance, // + Locale.class, Locale::new, // + UUID.class, UUID::fromString // + ); @Override public boolean canConvertTo(Class targetType) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java index fb884a84fd4b..c49bd2bc8bdf 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToJavaTimeConverter.java @@ -10,7 +10,7 @@ package org.junit.platform.commons.support.conversion; -import static java.util.Collections.unmodifiableMap; +import static java.util.Map.entry; import java.time.Duration; import java.time.Instant; @@ -26,7 +26,6 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; -import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -34,25 +33,22 @@ class StringToJavaTimeConverter implements StringToObjectConverter { - private static final Map, Function> CONVERTERS; - static { - Map, Function> converters = new HashMap<>(); - converters.put(Duration.class, Duration::parse); - converters.put(Instant.class, Instant::parse); - converters.put(LocalDate.class, LocalDate::parse); - converters.put(LocalDateTime.class, LocalDateTime::parse); - converters.put(LocalTime.class, LocalTime::parse); - converters.put(MonthDay.class, MonthDay::parse); - converters.put(OffsetDateTime.class, OffsetDateTime::parse); - converters.put(OffsetTime.class, OffsetTime::parse); - converters.put(Period.class, Period::parse); - converters.put(Year.class, Year::parse); - converters.put(YearMonth.class, YearMonth::parse); - converters.put(ZonedDateTime.class, ZonedDateTime::parse); - converters.put(ZoneId.class, ZoneId::of); - converters.put(ZoneOffset.class, ZoneOffset::of); - CONVERTERS = unmodifiableMap(converters); - } + private static final Map, Function> CONVERTERS = Map.ofEntries( // + entry(Duration.class, Duration::parse), // + entry(Instant.class, Instant::parse), // + entry(LocalDate.class, LocalDate::parse), // + entry(LocalDateTime.class, LocalDateTime::parse), // + entry(LocalTime.class, LocalTime::parse), // + entry(MonthDay.class, MonthDay::parse), // + entry(OffsetDateTime.class, OffsetDateTime::parse), // + entry(OffsetTime.class, OffsetTime::parse), // + entry(Period.class, Period::parse), // + entry(Year.class, Year::parse), // + entry(YearMonth.class, YearMonth::parse), // + entry(ZonedDateTime.class, ZonedDateTime::parse), // + entry(ZoneId.class, ZoneId::of), // + entry(ZoneOffset.class, ZoneOffset::of) // + ); @Override public boolean canConvertTo(Class targetType) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java index 972cd29b07e4..f21ee0429c1b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToNumberConverter.java @@ -10,11 +10,8 @@ package org.junit.platform.commons.support.conversion; -import static java.util.Collections.unmodifiableMap; - import java.math.BigDecimal; import java.math.BigInteger; -import java.util.HashMap; import java.util.Map; import java.util.function.Function; @@ -22,22 +19,19 @@ class StringToNumberConverter implements StringToObjectConverter { - private static final Map, Function> CONVERTERS; - static { - Map, Function> converters = new HashMap<>(); - converters.put(Byte.class, Byte::decode); - converters.put(Short.class, Short::decode); - converters.put(Integer.class, Integer::decode); - converters.put(Long.class, Long::decode); - converters.put(Float.class, Float::valueOf); - converters.put(Double.class, Double::valueOf); + private static final Map, Function> CONVERTERS = Map.of( // + Byte.class, Byte::decode, // + Short.class, Short::decode, // + Integer.class, Integer::decode, // + Long.class, Long::decode, // + Float.class, Float::valueOf, // + Double.class, Double::valueOf, // // Technically, BigInteger and BigDecimal constructors are covered by // FallbackStringToObjectConverter, but we have explicit conversion // configured for them anyway. - converters.put(BigInteger.class, BigInteger::new); - converters.put(BigDecimal.class, BigDecimal::new); - CONVERTERS = unmodifiableMap(converters); - } + BigInteger.class, BigInteger::new, // + BigDecimal.class, BigDecimal::new // + ); @Override public boolean canConvertTo(Class targetType) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index 11b657a3fcb0..47c316df2190 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -25,7 +25,6 @@ import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Parameter; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; @@ -295,7 +294,7 @@ public static List findRepeatableAnnotations(@Nullable Set found = new LinkedHashSet<>(16); findRepeatableAnnotations(element, annotationType, containerType, inherited, found, new HashSet<>(16)); // unmodifiable since returned from public, non-internal method(s) - return Collections.unmodifiableList(new ArrayList<>(found)); + return List.copyOf(found); } private static void findRepeatableAnnotations(AnnotatedElement element, diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java index c2056951ddf8..8874905af32a 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ExceptionUtils.java @@ -171,7 +171,7 @@ public static List findNestedThrowables(Throwable rootThrowable) { } } - return Collections.unmodifiableList(new ArrayList<>(visited)); + return List.copyOf(visited); } } 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 d85f942009c0..b7dd1735d4a4 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 @@ -1150,7 +1150,7 @@ public static List> findNestedClasses(Class clazz, Predicate(candidates)); + return List.copyOf(candidates); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index bf3ee3fc6d47..979278134116 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -14,9 +14,6 @@ import java.io.Serial; import java.io.Serializable; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashSet; import java.util.Objects; import java.util.Set; @@ -54,8 +51,7 @@ public final class TestTag implements Serializable { *
  • {@code !}: exclamation point
  • * */ - public static final Set RESERVED_CHARACTERS = Collections.unmodifiableSet( - new HashSet<>(Arrays.asList(",", "(", ")", "&", "|", "!"))); + public static final Set RESERVED_CHARACTERS = Set.of(",", "(", ")", "&", "|", "!"); /** * Determine if the supplied tag name is valid with regard to the supported diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java index cfff2d02cc4a..15438b93c4b1 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/CompositeTestSource.java @@ -10,11 +10,9 @@ package org.junit.platform.engine.support.descriptor; -import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serial; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -57,7 +55,7 @@ public static CompositeTestSource from(Collection sources) private CompositeTestSource(Collection sources) { Preconditions.notEmpty(sources, "TestSource collection must not be null or empty"); Preconditions.containsNoNullElements(sources, "individual TestSources must not be null"); - this.sources = unmodifiableList(new ArrayList<>(sources)); + this.sources = List.copyOf(sources); } /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 08d811926ec3..3b52f7f05412 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -10,11 +10,9 @@ package org.junit.platform.launcher.core; -import static java.util.Collections.unmodifiableList; import static java.util.Comparator.comparing; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -33,7 +31,7 @@ class ClasspathAlignmentChecker { // VisibleForTesting - static final List WELL_KNOWN_PACKAGES = unmodifiableList(Arrays.asList( // + static final List WELL_KNOWN_PACKAGES = List.of( // "org.junit.jupiter.api", // "org.junit.jupiter.engine", // "org.junit.jupiter.migrationsupport", // @@ -49,7 +47,7 @@ class ClasspathAlignmentChecker { "org.junit.platform.suite.engine", // "org.junit.platform.testkit", // "org.junit.vintage.engine" // - )); + ); static Optional check(LinkageError error) { ClassLoader classLoader = ClassLoaderUtils.getClassLoader(ClasspathAlignmentChecker.class); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/CompositeLauncherDiscoveryListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/CompositeLauncherDiscoveryListener.java index a9ba957786e4..f8695a9fc09d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/CompositeLauncherDiscoveryListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/CompositeLauncherDiscoveryListener.java @@ -12,8 +12,6 @@ import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.junit.platform.engine.DiscoveryIssue; @@ -33,7 +31,7 @@ class CompositeLauncherDiscoveryListener implements LauncherDiscoveryListener { private final List listeners; CompositeLauncherDiscoveryListener(List listeners) { - this.listeners = Collections.unmodifiableList(new ArrayList<>(listeners)); + this.listeners = List.copyOf(listeners); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/CompositeLauncherSessionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/CompositeLauncherSessionListener.java index c1c13327652c..e03a6940f237 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/CompositeLauncherSessionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/session/CompositeLauncherSessionListener.java @@ -12,8 +12,6 @@ import static org.junit.platform.commons.util.CollectionUtils.forEachInReverseOrder; -import java.util.ArrayList; -import java.util.Collections; import java.util.List; import org.junit.platform.launcher.LauncherSession; @@ -28,7 +26,7 @@ class CompositeLauncherSessionListener implements LauncherSessionListener { private final List listeners; CompositeLauncherSessionListener(List listeners) { - this.listeners = Collections.unmodifiableList(new ArrayList<>(listeners)); + this.listeners = List.copyOf(listeners); } @Override diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java index 203cac3e3f15..5847b73cbb7c 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportWriter.java @@ -13,7 +13,6 @@ import static java.text.MessageFormat.format; import static java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME; import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableMap; import static java.util.Comparator.naturalOrder; import static java.util.Objects.requireNonNull; import static java.util.function.Function.identity; @@ -41,7 +40,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.EnumSet; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; @@ -75,14 +73,11 @@ class XmlReportWriter { static final char ILLEGAL_CHARACTER_REPLACEMENT = '\uFFFD'; - private static final Map REPLACEMENTS_IN_ATTRIBUTE_VALUES; - static { - Map tmp = new HashMap<>(3); - tmp.put('\n', " "); - tmp.put('\r', " "); - tmp.put('\t', " "); - REPLACEMENTS_IN_ATTRIBUTE_VALUES = unmodifiableMap(tmp); - } + private static final Map REPLACEMENTS_IN_ATTRIBUTE_VALUES = Map.of( // + '\n', " ", // + '\r', " ", // + '\t', " " // + ); // Using zero-width assertions in the split pattern simplifies the splitting process: All split parts // (including the first and last one) can be used directly, without having to re-add separator characters. From c0b6e1e2ad73a4de6d7927453168b1debf41cd23 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:46:23 +0200 Subject: [PATCH 145/521] Delete `CollectionUtils.toSet` --- .../params/provider/CsvArgumentsProvider.java | 13 +++++----- .../provider/CsvFileArgumentsProvider.java | 3 +-- .../commons/util/CollectionUtils.java | 24 ------------------- 3 files changed, 7 insertions(+), 33 deletions(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index 3f961f83c718..9ec3aa038417 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -12,7 +12,6 @@ import static java.util.Objects.requireNonNull; import static org.junit.jupiter.params.provider.CsvParserFactory.createParserFor; -import static org.junit.platform.commons.util.CollectionUtils.toSet; import java.io.StringReader; import java.lang.annotation.Annotation; @@ -43,7 +42,7 @@ class CsvArgumentsProvider extends AnnotationBasedArgumentsProvider { @Override protected Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context, CsvSource csvSource) { - Set nullValues = toSet(csvSource.nullValues()); + Set nullValues = Set.of(csvSource.nullValues()); CsvParser csvParser = createParserFor(csvSource); final boolean textBlockDeclared = !csvSource.textBlock().isEmpty(); Preconditions.condition(csvSource.value().length > 0 ^ textBlockDeclared, @@ -59,11 +58,11 @@ private Stream parseTextBlock(CsvSource csvSource, CsvParser csvParse List argumentsList = new ArrayList<>(); try { - List csvRecords = csvParser.parseAll(new StringReader(textBlock)); + List<@Nullable String[]> csvRecords = csvParser.parseAll(new StringReader(textBlock)); String[] headers = useHeadersInDisplayName ? getHeaders(csvParser) : null; AtomicInteger index = new AtomicInteger(0); - for (String[] csvRecord : csvRecords) { + for (var csvRecord : csvRecords) { index.incrementAndGet(); Preconditions.notNull(csvRecord, () -> "Record at index " + index + " contains invalid CSV: \"\"\"\n" + textBlock + "\n\"\"\""); @@ -116,8 +115,8 @@ static String[] getHeaders(CsvParser csvParser) { * {@link Named} if necessary (for CSV header support), and returns the * CSV record wrapped in an {@link Arguments} instance. */ - static Arguments processCsvRecord(String[] csvRecord, Set nullValues, boolean useHeadersInDisplayName, - String @Nullable [] headers) { + static Arguments processCsvRecord(@Nullable String[] csvRecord, Set nullValues, + boolean useHeadersInDisplayName, String @Nullable [] headers) { // Nothing to process? if (nullValues.isEmpty() && !useHeadersInDisplayName) { @@ -132,7 +131,7 @@ static Arguments processCsvRecord(String[] csvRecord, Set nullValues, bo Object[] arguments = new Object[csvRecord.length]; for (int i = 0; i < csvRecord.length; i++) { Object column = csvRecord[i]; - if (nullValues.contains(column)) { + if (column != null && nullValues.contains(column)) { column = null; } if (useHeadersInDisplayName) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index a56ec8270b3a..f840c3bfa52e 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.params.provider.CsvArgumentsProvider.handleCsvException; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.processCsvRecord; import static org.junit.jupiter.params.provider.CsvParserFactory.createParserFor; -import static org.junit.platform.commons.util.CollectionUtils.toSet; import java.io.IOException; import java.io.InputStream; @@ -125,7 +124,7 @@ private static class CsvParserIterator implements Iterator { this.csvParser = csvParser; this.csvFileSource = csvFileSource; this.useHeadersInDisplayName = csvFileSource.useHeadersInDisplayName(); - this.nullValues = toSet(csvFileSource.nullValues()); + this.nullValues = Set.of(csvFileSource.nullValues()); advance(); } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index ed4e255620b7..b5bac6b02d55 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -23,12 +23,10 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; -import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Optional; -import java.util.Set; import java.util.function.Consumer; import java.util.stream.Collector; import java.util.stream.DoubleStream; @@ -96,28 +94,6 @@ private CollectionUtils() { : collection.iterator().next(); } - /** - * Convert the supplied array of values to a {@link Set}. - * - * @param values the array of values; never {@code null} - * @return a set of the values - * @throws PreconditionViolationException if the array is {@code null} - * @since 1.6 - */ - @API(status = INTERNAL, since = "1.6") - public static Set toSet(T[] values) { - Preconditions.notNull(values, "values array must not be null"); - if (values.length == 0) { - return Collections.emptySet(); - } - if (values.length == 1) { - return Collections.singleton(values[0]); - } - var set = new HashSet(); - Collections.addAll(set, values); - return set; - } - /** * Return a {@code Collector} that accumulates the input elements into a * new unmodifiable list, in encounter order. From e0a5504ccd0204ed95c70e17022fb8cc190cc726 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:48:23 +0200 Subject: [PATCH 146/521] Replace `CollectionUtils.toUnmodifiableList()` with `Stream.toList()` --- .../ExclusiveResourceCollector.java | 9 ++++--- .../descriptor/LifecycleMethodUtils.java | 3 +-- .../params/ParameterizedClassContext.java | 3 +-- .../commons/util/AnnotationUtils.java | 3 +-- .../commons/util/CollectionUtils.java | 26 ------------------- .../commons/util/ReflectionUtils.java | 9 +++---- .../engine/discovery/DiscoverySelectors.java | 5 ++-- .../engine/discovery/NestedClassSelector.java | 3 +-- .../support/hierarchical/LockManager.java | 5 ++-- .../junit/platform/launcher/TagFilter.java | 3 +-- .../suite/engine/LifecycleMethodUtils.java | 3 +-- .../ParameterizedTestIntegrationTests.java | 2 +- .../commons/util/CollectionUtilsTests.java | 11 -------- 13 files changed, 21 insertions(+), 64 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java index a7c49e9b14c7..6c08e136720c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExclusiveResourceCollector.java @@ -12,7 +12,6 @@ import static org.junit.jupiter.api.parallel.ResourceLockTarget.SELF; import static org.junit.platform.commons.support.AnnotationSupport.findRepeatableAnnotations; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.lang.reflect.AnnotatedElement; import java.util.Collection; @@ -105,12 +104,16 @@ Stream getDynamicResources( private List getProviders() { if (this.providers == null) { this.providers = annotations.stream() // - .flatMap(annotation -> Stream.of(annotation.providers()).map(ReflectionUtils::newInstance)) // - .collect(toUnmodifiableList()); + .flatMap(annotation -> instantiate(annotation.providers())) // + .toList(); } return providers; } + private static Stream instantiate(Class[] providers) { + return Stream.of(providers).map(ReflectionUtils::newInstance); + } + private static ExclusiveResource.LockMode toLockMode(ResourceAccessMode mode) { return switch (mode) { case READ -> ExclusiveResource.LockMode.READ; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java index 5c633980985c..954074408e1c 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/LifecycleMethodUtils.java @@ -13,7 +13,6 @@ import static org.junit.jupiter.engine.support.MethodReflectionUtils.getReturnType; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedMethods; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.engine.support.discovery.DiscoveryIssueReporter.Condition.alwaysSatisfied; import java.lang.annotation.Annotation; @@ -134,7 +133,7 @@ private static List findMethodsAndCheckVoidReturnType(Class testClass .peek(isNotPrivateWarning(issueReporter, annotationType::getSimpleName).toConsumer()) // .filter(returnsPrimitiveVoid(issueReporter, __ -> annotationType.getSimpleName()).and( additionalCondition).toPredicate()) // - .collect(toUnmodifiableList()); + .toList(); } private static Condition isStatic(DiscoveryIssueReporter issueReporter, diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java index 58b022d3f17a..b6002a4ad817 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassContext.java @@ -18,7 +18,6 @@ import static org.junit.platform.commons.support.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.support.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.support.ReflectionSupport.findFields; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.ReflectionUtils.isRecordClass; import java.lang.annotation.Annotation; @@ -161,7 +160,7 @@ private static
    List findLifec } return new ArgumentSetLifecycleMethod(method); }) // - .collect(toUnmodifiableList()); + .toList(); } private static A getAnnotation(Method method, Class annotationType) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java index 47c316df2190..0e7d7b7e2441 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/AnnotationUtils.java @@ -13,7 +13,6 @@ import static java.util.Arrays.asList; import static java.util.Objects.requireNonNull; import static org.apiguardian.api.API.Status.INTERNAL; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.ReflectionUtils.isInnerClass; import java.lang.annotation.Annotation; @@ -454,7 +453,7 @@ public static List findPublicAnnotatedFields(Class clazz, Class fie // @formatter:off return Arrays.stream(clazz.getFields()) .filter(field -> fieldType.isAssignableFrom(field.getType()) && isAnnotated(field, annotationType)) - .collect(toUnmodifiableList()); + .toList(); // @formatter:on } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index b5bac6b02d55..2305526dd882 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -12,8 +12,6 @@ import static java.util.Spliterator.ORDERED; import static java.util.Spliterators.spliteratorUnknownSize; -import static java.util.stream.Collectors.collectingAndThen; -import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.support.ReflectionSupport.invokeMethod; @@ -22,13 +20,11 @@ import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Optional; import java.util.function.Consumer; -import java.util.stream.Collector; import java.util.stream.DoubleStream; import java.util.stream.IntStream; import java.util.stream.LongStream; @@ -94,28 +90,6 @@ private CollectionUtils() { : collection.iterator().next(); } - /** - * Return a {@code Collector} that accumulates the input elements into a - * new unmodifiable list, in encounter order. - * - *

    There are no guarantees on the type or serializability of the list - * returned, so if more control over the returned list is required, - * consider creating a new {@code Collector} implementation like the - * following: - * - *

    -	 * public static <T> Collector<T, ?, List<T>> toUnmodifiableList(Supplier<List<T>> listSupplier) {
    -	 *     return Collectors.collectingAndThen(Collectors.toCollection(listSupplier), Collections::unmodifiableList);
    -	 * }
    - * - * @param the type of the input elements - * @return a {@code Collector} which collects all the input elements into - * an unmodifiable list, in encounter order - */ - public static Collector> toUnmodifiableList() { - return collectingAndThen(toList(), Collections::unmodifiableList); - } - /** * Determine if an instance of the supplied type can be converted into a * {@code Stream}. 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 b7dd1735d4a4..01e2a7224eff 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 @@ -16,7 +16,6 @@ import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.commons.util.PackageNameUtils.getPackageName; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; @@ -707,7 +706,7 @@ public static List readFieldValues(List fields, @Nullable Object .map(field -> tryToReadFieldValue(field, instance) .getOrThrow(ExceptionUtils::throwAsUncheckedException)) - .collect(toUnmodifiableList()); + .toList(); // @formatter:on } @@ -1314,7 +1313,7 @@ public static List> findConstructors(Class clazz, Predicate> findConstructors(Class clazz, Predicate findFields(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { - return streamFields(clazz, predicate, traversalMode).collect(toUnmodifiableList()); + return streamFields(clazz, predicate, traversalMode).toList(); } /** @@ -1594,7 +1593,7 @@ public static List findMethods(Class clazz, Predicate predica public static List findMethods(Class clazz, Predicate predicate, HierarchyTraversalMode traversalMode) { - return streamMethods(clazz, predicate, traversalMode).collect(toUnmodifiableList()); + return streamMethods(clazz, predicate, traversalMode).toList(); } /** 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 d65b7977ed1e..6bc7b4a5b951 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 @@ -13,7 +13,6 @@ import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.STABLE; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.io.File; import java.io.IOException; @@ -262,7 +261,7 @@ public static List selectClasspathRoots(Set classpa .map(Path::toUri) .map(ClasspathRootSelector::new) // unmodifiable since selectClasspathRoots is a public, non-internal method - .collect(toUnmodifiableList()); + .toList(); // @formatter:on } @@ -394,7 +393,7 @@ public static List selectModules(Set moduleNames) { return moduleNames.stream() .map(DiscoverySelectors::selectModule) // unmodifiable since this is a public, non-internal method - .collect(toUnmodifiableList()); + .toList(); // @formatter:on } 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 8c2b67753525..8ca60d18c740 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 @@ -15,7 +15,6 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.util.Arrays; import java.util.List; @@ -65,7 +64,7 @@ public class NestedClassSelector implements DiscoverySelector { this.classLoader = classLoader; this.enclosingClassSelectors = enclosingClassNames.stream() // .map(className -> new ClassSelector(classLoader, className)) // - .collect(toUnmodifiableList()); + .toList(); this.nestedClassSelector = new ClassSelector(classLoader, nestedClassName); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java index c8e236341726..3171c31d2b66 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/LockManager.java @@ -15,7 +15,6 @@ import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.GLOBAL_READ_WRITE; import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode.READ; @@ -66,7 +65,7 @@ private List toDistinctSortedResources(Collection resourcesWithSameKey.get(0)) - .collect(toUnmodifiableList()); + .toList(); // @formatter:on } @@ -89,7 +88,7 @@ private SingleLock toSingleLock(ExclusiveResource resource) { } private List toLocks(List resources) { - return resources.stream().map(this::toLock).collect(toUnmodifiableList()); + return resources.stream().map(this::toLock).toList(); } private Lock toLock(ExclusiveResource resource) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java index 51e37f95dbc6..413a4521424a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java @@ -12,7 +12,6 @@ import static java.util.Arrays.asList; import static org.apiguardian.api.API.Status.STABLE; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.util.List; import java.util.Set; @@ -173,7 +172,7 @@ private static String formatToString(List tagExpressions) { } private static List parseAll(List tagExpressions) { - return tagExpressions.stream().map(TagFilter::parse).collect(toUnmodifiableList()); + return tagExpressions.stream().map(TagFilter::parse).toList(); } private static TagExpression parse(@Nullable String tagExpression) { diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java index 2509ff0e4e87..214d036a35d5 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/LifecycleMethodUtils.java @@ -11,7 +11,6 @@ package org.junit.platform.suite.engine; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotatedMethods; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.lang.annotation.Annotation; import java.lang.reflect.Method; @@ -59,7 +58,7 @@ private static List findMethodsAndCheckStaticAndNonPrivate(Class test .and(isNotPrivate(annotationType, issueReporter)) // .and(hasNoParameters(annotationType, issueReporter)) // .toPredicate()) // - .collect(toUnmodifiableList()); + .toList(); } private static DiscoveryIssueReporter.Condition isStatic(Class annotationType, diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index bf6653dce499..379efee6ca38 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -225,7 +225,7 @@ void executesLinesFromClasspathResourceUsingTableFormatAndHeadersAndNullValues(S assertFruitTable(fruit, rank, testInfo); } - private void assertFruitTable(String fruit, double rank, TestInfo testInfo) { + private void assertFruitTable(@Nullable String fruit, double rank, TestInfo testInfo) { String displayName = testInfo.getDisplayName(); if (fruit == null) { diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java index 12ef9107f8ce..6c11ca4a55b7 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java @@ -16,7 +16,6 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.DynamicTest.dynamicTest; -import static org.junit.platform.commons.util.CollectionUtils.toUnmodifiableList; import java.lang.reflect.Array; import java.util.ArrayList; @@ -121,16 +120,6 @@ void collectionWithNullValues() { } } - @Nested - class UnmodifiableList { - - @Test - void throwsOnMutation() { - var numbers = Stream.of(1).collect(toUnmodifiableList()); - assertThrows(UnsupportedOperationException.class, numbers::clear); - } - } - @Nested class StreamConversion { From 2b1eac3ef37dbf894be8b877b053cf7381cfbf3f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:50:04 +0200 Subject: [PATCH 147/521] Pass `Charset` directly --- .../org/junit/platform/engine/UniqueIdFormat.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java index 5a96a33a6846..24047a30bcd9 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java @@ -15,7 +15,6 @@ import java.io.Serial; import java.io.Serializable; -import java.io.UnsupportedEncodingException; import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -51,12 +50,7 @@ private static String quote(char c) { } private static String encode(char c) { - try { - return URLEncoder.encode(String.valueOf(c), StandardCharsets.UTF_8.name()); - } - catch (UnsupportedEncodingException e) { - throw new AssertionError("UTF-8 should be supported", e); - } + return URLEncoder.encode(String.valueOf(c), StandardCharsets.UTF_8); } private final char openSegment; @@ -152,12 +146,7 @@ private String encode(String s) { } private static String decode(String s) { - try { - return URLDecoder.decode(s, StandardCharsets.UTF_8.name()); - } - catch (UnsupportedEncodingException e) { - throw new JUnitException("UTF-8 should be supported", e); - } + return URLDecoder.decode(s, StandardCharsets.UTF_8); } } From ad907d03239594d3361ddc74c2bd5a30020aadb7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:50:58 +0200 Subject: [PATCH 148/521] Delete `PackageNameUtils` --- .../commons/util/PackageNameUtils.java | 30 ------------------- .../commons/util/ReflectionUtils.java | 3 +- 2 files changed, 1 insertion(+), 32 deletions(-) delete mode 100644 junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java deleted file mode 100644 index 0cb6aec9e8d8..000000000000 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/PackageNameUtils.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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; - -/** - * Collection of utilities for working with package names. - * - *

    DISCLAIMER

    - * - *

    These utilities are intended solely for usage within the JUnit framework - * itself. Any usage by external parties is not supported. - * Use at your own risk! - * - * @since 1.11.3 - */ -class PackageNameUtils { - - static String getPackageName(Class clazz) { - return clazz.getPackageName(); - } - -} 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 01e2a7224eff..dbcf7e0aaf4a 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 @@ -16,7 +16,6 @@ import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; -import static org.junit.platform.commons.util.PackageNameUtils.getPackageName; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.BOTTOM_UP; import static org.junit.platform.commons.util.ReflectionUtils.HierarchyTraversalMode.TOP_DOWN; @@ -1877,7 +1876,7 @@ private static boolean isPackagePrivate(Member member) { } private static boolean declaredInSamePackage(Method m1, Method m2) { - return getPackageName(m1.getDeclaringClass()).equals(getPackageName(m2.getDeclaringClass())); + return m1.getDeclaringClass().getPackageName().equals(m2.getDeclaringClass().getPackageName()); } /** From 598ec60e7c2df636acf6c48681721daabd70cf17 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:53:26 +0200 Subject: [PATCH 149/521] Delete unused methods --- .../platform/commons/util/ReflectionUtils.java | 8 -------- .../platform/testkit/engine/EngineTestKit.java | 14 -------------- 2 files changed, 22 deletions(-) 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 dbcf7e0aaf4a..2e413b08c1c8 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 @@ -1647,14 +1647,6 @@ private static List findAllMethodsInHierarchy(Class clazz, HierarchyT return methods; } - /** - * Custom alternative to {@link Class#getFields()} that sorts the fields - * and converts them to a mutable list. - */ - private static List getFields(Class clazz) { - return toSortedMutableList(clazz.getFields()); - } - /** * Custom alternative to {@link Class#getDeclaredFields()} that sorts the * fields and converts them to a mutable list. 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 96e8fbcad24f..619acc7c5cbe 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 @@ -33,13 +33,10 @@ import org.junit.platform.engine.DiscoveryFilter; import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.DiscoverySelector; -import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.EngineExecutionListener; -import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.Filter; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestEngine; -import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.reporting.OutputDirectoryProvider; import org.junit.platform.engine.support.store.Namespace; import org.junit.platform.engine.support.store.NamespacedHierarchicalStore; @@ -251,17 +248,6 @@ public static EngineExecutionResults execute(TestEngine testEngine, LauncherDisc return executionRecorder.getExecutionResults(); } - private static void executeDirectly(TestEngine testEngine, EngineDiscoveryRequest discoveryRequest, - EngineExecutionListener listener) { - UniqueId engineUniqueId = UniqueId.forEngine(testEngine.getId()); - TestDescriptor engineTestDescriptor = testEngine.discover(discoveryRequest, engineUniqueId); - withRequestLevelStore(store -> { - ExecutionRequest request = ExecutionRequest.create(engineTestDescriptor, listener, - discoveryRequest.getConfigurationParameters(), discoveryRequest.getOutputDirectoryProvider(), store); - testEngine.execute(request); - }); - } - private static void executeUsingLauncherOrchestration(TestEngine testEngine, LauncherDiscoveryRequest discoveryRequest, EngineExecutionListener listener) { LauncherDiscoveryResult discoveryResult = discoverUsingOrchestrator(testEngine, discoveryRequest); From 46cfefeb81193d39ddb358084f0cb1c0cc0b54eb Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:54:51 +0200 Subject: [PATCH 150/521] Remove unnecessary non-capturing groups --- .../org/junit/platform/launcher/tagexpression/Tokenizer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java index 042f97eb12b1..57a5e6cbe687 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Tokenizer.java @@ -25,7 +25,7 @@ */ class Tokenizer { - private static final Pattern PATTERN = Pattern.compile("\\s*(?:(?:(?:any|none)\\(\\))|[()!|&]|(?:[^\\s()!|&]+))", + private static final Pattern PATTERN = Pattern.compile("\\s*(?:(?:any|none)\\(\\)|[()!|&]|[^\\s()!|&]+)", CASE_INSENSITIVE); List tokenize(@Nullable String infixTagExpression) { From 3d1b7aa9adfb1f16c43ab3cc68d0f53853c70d8a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 23 May 2025 17:58:55 +0200 Subject: [PATCH 151/521] Simplify usage of `Optional` --- .../jupiter/engine/discovery/MethodOrderingVisitor.java | 5 ++--- .../platform/engine/support/hierarchical/ResourceLock.java | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) 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 b4b2352aeafe..052f4cb822e9 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 @@ -73,9 +73,8 @@ protected boolean shouldNonMatchingDescriptorsComeBeforeOrderedOnes() { private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescriptor, Class testClass) { Optional methodOrderer = findAnnotation(testClass, TestMethodOrder.class)// .map(TestMethodOrder::value)// - . map(ReflectionSupport::newInstance)// - .map(Optional::of)// - .orElseGet(configuration::getDefaultTestMethodOrderer); + . map(ReflectionSupport::newInstance) // + .or(configuration::getDefaultTestMethodOrderer); orderContainedMethods(classBasedTestDescriptor, testClass, methodOrderer); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ResourceLock.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ResourceLock.java index 4f62637aa6ef..5022d88d0101 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ResourceLock.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ResourceLock.java @@ -90,6 +90,6 @@ default boolean isCompatible(ResourceLock other) { .filter(resource -> ExclusiveResource.COMPARATOR.compare(resource, ownResources.get(ownResources.size() - 1)) < 0); - return !(potentiallyDeadlockCausingAdditionalResource.isPresent()); + return potentiallyDeadlockCausingAdditionalResource.isEmpty(); } } From 0681c6f57e59db77e7075d2144cf1645e9e086c3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 13:45:24 +0200 Subject: [PATCH 152/521] Use records --- .../jupiter/api/AssertIterableEquals.java | 25 +------- .../junit/jupiter/api/AssertLinesMatch.java | 15 +---- .../DefaultDynamicTestInvocationContext.java | 8 +-- .../DefaultTestInstanceFactoryContext.java | 11 +--- .../execution/DefaultParameterContext.java | 13 ++-- .../execution/InvocationInterceptorChain.java | 13 +--- .../extension/DefaultPreInterruptContext.java | 6 +- .../extension/DefaultRepetitionInfo.java | 16 +---- .../RepeatedTestInvocationContext.java | 2 +- .../engine/extension/RepetitionExtension.java | 6 +- .../SameThreadTimeoutInvocation.java | 2 +- .../engine/extension/TempDirectory.java | 15 +---- .../engine/extension/TimeoutDuration.java | 31 +--------- .../jupiter/params/DefaultParameterInfo.java | 10 +-- .../ParameterizedInvocationContext.java | 9 +-- .../ParameterizedInvocationNameFormatter.java | 32 ++-------- .../junit/jupiter/params/ResolverFacade.java | 45 +++----------- .../AnnotationConsumerInitializer.java | 19 +----- .../commons/support/DefaultResource.java | 27 ++------ .../platform/commons/util/StringUtils.java | 20 +----- .../support/descriptor/DefaultUriSource.java | 26 +------- .../support/hierarchical/NodeTestTask.java | 20 +++--- .../hierarchical/NodeTestTaskContext.java | 31 +--------- .../store/NamespacedHierarchicalStore.java | 61 +++---------------- .../DemoEngineExecutionContext.java | 9 +-- .../MutableTestExecutionSummary.java | 12 +--- .../launcher/tagexpression/Operator.java | 19 +++--- .../launcher/tagexpression/ParseStatus.java | 4 +- .../launcher/tagexpression/ShuntingYard.java | 18 +++--- .../launcher/tagexpression/Token.java | 10 +-- .../launcher/tagexpression/TokenWith.java | 11 +--- .../suite/engine/SuiteTestDescriptor.java | 13 +--- .../support/UniqueIdStringifierTests.java | 18 ++---- ...nerWithCustomUniqueIdsAndDisplayNames.java | 16 +---- .../TestFactoryTestDescriptorTests.java | 8 +-- .../ParameterResolutionUtilsTests.java | 10 +-- ...rogrammaticExtensionRegistrationTests.java | 8 +-- .../rules/AbstractTestRuleAdapterTests.java | 8 +-- .../AggregatorIntegrationTests.java | 12 +--- .../launcher/tagexpression/TokenTests.java | 4 +- .../tagexpression/TokenizerTests.java | 4 +- ...OpenTestReportGeneratingListenerTests.java | 2 +- 42 files changed, 121 insertions(+), 528 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java index 6512d10e8f12..b9e70a58844d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertIterableEquals.java @@ -198,30 +198,7 @@ private static void failIterablesNotEqual(Object expected, Object actual, Deque< .buildAndThrow(); } - private final static class Pair { - private final Object left; - private final Object right; - - public Pair(Object left, Object right) { - this.left = left; - this.right = right; - } - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - Pair that = (Pair) o; - return Objects.equals(this.left, that.left) // - && Objects.equals(this.right, that.right); - } - - @Override - public int hashCode() { - return Objects.hash(left, right); - } + private record Pair(Object left, Object right) { } private enum Status { diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java index 2f61fe53e8e1..18cb6621d7c7 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java @@ -83,19 +83,8 @@ static void assertLinesMatch(List expectedLines, List actualLine new LinesMatcher(expectedLines, actualLines, messageOrSupplier).assertLinesMatch(); } - private static class LinesMatcher { - - private final List expectedLines; - private final List actualLines; - - @Nullable - private final Object messageOrSupplier; - - LinesMatcher(List expectedLines, List actualLines, @Nullable Object messageOrSupplier) { - this.expectedLines = expectedLines; - this.actualLines = actualLines; - this.messageOrSupplier = messageOrSupplier; - } + private record LinesMatcher(List expectedLines, List actualLines, + @Nullable Object messageOrSupplier) { void assertLinesMatch() { int expectedSize = expectedLines.size(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultDynamicTestInvocationContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultDynamicTestInvocationContext.java index 72ef0981b728..402b6478bbed 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultDynamicTestInvocationContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultDynamicTestInvocationContext.java @@ -18,13 +18,7 @@ * * @since 5.8 */ -class DefaultDynamicTestInvocationContext implements DynamicTestInvocationContext { - - private final Executable executable; - - DefaultDynamicTestInvocationContext(Executable executable) { - this.executable = executable; - } +record DefaultDynamicTestInvocationContext(Executable executable) implements DynamicTestInvocationContext { @Override public Executable getExecutable() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultTestInstanceFactoryContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultTestInstanceFactoryContext.java index 8414ab8c834a..096b6b4c60dc 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultTestInstanceFactoryContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DefaultTestInstanceFactoryContext.java @@ -20,15 +20,8 @@ * * @since 5.3 */ -class DefaultTestInstanceFactoryContext implements TestInstanceFactoryContext { - - private final Class testClass; - private final Optional outerInstance; - - DefaultTestInstanceFactoryContext(Class testClass, Optional outerInstance) { - this.testClass = testClass; - this.outerInstance = outerInstance; - } +record DefaultTestInstanceFactoryContext(Class testClass, Optional outerInstance) + implements TestInstanceFactoryContext { @Override public Class getTestClass() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultParameterContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultParameterContext.java index 23d2ada54331..4b4f48714d8b 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultParameterContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/DefaultParameterContext.java @@ -23,17 +23,12 @@ /** * @since 5.0 */ -class DefaultParameterContext implements ParameterContext { +record DefaultParameterContext(Parameter parameter, int index, Optional target) implements ParameterContext { - private final Parameter parameter; - private final int index; - private final Optional target; - - DefaultParameterContext(Parameter parameter, int index, Optional target) { + DefaultParameterContext { Preconditions.condition(index >= 0, "index must be greater than or equal to zero"); - this.parameter = Preconditions.notNull(parameter, "parameter must not be null"); - this.index = index; - this.target = Preconditions.notNull(target, "target must not be null"); + Preconditions.notNull(parameter, "parameter must not be null"); + Preconditions.notNull(target, "target must not be null"); } @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java index 6f2352716f99..f066298ade98 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java @@ -91,17 +91,8 @@ public interface VoidInterceptorCall { } - private static class InterceptedInvocation implements Invocation { - - private final Invocation invocation; - private final InterceptorCall call; - private final InvocationInterceptor interceptor; - - InterceptedInvocation(Invocation invocation, InterceptorCall call, InvocationInterceptor interceptor) { - this.invocation = invocation; - this.call = call; - this.interceptor = interceptor; - } + private record InterceptedInvocation(Invocation invocation, InterceptorCall call, + InvocationInterceptor interceptor) implements Invocation { @Override public T proceed() throws Throwable { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultPreInterruptContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultPreInterruptContext.java index 0e4be93b94e2..81fcd96f3228 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultPreInterruptContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultPreInterruptContext.java @@ -17,12 +17,10 @@ /** * @since 5.12 */ -class DefaultPreInterruptContext implements PreInterruptContext { - private final Thread threadToInterrupt; +record DefaultPreInterruptContext(Thread threadToInterrupt) implements PreInterruptContext { - DefaultPreInterruptContext(Thread threadToInterrupt) { + DefaultPreInterruptContext { Preconditions.notNull(threadToInterrupt, "threadToInterrupt must not be null"); - this.threadToInterrupt = threadToInterrupt; } @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultRepetitionInfo.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultRepetitionInfo.java index d9ecb54a3a68..3f92be90bf40 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultRepetitionInfo.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/DefaultRepetitionInfo.java @@ -18,20 +18,8 @@ /** * Default implementation of {@link RepetitionInfo}. */ -class DefaultRepetitionInfo implements RepetitionInfo { - - final int currentRepetition; - final int totalRepetitions; - final AtomicInteger failureCount; - final int failureThreshold; - - DefaultRepetitionInfo(int currentRepetition, int totalRepetitions, AtomicInteger failureCount, - int failureThreshold) { - this.currentRepetition = currentRepetition; - this.totalRepetitions = totalRepetitions; - this.failureCount = failureCount; - this.failureThreshold = failureThreshold; - } +record DefaultRepetitionInfo(int currentRepetition, int totalRepetitions, AtomicInteger failureCount, + int failureThreshold) implements RepetitionInfo { @Override public int getCurrentRepetition() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestInvocationContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestInvocationContext.java index b4f3f74e17b6..d8a735849d7e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestInvocationContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepeatedTestInvocationContext.java @@ -36,7 +36,7 @@ public RepeatedTestInvocationContext(DefaultRepetitionInfo repetitionInfo, @Override public String getDisplayName(int invocationIndex) { - return this.formatter.format(this.repetitionInfo.currentRepetition, this.repetitionInfo.totalRepetitions); + return this.formatter.format(this.repetitionInfo.currentRepetition(), this.repetitionInfo.totalRepetitions()); } @Override diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java index 6eac77602c66..388c8fa33840 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/RepetitionExtension.java @@ -63,13 +63,13 @@ public RepetitionInfo resolveParameter(ParameterContext parameterContext, Extens @Override public void testFailed(ExtensionContext context, @Nullable Throwable cause) { - this.repetitionInfo.failureCount.incrementAndGet(); + this.repetitionInfo.failureCount().incrementAndGet(); } @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - int failureThreshold = this.repetitionInfo.failureThreshold; - if (this.repetitionInfo.failureCount.get() >= failureThreshold) { + int failureThreshold = this.repetitionInfo.getFailureThreshold(); + if (this.repetitionInfo.getFailureCount() >= failureThreshold) { return disabled("Failure threshold [" + failureThreshold + "] exceeded"); } return enabled("Failure threshold not exceeded"); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java index 395726217fa9..c1df07a23e43 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SameThreadTimeoutInvocation.java @@ -44,7 +44,7 @@ class SameThreadTimeoutInvocation implements Invocat @Override public T proceed() throws Throwable { InterruptTask interruptTask = new InterruptTask(Thread.currentThread(), preInterruptCallback); - ScheduledFuture future = executor.schedule(interruptTask, timeout.getValue(), timeout.getUnit()); + ScheduledFuture future = executor.schedule(interruptTask, timeout.value(), timeout.unit()); Throwable failure = null; T result = null; try { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java index 3339a17c8f23..d352e94a358a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TempDirectory.java @@ -553,9 +553,7 @@ interface FileOperations { } - private static class FieldContext implements AnnotatedElementContext { - - private final Field field; + private record FieldContext(Field field) implements AnnotatedElementContext { private FieldContext(Field field) { this.field = Preconditions.notNull(field, "field must not be null"); @@ -578,15 +576,8 @@ public String toString() { } @SuppressWarnings("deprecation") - private static class FailureTracker implements Store.CloseableResource, AutoCloseable { - - private final ExtensionContext context; - private final ExtensionContext parentContext; - - private FailureTracker(ExtensionContext context, ExtensionContext parentContext) { - this.context = context; - this.parentContext = parentContext; - } + private record FailureTracker(ExtensionContext context, ExtensionContext parentContext) + implements Store.CloseableResource, AutoCloseable { @Override public void close() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java index 80b7f28e72e9..66c154faba5a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutDuration.java @@ -12,7 +12,6 @@ import java.time.Duration; import java.time.temporal.ChronoUnit; -import java.util.Objects; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Timeout; @@ -22,46 +21,18 @@ /** * @since 5.5 */ -class TimeoutDuration { +record TimeoutDuration(long value, TimeUnit unit) { static TimeoutDuration from(Timeout timeout) { return new TimeoutDuration(timeout.value(), timeout.unit()); } - private final long value; - private final TimeUnit unit; - TimeoutDuration(long value, TimeUnit unit) { Preconditions.condition(value > 0, () -> "timeout duration must be a positive number: " + value); this.value = value; this.unit = Preconditions.notNull(unit, "timeout unit must not be null"); } - public long getValue() { - return value; - } - - public TimeUnit getUnit() { - return unit; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - TimeoutDuration that = (TimeoutDuration) o; - return value == that.value && unit == that.unit; - } - - @Override - public int hashCode() { - return Objects.hash(value, unit); - } - @Override public String toString() { String label = unit.name().toLowerCase(); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/DefaultParameterInfo.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/DefaultParameterInfo.java index 96fffa5039d5..c74ba724ea76 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/DefaultParameterInfo.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/DefaultParameterInfo.java @@ -18,15 +18,7 @@ /** * @since 5.13 */ -class DefaultParameterInfo implements ParameterInfo { - - private final ParameterDeclarations declarations; - private final ArgumentsAccessor arguments; - - DefaultParameterInfo(ParameterDeclarations declarations, ArgumentsAccessor arguments) { - this.declarations = declarations; - this.arguments = arguments; - } +record DefaultParameterInfo(ParameterDeclarations declarations, ArgumentsAccessor arguments) implements ParameterInfo { @Override public ParameterDeclarations getDeclarations() { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java index 62e198e0cf2a..01e1d1e7f6a7 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationContext.java @@ -79,13 +79,8 @@ private void storeParameterInfo(ExtensionContext context) { } @SuppressWarnings({ "deprecation", "try" }) - private static class CloseableArgument implements ExtensionContext.Store.CloseableResource, AutoCloseable { - - private final AutoCloseable autoCloseable; - - CloseableArgument(AutoCloseable autoCloseable) { - this.autoCloseable = autoCloseable; - } + private record CloseableArgument(AutoCloseable autoCloseable) + implements ExtensionContext.Store.CloseableResource, AutoCloseable { @Override public void close() throws Exception { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java index 22eb77dc327f..82ac1a6f40a7 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedInvocationNameFormatter.java @@ -197,29 +197,11 @@ private static String argumentsPattern(int length) { .collect(joining(", ")); } - private static class PlaceholderPosition { - - final int index; - final String placeholder; - - PlaceholderPosition(int index, String placeholder) { - this.index = index; - this.placeholder = placeholder; - } - + private record PlaceholderPosition(int index, String placeholder) { } - private static class ArgumentsContext { - - private final int invocationIndex; - private final @Nullable Object[] consumedArguments; - private final Optional argumentSetName; - - ArgumentsContext(int invocationIndex, @Nullable Object[] consumedArguments, Optional argumentSetName) { - this.invocationIndex = invocationIndex; - this.consumedArguments = consumedArguments; - this.argumentSetName = argumentSetName; - } + private record ArgumentsContext(int invocationIndex, @Nullable Object[] consumedArguments, + Optional argumentSetName) { } @FunctionalInterface @@ -231,13 +213,7 @@ private interface PartialFormatter { } - private static class ArgumentSetNameFormatter implements PartialFormatter { - - private final String annotationName; - - ArgumentSetNameFormatter(String annotationName) { - this.annotationName = annotationName; - } + private record ArgumentSetNameFormatter(String annotationName) implements PartialFormatter { @Override public void append(ArgumentsContext context, StringBuffer result) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 6972c72d9ada..943aea5fba5d 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -478,18 +478,12 @@ Object resolve(FieldContext fieldContext, ExtensionContext extensionContext, Eva } - private static class Converter implements Resolver { - - private final ArgumentConverter argumentConverter; + private record Converter(ArgumentConverter argumentConverter) implements Resolver { private static Converter createDefault(ExtensionContext context) { return new Converter(new DefaultArgumentConverter(context)); } - Converter(ArgumentConverter argumentConverter) { - this.argumentConverter = argumentConverter; - } - @Override public @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { @@ -515,7 +509,7 @@ private static Converter createDefault(ExtensionContext context) { } } - private static class Aggregator implements Resolver { + private record Aggregator(ArgumentsAggregator argumentsAggregator) implements Resolver { private static final Aggregator DEFAULT = new Aggregator(new SimpleArgumentsAggregator() { @Override @@ -525,12 +519,6 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT } }); - private final ArgumentsAggregator argumentsAggregator; - - Aggregator(ArgumentsAggregator argumentsAggregator) { - this.argumentsAggregator = argumentsAggregator; - } - @Override public @Nullable Object resolve(ParameterContext parameterContext, int parameterIndex, ExtensionContext extensionContext, EvaluatedArgumentSet arguments, int invocationIndex) { @@ -558,16 +546,9 @@ protected Object aggregateArguments(ArgumentsAccessor accessor, Class targetT } } - private static class DefaultParameterDeclarations implements ParameterDeclarations { - - private final AnnotatedElement sourceElement; - private final NavigableMap declarationsByIndex; - - DefaultParameterDeclarations(AnnotatedElement sourceElement, - NavigableMap declarationsByIndex) { - this.sourceElement = sourceElement; - this.declarationsByIndex = declarationsByIndex; - } + private record DefaultParameterDeclarations(AnnotatedElement sourceElement, + NavigableMap declarationsByIndex) + implements ParameterDeclarations { @Override public AnnotatedElement getSourceElement() { @@ -743,21 +724,11 @@ public Optional getTarget() { } } - private static class DefaultArgumentSetLifecycleMethodParameterResolver + private record DefaultArgumentSetLifecycleMethodParameterResolver(ResolverFacade originalResolverFacade, + ResolverFacade lifecycleMethodResolverFacade, + Map parameterDeclarationMapping) implements ArgumentSetLifecycleMethod.ParameterResolver { - private final ResolverFacade originalResolverFacade; - private final ResolverFacade lifecycleMethodResolverFacade; - private final Map parameterDeclarationMapping; - - DefaultArgumentSetLifecycleMethodParameterResolver(ResolverFacade originalResolverFacade, - ResolverFacade lifecycleMethodResolverFacade, - Map parameterDeclarationMapping) { - this.originalResolverFacade = originalResolverFacade; - this.lifecycleMethodResolverFacade = lifecycleMethodResolverFacade; - this.parameterDeclarationMapping = parameterDeclarationMapping; - } - @Override public boolean supports(ParameterContext parameterContext) { return this.lifecycleMethodResolverFacade.findDeclaration(parameterContext.getIndex()) // diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index 5c80776b3be4..b6bdfd90f2a1 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -84,7 +84,7 @@ private static Class getAnnotationType(Method method) { int annotationIndex = annotationConsumingMethodSignatures.stream() // .filter(signature -> signature.isMatchingWith(method)) // .findFirst() // - .map(AnnotationConsumingMethodSignature::getAnnotationParameterIndex) // + .map(AnnotationConsumingMethodSignature::annotationParameterIndex) // .orElse(0); return (Class) method.getParameterTypes()[annotationIndex]; @@ -100,17 +100,8 @@ private static void initializeAnnotationConsumer(Annotati } } - private static class AnnotationConsumingMethodSignature { - - private final String methodName; - private final int parameterCount; - private final int annotationParameterIndex; - - AnnotationConsumingMethodSignature(String methodName, int parameterCount, int annotationParameterIndex) { - this.methodName = methodName; - this.parameterCount = parameterCount; - this.annotationParameterIndex = annotationParameterIndex; - } + private record AnnotationConsumingMethodSignature(String methodName, int parameterCount, + int annotationParameterIndex) { boolean isMatchingWith(Method method) { return method.getName().equals(methodName) // @@ -118,10 +109,6 @@ boolean isMatchingWith(Method method) { && method.getParameterTypes()[annotationParameterIndex].isAnnotation(); } - int getAnnotationParameterIndex() { - return annotationParameterIndex; - } - } } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/DefaultResource.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/DefaultResource.java index 26df8c0f876c..d8df57d38fdf 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/DefaultResource.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/DefaultResource.java @@ -13,7 +13,6 @@ import static org.apiguardian.api.API.Status.INTERNAL; import java.net.URI; -import java.util.Objects; import org.apiguardian.api.API; import org.junit.platform.commons.util.Preconditions; @@ -29,14 +28,11 @@ * @since 1.11 */ @API(status = INTERNAL, since = "1.12") -public class DefaultResource implements Resource { +public record DefaultResource(String name, URI uri) implements Resource { - private final String name; - private final URI uri; - - public DefaultResource(String name, URI uri) { - this.name = Preconditions.notNull(name, "name must not be null"); - this.uri = Preconditions.notNull(uri, "uri must not be null"); + public DefaultResource { + Preconditions.notNull(name, "name must not be null"); + Preconditions.notNull(uri, "uri must not be null"); } @Override @@ -49,21 +45,6 @@ public URI getUri() { return uri; } - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - DefaultResource that = (DefaultResource) o; - return name.equals(that.name) && uri.equals(that.uri); - } - - @Override - public int hashCode() { - return Objects.hash(name, uri); - } - @Override public String toString() { return new ToStringBuilder(this) // diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java index cdef22876436..e553d7eee88c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/StringUtils.java @@ -304,7 +304,7 @@ private static TwoPartSplitResult splitIntoTwo(String value, int index, int leng * @see StringUtils#splitIntoTwo(String, String) */ @API(status = INTERNAL, since = "1.11") - public interface TwoPartSplitResult { + public sealed interface TwoPartSplitResult { /** * Map the result of splitting a string into two parts or throw an exception. @@ -331,13 +331,7 @@ default T mapTwo(Supplier onePartExceptionCreato } - private static final class OnePart implements TwoPartSplitResult { - - private final String value; - - OnePart(String value) { - this.value = value; - } + private record OnePart(String value) implements TwoPartSplitResult { @Override public T map(Function onePartMapper, @@ -346,15 +340,7 @@ public T map(Function onePartMapper, } } - private static final class TwoParts implements TwoPartSplitResult { - - private final String first; - private final String second; - - TwoParts(String first, String second) { - this.first = first; - this.second = second; - } + private record TwoParts(String first, String second) implements TwoPartSplitResult { @Override public T map(Function onePartMapper, diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java index 334c1d6f4e93..a11f3af851a8 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/DefaultUriSource.java @@ -12,7 +12,6 @@ import java.io.Serial; import java.net.URI; -import java.util.Objects; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.commons.util.ToStringBuilder; @@ -22,15 +21,13 @@ * * @since 1.3 */ -class DefaultUriSource implements UriSource { +record DefaultUriSource(URI uri) implements UriSource { @Serial private static final long serialVersionUID = 1L; - private final URI uri; - - DefaultUriSource(URI uri) { - this.uri = Preconditions.notNull(uri, "URI must not be null"); + DefaultUriSource { + Preconditions.notNull(uri, "URI must not be null"); } @Override @@ -38,23 +35,6 @@ public URI getUri() { return uri; } - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - DefaultUriSource that = (DefaultUriSource) o; - return Objects.equals(this.uri, that.uri); - } - - @Override - public int hashCode() { - return this.uri.hashCode(); - } - @Override public String toString() { return new ToStringBuilder(this).append("uri", this.uri).toString(); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java index 5ad5e15a37a4..95af64b24296 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java @@ -81,12 +81,12 @@ class NodeTestTask implements TestTask { @Override public ResourceLock getResourceLock() { - return taskContext.getExecutionAdvisor().getResourceLock(testDescriptor); + return taskContext.executionAdvisor().getResourceLock(testDescriptor); } @Override public ExecutionMode getExecutionMode() { - return taskContext.getExecutionAdvisor().getForcedExecutionMode(testDescriptor) // + return taskContext.executionAdvisor().getForcedExecutionMode(testDescriptor) // .orElseGet(node::getExecutionMode); } @@ -102,7 +102,7 @@ void setParentContext(@Nullable C parentContext) { @Override public void execute() { try { - throwableCollector = taskContext.getThrowableCollectorFactory().create(); + throwableCollector = taskContext.throwableCollectorFactory().create(); prepare(); if (throwableCollector.isEmpty()) { checkWhetherSkipped(); @@ -148,7 +148,7 @@ private void checkWhetherSkipped() { } private void executeRecursively() { - taskContext.getListener().executionStarted(testDescriptor); + taskContext.listener().executionStarted(testDescriptor); started = true; var throwableCollector = requiredThrowableCollector(); @@ -170,7 +170,7 @@ private void executeRecursively() { if (!children.isEmpty()) { children.forEach(child -> child.setParentContext(context)); - taskContext.getExecutorService().invokeAll(children); + taskContext.executorService().invokeAll(children); } throwableCollector.execute(dynamicTestExecutor::awaitFinished); @@ -199,12 +199,12 @@ private void reportCompletion() { logger.debug(throwable, () -> "Failed to invoke nodeSkipped() on Node %s".formatted(testDescriptor.getUniqueId())); } - taskContext.getListener().executionSkipped(testDescriptor, skipResult.getReason().orElse("")); + taskContext.listener().executionSkipped(testDescriptor, skipResult.getReason().orElse("")); return; } if (!started) { // Call executionStarted first to comply with the contract of EngineExecutionListener. - taskContext.getListener().executionStarted(testDescriptor); + taskContext.listener().executionStarted(testDescriptor); } try { node.nodeFinished(requiredContext(), testDescriptor, throwableCollector.toTestExecutionResult()); @@ -214,7 +214,7 @@ private void reportCompletion() { logger.debug(throwable, () -> "Failed to invoke nodeFinished() on Node %s".formatted(testDescriptor.getUniqueId())); } - taskContext.getListener().executionFinished(testDescriptor, throwableCollector.toTestExecutionResult()); + taskContext.listener().executionFinished(testDescriptor, throwableCollector.toTestExecutionResult()); this.throwableCollector = null; } @@ -235,7 +235,7 @@ private class DefaultDynamicTestExecutor implements DynamicTestExecutor { @Override public void execute(TestDescriptor testDescriptor) { - execute(testDescriptor, taskContext.getListener()); + execute(testDescriptor, taskContext.listener()); } @Override @@ -257,7 +257,7 @@ public Future execute(TestDescriptor testDescriptor, EngineExecutionListener testDescriptor, () -> unfinishedTasks.remove(uniqueId)); nodeTestTask.setParentContext(context); unfinishedTasks.put(uniqueId, DynamicTaskState.unscheduled()); - Future future = taskContext.getExecutorService().submit(nodeTestTask); + Future future = taskContext.executorService().submit(nodeTestTask); unfinishedTasks.computeIfPresent(uniqueId, (__, state) -> DynamicTaskState.scheduled(future)); return future; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTaskContext.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTaskContext.java index a6298847d59a..005d8ab6d02c 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTaskContext.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTaskContext.java @@ -15,20 +15,8 @@ /** * @since 1.3.1 */ -class NodeTestTaskContext { - - private final EngineExecutionListener listener; - private final HierarchicalTestExecutorService executorService; - private final ThrowableCollector.Factory throwableCollectorFactory; - private final NodeExecutionAdvisor executionAdvisor; - - public NodeTestTaskContext(EngineExecutionListener listener, HierarchicalTestExecutorService executorService, - ThrowableCollector.Factory throwableCollectorFactory, NodeExecutionAdvisor executionAdvisor) { - this.listener = listener; - this.executorService = executorService; - this.throwableCollectorFactory = throwableCollectorFactory; - this.executionAdvisor = executionAdvisor; - } +record NodeTestTaskContext(EngineExecutionListener listener, HierarchicalTestExecutorService executorService, + ThrowableCollector.Factory throwableCollectorFactory, NodeExecutionAdvisor executionAdvisor) { NodeTestTaskContext withListener(EngineExecutionListener listener) { if (this.listener == listener) { @@ -37,19 +25,4 @@ NodeTestTaskContext withListener(EngineExecutionListener listener) { return new NodeTestTaskContext(listener, executorService, throwableCollectorFactory, executionAdvisor); } - EngineExecutionListener getListener() { - return listener; - } - - HierarchicalTestExecutorService getExecutorService() { - return executorService; - } - - ThrowableCollector.Factory getThrowableCollectorFactory() { - return throwableCollectorFactory; - } - - NodeExecutionAdvisor getExecutionAdvisor() { - return executionAdvisor; - } } 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 3f3c46278352..074d4ecdd329 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 @@ -17,7 +17,6 @@ import static org.junit.platform.commons.util.ReflectionUtils.isAssignableTo; import java.util.Comparator; -import java.util.Objects; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -327,44 +326,16 @@ private void rejectIfClosed() { } } - private static class CompositeKey { + private record CompositeKey(N namespace, Object key) { - private final N namespace; - private final Object key; - - private CompositeKey(N namespace, Object key) { - this.namespace = Preconditions.notNull(namespace, "namespace must not be null"); - this.key = Preconditions.notNull(key, "key must not be null"); - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - CompositeKey that = (CompositeKey) o; - return this.namespace.equals(that.namespace) && this.key.equals(that.key); - } - - @Override - public int hashCode() { - return Objects.hash(this.namespace, this.key); + CompositeKey { + Preconditions.notNull(namespace, "namespace must not be null"); + Preconditions.notNull(key, "key must not be null"); } } - private static class StoredValue { - - private final int order; - private final Supplier<@Nullable Object> supplier; - - StoredValue(int order, Supplier<@Nullable Object> supplier) { - this.order = order; - this.supplier = supplier; - } + private record StoredValue(int order, Supplier<@Nullable Object> supplier) { private @Nullable EvaluatedValue evaluateSafely(CompositeKey compositeKey) { try { @@ -386,23 +357,11 @@ private static class StoredValue { } - private static class EvaluatedValue { + private record EvaluatedValue(CompositeKey compositeKey, int order, @Nullable Object value) { private static final Comparator> REVERSE_INSERT_ORDER = comparing( (EvaluatedValue it) -> it.order).reversed(); - private final CompositeKey compositeKey; - private final int order; - - @Nullable - private final Object value; - - private EvaluatedValue(CompositeKey compositeKey, int order, @Nullable Object value) { - this.compositeKey = compositeKey; - this.order = order; - this.value = value; - } - private void close(CloseAction closeAction) throws Throwable { if (this.value != null) { closeAction.close(this.compositeKey.namespace, this.compositeKey.key, this.value); @@ -456,13 +415,7 @@ private synchronized void computeValue() { } } - private static class Failure { - - private final Throwable throwable; - - public Failure(Throwable throwable) { - this.throwable = throwable; - } + private record Failure(Throwable throwable) { } } diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoEngineExecutionContext.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoEngineExecutionContext.java index 2bb72762e96d..eb6f00ff5ec3 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoEngineExecutionContext.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoEngineExecutionContext.java @@ -15,12 +15,5 @@ /** * @since 1.0 */ -public class DemoEngineExecutionContext implements EngineExecutionContext { - - public final ExecutionRequest request; - - public DemoEngineExecutionContext(ExecutionRequest request) { - this.request = request; - } - +public record DemoEngineExecutionContext(ExecutionRequest request) implements EngineExecutionContext { } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java index f53d3381756d..483e67293da9 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/MutableTestExecutionSummary.java @@ -14,6 +14,7 @@ import static java.util.Collections.synchronizedList; import java.io.PrintWriter; +import java.io.Serial; import java.time.Duration; import java.util.ArrayList; import java.util.Collections; @@ -282,18 +283,11 @@ private int numberOfCommonFrames(StackTraceElement[] currentTrace, StackTraceEle return currentTrace.length - 1 - currentIndex; } - private static class DefaultFailure implements Failure { + private record DefaultFailure(TestIdentifier testIdentifier, Throwable exception) implements Failure { + @Serial private static final long serialVersionUID = 1L; - private final TestIdentifier testIdentifier; - private final Throwable exception; - - DefaultFailure(TestIdentifier testIdentifier, Throwable exception) { - this.testIdentifier = testIdentifier; - this.exception = exception; - } - @Override public TestIdentifier getTestIdentifier() { return testIdentifier; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java index 1d6731b7f2e3..55c483abbe93 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java @@ -45,9 +45,9 @@ static Operator unaryOperator(String representation, int precedence, Associativi return new Operator(representation, precedence, 1, associativity, (expressions, operatorToken) -> { TokenWith rhs = expressions.pop(); - if (operatorToken.isLeftOf(rhs.token)) { - Token combinedToken = operatorToken.concatenate(rhs.token); - expressions.push(new TokenWith<>(combinedToken, unaryExpression.apply(rhs.element))); + if (operatorToken.isLeftOf(rhs.token())) { + Token combinedToken = operatorToken.concatenate(rhs.token()); + expressions.push(new TokenWith<>(combinedToken, unaryExpression.apply(rhs.element()))); return success(); } return missingRhsOperand(operatorToken, representation); @@ -61,13 +61,13 @@ static Operator binaryOperator(String representation, int precedence, Associativ return new Operator(representation, precedence, 2, associativity, (expressions, operatorToken) -> { TokenWith rhs = expressions.pop(); TokenWith lhs = expressions.pop(); - Token lhsToken = lhs.token; - if (lhsToken.isLeftOf(operatorToken) && operatorToken.isLeftOf(rhs.token)) { - Token combinedToken = lhsToken.concatenate(operatorToken).concatenate(rhs.token); - expressions.push(new TokenWith<>(combinedToken, binaryExpression.apply(lhs.element, rhs.element))); + Token lhsToken = lhs.token(); + if (lhsToken.isLeftOf(operatorToken) && operatorToken.isLeftOf(rhs.token())) { + Token combinedToken = lhsToken.concatenate(operatorToken).concatenate(rhs.token()); + expressions.push(new TokenWith<>(combinedToken, binaryExpression.apply(lhs.element(), rhs.element()))); return success(); } - if (rhs.token.isLeftOf(operatorToken)) { + if (rhs.token().isLeftOf(operatorToken)) { return missingRhsOperand(operatorToken, representation); } if (operatorToken.isLeftOf(lhsToken)) { @@ -134,7 +134,8 @@ private String createMissingOperandMessage(Stack> expre if (2 == mismatch) { return "missing lhs and rhs operand"; } - return missingOneOperand(operatorToken.isLeftOf(requireNonNull(expressions.peek()).token) ? "lhs" : "rhs"); + return missingOneOperand( + operatorToken.isLeftOf(requireNonNull(expressions.peek()).token()) ? "lhs" : "rhs"); } return "missing operand"; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java index 06aa9db6703b..9f1b124c6133 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java @@ -45,8 +45,8 @@ static ParseStatus errorAt(Token token, String operatorRepresentation, String me } static ParseStatus missingOperatorBetween(TokenWith lhs, TokenWith rhs) { - String lhsString = "'" + lhs.element.toString() + "' at index " + format(lhs.token.lastCharacterIndex()); - String rhsString = "'" + rhs.element.toString() + "' at index " + format(rhs.token.trimmedTokenStartIndex()); + String lhsString = "'" + lhs.element() + "' at index " + format(lhs.token().lastCharacterIndex()); + String rhsString = "'" + rhs.element() + "' at index " + format(rhs.token().trimmedTokenStartIndex()); return error("missing operator between " + lhsString + " and " + rhsString); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java index 3808ad6c6f5b..8a1922012d2d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ShuntingYard.java @@ -56,7 +56,7 @@ public ParseResult execute() { if (parseStatus.isError()) { return ParseResults.error(requireNonNull(parseStatus.errorMessage)); } - return ParseResults.success(expressions.pop().element); + return ParseResults.success(expressions.pop().element()); } private ParseStatus processTokens() { @@ -97,11 +97,11 @@ private TagExpression convertLeafTokenToExpression(String trimmed) { private ParseStatus findMatchingLeftParenthesis(Token token) { while (!operators.isEmpty()) { TokenWith tokenWithWithOperator = operators.pop(); - Operator operator = tokenWithWithOperator.element; + Operator operator = tokenWithWithOperator.element(); if (LeftParenthesis.equals(operator)) { return success(); } - ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token); + ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token()); if (parseStatus.isError()) { return parseStatus; } @@ -113,8 +113,8 @@ private ParseStatus findOperands(Token token, Operator currentOperator) { while (currentOperator.hasLowerPrecedenceThan(previousOperator()) || currentOperator.hasSamePrecedenceAs(previousOperator()) && currentOperator.isLeftAssociative()) { TokenWith tokenWithWithOperator = operators.pop(); - ParseStatus parseStatus = tokenWithWithOperator.element.createAndAddExpressionTo(expressions, - tokenWithWithOperator.token); + ParseStatus parseStatus = tokenWithWithOperator.element().createAndAddExpressionTo(expressions, + tokenWithWithOperator.token()); if (parseStatus.isError()) { return parseStatus; } @@ -124,7 +124,7 @@ private ParseStatus findOperands(Token token, Operator currentOperator) { } private Operator previousOperator() { - return operators.peek().element; + return operators.peek().element(); } private void pushExpressionAt(Token token, TagExpression tagExpression) { @@ -138,11 +138,11 @@ private void pushOperatorAt(Token token, Operator operator) { private ParseStatus consumeRemainingOperators() { while (!operators.isEmpty()) { TokenWith tokenWithWithOperator = operators.pop(); - Operator operator = tokenWithWithOperator.element; + Operator operator = tokenWithWithOperator.element(); if (LeftParenthesis.equals(operator)) { - return missingClosingParenthesis(tokenWithWithOperator.token, operator.representation()); + return missingClosingParenthesis(tokenWithWithOperator.token(), operator.representation()); } - ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token); + ParseStatus parseStatus = operator.createAndAddExpressionTo(expressions, tokenWithWithOperator.token()); if (parseStatus.isError()) { return parseStatus; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Token.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Token.java index 4b90dd72c915..b239179f68e2 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Token.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Token.java @@ -13,15 +13,7 @@ /** * @since 1.1 */ -class Token { - - final int startIndex; - final String rawString; - - Token(int startIndex, String rawString) { - this.startIndex = startIndex; - this.rawString = rawString; - } +record Token(int startIndex, String rawString) { String string() { return rawString.trim(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TokenWith.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TokenWith.java index 161cb229f6e7..1e387dd83eaa 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TokenWith.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/TokenWith.java @@ -13,14 +13,5 @@ /** * @since 1.1 */ -class TokenWith { - - final Token token; - final T element; - - TokenWith(Token token, T element) { - this.token = token; - this.element = element; - } - +record TokenWith(Token token, T element) { } diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index d5e474519108..e9c78c58ff6c 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -230,7 +230,9 @@ private static class LifecycleMethods { } } - private static class DiscoveryIssueForwardingListener implements LauncherDiscoveryListener { + private record DiscoveryIssueForwardingListener(EngineDiscoveryListener discoveryListener, + BiFunction issueTransformer) + implements LauncherDiscoveryListener { private static final Predicate SUITE_SEGMENTS = where(Segment::getType, isEqual(SEGMENT_TYPE)); @@ -256,15 +258,6 @@ static DiscoveryIssueForwardingListener create(UniqueId id, EngineDiscoveryListe })); } - private final EngineDiscoveryListener discoveryListener; - private final BiFunction issueTransformer; - - private DiscoveryIssueForwardingListener(EngineDiscoveryListener discoveryListener, - BiFunction issueTransformer) { - this.discoveryListener = discoveryListener; - this.issueTransformer = issueTransformer; - } - @Override public void issueEncountered(UniqueId engineUniqueId, DiscoveryIssue issue) { DiscoveryIssue transformedIssue = this.issueTransformer.apply(engineUniqueId, issue); diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/UniqueIdStringifierTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/UniqueIdStringifierTests.java index d8859b1e1c31..b2a5d0482872 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/UniqueIdStringifierTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/support/UniqueIdStringifierTests.java @@ -17,6 +17,7 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectStreamException; +import java.io.Serial; import java.io.Serializable; import java.util.Base64; @@ -45,7 +46,7 @@ void serializesUnknownTypes() throws Exception { var deserializedObject = deserialize(decodeBase64(serialized)); assertThat(deserializedObject).isInstanceOf(MyCustomId.class); - assertEquals(42, ((MyCustomId) deserializedObject).getValue()); + assertEquals(42, ((MyCustomId) deserializedObject).value()); } @Test @@ -68,26 +69,19 @@ private Object deserialize(byte[] bytes) throws Exception { } } - private static class MyCustomId implements Serializable { + private record MyCustomId(int value) implements Serializable { + @Serial private static final long serialVersionUID = 1L; - private final int value; - - MyCustomId(int value) { - this.value = value; - } - - int getValue() { - return value; - } - } private static class ClassWithErroneousSerialization implements Serializable { + @Serial private static final long serialVersionUID = 1L; + @Serial Object writeReplace() throws ObjectStreamException { throw new InvalidObjectException("failed on purpose"); } diff --git a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/RunnerWithCustomUniqueIdsAndDisplayNames.java b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/RunnerWithCustomUniqueIdsAndDisplayNames.java index f3af1814485d..e449e256ec4d 100644 --- a/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/RunnerWithCustomUniqueIdsAndDisplayNames.java +++ b/junit-vintage-engine/src/testFixtures/java/org/junit/vintage/engine/samples/junit4/RunnerWithCustomUniqueIdsAndDisplayNames.java @@ -53,28 +53,18 @@ private String getLabel(Annotatable element, Supplier fallback) { return label == null ? fallback.get() : label.value(); } - private static class CustomUniqueId implements Serializable { + private record CustomUniqueId(String testName) implements Serializable { @Serial private static final long serialVersionUID = 1L; - private final String testName; - - public CustomUniqueId(String testName) { - this.testName = testName; - } - @Override public boolean equals(Object obj) { - if (obj instanceof CustomUniqueId that) { - return Objects.equals(this.testName, that.testName); + if (obj instanceof CustomUniqueId(String name)) { + return Objects.equals(this.testName, name); } return false; } - @Override - public int hashCode() { - return testName.hashCode(); - } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java index da14c6c3ae6c..287dcb25c0d9 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptorTests.java @@ -203,13 +203,7 @@ private void prepareMockForTestInstanceWithCustomStream(Stream stream) { } - private static class CustomStreamTestCase { - - private final Stream mockStream; - - CustomStreamTestCase(Stream mockStream) { - this.mockStream = mockStream; - } + private record CustomStreamTestCase(Stream mockStream) { @TestFactory Stream customStream() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index cd68a46daf63..fbf2f4a9fb39 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -346,15 +346,7 @@ static class ArgumentRecordingParameterResolver implements ParameterResolver { ArgumentRecordingParameterResolver.@Nullable Arguments supportsArguments; ArgumentRecordingParameterResolver.@Nullable Arguments resolveArguments; - static class Arguments { - - final ParameterContext parameterContext; - final ExtensionContext extensionContext; - - Arguments(ParameterContext parameterContext, ExtensionContext extensionContext) { - this.parameterContext = parameterContext; - this.extensionContext = extensionContext; - } + record Arguments(ParameterContext parameterContext, ExtensionContext extensionContext) { } @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java index 49519b77b131..61dd3d5bb089 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java @@ -466,13 +466,7 @@ void test(String wisdom) { } - private static class CrystalBall implements ParameterResolver { - - private final String wisdom; - - public CrystalBall(String wisdom) { - this.wisdom = wisdom; - } + private record CrystalBall(String wisdom) implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java index 9890182b4a40..40fb18c29adf 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java @@ -65,13 +65,7 @@ private static class TestableTestRuleAdapter extends AbstractTestRuleAdapter { } } - private static class SimpleRuleAnnotatedMember implements TestRuleAnnotatedMember { - - private final TestRule testRule; - - SimpleRuleAnnotatedMember(TestRule testRule) { - this.testRule = testRule; - } + private record SimpleRuleAnnotatedMember(TestRule testRule) implements TestRuleAnnotatedMember { @Override public TestRule getTestRule() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java index b90fe9521334..1d57fbf27f51 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/aggregator/AggregatorIntegrationTests.java @@ -253,17 +253,7 @@ enum Gender { } @NullUnmarked - static class Address { - - final String street; - final String city; - final int zipCode; - - Address(String street, String city, int zipCode) { - this.street = street; - this.city = city; - this.zipCode = zipCode; - } + record Address(String street, String city, int zipCode) { } @Retention(RetentionPolicy.RUNTIME) diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenTests.java index edee8f37edaf..46d8fd92b86e 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenTests.java @@ -43,8 +43,8 @@ void concatenateTwoTokens() { var one = tokens.get(0); var two = tokens.get(1); var joined = one.concatenate(two); - assertThat(joined.rawString).isEqualTo(" ! foo"); - assertThat(joined.startIndex).isEqualTo(0); + assertThat(joined.rawString()).isEqualTo(" ! foo"); + assertThat(joined.startIndex()).isEqualTo(0); } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java index f305c8b26362..659174d43310 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java @@ -79,11 +79,11 @@ void extractStartPositionOfRawString() { } private Stream startIndicesExtractedFrom(String expression) { - return tokensExtractedFrom(expression).map(token -> token.startIndex); + return tokensExtractedFrom(expression).map(token -> token.startIndex()); } private Stream rawStringsExtractedFrom(String expression) { - return tokensExtractedFrom(expression).map(token -> token.rawString); + return tokensExtractedFrom(expression).map(token -> token.rawString()); } private List tokenStringsExtractedFrom(@Nullable String expression) { 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 80a076abaa59..115ae191ff2b 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 @@ -81,7 +81,7 @@ void writesValidXmlReport(@TempDir Path tempDirectory) throws Exception { var engine = new DemoHierarchicalTestEngine("dummy"); engine.addTest("failingTest", "display<-->Name 😎", (context, descriptor) -> { try { - var listener = context.request.getEngineExecutionListener(); + var listener = context.request().getEngineExecutionListener(); listener.reportingEntryPublished(descriptor, ReportEntry.from("key", "value")); listener.fileEntryPublished(descriptor, FileEntry.from( Files.writeString(tempDirectory.resolve("test.txt"), "Hello, world!"), "text/plain")); From ded1a266a7ae564877ec09b5e0ebf28c4ac15ecc Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 17:13:35 +0200 Subject: [PATCH 153/521] Use pattern variables --- .../junit/jupiter/engine/descriptor/JupiterTestDescriptor.java | 3 +-- .../junit/jupiter/engine/discovery/MethodSelectorResolver.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index ceebc08fe2c7..028450c8cbfe 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -138,8 +138,7 @@ public ExecutionMode getExecutionMode() { return executionMode.get(); } Optional parent = getParent(); - while (parent.isPresent() && parent.get() instanceof JupiterTestDescriptor) { - JupiterTestDescriptor jupiterParent = (JupiterTestDescriptor) parent.get(); + while (parent.isPresent() && parent.get() instanceof JupiterTestDescriptor jupiterParent) { executionMode = jupiterParent.getExplicitExecutionMode(); if (executionMode.isPresent()) { return executionMode.get(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java index ee187caf066f..4cfcdc69f9ec 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodSelectorResolver.java @@ -138,8 +138,7 @@ public Resolution resolve(UniqueIdSelector selector, Context context) { @Override public Resolution resolve(IterationSelector selector, Context context) { - if (selector.getParentSelector() instanceof MethodSelector) { - MethodSelector methodSelector = (MethodSelector) selector.getParentSelector(); + if (selector.getParentSelector() instanceof MethodSelector methodSelector) { return resolve(context, emptyList(), methodSelector.getJavaClass(), methodSelector::getJavaMethod, (testDescriptor, childSelectorsSupplier) -> { if (testDescriptor instanceof Filterable filterable) { From 2922d2d14aef0d35c442dca9d49355dcee125623 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 17:15:45 +0200 Subject: [PATCH 154/521] Deprecate `Filter#adaptFilter` --- .../src/main/java/org/junit/platform/engine/Filter.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java index b500a1320a2b..83511c09bdf8 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/Filter.java @@ -11,6 +11,7 @@ package org.junit.platform.engine; import static java.util.Arrays.asList; +import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.CompositeFilter.alwaysIncluded; @@ -94,6 +95,8 @@ static Filter composeFilters(Collection> filters) { * @param adaptee the filter to be adapted * @param converter the converter function to apply */ + @API(status = DEPRECATED, since = "6.0") + @Deprecated(since = "6.0", forRemoval = true) static Filter adaptFilter(Filter adaptee, Function converter) { return input -> adaptee.apply(converter.apply(input)); } From 72c405c4d784ca4b4726c6172b4bcfecc4ac3d71 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 17:18:07 +0200 Subject: [PATCH 155/521] Replace `Collectors.toList()` with `Stream.toList()` --- .../src/main/java/org/junit/jupiter/api/AssertAll.java | 3 +-- .../java/org/junit/jupiter/api/AssertLinesMatch.java | 5 ++--- .../engine/descriptor/ClassTemplateTestDescriptor.java | 5 ++--- .../jupiter/engine/descriptor/TemplateExecutor.java | 4 +--- .../engine/discovery/AbstractOrderingVisitor.java | 5 ++--- .../engine/discovery/MethodSelectorResolver.java | 3 +-- .../engine/execution/ParameterResolutionUtils.java | 3 +-- .../engine/extension/MutableExtensionRegistry.java | 3 +-- .../params/ParameterizedClassInvocationContext.java | 3 +-- .../java/org/junit/jupiter/params/ResolverFacade.java | 3 +-- .../params/provider/CsvFileArgumentsProvider.java | 3 +-- .../params/provider/MethodArgumentsProvider.java | 3 +-- .../params/provider/ValueArgumentsProvider.java | 6 ++---- .../support/scanning/DefaultClasspathScanner.java | 5 ++--- .../commons/util/ClassNamePatternFilterUtils.java | 3 +-- .../platform/commons/util/ClasspathScannerLoader.java | 3 +-- .../org/junit/platform/commons/util/ModuleUtils.java | 5 ++--- .../console/options/ClasspathEntriesConverter.java | 3 +-- .../platform/console/options/TestDiscoveryOptions.java | 3 +-- .../java/org/junit/platform/engine/UniqueIdFormat.java | 3 +-- .../engine/discovery/AbstractClassNameFilter.java | 3 +-- .../platform/engine/discovery/DiscoverySelectors.java | 3 +-- .../platform/engine/discovery/NestedClassSelector.java | 7 +++---- .../junit/platform/launcher/AbstractMethodFilter.java | 3 +-- .../java/org/junit/platform/launcher/EngineFilter.java | 3 +-- .../launcher/core/CompositeTestExecutionListener.java | 4 +--- .../launcher/core/DefaultDiscoveryRequest.java | 5 ++--- .../launcher/core/LauncherDiscoveryResult.java | 3 +-- .../platform/launcher/core/ServiceLoaderRegistry.java | 4 +--- .../core/StackTracePruningEngineExecutionListener.java | 3 +-- .../platform/reporting/legacy/xml/XmlReportData.java | 3 +-- .../suite/commons/AdditionalDiscoverySelectors.java | 10 +++++----- .../commons/SuiteLauncherDiscoveryRequestBuilder.java | 3 +-- .../org/junit/platform/testkit/engine/Assertions.java | 3 +-- .../junit/platform/testkit/engine/EventConditions.java | 7 +++---- .../java/org/junit/platform/testkit/engine/Events.java | 5 ++--- .../testkit/engine/TestExecutionResultConditions.java | 9 ++++----- .../vintage/engine/descriptor/TestSourceProvider.java | 5 ++--- .../org/junit/vintage/engine/execution/TestRun.java | 3 +-- .../vintage/engine/execution/VintageExecutor.java | 3 +-- .../jupiter/api/AssertLinesMatchAssertionsTests.java | 5 ++--- .../java/org/junit/jupiter/api/DynamicTestTests.java | 3 +-- .../org/junit/platform/StackTracePruningTests.java | 2 +- .../support/scanning/DefaultClasspathScannerTests.java | 5 ++--- .../engine/discovery/DiscoverySelectorsTests.java | 3 +-- 45 files changed, 67 insertions(+), 114 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java index 666b7bb75dcc..14cc239ce08d 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertAll.java @@ -14,7 +14,6 @@ import java.util.Collection; import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.jspecify.annotations.Nullable; @@ -75,7 +74,7 @@ static void assertAll(@Nullable String heading, Stream executables) } }) // .filter(Objects::nonNull) // - .collect(Collectors.toList()); + .toList(); if (!failures.isEmpty()) { MultipleFailuresError multipleFailuresError = new MultipleFailuresError(heading, failures); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java index 18cb6621d7c7..16921e088eff 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertLinesMatch.java @@ -19,7 +19,6 @@ import java.util.Deque; import java.util.List; import java.util.regex.PatternSyntaxException; -import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -65,8 +64,8 @@ static void assertLinesMatch(Stream expectedLines, Stream actual return; } - List expectedListOfStrings = expectedLines.collect(Collectors.toList()); - List actualListOfStrings = actualLines.collect(Collectors.toList()); + List expectedListOfStrings = expectedLines.toList(); + List actualListOfStrings = actualLines.toList(); assertLinesMatch(expectedListOfStrings, actualListOfStrings, messageOrSupplier); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java index 35360b0b33ab..29fb3c54652d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassTemplateTestDescriptor.java @@ -11,7 +11,6 @@ package org.junit.jupiter.engine.descriptor; import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import static org.junit.jupiter.engine.descriptor.LifecycleMethodUtils.validateClassTemplateInvocationLifecycleMethodsAreDeclaredCorrectly; @@ -108,9 +107,9 @@ protected JupiterTestDescriptor copyIncludingDescendants(UnaryOperator copy.childrenPrototypes.add(newChild); }); this.childrenPrototypesByIndex.forEach((index, oldChildren) -> { - List newChildren = oldChildren.stream() // + List newChildren = oldChildren.stream() // .map(oldChild -> ((JupiterTestDescriptor) oldChild).copyIncludingDescendants(uniqueIdTransformer)) // - .collect(toList()); + .toList(); copy.childrenPrototypesByIndex.put(index, newChildren); }); return copy; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TemplateExecutor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TemplateExecutor.java index b2537fb226c9..acb006eb0370 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TemplateExecutor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TemplateExecutor.java @@ -10,8 +10,6 @@ package org.junit.jupiter.engine.descriptor; -import static java.util.stream.Collectors.toList; - import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicInteger; @@ -81,7 +79,7 @@ private void executeForProvider(P provider, AtomicInteger invocationIndex, private List

    validateProviders(ExtensionContext extensionContext, ExtensionRegistry extensionRegistry) { List

    providers = extensionRegistry.stream(providerType) // .filter(provider -> supports(provider, extensionContext)) // - .collect(toList()); + .toList(); return Preconditions.notEmpty(providers, this::getNoRegisteredProviderErrorMessage); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java index fba71e40357a..5dfedbc48ee3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/AbstractOrderingVisitor.java @@ -13,7 +13,6 @@ import static java.util.Comparator.comparing; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; import java.util.ArrayList; import java.util.HashMap; @@ -110,11 +109,11 @@ protected > enclosingClasses, Cla "Possible configuration error: method [%s] resulted in multiple TestDescriptors %s. " + "This is typically the result of annotating a method with multiple competing annotations " + "such as @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, etc.", - method.toGenericString(), testDescriptors.map(d -> d.getClass().getName()).collect(toList())); + method.toGenericString(), testDescriptors.map(d -> d.getClass().getName()).toList()); issueReporter.reportIssue( DiscoveryIssue.builder(Severity.WARNING, message).source(MethodSource.from(method))); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java index c83032af3ac8..6b8379a56f1f 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ParameterResolutionUtils.java @@ -11,7 +11,6 @@ package org.junit.jupiter.engine.execution; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.util.KotlinReflectionUtils.getKotlinSuspendingFunctionParameters; import static org.junit.platform.commons.util.KotlinReflectionUtils.isKotlinSuspendingFunction; @@ -132,7 +131,7 @@ public class ParameterResolutionUtils { // @formatter:off List matchingResolvers = extensionRegistry.stream(ParameterResolver.class) .filter(resolver -> resolver.supportsParameter(parameterContext, extensionContext.get(resolver))) - .collect(toList()); + .toList(); // @formatter:on if (matchingResolvers.isEmpty()) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java index 9ca2552765ec..fdd84569d7e1 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/MutableExtensionRegistry.java @@ -27,7 +27,6 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.apiguardian.api.API; @@ -122,7 +121,7 @@ private static void logExcludedExtensions(List> exclu List excludeExtensionNames = excludedExtensions .stream() .map(Class::getName) - .collect(Collectors.toList()); + .toList(); // @formatter:on logger.config(() -> "Excluded auto-detected extensions due to configured includes/excludes: %s".formatted( excludeExtensionNames)); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java index 0344bb9abca5..b4d8a5e63122 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedClassInvocationContext.java @@ -10,7 +10,6 @@ package org.junit.jupiter.params; -import static java.util.stream.Collectors.toList; import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_METHOD; import java.util.List; @@ -42,7 +41,7 @@ public String getDisplayName(int invocationIndex) { @Override public List getAdditionalExtensions() { return Stream.concat(Stream.of(createParameterInjector()), createLifecycleMethodInvokers()) // - .collect(toList()); + .toList(); } @Override diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 943aea5fba5d..bdec2d6af084 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -13,7 +13,6 @@ import static java.lang.System.lineSeparator; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; @@ -402,7 +401,7 @@ private static void validateIndexedParameters( private static void validateIndexedParameterDeclarations(int index, List declarations, List errors) { - List fields = declarations.stream().map(FieldParameterDeclaration::getField).collect(toList()); + List fields = declarations.stream().map(FieldParameterDeclaration::getField).toList(); if (index < 0) { declarations.stream() // .map( diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java index f840c3bfa52e..fe5bc1583084 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileArgumentsProvider.java @@ -12,7 +12,6 @@ import static java.util.Objects.requireNonNull; import static java.util.Spliterators.spliteratorUnknownSize; -import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.getHeaders; import static org.junit.jupiter.params.provider.CsvArgumentsProvider.handleCsvException; @@ -63,7 +62,7 @@ protected Stream provideArguments(ParameterDeclarations par Stream resources = Arrays.stream(csvFileSource.resources()).map(inputStreamProvider::classpathResource); Stream files = Arrays.stream(csvFileSource.files()).map(inputStreamProvider::file); - List sources = Stream.concat(resources, files).collect(toList()); + List sources = Stream.concat(resources, files).toList(); // @formatter:off return Preconditions.notEmpty(sources, "Resources or files must not be empty") diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java index d4af42cebd1f..227fefc9aa17 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodArgumentsProvider.java @@ -12,7 +12,6 @@ import static java.lang.String.format; import static java.util.Arrays.stream; -import static java.util.stream.Collectors.toList; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import static org.junit.platform.commons.util.CollectionUtils.isConvertibleToStream; @@ -154,7 +153,7 @@ private static Method findFactoryMethodBySimpleName(Class clazz, Optional candidates = ReflectionUtils.findMethods(clazz, isCandidate); - List factoryMethods = candidates.stream().filter(isFactoryMethod).collect(toList()); + List factoryMethods = candidates.stream().filter(isFactoryMethod).toList(); Preconditions.notEmpty(factoryMethods, () -> { if (candidates.isEmpty()) { diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java index a3a929dfa2ba..2872c51e5ae8 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueArgumentsProvider.java @@ -10,8 +10,6 @@ package org.junit.jupiter.params.provider; -import static java.util.stream.Collectors.toList; - import java.lang.reflect.Array; import java.util.Arrays; import java.util.List; @@ -36,7 +34,7 @@ protected Stream provideArguments(ParameterDeclarations par private Object[] getArgumentsFromSource(ValueSource valueSource) { // @formatter:off - List arrays = + List arrays = Stream.of( valueSource.shorts(), valueSource.bytes(), @@ -50,7 +48,7 @@ private Object[] getArgumentsFromSource(ValueSource valueSource) { valueSource.classes() ) .filter(array -> Array.getLength(array) > 0) - .collect(toList()); + .toList(); // @formatter:on Preconditions.condition(arrays.size() == 1, () -> "Exactly one type of input must be provided in the @" diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java index 0e9bb167a491..427b8867d946 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/scanning/DefaultClasspathScanner.java @@ -12,7 +12,6 @@ import static java.util.Collections.emptyList; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.support.scanning.ClasspathFilters.CLASS_FILE_SUFFIX; import static org.junit.platform.commons.util.StringUtils.isNotBlank; @@ -131,7 +130,7 @@ private List> findClassesForUris(List baseUris, String basePackage .map(baseUri -> findClassesForUri(baseUri, basePackageName, classFilter)) .flatMap(Collection::stream) .distinct() - .collect(toList()); + .toList(); // @formatter:on } @@ -155,7 +154,7 @@ private List findResourcesForUris(List baseUris, String basePacka .map(baseUri -> findResourcesForUri(baseUri, basePackageName, resourceFilter)) .flatMap(Collection::stream) .distinct() - .collect(toList()); + .toList(); // @formatter:on } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassNamePatternFilterUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassNamePatternFilterUtils.java index 0ae9e0b5da25..bfe483dd0957 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassNamePatternFilterUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClassNamePatternFilterUtils.java @@ -10,7 +10,6 @@ package org.junit.platform.commons.util; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import java.util.Arrays; @@ -124,7 +123,7 @@ private static List convertToRegularExpressions(String patterns) { .map(String::trim) .map(ClassNamePatternFilterUtils::replaceRegExElements) .map(Pattern::compile) - .collect(toList()); + .toList(); // @formatter:on } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java index 0560ad7e8a5f..cfa60d58369b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ClasspathScannerLoader.java @@ -10,7 +10,6 @@ package org.junit.platform.commons.util; -import static java.util.stream.Collectors.toList; import static java.util.stream.StreamSupport.stream; import java.util.List; @@ -29,7 +28,7 @@ static ClasspathScanner getInstance() { ServiceLoader serviceLoader = ServiceLoader.load(ClasspathScanner.class, ClassLoaderUtils.getDefaultClassLoader()); - List classpathScanners = stream(serviceLoader.spliterator(), false).collect(toList()); + List classpathScanners = stream(serviceLoader.spliterator(), false).toList(); if (classpathScanners.size() == 1) { return classpathScanners.get(0); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index 9b069eef54d8..89c38637336c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -31,7 +31,6 @@ import java.util.Optional; import java.util.Set; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.apiguardian.api.API; @@ -229,7 +228,7 @@ List> scan(ModuleReference reference) { .filter(classFilter::match) .map(this::loadClassUnchecked) .filter(classFilter::match) - .collect(Collectors.toList()); + .toList(); // @formatter:on } } @@ -288,7 +287,7 @@ List scan(ModuleReference reference) { return names.filter(name -> !name.endsWith(".class")) .map(this::loadResourceUnchecked) .filter(resourceFilter) - .collect(Collectors.toList()); + .toList(); // @formatter:on } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/ClasspathEntriesConverter.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/ClasspathEntriesConverter.java index a0f2fa15774d..9de9395df764 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/ClasspathEntriesConverter.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/ClasspathEntriesConverter.java @@ -14,7 +14,6 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; -import java.util.stream.Collectors; import java.util.stream.Stream; import picocli.CommandLine; @@ -23,7 +22,7 @@ class ClasspathEntriesConverter implements CommandLine.ITypeConverter @Override public List convert(String value) { - return Stream.of(value.split(File.pathSeparator)).map(Paths::get).collect(Collectors.toList()); + return Stream.of(value.split(File.pathSeparator)).map(Paths::get).toList(); } } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java index 030cc1475b2f..bd1ede77223b 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java @@ -13,7 +13,6 @@ import static java.util.Collections.emptyList; import static java.util.Collections.emptyMap; import static java.util.Collections.singletonList; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN; @@ -96,7 +95,7 @@ public void setScanClasspath(boolean scanClasspath) { } public List getExistingAdditionalClasspathEntries() { - return this.additionalClasspathEntries.stream().filter(Files::exists).collect(toList()); + return this.additionalClasspathEntries.stream().filter(Files::exists).toList(); } public List getAdditionalClasspathEntries() { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java index 24047a30bcd9..87275e54ba4d 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueIdFormat.java @@ -11,7 +11,6 @@ package org.junit.platform.engine; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import java.io.Serial; import java.io.Serializable; @@ -88,7 +87,7 @@ private static String encode(char c) { */ UniqueId parse(String source) throws JUnitException { String[] parts = source.split(String.valueOf(this.segmentDelimiter)); - List segments = Arrays.stream(parts).map(this::createSegment).collect(toList()); + List segments = Arrays.stream(parts).map(this::createSegment).toList(); return new UniqueId(this, segments); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/AbstractClassNameFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/AbstractClassNameFilter.java index ae047beed04c..94ac57e783e4 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/AbstractClassNameFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/AbstractClassNameFilter.java @@ -11,7 +11,6 @@ package org.junit.platform.engine.discovery; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import java.util.Arrays; import java.util.List; @@ -36,7 +35,7 @@ abstract class AbstractClassNameFilter implements ClassNameFilter { AbstractClassNameFilter(String... patterns) { Preconditions.notEmpty(patterns, "patterns array must not be null or empty"); Preconditions.containsNoNullElements(patterns, "patterns array must not contain null elements"); - this.patterns = Arrays.stream(patterns).map(Pattern::compile).collect(toList()); + this.patterns = Arrays.stream(patterns).map(Pattern::compile).toList(); this.patternDescription = Arrays.stream(patterns).collect(joining("' OR '", "'", "'")); } 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 6bc7b4a5b951..94a810396766 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 @@ -10,7 +10,6 @@ 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.STABLE; @@ -353,7 +352,7 @@ public static ClasspathResourceSelector selectClasspathResource(String classpath 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"); - List resourceNames = classpathResources.stream().map(Resource::getName).distinct().collect(toList()); + List resourceNames = classpathResources.stream().map(Resource::getName).distinct().toList(); Preconditions.condition(resourceNames.size() == 1, "all classpath resources must have the same name"); Preconditions.notBlank(resourceNames.get(0), "classpath resource names must not be null or blank"); return new ClasspathResourceSelector(classpathResources); 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 8ca60d18c740..31f48c893358 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 @@ -11,7 +11,6 @@ package org.junit.platform.engine.discovery; 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.STABLE; @@ -70,7 +69,7 @@ public class NestedClassSelector implements DiscoverySelector { NestedClassSelector(List> enclosingClasses, Class nestedClass) { this.classLoader = nestedClass.getClassLoader(); - this.enclosingClassSelectors = enclosingClasses.stream().map(ClassSelector::new).collect(toList()); + this.enclosingClassSelectors = enclosingClasses.stream().map(ClassSelector::new).toList(); this.nestedClassSelector = new ClassSelector(nestedClass); } @@ -89,7 +88,7 @@ public class NestedClassSelector implements DiscoverySelector { * Get the names of the classes enclosing the selected nested class. */ public List getEnclosingClassNames() { - return this.enclosingClassSelectors.stream().map(ClassSelector::getClassName).collect(toList()); + return this.enclosingClassSelectors.stream().map(ClassSelector::getClassName).toList(); } /** @@ -102,7 +101,7 @@ public List getEnclosingClassNames() { * {@link PreconditionViolationException} if the classes cannot be loaded. */ public List> getEnclosingClasses() { - return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).collect(toList()); + return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).toList(); } /** diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java index 6c2eb66988da..83d02375b47b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java @@ -11,7 +11,6 @@ package org.junit.platform.launcher; import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toList; import java.util.Arrays; import java.util.List; @@ -39,7 +38,7 @@ abstract class AbstractMethodFilter implements MethodFilter { AbstractMethodFilter(String... patterns) { Preconditions.notEmpty(patterns, "patterns array must not be null or empty"); Preconditions.containsNoNullElements(patterns, "patterns array must not contain null elements"); - this.patterns = Arrays.stream(patterns).map(Pattern::compile).collect(toList()); + this.patterns = Arrays.stream(patterns).map(Pattern::compile).toList(); this.patternDescription = Arrays.stream(patterns).collect(joining("' OR '", "'", "'")); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java index bd3f183d6652..6c8c7363fb86 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineFilter.java @@ -10,7 +10,6 @@ package org.junit.platform.launcher; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.apiguardian.api.API.Status.STABLE; import static org.junit.platform.engine.FilterResult.includedIf; @@ -150,7 +149,7 @@ private static List validateAndTrim(List engineIds) { return engineIds.stream() .map(id -> Preconditions.notBlank(id, "engine ID must not be null or blank").trim()) .distinct() - .collect(toList()); + .toList(); // @formatter:on } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java index c47461c561b0..f514df6da9a2 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/CompositeTestExecutionListener.java @@ -10,8 +10,6 @@ package org.junit.platform.launcher.core; -import static java.util.stream.Collectors.toList; - import java.util.ArrayList; import java.util.List; import java.util.function.Consumer; @@ -39,7 +37,7 @@ class CompositeTestExecutionListener implements TestExecutionListener { this.eagerTestExecutionListeners = this.testExecutionListeners.stream() // .filter(EagerTestExecutionListener.class::isInstance) // .map(EagerTestExecutionListener.class::cast) // - .collect(toList()); + .toList(); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java index 70106c48fb72..849de3baf267 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java @@ -11,7 +11,6 @@ package org.junit.platform.launcher.core; import static java.util.Collections.unmodifiableList; -import static java.util.stream.Collectors.toList; import java.util.List; @@ -70,7 +69,7 @@ final class DefaultDiscoveryRequest implements LauncherDiscoveryRequest { @Override public List getSelectorsByType(Class selectorType) { Preconditions.notNull(selectorType, "selectorType must not be null"); - return this.selectors.stream().filter(selectorType::isInstance).map(selectorType::cast).collect(toList()); + return this.selectors.stream().filter(selectorType::isInstance).map(selectorType::cast).toList(); } @Override @@ -81,7 +80,7 @@ public List getEngineFilters() { @Override public > List getFiltersByType(Class filterType) { Preconditions.notNull(filterType, "filterType must not be null"); - return this.discoveryFilters.stream().filter(filterType::isInstance).map(filterType::cast).collect(toList()); + return this.discoveryFilters.stream().filter(filterType::isInstance).map(filterType::cast).toList(); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java index 9be73b2ed4c8..6827cd0246a0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherDiscoveryResult.java @@ -21,7 +21,6 @@ import java.util.Map; import java.util.Optional; import java.util.function.Predicate; -import java.util.stream.Collectors; import org.apiguardian.api.API; import org.jspecify.annotations.Nullable; @@ -84,7 +83,7 @@ boolean containsCriticalIssuesOrContainsTests() { Collection getEngineTestDescriptors() { return this.testEngineResults.values().stream() // .map(EngineResultInfo::getRootDescriptor) // - .collect(Collectors.toList()); + .toList(); } public LauncherDiscoveryResult withRetainedEngines(Predicate predicate) { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java index f090b2bbdf12..eebd6de021f7 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ServiceLoaderRegistry.java @@ -10,8 +10,6 @@ package org.junit.platform.launcher.core; -import static java.util.stream.Collectors.toList; - import java.util.ArrayList; import java.util.List; import java.util.ServiceLoader; @@ -58,7 +56,7 @@ private static List load(Class type, Predicate classNameFilter Function, String> logMessageSupplier) { ServiceLoader serviceLoader = ServiceLoader.load(type, ClassLoaderUtils.getDefaultClassLoader()); Predicate> providerPredicate = clazz -> classNameFilter.test(clazz.getName()); - List instances = ServiceLoaderUtils.filter(serviceLoader, providerPredicate).collect(toList()); + List instances = ServiceLoaderUtils.filter(serviceLoader, providerPredicate).toList(); getLogger().config(() -> logMessageSupplier.apply(instances)); return instances; } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java index 4fa0a8023fdb..835a272e0af9 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/StackTracePruningEngineExecutionListener.java @@ -13,7 +13,6 @@ import java.util.List; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.engine.EngineExecutionListener; @@ -63,7 +62,7 @@ else if (source instanceof MethodSource methodSource) { } }) // .filter(Objects::nonNull) // - .collect(Collectors.toList()); + .toList(); } } diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java index 477c314d2541..cf78931aca0d 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/XmlReportData.java @@ -11,7 +11,6 @@ package org.junit.platform.reporting.legacy.xml; import static java.util.Collections.emptyList; -import static java.util.stream.Collectors.toList; import static org.junit.platform.engine.TestExecutionResult.Status.ABORTED; import java.time.Clock; @@ -110,7 +109,7 @@ List getResults(TestIdentifier testIdentifier) { return getAncestors(testIdentifier).stream() // .map(this.finishedTests::get) // .filter(Objects::nonNull) // - .collect(toList()); + .toList(); } List getReportEntries(TestIdentifier testIdentifier) { diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/AdditionalDiscoverySelectors.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/AdditionalDiscoverySelectors.java index 969fe04e9376..bbfe6aa026ac 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/AdditionalDiscoverySelectors.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/AdditionalDiscoverySelectors.java @@ -41,7 +41,7 @@ static List selectUris(String... uris) { return uniqueStreamOf(uris) .filter(StringUtils::isNotBlank) .map(DiscoverySelectors::selectUri) - .collect(Collectors.toList()); + .toList(); // @formatter:on } @@ -53,7 +53,7 @@ static List selectDirectories(String... paths) { return uniqueStreamOf(paths) .filter(StringUtils::isNotBlank) .map(DiscoverySelectors::selectDirectory) - .collect(Collectors.toList()); + .toList(); // @formatter:on } @@ -64,7 +64,7 @@ static List selectPackages(String... packageNames) { // @formatter:off return uniqueStreamOf(packageNames) .map(DiscoverySelectors::selectPackage) - .collect(Collectors.toList()); + .toList(); // @formatter:on } @@ -113,9 +113,9 @@ static ClasspathResourceSelector selectClasspathResource(String classpathResourc return DiscoverySelectors.selectClasspathResource(classpathResourceName, FilePosition.from(line, column)); } - static List parseIdentifiers(String[] identifiers) { + static List parseIdentifiers(String[] identifiers) { return DiscoverySelectors.parseAll(identifiers) // - .collect(Collectors.toList()); + .toList(); } private static Stream uniqueStreamOf(T[] elements) { diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java index 8176e6b070a5..52da2210aafb 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java @@ -10,7 +10,6 @@ package org.junit.platform.suite.commons; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; @@ -462,7 +461,7 @@ private List selectClasses(Class suiteClass, SelectClasses ann return toClassSelectors(suiteClass, annotation) // .distinct() // .peek(selector -> this.selectedClassNames.add(selector.getClassName())) // - .collect(toList()); + .toList(); } private static Stream toClassSelectors(Class suiteClass, SelectClasses annotation) { diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java index 3a2a471980fc..2f7d3e157304 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Assertions.java @@ -12,7 +12,6 @@ import java.util.List; import java.util.Objects; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.platform.commons.util.Preconditions; @@ -50,7 +49,7 @@ static void assertAll(String heading, Stream executables) { } }) // .filter(Objects::nonNull) // - .collect(Collectors.toList()); + .toList(); if (!failures.isEmpty()) { MultipleFailuresError multipleFailuresError = new MultipleFailuresError(heading, failures); 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 92e746a4968c..2cb550ed304c 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 @@ -11,7 +11,6 @@ package org.junit.platform.testkit.engine; 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; @@ -326,7 +325,7 @@ public static Condition uniqueIdSubstrings(String... uniqueIdSubstrings) */ public static Condition uniqueIdSubstrings(List uniqueIdSubstrings) { // The following worked with AssertJ 3.13.2 - // return allOf(uniqueIdSubstrings.stream().map(EventConditions::uniqueIdSubstring).collect(toList())); + // return allOf(uniqueIdSubstrings.stream().map(EventConditions::uniqueIdSubstring).toList()); // Workaround for a regression in AssertJ 3.14.0 that loses the individual descriptions // when multiple conditions are supplied as an Iterable instead of as an array. @@ -336,8 +335,8 @@ public static Condition uniqueIdSubstrings(List uniqueIdSubstring // does not track all descriptions. List> conditions = uniqueIdSubstrings.stream()// .map(EventConditions::uniqueIdSubstring)// - .collect(toList()); - List descriptions = conditions.stream().map(Condition::description).collect(toList()); + .toList(); + List descriptions = conditions.stream().map(Condition::description).toList(); return allOf(conditions).describedAs(new JoinDescription("all of :[", "]", descriptions)); } 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 ff1f6ae4af51..5975982d2c0e 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 @@ -12,7 +12,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; @@ -58,7 +57,7 @@ public final class Events { private final String category; Events(Stream events, String category) { - this(Preconditions.notNull(events, "Event stream must not be null").collect(toList()), category); + this(Preconditions.notNull(events, "Event stream must not be null").toList(), category); } Events(List events, String category) { @@ -447,7 +446,7 @@ private static void assertEventsMatchLooselyInOrder(List events, Conditio .map(condition -> findEvent(events, softly, condition)) .filter(Objects::nonNull) .map(events::indexOf) - .collect(toList()); + .toList(); // @formatter:on if (isNotInIncreasingOrder(indices)) { 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..ad3da44665fa 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 @@ -11,7 +11,6 @@ package org.junit.platform.testkit.engine; 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; @@ -63,7 +62,7 @@ public static Condition status(Status expectedStatus) { public static Condition throwable(Condition... conditions) { List> list = Arrays.stream(conditions)// .map(TestExecutionResultConditions::throwable)// - .collect(toList()); + .toList(); return Assertions.allOf(list); } @@ -81,7 +80,7 @@ public static Condition throwable(Condition... c public static Condition cause(Condition... conditions) { List> list = Arrays.stream(conditions)// .map(TestExecutionResultConditions::cause)// - .collect(toList()); + .toList(); return Assertions.allOf(list); } @@ -101,7 +100,7 @@ public static Condition cause(Condition... conditions) { public static Condition rootCause(Condition... conditions) { List> list = Arrays.stream(conditions)// .map(TestExecutionResultConditions::rootCause)// - .collect(toList()); + .toList(); return Assertions.allOf(list); } @@ -119,7 +118,7 @@ public static Condition rootCause(Condition... conditions) public static Condition suppressed(int index, Condition... conditions) { List> list = Arrays.stream(conditions)// .map(condition -> suppressed(index, condition))// - .collect(toList()); + .toList(); return Assertions.allOf(list); } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java index 78fd2afbb585..65a748aa89ec 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/descriptor/TestSourceProvider.java @@ -12,7 +12,6 @@ import static java.util.Collections.synchronizedMap; import static java.util.function.Predicate.isEqual; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.platform.commons.support.HierarchyTraversalMode.TOP_DOWN; import static org.junit.platform.commons.support.ReflectionSupport.findMethods; @@ -77,14 +76,14 @@ private String sanitizeMethodName(String methodName) { List methods = methodsCache.computeIfAbsent(testClass, clazz -> findMethods(clazz, m -> true, TOP_DOWN)).stream() // .filter(where(Method::getName, isEqual(methodName))) // - .collect(toList()); + .toList(); if (methods.isEmpty()) { return null; } if (methods.size() == 1) { return methods.get(0); } - methods = methods.stream().filter(ModifierSupport::isPublic).collect(toList()); + methods = methods.stream().filter(ModifierSupport::isPublic).toList(); if (methods.size() == 1) { return methods.get(0); } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java index 8ddde9d15c66..1b7814a8a106 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/TestRun.java @@ -13,7 +13,6 @@ import static java.util.Collections.emptyList; import static java.util.Objects.requireNonNull; import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toMap; import static java.util.stream.Stream.concat; import static org.junit.platform.engine.TestExecutionResult.failed; @@ -198,7 +197,7 @@ TestExecutionResult getStoredResultOrSuccessful(TestDescriptor testDescriptor) { .stream() .map(TestExecutionResult::getThrowable) .map(Optional::orElseThrow) - .collect(toList()); + .toList(); // @formatter:on MultipleFailuresError multipleFailuresError = new MultipleFailuresError("", failures); failures.forEach(multipleFailuresError::addSuppressed); diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java index 64bc1dc03b1a..6ba96f93bbfd 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java @@ -11,7 +11,6 @@ package org.junit.vintage.engine.execution; import static java.util.Objects.requireNonNullElse; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.INTERNAL; import static org.junit.vintage.engine.Constants.PARALLEL_CLASS_EXECUTION; import static org.junit.vintage.engine.Constants.PARALLEL_EXECUTION_ENABLED; @@ -131,7 +130,7 @@ private List collectRunnerTestDescriptors(ExecutorService return engineDescriptor.getModifiableChildren().stream() // .map(RunnerTestDescriptor.class::cast) // .map(it -> methods ? parallelMethodExecutor(it, executorService) : it) // - .collect(toList()); + .toList(); } private RunnerTestDescriptor parallelMethodExecutor(RunnerTestDescriptor runnerTestDescriptor, diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java index a1d9720c7cda..9cbb09c270ec 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java @@ -27,7 +27,6 @@ import java.util.List; import java.util.Random; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -242,8 +241,8 @@ void assertLinesMatchMatches() { @Test void largeListsThatDoNotMatchAreTruncated() { - var expected = IntStream.range(1, 999).boxed().map(Object::toString).collect(Collectors.toList()); - var actual = IntStream.range(0, 1000).boxed().map(Object::toString).collect(Collectors.toList()); + var expected = IntStream.range(1, 999).boxed().map(Object::toString).toList(); + var actual = IntStream.range(0, 1000).boxed().map(Object::toString).toList(); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual, "custom message")); var expectedMessage = String.join(System.lineSeparator(), List.of( // diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java index 5f33ded5be82..409940b6212d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/DynamicTestTests.java @@ -24,7 +24,6 @@ import java.util.List; import java.util.Locale; import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.jspecify.annotations.Nullable; @@ -160,7 +159,7 @@ void streamFromIteratorWithNamedExecutables() throws Throwable { } private void assertStream(Stream stream) throws Throwable { - List dynamicTests = stream.collect(Collectors.toList()); + List dynamicTests = stream.toList(); assertThat(dynamicTests).extracting(DynamicTest::getDisplayName).containsExactly("FOO", "BAR", "BAZ"); diff --git a/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java b/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java index d5dbca29324e..5f7b97f88728 100644 --- a/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java +++ b/platform-tests/src/test/java/org/junit/platform/StackTracePruningTests.java @@ -182,7 +182,7 @@ private static Throwable getThrowable(EngineExecutionResults results) { private static void assertStackTraceMatch(List stackTrace, String expectedLines) { List stackStraceAsLines = stackTrace.stream() // .map(StackTraceElement::toString) // - .collect(Collectors.toList()); + .toList(); assertLinesMatch(expectedLines.lines().toList(), stackStraceAsLines); } 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 8f40d780c8a5..d407c2f0401c 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 @@ -40,7 +40,6 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.spi.ToolProvider; -import java.util.stream.Collectors; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.fixtures.TrackLogRecords; @@ -334,12 +333,12 @@ private void checkModules2500(ModuleFinder finder) { ReflectionUtils::tryToLoadClass); { var classes = classpathScanner.scanForClassesInPackage("foo", allClasses); - var classNames = classes.stream().map(Class::getName).collect(Collectors.toList()); + var classNames = classes.stream().map(Class::getName).toList(); assertThat(classNames).hasSize(2).contains("foo.Foo", "foo.bar.FooBar"); } { var classes = classpathScanner.scanForClassesInPackage("foo.bar", allClasses); - var classNames = classes.stream().map(Class::getName).collect(Collectors.toList()); + var classNames = classes.stream().map(Class::getName).toList(); assertThat(classNames).hasSize(1).contains("foo.bar.FooBar"); } } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java index fdc03244c95a..85ca8917a208 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/discovery/DiscoverySelectorsTests.java @@ -42,7 +42,6 @@ import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.jupiter.api.DisplayName; @@ -441,7 +440,7 @@ void selectModuleByNamePreconditions() { @Test void selectModulesByNames() { var selectors = selectModules(Set.of("a", "b")); - var names = selectors.stream().map(ModuleSelector::getModuleName).collect(Collectors.toList()); + var names = selectors.stream().map(ModuleSelector::getModuleName).toList(); assertThat(names).containsExactlyInAnyOrder("b", "a"); } From 6183a6356cd58ecabdeee8c7a6c840d3540bf73a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 17:33:56 +0200 Subject: [PATCH 156/521] Use more immutable collection factory methods --- .../src/test/java/example/ClassTemplateDemo.java | 4 +--- .../java/example/ExternalFieldSourceDemo.java | 4 +--- .../jupiter/api/extension/ExtensionContext.java | 8 +++----- .../engine/descriptor/DisplayNameUtils.java | 8 +------- .../engine/descriptor/ResourceLockAware.java | 7 +------ .../junit/platform/commons/util/ModuleUtils.java | 5 ++--- .../platform/commons/util/ReflectionUtils.java | 16 +++++++--------- .../java/org/junit/platform/engine/UniqueId.java | 10 ++++------ .../support/hierarchical/CompositeLock.java | 4 +--- .../platform/engine/support/store/Namespace.java | 5 ++--- .../launcher/core/DefaultDiscoveryRequest.java | 14 ++++++-------- .../launcher/core/DiscoveryIssueNotifier.java | 16 ++++++++-------- .../testkit/engine/EngineDiscoveryResults.java | 3 +-- .../junit/platform/testkit/engine/Events.java | 3 +-- .../platform/testkit/engine/Executions.java | 6 ++---- 15 files changed, 41 insertions(+), 72 deletions(-) diff --git a/documentation/src/test/java/example/ClassTemplateDemo.java b/documentation/src/test/java/example/ClassTemplateDemo.java index d1035b434348..93f669ab5be2 100644 --- a/documentation/src/test/java/example/ClassTemplateDemo.java +++ b/documentation/src/test/java/example/ClassTemplateDemo.java @@ -11,11 +11,9 @@ package example; import static java.util.Collections.singletonList; -import static java.util.Collections.unmodifiableList; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; -import java.util.Arrays; import java.util.List; import java.util.stream.Stream; @@ -36,7 +34,7 @@ class ClassTemplateDemo { static final List WELL_KNOWN_FRUITS // tag::custom_line_break[] - = unmodifiableList(Arrays.asList("apple", "banana", "lemon")); + = List.of("apple", "banana", "lemon"); //end::user_guide[] @Nullable diff --git a/documentation/src/test/java/example/ExternalFieldSourceDemo.java b/documentation/src/test/java/example/ExternalFieldSourceDemo.java index b6bdc67d5364..d981669d46dc 100644 --- a/documentation/src/test/java/example/ExternalFieldSourceDemo.java +++ b/documentation/src/test/java/example/ExternalFieldSourceDemo.java @@ -10,8 +10,6 @@ package example; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.junit.jupiter.params.ParameterizedTest; @@ -30,6 +28,6 @@ void testWithExternalFieldSource(String tropicalFruit) { class FruitUtils { - public static final List tropicalFruits = Collections.unmodifiableList(Arrays.asList("pineapple", "kiwi")); + public static final List tropicalFruits = List.of("pineapple", "kiwi"); } 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 e8e5133baa9e..a4f2a09a56b2 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 @@ -10,7 +10,6 @@ package org.junit.jupiter.api.extension; -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; @@ -20,7 +19,6 @@ import java.lang.reflect.Method; import java.nio.file.Path; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Map; @@ -770,13 +768,13 @@ class Namespace { public static Namespace create(Object... parts) { Preconditions.notEmpty(parts, "parts array must not be null or empty"); Preconditions.containsNoNullElements(parts, "individual parts must not be null"); - return new Namespace(new ArrayList<>(Arrays.asList(parts))); + return new Namespace(List.of(parts)); } private final List parts; private Namespace(List parts) { - this.parts = parts; + this.parts = List.copyOf(parts); } @Override @@ -815,7 +813,7 @@ public Namespace append(Object... parts) { @API(status = INTERNAL, since = "5.13") public List getParts() { - return unmodifiableList(parts); + return parts; } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java index edf8a8d117d0..bb8d5e5427b2 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DisplayNameUtils.java @@ -10,8 +10,6 @@ package org.junit.jupiter.engine.descriptor; -import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableList; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import java.lang.reflect.AnnotatedElement; @@ -126,7 +124,7 @@ private static Supplier createDisplayNameSupplier(Supplier Class testClass, JupiterConfiguration configuration, BiFunction>, String> generatorFunction) { return () -> { - List> enclosingInstanceTypes = makeUnmodifiable(enclosingInstanceTypesSupplier.get()); + List> enclosingInstanceTypes = List.copyOf(enclosingInstanceTypesSupplier.get()); return findDisplayNameGenerator(enclosingInstanceTypes, testClass) // .map(it -> generatorFunction.apply(it, enclosingInstanceTypes)) // .orElseGet(() -> generatorFunction.apply(configuration.getDefaultDisplayNameGenerator(), @@ -134,10 +132,6 @@ private static Supplier createDisplayNameSupplier(Supplier }; } - private static List makeUnmodifiable(List list) { - return list.isEmpty() ? emptyList() : unmodifiableList(list); - } - private static Optional findDisplayNameGenerator(List> enclosingInstanceTypes, Class testClass) { Preconditions.notNull(testClass, "Test class must not be null"); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java index 47c1cf12bf6b..664462e45d6a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java @@ -10,8 +10,6 @@ package org.junit.jupiter.engine.descriptor; -import static java.util.Collections.emptyList; -import static java.util.Collections.unmodifiableList; import static org.junit.jupiter.api.parallel.ResourceLockTarget.CHILDREN; import java.util.ArrayDeque; @@ -80,14 +78,11 @@ static Function> enclosin @Override public Set apply(ResourceLocksProvider provider) { if (this.enclosingInstanceTypes == null) { - this.enclosingInstanceTypes = makeUnmodifiable(enclosingInstanceTypesSupplier.get()); + this.enclosingInstanceTypes = List.copyOf(enclosingInstanceTypesSupplier.get()); } return evaluator.apply(provider, this.enclosingInstanceTypes); } - private List makeUnmodifiable(List list) { - return list.isEmpty() ? emptyList() : unmodifiableList(list); - } }; } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index 89c38637336c..3538518cfa2b 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -25,7 +25,6 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; -import java.util.Collections; import java.util.LinkedHashSet; import java.util.List; import java.util.Optional; @@ -181,7 +180,7 @@ private static List> scan(Set references, ClassFilter classes.addAll(scanner.scan(reference)); } logger.debug(() -> "Found " + classes.size() + " classes: " + classes); - return Collections.unmodifiableList(classes); + return List.copyOf(classes); } /** @@ -197,7 +196,7 @@ private static List scan(Set references, Predicate "Found " + classes.size() + " classes: " + classes); - return Collections.unmodifiableList(classes); + return List.copyOf(classes); } /** 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 2e413b08c1c8..fc1f9192a5ff 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 @@ -703,8 +703,7 @@ public static List readFieldValues(List fields, @Nullable Object return fields.stream() .filter(predicate) .map(field -> - tryToReadFieldValue(field, instance) - .getOrThrow(ExceptionUtils::throwAsUncheckedException)) + tryToReadFieldValue(field, instance).getOrThrow(ExceptionUtils::throwAsUncheckedException)) .toList(); // @formatter:on } @@ -1017,14 +1016,14 @@ public static Stream> streamAllClassesInClasspathRoot(URI root, Predica * @since 1.1 */ public static List> findAllClassesInClasspathRoot(URI root, ClassFilter classFilter) { - return Collections.unmodifiableList(classpathScanner.scanForClassesInClasspathRoot(root, classFilter)); + return List.copyOf(classpathScanner.scanForClassesInClasspathRoot(root, classFilter)); } /** * @since 1.11 */ public static List findAllResourcesInClasspathRoot(URI root, Predicate resourceFilter) { - return Collections.unmodifiableList(classpathScanner.scanForResourcesInClasspathRoot(root, resourceFilter)); + return List.copyOf(classpathScanner.scanForResourcesInClasspathRoot(root, resourceFilter)); } /** @@ -1063,15 +1062,14 @@ public static Stream> streamAllClassesInPackage(String basePackageName, * @since 1.1 */ public static List> findAllClassesInPackage(String basePackageName, ClassFilter classFilter) { - return Collections.unmodifiableList(classpathScanner.scanForClassesInPackage(basePackageName, classFilter)); + return List.copyOf(classpathScanner.scanForClassesInPackage(basePackageName, classFilter)); } /** * @since 1.11 */ public static List findAllResourcesInPackage(String basePackageName, Predicate resourceFilter) { - return Collections.unmodifiableList( - classpathScanner.scanForResourcesInPackage(basePackageName, resourceFilter)); + return List.copyOf(classpathScanner.scanForResourcesInPackage(basePackageName, resourceFilter)); } /** @@ -1112,14 +1110,14 @@ public static Stream> streamAllClassesInModule(String moduleName, Predi * @since 1.1.1 */ public static List> findAllClassesInModule(String moduleName, ClassFilter classFilter) { - return Collections.unmodifiableList(ModuleUtils.findAllClassesInModule(moduleName, classFilter)); + return List.copyOf(ModuleUtils.findAllClassesInModule(moduleName, classFilter)); } /** * @since 1.11 */ public static List findAllResourcesInModule(String moduleName, Predicate resourceFilter) { - return Collections.unmodifiableList(ModuleUtils.findAllResourcesInModule(moduleName, resourceFilter)); + return List.copyOf(ModuleUtils.findAllResourcesInModule(moduleName, resourceFilter)); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java index ce1bb7654029..ab5a002a64c2 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java @@ -10,8 +10,6 @@ package org.junit.platform.engine; -import static java.util.Collections.singletonList; -import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.STABLE; import java.io.Serial; @@ -97,7 +95,7 @@ public static UniqueId root(String segmentType, String value) { private transient SoftReference toString; private UniqueId(UniqueIdFormat uniqueIdFormat, Segment segment) { - this(uniqueIdFormat, singletonList(segment)); + this(uniqueIdFormat, List.of(segment)); } /** @@ -109,7 +107,7 @@ private UniqueId(UniqueIdFormat uniqueIdFormat, Segment segment) { */ UniqueId(UniqueIdFormat uniqueIdFormat, List segments) { this.uniqueIdFormat = uniqueIdFormat; - this.segments = segments; + this.segments = List.copyOf(segments); } final Optional getRoot() { @@ -130,7 +128,7 @@ public final Optional getEngineId() { * {@code UniqueId}. */ public final List getSegments() { - return unmodifiableList(this.segments); + return this.segments; } /** @@ -218,7 +216,7 @@ public boolean hasPrefix(UniqueId potentialPrefix) { @API(status = STABLE, since = "1.5") public UniqueId removeLastSegment() { Preconditions.condition(this.segments.size() > 1, "Cannot remove last remaining segment"); - return new UniqueId(uniqueIdFormat, new ArrayList<>(this.segments.subList(0, this.segments.size() - 1))); + return new UniqueId(uniqueIdFormat, List.copyOf(this.segments.subList(0, this.segments.size() - 1))); } /** diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/CompositeLock.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/CompositeLock.java index 76dbbb6b984c..7ac65a73e6a1 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/CompositeLock.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/CompositeLock.java @@ -10,8 +10,6 @@ package org.junit.platform.engine.support.hierarchical; -import static java.util.Collections.unmodifiableList; - import java.util.ArrayList; import java.util.List; import java.util.concurrent.ForkJoinPool; @@ -31,7 +29,7 @@ class CompositeLock implements ResourceLock { CompositeLock(List resources, List locks) { Preconditions.condition(resources.size() == locks.size(), "Resources and locks must have the same size"); - this.resources = unmodifiableList(resources); + this.resources = List.copyOf(resources); this.locks = Preconditions.notEmpty(locks, "Locks must not be empty"); this.exclusive = resources.stream().anyMatch( resource -> resource.getLockMode() == ExclusiveResource.LockMode.READ_WRITE); 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..31de08b01692 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 @@ -13,7 +13,6 @@ import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -48,7 +47,7 @@ public class Namespace { public static Namespace create(Object... parts) { Preconditions.notEmpty(parts, "parts array must not be null or empty"); Preconditions.containsNoNullElements(parts, "individual parts must not be null"); - return new Namespace(Arrays.asList(parts)); + return new Namespace(List.of(parts)); } /** @@ -68,7 +67,7 @@ public static Namespace create(List objects) { private final List parts; private Namespace(List parts) { - this.parts = new ArrayList<>(parts); + this.parts = List.copyOf(parts); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java index 849de3baf267..2951e31764f3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DefaultDiscoveryRequest.java @@ -10,8 +10,6 @@ package org.junit.platform.launcher.core; -import static java.util.Collections.unmodifiableList; - import java.util.List; import org.junit.platform.commons.util.Preconditions; @@ -57,10 +55,10 @@ final class DefaultDiscoveryRequest implements LauncherDiscoveryRequest { List> discoveryFilters, List postDiscoveryFilters, LauncherConfigurationParameters configurationParameters, LauncherDiscoveryListener discoveryListener, OutputDirectoryProvider outputDirectoryProvider) { - this.selectors = selectors; - this.engineFilters = engineFilters; - this.discoveryFilters = discoveryFilters; - this.postDiscoveryFilters = postDiscoveryFilters; + this.selectors = List.copyOf(selectors); + this.engineFilters = List.copyOf(engineFilters); + this.discoveryFilters = List.copyOf(discoveryFilters); + this.postDiscoveryFilters = List.copyOf(postDiscoveryFilters); this.configurationParameters = configurationParameters; this.discoveryListener = discoveryListener; this.outputDirectoryProvider = outputDirectoryProvider; @@ -74,7 +72,7 @@ public List getSelectorsByType(Class selecto @Override public List getEngineFilters() { - return unmodifiableList(this.engineFilters); + return this.engineFilters; } @Override @@ -85,7 +83,7 @@ public > List getFiltersByType(Class filterTy @Override public List getPostDiscoveryFilters() { - return unmodifiableList(this.postDiscoveryFilters); + return this.postDiscoveryFilters; } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java index 0d7e8d901a61..1e515657ce9b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DiscoveryIssueNotifier.java @@ -10,12 +10,11 @@ package org.junit.platform.launcher.core; -import static java.util.Collections.emptyList; import static java.util.Comparator.comparing; import static java.util.stream.Collectors.partitioningBy; +import static java.util.stream.Collectors.toUnmodifiableList; import static org.junit.platform.commons.util.ExceptionUtils.readStackTrace; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.function.Consumer; @@ -36,7 +35,7 @@ */ class DiscoveryIssueNotifier { - static final DiscoveryIssueNotifier NO_ISSUES = new DiscoveryIssueNotifier(emptyList(), emptyList(), emptyList()); + static final DiscoveryIssueNotifier NO_ISSUES = new DiscoveryIssueNotifier(List.of(), List.of(), List.of()); private static final Logger logger = LoggerFactory.getLogger(DiscoveryIssueNotifier.class); private final List allIssues; @@ -48,21 +47,22 @@ static DiscoveryIssueNotifier from(Severity criticalSeverity, List criticalIssues = issuesByCriticality.get(true); List nonCriticalIssues = issuesByCriticality.get(false); - return new DiscoveryIssueNotifier(new ArrayList<>(issues), criticalIssues, nonCriticalIssues); + return new DiscoveryIssueNotifier(issues, criticalIssues, nonCriticalIssues); } private static Map> partitionByCriticality(Severity criticalSeverity, List issues) { return issues.stream() // .sorted(comparing(DiscoveryIssue::severity).reversed()) // - .collect(partitioningBy(issue -> issue.severity().compareTo(criticalSeverity) >= 0)); + .collect( + partitioningBy(issue -> issue.severity().compareTo(criticalSeverity) >= 0, toUnmodifiableList())); } private DiscoveryIssueNotifier(List allIssues, List criticalIssues, List nonCriticalIssues) { - this.allIssues = allIssues; - this.criticalIssues = criticalIssues; - this.nonCriticalIssues = nonCriticalIssues; + this.allIssues = List.copyOf(allIssues); + this.criticalIssues = List.copyOf(criticalIssues); + this.nonCriticalIssues = List.copyOf(nonCriticalIssues); } List getAllIssues() { 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..250efe604803 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 @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static java.util.Collections.unmodifiableList; import static org.apiguardian.api.API.Status.EXPERIMENTAL; import java.util.List; @@ -36,7 +35,7 @@ public class EngineDiscoveryResults { EngineDiscoveryResults(TestDescriptor engineDescriptor, List discoveryIssues) { this.engineDescriptor = Preconditions.notNull(engineDescriptor, "Engine descriptor must not be null"); - this.discoveryIssues = unmodifiableList( + this.discoveryIssues = List.copyOf( Preconditions.notNull(discoveryIssues, "Discovery issues list must not be null")); Preconditions.containsNoNullElements(discoveryIssues, "Discovery issues list must not contain null elements"); } 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 5975982d2c0e..d2241a0d4a24 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 @@ -23,7 +23,6 @@ import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -64,7 +63,7 @@ public final class Events { Preconditions.notNull(events, "Event list must not be null"); Preconditions.containsNoNullElements(events, "Event list must not contain null elements"); - this.events = Collections.unmodifiableList(events); + this.events = List.copyOf(events); this.category = category; } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java index fae09e861905..d17173d11c79 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java @@ -10,7 +10,6 @@ package org.junit.platform.testkit.engine; -import static java.util.stream.Collectors.toList; import static org.apiguardian.api.API.Status.MAINTAINED; import java.io.OutputStream; @@ -18,7 +17,6 @@ import java.io.Writer; import java.time.Instant; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -48,7 +46,7 @@ public final class Executions { private Executions(Stream executions, String category) { Preconditions.notNull(executions, "Execution stream must not be null"); - this.executions = Collections.unmodifiableList(executions.collect(toList())); + this.executions = executions.toList(); this.category = category; } @@ -56,7 +54,7 @@ private Executions(Stream executions, String category) { Preconditions.notNull(events, "Event list must not be null"); Preconditions.containsNoNullElements(events, "Event list must not contain null elements"); - this.executions = Collections.unmodifiableList(createExecutions(events)); + this.executions = List.copyOf(createExecutions(events)); this.category = category; } From 34e662738b935e79a841374708e6a0b8b0690f17 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 19:16:05 +0200 Subject: [PATCH 157/521] Fix nullability annotations in `ReflectionUtils` and `AnnotationSupport` --- .../commons/support/AnnotationSupport.java | 14 ++++++++------ .../platform/commons/util/ReflectionUtils.java | 6 +++--- 2 files changed, 11 insertions(+), 9 deletions(-) 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 d8a0c6164fec..a29801a7c333 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 @@ -443,7 +443,8 @@ public static List findAnnotatedFields(Class clazz, Class findAnnotatedFieldValues(Object instance, Class annotationType) { + public static List<@Nullable Object> findAnnotatedFieldValues(Object instance, + Class annotationType) { Preconditions.notNull(instance, "instance must not be null"); List fields = findAnnotatedFields(instance.getClass(), annotationType, ModifierSupport::isNotStatic, @@ -475,7 +476,8 @@ public static List findAnnotatedFieldValues(Object instance, Class findAnnotatedFieldValues(Class clazz, Class annotationType) { + public static List<@Nullable Object> findAnnotatedFieldValues(Class clazz, + Class annotationType) { List fields = findAnnotatedFields(clazz, annotationType, ModifierSupport::isStatic, HierarchyTraversalMode.TOP_DOWN); @@ -510,8 +512,8 @@ public static List findAnnotatedFieldValues(Class clazz, Class List findAnnotatedFieldValues(Object instance, Class annotationType, - Class fieldType) { + public static List findAnnotatedFieldValues(Object instance, + Class annotationType, Class fieldType) { Preconditions.notNull(instance, "instance must not be null"); Preconditions.notNull(fieldType, "fieldType must not be null"); @@ -552,8 +554,8 @@ public static List findAnnotatedFieldValues(Object instance, Class List findAnnotatedFieldValues(Class clazz, Class annotationType, - Class fieldType) { + public static List findAnnotatedFieldValues(Class clazz, + Class annotationType, Class fieldType) { Preconditions.notNull(fieldType, "fieldType must not be 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 fc1f9192a5ff..0e90c574e5a7 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 @@ -626,7 +626,7 @@ public static T newInstance(Constructor constructor, @Nullable Object... * @see #tryToReadFieldValue(Field, Object) */ @API(status = INTERNAL, since = "1.4") - public static Try tryToReadFieldValue(Class clazz, String fieldName, T instance) { + public static Try tryToReadFieldValue(Class clazz, String fieldName, @Nullable T instance) { Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notBlank(fieldName, "Field name must not be null or blank"); @@ -677,7 +677,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - public static List readFieldValues(List fields, @Nullable Object instance) { + public static List<@Nullable Object> readFieldValues(List fields, @Nullable Object instance) { return readFieldValues(fields, instance, field -> true); } @@ -694,7 +694,7 @@ public static List readFieldValues(List fields, @Nullable Object * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - public static List readFieldValues(List fields, @Nullable Object instance, + public static List<@Nullable Object> readFieldValues(List fields, @Nullable Object instance, Predicate predicate) { Preconditions.notNull(fields, "fields list must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); From a1ba64c1edbeae31cb8208123d07857a031ed982 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 19:20:03 +0200 Subject: [PATCH 158/521] Fix nullability annotation in `RecordArguments` --- .../org/junit/jupiter/params/provider/RecordArguments.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/junit-jupiter-params/src/testFixtures/java/org/junit/jupiter/params/provider/RecordArguments.java b/junit-jupiter-params/src/testFixtures/java/org/junit/jupiter/params/provider/RecordArguments.java index 96213c64e57e..1ecc810c460c 100644 --- a/junit-jupiter-params/src/testFixtures/java/org/junit/jupiter/params/provider/RecordArguments.java +++ b/junit-jupiter-params/src/testFixtures/java/org/junit/jupiter/params/provider/RecordArguments.java @@ -12,12 +12,13 @@ import java.util.Arrays; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.support.ReflectionSupport; public interface RecordArguments extends Arguments { @Override - default Object[] get() { + default @Nullable Object[] get() { return Arrays.stream(getClass().getRecordComponents()) // .map(component -> ReflectionSupport.invokeMethod(component.getAccessor(), this)) // .toArray(); From a42d474ac3d4122748c26f5c382f181b64779e61 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 19:20:16 +0200 Subject: [PATCH 159/521] Remove unnecessary reflection --- .../platform/launcher/core/ClasspathAlignmentChecker.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 3b52f7f05412..108761077cd0 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -22,7 +22,6 @@ import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; -import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.ClassLoaderUtils; /** @@ -51,11 +50,7 @@ class ClasspathAlignmentChecker { static Optional check(LinkageError error) { ClassLoader classLoader = ClassLoaderUtils.getClassLoader(ClasspathAlignmentChecker.class); - Function packageLookup = name -> ReflectionSupport.findMethod(ClassLoader.class, - "getDefinedPackage", String.class) // - .map(m -> (Package) ReflectionSupport.invokeMethod(m, classLoader, name)) // - .orElseGet(() -> getPackage(name)); - return check(error, packageLookup); + return check(error, classLoader::getDefinedPackage); } // VisibleForTesting From e9d71d67e49d42b30ebc7036140787f6644aebd0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 24 May 2025 19:21:00 +0200 Subject: [PATCH 160/521] Remove unused method --- .../launcher/core/LauncherConfigurationParameters.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java index ebb0f19a3df4..cfea8896710d 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherConfigurationParameters.java @@ -155,10 +155,6 @@ private interface ParameterProvider { @Nullable String getValue(String key); - default int size() { - return 0; - } - Set keySet(); static ParameterProvider explicit(Map configParams) { @@ -168,11 +164,6 @@ static ParameterProvider explicit(Map configParams) { return configParams.get(key); } - @Override - public int size() { - return configParams.size(); - } - @Override public Set keySet() { return configParams.keySet(); From a4d9932367be469be73caf207c6d00f4c1d1384f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 25 May 2025 11:00:56 +0000 Subject: [PATCH 161/521] Update sbt/setup-sbt action to v1.1.8 (#4573) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1112fbd68860..bc3320b3039f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,7 +89,7 @@ jobs: with: java-version: 21 distribution: temurin - - uses: sbt/setup-sbt@26ab4b0fa1c47fa62fc1f6e51823a658fb6c760c # v1.1.7 + - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 - name: Update JUnit dependencies in samples run: java src/Updater.java ${{ inputs.releaseVersion }} working-directory: junit5-samples @@ -234,7 +234,7 @@ jobs: with: java-version: 21 distribution: temurin - - uses: sbt/setup-sbt@26ab4b0fa1c47fa62fc1f6e51823a658fb6c760c # v1.1.7 + - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 - name: Update JUnit dependencies in samples run: java src/Updater.java ${{ inputs.releaseVersion }} - name: Build samples From fd0ca15f01044b270ec5e23a71812fcd020f63be Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Sun, 25 May 2025 15:33:38 +0200 Subject: [PATCH 162/521] Update link to Maven snapshots --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9ad2cd01fba5..20fce47b68be 100644 --- a/README.md +++ b/README.md @@ -94,7 +94,7 @@ Consult the [Dependency Metadata] section of the [User Guide] for a list of all of the JUnit Platform, JUnit Jupiter, and JUnit Vintage. See also for releases and - for snapshots. + for snapshots. [Codecov]: https://codecov.io/gh/junit-team/junit5 From b2f4d092e0a6aa0267e7714047769e7018c0c449 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 11:42:21 +0200 Subject: [PATCH 163/521] Implement Kotlin reflection calls in Java (#4562) To avoid problems when working on the codebase with Eclipse. --- .../commons/util/KotlinReflectionUtils.java | 10 +- .../util/KotlinSuspendingFunctionUtils.java | 108 ++++++++++++++++++ .../commons/util/ReflectionUtils.java | 2 +- .../commons/util/KotlinReflectionUtils.kt | 59 ---------- 4 files changed, 114 insertions(+), 65 deletions(-) create mode 100644 junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java delete mode 100644 junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt 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 index bb8fc03d327b..99975cd24a1c 100644 --- 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 @@ -74,29 +74,29 @@ private static boolean isKotlinType(Class clazz) { public static Class getKotlinSuspendingFunctionReturnType(Method method) { requireKotlinReflect(method); - return KotlinReflectionUtilsKt.getReturnType(method); + return KotlinSuspendingFunctionUtils.getReturnType(method); } public static Type getKotlinSuspendingFunctionGenericReturnType(Method method) { requireKotlinReflect(method); - return KotlinReflectionUtilsKt.getGenericReturnType(method); + return KotlinSuspendingFunctionUtils.getGenericReturnType(method); } public static Parameter[] getKotlinSuspendingFunctionParameters(Method method) { requireKotlinReflect(method); - return KotlinReflectionUtilsKt.getParameters(method); + return KotlinSuspendingFunctionUtils.getParameters(method); } public static Class[] getKotlinSuspendingFunctionParameterTypes(Method method) { requireKotlinReflect(method); - return KotlinReflectionUtilsKt.getParameterTypes(method); + return KotlinSuspendingFunctionUtils.getParameterTypes(method); } public static @Nullable Object invokeKotlinSuspendingFunction(Method method, @Nullable Object target, @Nullable Object[] args) { requireKotlinReflect(method); requireKotlinxCoroutines(method); - return KotlinReflectionUtilsKt.invoke(method, target, args); + return KotlinSuspendingFunctionUtils.invoke(method, target, args); } private static void requireKotlinReflect(Method method) { diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java new file mode 100644 index 000000000000..9be5fba56ee2 --- /dev/null +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java @@ -0,0 +1,108 @@ +/* + * 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 kotlin.jvm.JvmClassMappingKt.getJavaClass; +import static kotlin.reflect.full.KCallables.callSuspendBy; +import static kotlin.reflect.jvm.KCallablesJvm.isAccessible; +import static kotlin.reflect.jvm.KCallablesJvm.setAccessible; +import static kotlin.reflect.jvm.KTypesJvm.getJvmErasure; +import static kotlin.reflect.jvm.ReflectJvmMapping.getJavaType; +import static kotlinx.coroutines.BuildersKt.runBlocking; +import static org.junit.platform.commons.util.ExceptionUtils.throwAsUncheckedException; +import static org.junit.platform.commons.util.ReflectionUtils.getUnderlyingCause; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.lang.reflect.Type; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import kotlin.Unit; +import kotlin.coroutines.EmptyCoroutineContext; +import kotlin.reflect.KFunction; +import kotlin.reflect.KParameter; +import kotlin.reflect.jvm.ReflectJvmMapping; + +class KotlinSuspendingFunctionUtils { + + static Class getReturnType(Method method) { + var returnType = getJavaClass(getJvmErasure(getKotlinFunction(method).getReturnType())); + if (Unit.class.equals(returnType)) { + return void.class; + } + return returnType; + } + + static Type getGenericReturnType(Method method) { + return getJavaType(getKotlinFunction(method).getReturnType()); + } + + static Parameter[] getParameters(Method method) { + var parameterCount = method.getParameterCount(); + if (parameterCount == 1) { + return new Parameter[0]; + } + return Arrays.copyOf(method.getParameters(), parameterCount - 1); + } + + static Class[] getParameterTypes(Method method) { + var parameterCount = method.getParameterCount(); + if (parameterCount == 1) { + return new Class[0]; + } + return Arrays.stream(method.getParameterTypes()).limit(parameterCount - 1).toArray(Class[]::new); + } + + static Object invoke(Method method, Object target, Object[] args) { + try { + return invoke(getKotlinFunction(method), target, args); + } + catch (InterruptedException e) { + throw throwAsUncheckedException(e); + } + } + + private static T invoke(KFunction function, Object target, Object[] args) throws InterruptedException { + if (!isAccessible(function)) { + setAccessible(function, true); + } + return runBlocking(EmptyCoroutineContext.INSTANCE, (__, continuation) -> { + try { + return callSuspendBy(function, toArgumentMap(target, args, function), continuation); + } + catch (Exception e) { + throw throwAsUncheckedException(getUnderlyingCause(e)); + } + }); + } + + private static Map toArgumentMap(Object target, Object[] args, KFunction function) { + Map arguments = new HashMap<>(args.length + 1); + int index = 0; + for (KParameter parameter : function.getParameters()) { + switch (parameter.getKind()) { + case INSTANCE -> arguments.put(parameter, target); + case VALUE, EXTENSION_RECEIVER -> { + arguments.put(parameter, args[index]); + index++; + } + } + } + return arguments; + } + + private static KFunction getKotlinFunction(Method method) { + return Preconditions.notNull(ReflectJvmMapping.getKotlinFunction(method), + () -> "Failed to get Kotlin function for method: " + method); + } +} 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 0e90c574e5a7..5ef713bde498 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 @@ -1977,7 +1977,7 @@ private static boolean isSearchable(@Nullable Class clazz) { * {@linkplain InvocationTargetException#getTargetException() target * exception}; otherwise, this method returns the supplied {@code Throwable}. */ - private static Throwable getUnderlyingCause(Throwable t) { + static Throwable getUnderlyingCause(Throwable t) { if (t instanceof InvocationTargetException) { return getUnderlyingCause(((InvocationTargetException) t).getTargetException()); } diff --git a/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt b/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt deleted file mode 100644 index 4bd3fe0d53ce..000000000000 --- a/junit-platform-commons/src/main/kotlin/org/junit/platform/commons/util/KotlinReflectionUtils.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 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 - */ -@file:JvmName("KotlinReflectionUtilsKt") - -package org.junit.platform.commons.util - -import kotlinx.coroutines.runBlocking -import java.lang.reflect.InvocationTargetException -import java.lang.reflect.Method -import kotlin.reflect.full.callSuspend -import kotlin.reflect.full.valueParameters -import kotlin.reflect.jvm.javaType -import kotlin.reflect.jvm.jvmErasure -import kotlin.reflect.jvm.kotlinFunction - -internal fun getReturnType(method: Method): Class = - with(method.kotlinFunction!!.returnType.jvmErasure) { - if (this == Unit::class) { - Void.TYPE - } else { - java - } - } - -internal fun getGenericReturnType(method: Method) = method.kotlinFunction!!.returnType.javaType - -internal fun getParameterTypes(method: Method) = - method.kotlinFunction!! - .parameters - .map { it.type.jvmErasure.java } - .toTypedArray() - -internal fun getParameters(method: Method) = - method.kotlinFunction!!.valueParameters.size.let { - if (it > 0) { - method.parameters.copyOf(it) - } else { - emptyArray() - } - } - -internal fun invoke( - method: Method, - target: Any?, - vararg args: Any? -) = runBlocking { - try { - method.kotlinFunction!!.callSuspend(target, *args) - } catch (e: InvocationTargetException) { - throw e.targetException - } -} From 0fbe4b87fd0718396efdc5ae60016152e149adbe Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 11:43:06 +0200 Subject: [PATCH 164/521] Remove support for legacy semantics for field/method search (#4575) Co-authored-by: Sam Brannen <104798+sbrannen@users.noreply.github.com> --- .../release-notes/release-notes-6.0.0-M1.adoc | 5 + .../docs/asciidoc/user-guide/extensions.adoc | 27 +---- .../commons/util/ReflectionUtils.java | 108 ++++-------------- .../commons/util/AnnotationUtilsTests.java | 17 --- .../commons/util/ReflectionUtilsTests.java | 70 ------------ 5 files changed, 32 insertions(+), 195 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 28e79fd1e8b7..29966c74f2c9 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -70,6 +70,11 @@ repository on GitHub. - `EngineTestKit.execute(String, EngineDiscoveryRequest)`, `EngineTestKit.execute(TestEngine, EngineDiscoveryRequest)`, and `EngineTestKit.Builder.filters(...)` methods +* Support for "legacy semantics" for field and method searches that used to be + configurable via the `junit.platform.reflection.search.useLegacySemantics` system + property has been removed. JUnit now always adheres to standard Java semantics regarding + whether a given field or method is visible or overridden according to the rules of the + Java language. [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/extensions.adoc b/documentation/src/docs/asciidoc/user-guide/extensions.adoc index e1a3b351aedb..49ec9920176e 100644 --- a/documentation/src/docs/asciidoc/user-guide/extensions.adoc +++ b/documentation/src/docs/asciidoc/user-guide/extensions.adoc @@ -995,30 +995,9 @@ Various methods in `AnnotationSupport` and `ReflectionSupport` use search algori traverse type hierarchies to locate matching fields and methods – for example, `AnnotationSupport.findAnnotatedFields(...)`, `ReflectionSupport.findMethods(...)`, etc. -As of JUnit 5.11 (JUnit Platform 1.11), field and method search algorithms adhere to -standard Java semantics regarding whether a given field or method is visible or overridden -according to the rules of the Java language. - -Prior to JUnit 5.11, the field and method search algorithms applied what we now refer to -as "legacy semantics". Legacy semantics consider fields and methods to be _hidden_, -_shadowed_, or _superseded_ by fields and methods in super types (superclasses or -interfaces) based solely on the field's name or the method's signature, disregarding the -actual Java language semantics for visibility and the rules that determine if one method -overrides another method. - -Although the JUnit team recommends the use of the standard search semantics, developers -may optionally revert to the legacy semantics via the -`junit.platform.reflection.search.useLegacySemantics` JVM system property. - -For example, to enable legacy search semantics for fields and methods, you can start your -JVM with the following system property. - -`-Djunit.platform.reflection.search.useLegacySemantics=true` - -NOTE: Due to the low-level nature of the feature, the -`junit.platform.reflection.search.useLegacySemantics` flag can only be set via a JVM -system property. It cannot be set via a <>. +The field and method search algorithms adhere to standard Java semantics regarding whether +a given field or method is visible or overridden according to the rules of the Java +language. [[extensions-execution-order]] === Relative Execution Order of User Code and Extensions 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 5ef713bde498..8394fc2ebc27 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 @@ -83,27 +83,6 @@ @API(status = INTERNAL, since = "1.0") public final class ReflectionUtils { - /** - * Property name used to signal that legacy semantics should be used when - * searching for fields and methods within a type hierarchy: {@value}. - * - *

    Value must be either {@code true} or {@code false} (ignoring case); - * defaults to {@code false}. - * - *

    When set to {@code false} (either explicitly or implicitly), field and - * method searches will adhere to Java semantics regarding whether a given - * field or method is visible or overridden, where the latter only applies - * to methods. When set to {@code true}, the semantics used in versions prior - * to JUnit 5.11 (JUnit Platform 1.11) will be used, which means that fields - * and methods can hide, shadow, or supersede fields and methods in supertypes - * based solely on the field's name or the method's signature, disregarding - * the actual Java language semantics for visibility and whether a method - * overrides another method. - * - * @since 1.11 - */ - private static final String USE_LEGACY_SEARCH_SEMANTICS_PROPERTY_NAME = "junit.platform.reflection.search.useLegacySemantics"; - private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class); private ReflectionUtils() { @@ -250,8 +229,6 @@ public enum HierarchyTraversalMode { primitiveToWrapperMap = Collections.unmodifiableMap(primitivesToWrappers); } - static volatile boolean useLegacySearchSemantics = getLegacySearchSemanticsFlag(); - public static boolean isPublic(Class clazz) { Preconditions.notNull(clazz, "Class must not be null"); return Modifier.isPublic(clazz.getModifiers()); @@ -1353,23 +1330,19 @@ private static List findAllFieldsInHierarchy(Class clazz, HierarchyTra Field[] localFields = getDeclaredFields(clazz).stream() .filter(field -> !field.isSynthetic()) .toArray(Field[]::new); - Field[] superclassFields = getSuperclassFields(clazz, traversalMode).stream() - .filter(field -> isNotShadowedByLocalFields(field, localFields)) - .toArray(Field[]::new); - Field[] interfaceFields = getInterfaceFields(clazz, traversalMode).stream() - .filter(field -> isNotShadowedByLocalFields(field, localFields)) - .toArray(Field[]::new); // @formatter:on + List superclassFields = getSuperclassFields(clazz, traversalMode); + List interfaceFields = getInterfaceFields(clazz, traversalMode); - List fields = new ArrayList<>(superclassFields.length + interfaceFields.length + localFields.length); + List fields = new ArrayList<>(superclassFields.size() + interfaceFields.size() + localFields.length); if (traversalMode == TOP_DOWN) { - Collections.addAll(fields, superclassFields); - Collections.addAll(fields, interfaceFields); + fields.addAll(superclassFields); + fields.addAll(interfaceFields); } Collections.addAll(fields, localFields); if (traversalMode == BOTTOM_UP) { - Collections.addAll(fields, interfaceFields); - Collections.addAll(fields, superclassFields); + fields.addAll(interfaceFields); + fields.addAll(superclassFields); } return fields; } @@ -1780,21 +1753,18 @@ private static List getInterfaceMethods(Class clazz, HierarchyTravers private static List getInterfaceFields(Class clazz, HierarchyTraversalMode traversalMode) { List allInterfaceFields = new ArrayList<>(); for (Class ifc : clazz.getInterfaces()) { + Field[] localInterfaceFields = ifc.getFields(); Arrays.sort(localInterfaceFields, ReflectionUtils::defaultFieldSorter); - // @formatter:off - Field[] superinterfaceFields = getInterfaceFields(ifc, traversalMode).stream() - .filter(field -> isNotShadowedByLocalFields(field, localInterfaceFields)) - .toArray(Field[]::new); - // @formatter:on + List superinterfaceFields = getInterfaceFields(ifc, traversalMode); if (traversalMode == TOP_DOWN) { - Collections.addAll(allInterfaceFields, superinterfaceFields); + allInterfaceFields.addAll(superinterfaceFields); } Collections.addAll(allInterfaceFields, localInterfaceFields); if (traversalMode == BOTTOM_UP) { - Collections.addAll(allInterfaceFields, superinterfaceFields); + allInterfaceFields.addAll(superinterfaceFields); } } return allInterfaceFields; @@ -1808,18 +1778,6 @@ private static List getSuperclassFields(Class clazz, HierarchyTraversa return findAllFieldsInHierarchy(superclass, traversalMode); } - private static boolean isNotShadowedByLocalFields(Field field, Field[] localFields) { - if (useLegacySearchSemantics) { - for (Field local : localFields) { - if (local.getName().equals(field.getName())) { - return false; - } - } - return true; - } - return true; - } - private static List getSuperclassMethods(Class clazz, HierarchyTraversalMode traversalMode) { Class superclass = clazz.getSuperclass(); if (!isSearchable(superclass)) { @@ -1838,23 +1796,20 @@ private static boolean isNotOverriddenByLocalMethods(Method method, Method[] loc } private static boolean isMethodOverriddenBy(Method upper, Method lower) { - // If legacy search semantics are enabled, skip to hasCompatibleSignature() check. - if (!useLegacySearchSemantics) { - // A static method cannot override anything. - if (Modifier.isStatic(lower.getModifiers())) { - return false; - } + // A static method cannot override anything. + if (Modifier.isStatic(lower.getModifiers())) { + return false; + } - // Cannot override a private, static, or final method. - int modifiers = upper.getModifiers(); - if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { - return false; - } + // Cannot override a private, static, or final method. + int modifiers = upper.getModifiers(); + if (Modifier.isPrivate(modifiers) || Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) { + return false; + } - // Cannot override a package-private method in another package. - if (isPackagePrivate(upper) && !declaredInSamePackage(upper, lower)) { - return false; - } + // Cannot override a package-private method in another package. + if (isPackagePrivate(upper) && !declaredInSamePackage(upper, lower)) { + return false; } return hasCompatibleSignature(upper, lower.getName(), lower.getParameterTypes()); @@ -1897,10 +1852,7 @@ private static boolean hasCompatibleSignature(Method candidate, String methodNam } } // lower is sub-signature of upper: check for generics in upper method - if (isGeneric(candidate)) { - return true; - } - return false; + return isGeneric(candidate); } static boolean isGeneric(Method method) { @@ -1984,18 +1936,6 @@ static Throwable getUnderlyingCause(Throwable t) { return t; } - private static boolean getLegacySearchSemanticsFlag() { - String rawValue = System.getProperty(USE_LEGACY_SEARCH_SEMANTICS_PROPERTY_NAME); - if (StringUtils.isBlank(rawValue)) { - return false; - } - String value = rawValue.trim().toLowerCase(); - boolean isTrue = "true".equals(value); - Preconditions.condition(isTrue || "false".equals(value), () -> USE_LEGACY_SEARCH_SEMANTICS_PROPERTY_NAME - + " property must be 'true' or 'false' (ignoring case): " + rawValue); - return isTrue; - } - private interface Visitor { /** 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 31c65511af00..724b500f6d05 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 @@ -504,23 +504,6 @@ void findAnnotatedFieldsFindsAllFieldsInTypeHierarchy() { .containsExactly("interface", "interface-shadow"); } - @Test - void findAnnotatedFieldsForShadowedFieldsInLegacyMode() { - try { - ReflectionUtils.useLegacySearchSemantics = true; - - assertThat(findShadowingAnnotatedFields(Annotation1.class))// - .containsExactly("super-shadow", "foo-shadow", "baz-shadow"); - assertThat(findShadowingAnnotatedFields(Annotation2.class))// - .containsExactly("bar-shadow", "baz-shadow"); - assertThat(findShadowingAnnotatedFields(Annotation3.class))// - .containsExactly("interface-shadow"); - } - finally { - ReflectionUtils.useLegacySearchSemantics = false; - } - } - private List findShadowingAnnotatedFields(Class annotationType) { var fields = findAnnotatedFields(ClassWithShadowedAnnotatedFields.class, annotationType, isStringField); var values = ReflectionUtils.readFieldValues(fields, new ClassWithShadowedAnnotatedFields()); 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 9738a86ef7a6..709c6fed82aa 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 @@ -1665,41 +1665,6 @@ void findMethodsWithoutStaticHidingUsingHierarchyUpMode() throws Exception { assertThat(methods.subList(7, 9)).containsOnly(ifcMethod1, ifcMethod2); } - /** - * In legacy mode, "static hiding" occurs. - */ - @Test - void findMethodsWithStaticHidingUsingHierarchyUpModeInLegacyMode() throws Exception { - try { - ReflectionUtils.useLegacySearchSemantics = true; - - Class ifc = StaticMethodHidingInterface.class; - Class parent = StaticMethodHidingParent.class; - Class child = StaticMethodHidingChild.class; - - var ifcMethod2 = ifc.getDeclaredMethod("method2", int.class, int.class); - var childMethod1 = child.getDeclaredMethod("method1", String.class); - var childMethod4 = child.getDeclaredMethod("method4", boolean.class); - var childMethod5 = child.getDeclaredMethod("method5", Long.class); - var parentMethod2 = parent.getDeclaredMethod("method2", int.class, int.class, int.class); - var parentMethod5 = parent.getDeclaredMethod("method5", String.class); - - assertThat(findMethods(child, methodContains1, BOTTOM_UP)).containsExactly(childMethod1); - assertThat(findMethods(child, methodContains2, BOTTOM_UP)).containsExactly(parentMethod2, ifcMethod2); - assertThat(findMethods(child, methodContains4, BOTTOM_UP)).containsExactly(childMethod4); - assertThat(findMethods(child, methodContains5, BOTTOM_UP)).containsExactly(childMethod5, parentMethod5); - - var methods = findMethods(child, method -> true, BOTTOM_UP); - assertEquals(6, methods.size()); - assertThat(methods.subList(0, 3)).containsOnly(childMethod1, childMethod4, childMethod5); - assertThat(methods.subList(3, 5)).containsOnly(parentMethod2, parentMethod5); - assertEquals(ifcMethod2, methods.get(5)); - } - finally { - ReflectionUtils.useLegacySearchSemantics = false; - } - } - /** * In non-legacy mode, "static hiding" does not occur. */ @@ -1732,41 +1697,6 @@ void findMethodsWithoutStaticHidingUsingHierarchyDownMode() throws Exception { assertThat(methods.subList(6, 9)).containsOnly(childMethod1, childMethod4, childMethod5); } - /** - * In legacy mode, "static hiding" occurs. - */ - @Test - void findMethodsWithStaticHidingUsingHierarchyDownModeInLegacyMode() throws Exception { - try { - ReflectionUtils.useLegacySearchSemantics = true; - - Class ifc = StaticMethodHidingInterface.class; - Class parent = StaticMethodHidingParent.class; - Class child = StaticMethodHidingChild.class; - - var ifcMethod2 = ifc.getDeclaredMethod("method2", int.class, int.class); - var childMethod1 = child.getDeclaredMethod("method1", String.class); - var childMethod4 = child.getDeclaredMethod("method4", boolean.class); - var childMethod5 = child.getDeclaredMethod("method5", Long.class); - var parentMethod2 = parent.getDeclaredMethod("method2", int.class, int.class, int.class); - var parentMethod5 = parent.getDeclaredMethod("method5", String.class); - - assertThat(findMethods(child, methodContains1, TOP_DOWN)).containsExactly(childMethod1); - assertThat(findMethods(child, methodContains2, TOP_DOWN)).containsExactly(ifcMethod2, parentMethod2); - assertThat(findMethods(child, methodContains4, TOP_DOWN)).containsExactly(childMethod4); - assertThat(findMethods(child, methodContains5, TOP_DOWN)).containsExactly(parentMethod5, childMethod5); - - var methods = findMethods(child, method -> true, TOP_DOWN); - assertEquals(6, methods.size()); - assertEquals(ifcMethod2, methods.getFirst()); - assertThat(methods.subList(1, 3)).containsOnly(parentMethod2, parentMethod5); - assertThat(methods.subList(3, 6)).containsOnly(childMethod1, childMethod4, childMethod5); - } - finally { - ReflectionUtils.useLegacySearchSemantics = false; - } - } - @Test void findMethodsDoesNotReturnOverriddenMethods() { Predicate isSpecial = method -> method.isAnnotationPresent(Special.class); From dcc8719eab0842fc31146efa325238e1db14b8f4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 11:48:15 +0200 Subject: [PATCH 165/521] Add missing `@Nullable` annotations --- .../commons/util/KotlinSuspendingFunctionUtils.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java index 9be5fba56ee2..363af7fcffc3 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/KotlinSuspendingFunctionUtils.java @@ -27,6 +27,8 @@ import java.util.HashMap; import java.util.Map; +import org.jspecify.annotations.Nullable; + import kotlin.Unit; import kotlin.coroutines.EmptyCoroutineContext; import kotlin.reflect.KFunction; @@ -63,7 +65,7 @@ static Class[] getParameterTypes(Method method) { return Arrays.stream(method.getParameterTypes()).limit(parameterCount - 1).toArray(Class[]::new); } - static Object invoke(Method method, Object target, Object[] args) { + static @Nullable Object invoke(Method method, @Nullable Object target, @Nullable Object[] args) { try { return invoke(getKotlinFunction(method), target, args); } @@ -72,7 +74,8 @@ static Object invoke(Method method, Object target, Object[] args) { } } - private static T invoke(KFunction function, Object target, Object[] args) throws InterruptedException { + private static @Nullable T invoke(KFunction function, @Nullable Object target, @Nullable Object[] args) + throws InterruptedException { if (!isAccessible(function)) { setAccessible(function, true); } @@ -86,8 +89,9 @@ private static T invoke(KFunction function, Object target, Object[] args) }); } - private static Map toArgumentMap(Object target, Object[] args, KFunction function) { - Map arguments = new HashMap<>(args.length + 1); + private static Map toArgumentMap(@Nullable Object target, @Nullable Object[] args, + KFunction function) { + Map arguments = new HashMap<>(args.length + 1); int index = 0; for (KParameter parameter : function.getParameters()) { switch (parameter.getKind()) { From 3d2afe753c241c3ed8ac4d2896626f3773062e5f Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 12:57:56 +0200 Subject: [PATCH 166/521] Add missing word --- documentation/src/docs/asciidoc/user-guide/writing-tests.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index d20da177fbef..8971ad0b4996 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1595,7 +1595,7 @@ _Parameterized tests_ make it possible to run a test method multiple times with arguments. They are declared just like regular `@Test` methods but use the `{ParameterizedTest}` annotation instead. -_Parameterized classes_ make it possible to run _all_ tests in test class, including +_Parameterized classes_ make it possible to run _all_ tests in a test class, including <>, multiple times with different arguments. They are declared just like regular test classes and may contain any supported test method type (including `@ParameterizedTest`) but annotated with the `{ParameterizedClass}` annotation. From 87e3a7b64c07eae0af7ec13a2b8b598fe10b4c3a Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 15:18:33 +0200 Subject: [PATCH 167/521] Link to upgrade instructions wrt. GraalVM in the wiki --- .../release-notes/release-notes-5.13.0.adoc | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index ea4319391681..35cb9c69ed32 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -30,11 +30,14 @@ repository on GitHub. [[release-notes-5.13.0-overall-new-features-and-improvements]] ==== Deprecations and Breaking Changes -* The JUnit feature in GraalVM Native Build Tools has been rewritten to no longer require - JUnit classes to be initialized at build time. Therefore, JUnit's JARs no longer ship - with `native-image.properties` files that contain `--initialize-at-build-time` options - (introduced in 5.12.0). Please update to the most recent version of GraalVM Native Build - Tools prior to upgrading to this version of JUnit. +* The JUnit feature in GraalVM Native Build Tools (NBT) has been rewritten to no longer + require JUnit classes to be initialized at build time when running on JDK 22 and later. + Therefore, JUnit's JARs no longer ship with `native-image.properties` files that contain + `--initialize-at-build-time` options (introduced in 5.12.0). Please update to the most + recent version of GraalVM Native Build Tools prior to upgrading to this version of + JUnit. Please refer to the + https://github.com/junit-team/junit5/wiki/Upgrading-to-JUnit-5.13[Upgrade Instructions] + in the wiki for details if you're on NBT 0.10.x or earlier. [[release-notes-5.13.0-junit-platform]] From 27d9eae446d42a6aeb79b84d4fc512387863d551 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 15:19:05 +0200 Subject: [PATCH 168/521] Split list of `--initialize-at-build-time` classes by version --- .../projects/graalvm-starter/build.gradle.kts | 47 ++++++++++--------- .../graalvm-starter/settings.gradle.kts | 19 ++++++++ 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index 3ba8850b7fbf..f37170d70e74 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -5,11 +5,6 @@ plugins { val junitVersion: String by project -repositories { - maven { url = uri(file(System.getProperty("maven.repo"))) } - mavenCentral() -} - dependencies { testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") testImplementation("junit:junit:4.13.2") @@ -32,29 +27,37 @@ tasks.test { } } -// These will be part of the next version of native-build-tools -// see https://github.com/graalvm/native-build-tools/pull/693 -val initializeAtBuildTime = listOf( - "org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor\$ClassInfo", - "org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor\$LifecycleMethods", - "org.junit.jupiter.engine.descriptor.ClassTemplateInvocationTestDescriptor", - "org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor", - "org.junit.jupiter.engine.descriptor.DynamicDescendantFilter\$Mode", - "org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector\$1", - "org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor\$MethodInfo", - "org.junit.jupiter.engine.discovery.ClassSelectorResolver\$DummyClassTemplateInvocationContext", - "org.junit.platform.launcher.core.DiscoveryIssueNotifier", - "org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider", - "org.junit.platform.launcher.core.LauncherDiscoveryResult\$EngineResultInfo", - "org.junit.platform.suite.engine.SuiteTestDescriptor\$LifecycleMethods", +val initializeAtBuildTime = mapOf( + // These will be part of the next version of native-build-tools + // see https://github.com/graalvm/native-build-tools/pull/693 + "5.13" to listOf( + "org.junit.jupiter.api.DisplayNameGenerator\$IndicativeSentences", + "org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor\$ClassInfo", + "org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor\$LifecycleMethods", + "org.junit.jupiter.engine.descriptor.ClassTemplateInvocationTestDescriptor", + "org.junit.jupiter.engine.descriptor.ClassTemplateTestDescriptor", + "org.junit.jupiter.engine.descriptor.DynamicDescendantFilter\$Mode", + "org.junit.jupiter.engine.descriptor.ExclusiveResourceCollector\$1", + "org.junit.jupiter.engine.descriptor.MethodBasedTestDescriptor\$MethodInfo", + "org.junit.jupiter.engine.discovery.ClassSelectorResolver\$DummyClassTemplateInvocationContext", + "org.junit.platform.engine.support.store.NamespacedHierarchicalStore\$EvaluatedValue", + "org.junit.platform.launcher.core.DiscoveryIssueNotifier", + "org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider", + "org.junit.platform.launcher.core.LauncherDiscoveryResult\$EngineResultInfo", + "org.junit.platform.suite.engine.SuiteTestDescriptor\$LifecycleMethods", + ), + // These need to be added to native-build-tools + "6.0" to listOf( + "org.junit.platform.commons.util.KotlinReflectionUtils", + "org.junit.platform.launcher.core.LauncherPhase", + ) ) graalvmNative { binaries { named("test") { - buildArgs.add("--strict-image-heap") buildArgs.add("-H:+ReportExceptionStackTraces") - buildArgs.add("--initialize-at-build-time=${initializeAtBuildTime.joinToString(",")}") + buildArgs.add("--initialize-at-build-time=${initializeAtBuildTime.values.flatten().joinToString(",")}") } } } diff --git a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts index 0b5bc3f36576..3a946457a66f 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts @@ -6,6 +6,11 @@ pluginManagement { repositories { mavenCentral() gradlePluginPortal() + maven(url = "https://raw.githubusercontent.com/graalvm/native-build-tools/snapshots") { + mavenContent { + snapshotsOnly() + } + } } } @@ -13,4 +18,18 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" } +dependencyResolutionManagement { + repositories { + repositories { + maven { url = uri(file(System.getProperty("maven.repo"))) } + mavenCentral() + maven(url = "https://raw.githubusercontent.com/graalvm/native-build-tools/snapshots") { + mavenContent { + snapshotsOnly() + } + } + } + } +} + rootProject.name = "graalvm-starter" From b6636bbf107220927e289dca7145bf8f3dfa97d7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 15:25:24 +0200 Subject: [PATCH 169/521] Move `LauncherPhase` to 5.13 list --- .../projects/graalvm-starter/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index f37170d70e74..fc5e3c8a2433 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -44,12 +44,12 @@ val initializeAtBuildTime = mapOf( "org.junit.platform.launcher.core.DiscoveryIssueNotifier", "org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider", "org.junit.platform.launcher.core.LauncherDiscoveryResult\$EngineResultInfo", + "org.junit.platform.launcher.core.LauncherPhase", "org.junit.platform.suite.engine.SuiteTestDescriptor\$LifecycleMethods", ), // These need to be added to native-build-tools "6.0" to listOf( "org.junit.platform.commons.util.KotlinReflectionUtils", - "org.junit.platform.launcher.core.LauncherPhase", ) ) From 67c357c578cfbb0bbce2980e39d69ae4754d7342 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 15:36:51 +0200 Subject: [PATCH 170/521] Test against snapshot version of native-build-tools In order to catch classes missing after the refactoring --- .../projects/graalvm-starter/settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts index 3a946457a66f..6a59f78e05fd 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts @@ -1,7 +1,7 @@ pluginManagement { plugins { // TODO Remove custom config in build.gradle.kts when upgrading - id("org.graalvm.buildtools.native") version "0.10.6" + id("org.graalvm.buildtools.native") version "0.11.0-SNAPSHOT" } repositories { mavenCentral() From f8ae3397383399f4f1297db1525daa7c20697f66 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 15:37:11 +0200 Subject: [PATCH 171/521] Add two missing classes from junit-platform-suite-engine --- .../projects/graalvm-starter/build.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index fc5e3c8a2433..09fe0465d37a 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -45,6 +45,8 @@ val initializeAtBuildTime = mapOf( "org.junit.platform.launcher.core.HierarchicalOutputDirectoryProvider", "org.junit.platform.launcher.core.LauncherDiscoveryResult\$EngineResultInfo", "org.junit.platform.launcher.core.LauncherPhase", + "org.junit.platform.suite.engine.DiscoverySelectorResolver", + "org.junit.platform.suite.engine.SuiteTestDescriptor\$DiscoveryIssueForwardingListener", "org.junit.platform.suite.engine.SuiteTestDescriptor\$LifecycleMethods", ), // These need to be added to native-build-tools From 9cdf394e02e2eec5dbe15294577a7ec1be181ec8 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 26 May 2025 18:06:00 +0200 Subject: [PATCH 172/521] Tweak generated Eclipse settings * Remove `module-info.java` from its source folders * Compile using the classpath only --- .../junitbuild.java-library-conventions.gradle.kts | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 63bf6e8eb36b..c28eff9f26e9 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 @@ -4,6 +4,7 @@ import junitbuild.extensions.isSnapshot import org.gradle.plugins.ide.eclipse.model.Classpath import org.gradle.plugins.ide.eclipse.model.Library import org.gradle.plugins.ide.eclipse.model.ProjectDependency +import org.gradle.plugins.ide.eclipse.model.SourceFolder plugins { `java-library` @@ -51,6 +52,15 @@ eclipse { // Java Template Engine (JTE) which is used to generate the JRE enum and // dependent tests. entries.removeIf { it is ProjectDependency && it.path.equals("/code-generator-model") } + entries.filterIsInstance().forEach { + it.excludes.add("**/module-info.java") + } + entries.filterIsInstance().forEach { + it.entryAttributes.remove("module") + } + entries.filterIsInstance().forEach { + it.entryAttributes.remove("module") + } } } From 3d74a06879fd97ab91f287c74f8e4ea21e36a9ca Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Mon, 26 May 2025 18:18:51 +0200 Subject: [PATCH 173/521] Update links to Maven Central and GitHub Discussions Co-authored-by: Marc Philipp --- README.md | 15 +++++---------- .../src/docs/asciidoc/link-attributes.adoc | 4 ++-- .../src/docs/asciidoc/user-guide/appendix.adoc | 11 ++++++++--- .../src/docs/asciidoc/user-guide/overview.adoc | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 20fce47b68be..3f1c7842bbc4 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ label are specifically targeted for community contributions. ## Getting Help -Ask JUnit-related questions on [StackOverflow] or chat with the community on [Gitter]. +Ask JUnit-related questions on [StackOverflow] or use the Q&A category on [GitHub Discussions]. ## Continuous Integration Builds @@ -73,14 +73,12 @@ task outputs from previous CI builds. You need [JDK 21] to build JUnit. [Gradle toolchains] are used to detect and potentially download additional JDKs for compilation and test execution. -All modules can be _built_ and _tested_ with the [Gradle Wrapper] using the following command. +All modules can be _built_ and _tested_ with the [Gradle Wrapper] using the following command: `./gradlew build` -## Installing in Local Maven Repository - -All modules can be _installed_ with the [Gradle Wrapper] in a local Maven repository for -consumption in other projects via the following command. +All modules can be _installed_ in a local Maven repository for consumption in other local +projects via the following command: `./gradlew publishToMavenLocal` @@ -93,14 +91,11 @@ consumption in other projects via the following command. Consult the [Dependency Metadata] section of the [User Guide] for a list of all artifacts of the JUnit Platform, JUnit Jupiter, and JUnit Vintage. -See also for releases and - for snapshots. - [Codecov]: https://codecov.io/gh/junit-team/junit5 [CONTRIBUTING.md]: https://github.com/junit-team/junit5/blob/HEAD/CONTRIBUTING.md [Dependency Metadata]: https://junit.org/junit5/docs/current/user-guide/#dependency-metadata -[Gitter]: https://gitter.im/junit-team/junit5 +[GitHub Discussions]: https://github.com/junit-team/junit5/discussions/categories/q-a [Gradle toolchains]: https://docs.gradle.org/current/userguide/toolchains.html [Gradle Wrapper]: https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:using_wrapper [JaCoCo]: https://www.eclemma.org/jacoco/ diff --git a/documentation/src/docs/asciidoc/link-attributes.adoc b/documentation/src/docs/asciidoc/link-attributes.adoc index 1ff758f67003..049c6980fe1b 100644 --- a/documentation/src/docs/asciidoc/link-attributes.adoc +++ b/documentation/src/docs/asciidoc/link-attributes.adoc @@ -3,7 +3,7 @@ ifdef::backend-pdf[] :javadoc-root: https://junit.org/junit5/docs/{docs-version}/api endif::[] // Snapshot Repository -:snapshot-repo: https://central.sonatype.com/repository/maven-snapshots +:snapshot-repo: https://central.sonatype.com/service/rest/repository/browse/maven-snapshots // Base Links :junit-team: https://github.com/junit-team :junit5-repo: {junit-team}/junit5 @@ -238,7 +238,7 @@ endif::[] :API: https://apiguardian-team.github.io/apiguardian/docs/current/api/[@API] :API_Guardian: https://github.com/apiguardian-team/apiguardian[@API Guardian] :AssertJ: https://assertj.github.io/doc/[AssertJ] -:Gitter: https://gitter.im/junit-team/junit5[Gitter] +:DiscussionsQA: https://github.com/junit-team/junit5/discussions/categories/q-a[Q&A category on GitHub Discussions] :Hamcrest: https://hamcrest.org/JavaHamcrest/[Hamcrest] :Jimfs: https://google.github.io/jimfs/[Jimfs] :Log4j: https://logging.apache.org/log4j/2.x/[Log4j] diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index b31e6a379eae..ef8c60dd4385 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -17,9 +17,14 @@ artifacts in the repositories were actually generated from this source code. [[dependency-metadata]] === Dependency Metadata -Artifacts for final releases and milestones are deployed to {Maven_Central}, and snapshot -artifacts are deployed to Sonatype's {snapshot-repo}[snapshots repository] under -{snapshot-repo}/org/junit/[/org/junit]. +Artifacts for final releases and milestones are deployed to {Maven_Central}. Consult +https://central.sonatype.org/consume/[Sonatype's documentation] for how to consume those +artifacts with a build tool of your choice. + +Snapshot artifacts are deployed to Sonatype's {snapshot-repo}[snapshots repository] +under {snapshot-repo}/org/junit/[/org/junit]. Please refer to +https://central.sonatype.org/publish/publish-portal-snapshots/#consuming-snapshot-releases-for-your-project[Sonatype's documentation] +for instructions on how to consume them with a build tool of your choice. The sections below list all artifacts with their versions for the three groups: <>, diff --git a/documentation/src/docs/asciidoc/user-guide/overview.adoc b/documentation/src/docs/asciidoc/user-guide/overview.adoc index a366b0b4e972..49a8429304c0 100644 --- a/documentation/src/docs/asciidoc/user-guide/overview.adoc +++ b/documentation/src/docs/asciidoc/user-guide/overview.adoc @@ -47,7 +47,7 @@ has been compiled with previous versions of the JDK. [[overview-getting-help]] === Getting Help -Ask JUnit-related questions on {StackOverflow} or chat with the community on {Gitter}. +Ask JUnit-related questions on {StackOverflow} or use the {DiscussionsQA}. [[overview-getting-started]] === Getting Started From a41c2c113a2da942cc0d7beaa2918da4696be9e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 03:59:20 +0000 Subject: [PATCH 174/521] Update dependency com.sonofab1rd:univocity-parsers to v2.10.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9e629f71513f..1ba898e0fc64 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -71,7 +71,7 @@ slf4j-julBinding = { module = "org.slf4j:slf4j-jdk14", version = "2.0.17" } snapshotTests-junit5 = { module = "de.skuzzle.test:snapshot-tests-junit5", version.ref = "snapshotTests" } snapshotTests-xml = { module = "de.skuzzle.test:snapshot-tests-xml", version.ref = "snapshotTests" } spock1 = { module = "org.spockframework:spock-core", version = "1.3-groovy-2.5" } -univocity-parsers = { module = "com.sonofab1rd:univocity-parsers", version = "2.10.1" } +univocity-parsers = { module = "com.sonofab1rd:univocity-parsers", version = "2.10.2" } xmlunit-assertj = { module = "org.xmlunit:xmlunit-assertj3", version.ref = "xmlunit" } xmlunit-placeholders = { module = "org.xmlunit:xmlunit-placeholders", version.ref = "xmlunit" } testingAnnotations = { module = "com.gradle:develocity-testing-annotations", version = "2.0.1" } From e886149a723ba7533d4e7b8ca1a767a77942c277 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 May 2025 09:17:32 +0200 Subject: [PATCH 175/521] Make dependency on open-test-reporting-tooling-spi non-optional Since the module descriptor requires it, it cannot be optional but must be a regular dependency. Otherwise, using junit-platform-reporting on the module path will fail. --- junit-platform-reporting/junit-platform-reporting.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junit-platform-reporting/junit-platform-reporting.gradle.kts b/junit-platform-reporting/junit-platform-reporting.gradle.kts index 81f6274eb72a..5bc26173b981 100644 --- a/junit-platform-reporting/junit-platform-reporting.gradle.kts +++ b/junit-platform-reporting/junit-platform-reporting.gradle.kts @@ -13,11 +13,11 @@ dependencies { api(platform(projects.junitBom)) api(projects.junitPlatformLauncher) + implementation(libs.openTestReporting.tooling.spi) + compileOnlyApi(libs.apiguardian) compileOnly(libs.jspecify) - compileOnlyApi(libs.openTestReporting.tooling.spi) - shadowed(libs.openTestReporting.events) osgiVerification(projects.junitJupiterEngine) From cbb95ecfe9914fcb563c931febd924bb7717c9bb Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 May 2025 09:17:59 +0200 Subject: [PATCH 176/521] Remove junit-platform-reporting from `reflection-tests` --- .../projects/reflection-tests/build.gradle.kts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts index 38982a672139..c1eff1a2aa88 100644 --- a/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts +++ b/platform-tooling-support-tests/projects/reflection-tests/build.gradle.kts @@ -12,7 +12,7 @@ repositories { dependencies { testImplementation("org.junit.jupiter:junit-jupiter:$junitVersion") testImplementation("org.junit.jupiter:junit-jupiter-engine:$junitVersion") - testRuntimeOnly("org.junit.platform:junit-platform-reporting:$junitVersion") + testRuntimeOnly("org.junit.platform:junit-platform-launcher:$junitVersion") } java { @@ -31,12 +31,4 @@ tasks.test { reports { html.required = true } - - val outputDir = reports.junitXml.outputLocation - jvmArgumentProviders += CommandLineArgumentProvider { - listOf( - "-Djunit.platform.reporting.open.xml.enabled=true", - "-Djunit.platform.reporting.output.dir=${outputDir.get().asFile.absolutePath}" - ) - } } From 3f3f809dd03eb78f6ea6e4b9c3d28dfc86cf82ba Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 May 2025 09:18:41 +0200 Subject: [PATCH 177/521] Enable `jupiter-starter` to configure open-test-reporting snapshots --- .../projects/graalvm-starter/settings.gradle.kts | 6 ++++++ .../projects/jupiter-starter/build.gradle.kts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts index 6a59f78e05fd..f0890183d0f2 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts @@ -28,6 +28,12 @@ dependencyResolutionManagement { snapshotsOnly() } } + maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { + mavenContent { + snapshotsOnly() + includeGroup("org.opentest4j.reporting") + } + } } } } diff --git a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts index 2714c5c41b51..3a43729855f2 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts @@ -7,6 +7,12 @@ val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() + maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { + mavenContent { + snapshotsOnly() + includeGroup("org.opentest4j.reporting") + } + } } dependencies { From af1242ea9ef353ab83ad5f21ca6721afe808bb04 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 May 2025 09:04:38 +0200 Subject: [PATCH 178/521] Force Gradle to update snapshots --- .../platform/tooling/support/tests/GraalVmStarterTests.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java index e74c1400bd9c..560ec627068e 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java @@ -50,7 +50,7 @@ void runsTestsInNativeImage(@TempDir Path workspace, @FilePrefix("gradle") Outpu graalVmHome.orElseThrow(TestAbortedException::new).toString()).addArguments( "-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("javaToolchains", "nativeTest", "--no-daemon", "--stacktrace", "--no-build-cache", - "--warning-mode=fail") // + "--warning-mode=fail", "--refresh-dependencies") // .redirectOutput(outputFiles) // .startAndWait(); From 3a1a69c00496561a1079f80b50ecbf96b6ee7725 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 07:39:15 +0000 Subject: [PATCH 179/521] Update dependency org.apache.groovy:groovy to v4.0.27 (#4585) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 1ba898e0fc64..823093524d99 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -36,7 +36,7 @@ checkstyle = { module = "com.puppycrawl.tools:checkstyle", version.ref = "checks classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.179" } commons-io = { module = "commons-io:commons-io", version = "2.19.0" } errorProne-core = { module = "com.google.errorprone:error_prone_core", version = "2.38.0" } -groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.26" } +groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.27" } groovy2-bom = { module = "org.codehaus.groovy:groovy-bom", version = "2.5.23" } hamcrest = { module = "org.hamcrest:hamcrest", version = "3.0" } jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" } From a2af0d91b2771a280512a96987b2842691729974 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 27 May 2025 14:06:16 +0200 Subject: [PATCH 180/521] Update Kotlin to 2.2.0-RC (#4588) --- .../docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 3 ++- gradle/libs.versions.toml | 2 +- .../projects/gradle-kotlin-extensions/build.gradle.kts | 2 +- .../projects/kotlin-coroutines/build.gradle.kts | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 29966c74f2c9..626753edd77e 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -21,7 +21,8 @@ repository on GitHub. [[release-notes-6.0.0-M1-overall-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes -* Minimum required Java version is now Java 17. +* Minimum required Java version is now 17. +* Minimum required Kotlin version is now 2.2. * Platform, Jupiter, and Vintage artifacts now use the same version number. [[release-notes-6.0.0-M1-overall-new-features-and-improvements]] diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 823093524d99..7c21c338bb90 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -105,7 +105,7 @@ gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating -kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.1.21" } +kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC" } nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 539c5f9b0b22..76d33e06b27d 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 plugins { - kotlin("jvm") version "2.1.21" + kotlin("jvm") version "2.2.0-RC" } repositories { diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts index 2639b23567a5..64410c4e7759 100644 --- a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.1.21" + kotlin("jvm") version "2.2.0-RC" } val junitVersion: String by project From fa3c065741593123d359bcd20c81067301a5021b Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 27 May 2025 15:40:47 +0200 Subject: [PATCH 181/521] Fix console launcher's `--uid` option (#4589) Prior to this commit, unique id selectors weren't included in the list of explicit selectors - which resulted a false error message: ``` Please specify an explicit selector option or use `--scan-class-path` or `--scan-modules` ``` Fixes #4587 --------- Co-authored-by: Marc Philipp --- .../release-notes/release-notes-5.13.0.adoc | 1 + .../asciidoc/user-guide/running-tests.adoc | 2 +- .../console/options/TestDiscoveryOptions.java | 1 + .../tasks/DiscoveryRequestCreatorTests.java | 18 ++++++++++++++++++ 4 files changed, 21 insertions(+), 1 deletion(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index 35cb9c69ed32..35efebf70ac0 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -52,6 +52,7 @@ repository on GitHub. the `ConsoleLauncher`. Prior to this release, the created class loader was closed prior to JVM shutdown hooks being invoked, which caused hooks to fail with a `ClassNotFoundException` when loading classes during shutdown. +* Fix support of `--uid` and `--select-unique-id` options in the console launcher. [[release-notes-5.13.0-junit-platform-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes diff --git a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc index b548c880af08..884929e15237 100644 --- a/documentation/src/docs/asciidoc/user-guide/running-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/running-tests.adoc @@ -861,7 +861,7 @@ The following discovery selectors are provided out of the box: | `{NestedClassSelector}` | `{DiscoverySelectors_selectNestedClass}` | `{Select}("")` | `--select ` | `nested-class:com.acme.Foo/Bar` | `{NestedMethodSelector}` | `{DiscoverySelectors_selectNestedMethod}` | `{Select}("")` | `--select ` | `nested-method:com.acme.Foo/Bar#m` | `{PackageSelector}` | `{DiscoverySelectors_selectPackage}` | `{SelectPackages}` | `--select-package com.acme.foo` | `package:com.acme.foo` -| `{UniqueIdSelector}` | `{DiscoverySelectors_selectUniqueId}` | `{Select}("")` | `--select ` | `uid:...` +| `{UniqueIdSelector}` | `{DiscoverySelectors_selectUniqueId}` | `{Select}("")` | `--select-unique-id ` | `uid:[engine:Foo]/[segment:Bar]` | `{UriSelector}` | `{DiscoverySelectors_selectUri}` | `{SelectUris}` | `--select-uri \file:///foo.txt` | `uri:file:///foo.txt` |=== diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java index bd1ede77223b..93e9a77d3366 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java @@ -204,6 +204,7 @@ public void setSelectorIdentifiers(List selectorIde public List getExplicitSelectors() { List selectors = new ArrayList<>(); + selectors.addAll(getSelectedUniqueIds()); selectors.addAll(getSelectedUris()); selectors.addAll(getSelectedFiles()); selectors.addAll(getSelectedDirectories()); diff --git a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java index 2c238614bce1..fdef039fe467 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/console/tasks/DiscoveryRequestCreatorTests.java @@ -22,6 +22,7 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectPackage; +import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUniqueId; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectUri; import java.io.File; @@ -36,6 +37,7 @@ import org.junit.platform.commons.PreconditionViolationException; import org.junit.platform.console.options.TestDiscoveryOptions; import org.junit.platform.engine.Filter; +import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.discovery.ClassNameFilter; import org.junit.platform.engine.discovery.ClassSelector; import org.junit.platform.engine.discovery.ClasspathResourceSelector; @@ -46,6 +48,7 @@ import org.junit.platform.engine.discovery.MethodSelector; import org.junit.platform.engine.discovery.PackageNameFilter; import org.junit.platform.engine.discovery.PackageSelector; +import org.junit.platform.engine.discovery.UniqueIdSelector; import org.junit.platform.engine.discovery.UriSelector; import org.junit.platform.launcher.LauncherDiscoveryRequest; @@ -218,6 +221,21 @@ void convertsEngineOptions() { assertThat(engineFilters.get(1).toString()).contains("excludes", "[engine2]"); } + @Test + void propagatesUniqueIdSelectors() { + options.setSelectedUniqueId(List.of(selectUniqueId("[engine:a]/[1:1]"), selectUniqueId("[engine:b]/[2:2]"))); + + var request = convert(); + var uriSelectors = request.getSelectorsByType(UniqueIdSelector.class); + + assertThat(uriSelectors) // + .extracting(UniqueIdSelector::getUniqueId) // + .containsExactly( // + UniqueId.parse("[engine:a]/[1:1]"), //, // + UniqueId.parse("[engine:b]/[2:2]") // + ); + } + @Test void propagatesUriSelectors() { options.setSelectedUris(List.of(selectUri("a"), selectUri("b"))); From e20bd038b95ca362cb288052c8964063c244b5d8 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Tue, 27 May 2025 19:13:52 +0200 Subject: [PATCH 182/521] Move examples from java21 to standard java source folder --- .../test/{java21 => java}/example/DynamicTestsNamedDemo.java | 0 .../example/MyFirstJUnitJupiterRecordTests.java | 0 .../{java21 => java}/example/ParameterizedLifecycleDemo.java | 0 .../{java21 => java}/example/ParameterizedRecordDemo.java | 0 documentation/src/test/java21/example/package-info.java | 5 ----- 5 files changed, 5 deletions(-) rename documentation/src/test/{java21 => java}/example/DynamicTestsNamedDemo.java (100%) rename documentation/src/test/{java21 => java}/example/MyFirstJUnitJupiterRecordTests.java (100%) rename documentation/src/test/{java21 => java}/example/ParameterizedLifecycleDemo.java (100%) rename documentation/src/test/{java21 => java}/example/ParameterizedRecordDemo.java (100%) delete mode 100644 documentation/src/test/java21/example/package-info.java diff --git a/documentation/src/test/java21/example/DynamicTestsNamedDemo.java b/documentation/src/test/java/example/DynamicTestsNamedDemo.java similarity index 100% rename from documentation/src/test/java21/example/DynamicTestsNamedDemo.java rename to documentation/src/test/java/example/DynamicTestsNamedDemo.java diff --git a/documentation/src/test/java21/example/MyFirstJUnitJupiterRecordTests.java b/documentation/src/test/java/example/MyFirstJUnitJupiterRecordTests.java similarity index 100% rename from documentation/src/test/java21/example/MyFirstJUnitJupiterRecordTests.java rename to documentation/src/test/java/example/MyFirstJUnitJupiterRecordTests.java diff --git a/documentation/src/test/java21/example/ParameterizedLifecycleDemo.java b/documentation/src/test/java/example/ParameterizedLifecycleDemo.java similarity index 100% rename from documentation/src/test/java21/example/ParameterizedLifecycleDemo.java rename to documentation/src/test/java/example/ParameterizedLifecycleDemo.java diff --git a/documentation/src/test/java21/example/ParameterizedRecordDemo.java b/documentation/src/test/java/example/ParameterizedRecordDemo.java similarity index 100% rename from documentation/src/test/java21/example/ParameterizedRecordDemo.java rename to documentation/src/test/java/example/ParameterizedRecordDemo.java diff --git a/documentation/src/test/java21/example/package-info.java b/documentation/src/test/java21/example/package-info.java deleted file mode 100644 index a2bcf4a4db17..000000000000 --- a/documentation/src/test/java21/example/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ - -@NullMarked -package example; - -import org.jspecify.annotations.NullMarked; From 7137ba7f2ef6a5f3503cd824acac063f59a11603 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Tue, 27 May 2025 19:14:46 +0200 Subject: [PATCH 183/521] Clean up warnings --- documentation/src/test/java/example/DynamicTestsDemo.java | 2 +- .../support/conversion/StringToCommonJavaTypesConverter.java | 1 + .../jupiter/engine/descriptor/ResourceAutoClosingTests.java | 4 ++++ .../org/junit/platform/commons/util/CollectionUtilsTests.java | 2 +- 4 files changed, 7 insertions(+), 2 deletions(-) diff --git a/documentation/src/test/java/example/DynamicTestsDemo.java b/documentation/src/test/java/example/DynamicTestsDemo.java index f6adb6b2117b..547a3e122174 100644 --- a/documentation/src/test/java/example/DynamicTestsDemo.java +++ b/documentation/src/test/java/example/DynamicTestsDemo.java @@ -103,7 +103,7 @@ Stream generateRandomNumberOfTests() { // Generates random positive integers between 0 and 100 until // a number evenly divisible by 7 is encountered. - Iterator inputGenerator = new Iterator() { + Iterator inputGenerator = new Iterator<>() { Random random = new Random(); // end::user_guide[] diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java index 5d0d3db7fd3b..7eb2bd31bd16 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/StringToCommonJavaTypesConverter.java @@ -27,6 +27,7 @@ class StringToCommonJavaTypesConverter implements StringToObjectConverter { + @SuppressWarnings("deprecation") private static final Map, Function> CONVERTERS = Map.of( // // java.io and java.nio File.class, File::new, // diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java index 717c40b9e5f6..86bc5ffa08f3 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ResourceAutoClosingTests.java @@ -35,6 +35,7 @@ class ResourceAutoClosingTests { NamespacedHierarchicalStoreProviders.dummyNamespacedHierarchicalStore()); @Test + @SuppressWarnings("resource") void shouldCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsTrue() throws Exception { AutoCloseableResource resource = new AutoCloseableResource(); when(configuration.isClosingStoredAutoCloseablesEnabled()).thenReturn(true); @@ -50,6 +51,7 @@ void shouldCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsTrue() th } @Test + @SuppressWarnings("resource") void shouldNotCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsFalse() throws Exception { AutoCloseableResource resource = new AutoCloseableResource(); when(configuration.isClosingStoredAutoCloseablesEnabled()).thenReturn(false); @@ -65,6 +67,7 @@ void shouldNotCloseAutoCloseableWhenIsClosingStoredAutoCloseablesEnabledIsFalse( } @Test + @SuppressWarnings("resource") void shouldLogWarningWhenResourceImplementsCloseableResourceButNotAutoCloseableAndConfigIsTrue( @TrackLogRecords LogRecordListener listener) throws Exception { ExecutionRecorder executionRecorder = new ExecutionRecorder(); @@ -84,6 +87,7 @@ void shouldLogWarningWhenResourceImplementsCloseableResourceButNotAutoCloseableA } @Test + @SuppressWarnings("resource") void shouldNotLogWarningWhenResourceImplementsCloseableResourceAndAutoCloseableAndConfigIsFalse( @TrackLogRecords LogRecordListener listener) throws Exception { ExecutionRecorder executionRecorder = new ExecutionRecorder(); diff --git a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java index 6c11ca4a55b7..b6b5780c1e41 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/util/CollectionUtilsTests.java @@ -240,7 +240,7 @@ void toStreamWithLongStream() { } @Test - @SuppressWarnings({ "unchecked" }) + @SuppressWarnings({ "unchecked", "serial" }) void toStreamWithCollection() { var collectionStreamClosed = new AtomicBoolean(false); var input = new ArrayList<>(List.of("foo", "bar")) { From 9e1b7f86f0891b0688916a950eca6bcaea7b43d1 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Tue, 27 May 2025 19:15:06 +0200 Subject: [PATCH 184/521] Remove unused code --- .../launcher/core/ClasspathAlignmentChecker.java | 4 ---- .../jupiter/engine/descriptor/DisplayNameUtilsTests.java | 9 --------- 2 files changed, 13 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java index 108761077cd0..95eb68987e26 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/ClasspathAlignmentChecker.java @@ -87,8 +87,4 @@ static Optional check(LinkageError error, Function new AssertionError("Failed to find warning log record")); - } - @DisplayName("my-test-case\t") @DisplayNameGeneration(value = CustomDisplayNameGenerator.class) static class MyTestCase { void test1() { } - } @DisplayName("") From ded71c8d1b678e040fc8231189640af4299f6a8c Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Tue, 27 May 2025 19:15:32 +0200 Subject: [PATCH 185/521] Avoid use of Stream#toList() to support compilation in Eclipse IDE --- .../java/org/junit/platform/commons/util/ModuleUtils.java | 4 +++- .../junit/platform/engine/discovery/NestedClassSelector.java | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index 3538518cfa2b..e3bacea88c3c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -13,6 +13,7 @@ import static java.util.Objects.requireNonNull; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toCollection; +import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; @@ -227,7 +228,8 @@ List> scan(ModuleReference reference) { .filter(classFilter::match) .map(this::loadClassUnchecked) .filter(classFilter::match) - .toList(); + // We do not use Stream#toList() due to an issue with the Eclipse compiler. + .collect(toList()); // @formatter:on } } 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 31f48c893358..bde08e228967 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 @@ -11,6 +11,7 @@ package org.junit.platform.engine.discovery; 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.STABLE; @@ -101,7 +102,8 @@ public List getEnclosingClassNames() { * {@link PreconditionViolationException} if the classes cannot be loaded. */ public List> getEnclosingClasses() { - return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).toList(); + // We do not use Stream#toList() due to an issue with the Eclipse compiler. + return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).collect(toList()); } /** From 2b318913e9f02974db925ab75edfb515d575fa90 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 08:20:46 +0200 Subject: [PATCH 186/521] Remove remnants of `testRelease21` source set --- documentation/documentation.gradle.kts | 12 ------ .../asciidoc/user-guide/writing-tests.adoc | 9 ++-- ...java-multi-release-test-sources.gradle.kts | 42 ------------------- 3 files changed, 4 insertions(+), 59 deletions(-) delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-test-sources.gradle.kts diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 2c34e5fda5e5..fffaa8355287 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -17,7 +17,6 @@ plugins { alias(libs.plugins.gitPublish) alias(libs.plugins.plantuml) id("junitbuild.build-parameters") - id("junitbuild.java-multi-release-test-sources") id("junitbuild.java-nullability-conventions") id("junitbuild.kotlin-library-conventions") id("junitbuild.testing-conventions") @@ -206,10 +205,6 @@ tasks { } } - testRelease21 { - include("**/*Demo.class") - } - check { dependsOn(consoleLauncherTest) } @@ -343,13 +338,6 @@ tasks { inputs.dir(kotlin.srcDirs.first()) } - sourceSets["testRelease21"].apply { - attributes(mapOf( - "testRelease21Dir" to java.srcDirs.first() - )) - inputs.dir(java.srcDirs.first()) - } - jvm { // To avoid warning, see https://github.com/asciidoctor/asciidoctor-gradle-plugin/issues/597 jvmArgs( diff --git a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc index 8971ad0b4996..41555bc48620 100644 --- a/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc +++ b/documentation/src/docs/asciidoc/user-guide/writing-tests.adoc @@ -1,6 +1,5 @@ :testDir: ../../../../src/test/java :testResourcesDir: ../../../../src/test/resources -:testRelease21Dir: ../../../../src/test/java21 :kotlinTestDir: ../../../../src/test/kotlin [[writing-tests]] @@ -282,7 +281,7 @@ following example. [source,java,indent=0] .A test class written as a Java record ---- -include::{testRelease21Dir}/example/MyFirstJUnitJupiterRecordTests.java[tags=user_guide] +include::{testDir}/example/MyFirstJUnitJupiterRecordTests.java[tags=user_guide] ---- Test and lifecycle methods may be written in Kotlin and may optionally use the `suspend` @@ -1719,7 +1718,7 @@ boilerplate code of declaring a test class constructor. [source,java,indent=0] ---- -include::{testRelease21Dir}/example/ParameterizedRecordDemo.java[tags=example] +include::{testDir}/example/ParameterizedRecordDemo.java[tags=example] ---- [[writing-tests-parameterized-tests-consuming-arguments-field-injection]] @@ -2831,7 +2830,7 @@ by the following example. [source,java,indent=0] .Using parameterized class lifecycle methods ---- -include::{testRelease21Dir}/example/ParameterizedLifecycleDemo.java[tags=example] +include::{testDir}/example/ParameterizedLifecycleDemo.java[tags=example] ---- <1> Initialization of the argument _before_ each invocation of the parameterized class <2> Usage of the previously initialized argument in a test method @@ -2962,7 +2961,7 @@ interface along with `Named` via the `NamedExecutable` base class. [source,java] ---- -include::{testRelease21Dir}/example/DynamicTestsNamedDemo.java[tags=user_guide] +include::{testDir}/example/DynamicTestsNamedDemo.java[tags=user_guide] ---- [[writing-tests-dynamic-tests-uri-test-source]] diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-test-sources.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-test-sources.gradle.kts deleted file mode 100644 index 4dd191dbe0b0..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-multi-release-test-sources.gradle.kts +++ /dev/null @@ -1,42 +0,0 @@ -import junitbuild.extensions.capitalized - -plugins { - id("junitbuild.java-library-conventions") -} - -listOf(21).forEach { javaVersion -> - val sourceSet = sourceSets.register("testRelease${javaVersion}") { - compileClasspath += sourceSets.main.get().output - runtimeClasspath += sourceSets.main.get().output - java { - setSrcDirs(setOf("src/test/java${javaVersion}")) - } - } - - configurations { - named(sourceSet.get().compileClasspathConfigurationName).configure { - extendsFrom(configurations.testCompileClasspath.get()) - } - named(sourceSet.get().runtimeClasspathConfigurationName).configure { - extendsFrom(configurations.testRuntimeClasspath.get()) - } - } - - tasks { - val testTask = register("testRelease${javaVersion}") { - group = "verification" - description = "Runs the tests for Java ${javaVersion}" - testClassesDirs = sourceSet.get().output.classesDirs - classpath = sourceSet.get().runtimeClasspath - } - check { - dependsOn(testTask) - } - named(sourceSet.get().compileJavaTaskName).configure { - options.release = javaVersion - } - named("checkstyle${sourceSet.name.capitalized()}").configure { - config = resources.text.fromFile(checkstyle.configDirectory.file("checkstyleTest.xml")) - } - } -} From b8f3097eeb1f9ec562c09b3221d725e57f5fcab0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 06:32:23 +0000 Subject: [PATCH 187/521] Update plugin develocity to v4.0.2 (#4590) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c21c338bb90..955cadcfdd43 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -97,7 +97,7 @@ asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor-pl bnd = { id = "biz.aQute.bnd", version.ref = "bnd" } buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" } commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" } -develocity = { id = "com.gradle.develocity", version = "4.0.1" } +develocity = { id = "com.gradle.develocity", version = "4.0.2" } errorProne = { id = "net.ltgt.errorprone", version = "4.2.0" } extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" } foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "1.0.0" } From d4c2ea6e6dc1e745ce2e4b77768a61058d993302 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 08:29:39 +0200 Subject: [PATCH 188/521] Restore `Stream#toList()` by adding explicit type arguments for Eclipse --- .../java/org/junit/platform/commons/util/ModuleUtils.java | 6 ++---- .../platform/engine/discovery/NestedClassSelector.java | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java index e3bacea88c3c..40208636bd4c 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/ModuleUtils.java @@ -13,7 +13,6 @@ import static java.util.Objects.requireNonNull; import static java.util.function.Predicate.isEqual; import static java.util.stream.Collectors.toCollection; -import static java.util.stream.Collectors.toList; import static java.util.stream.Collectors.toSet; import static org.apiguardian.api.API.Status.INTERNAL; @@ -226,10 +225,9 @@ List> scan(ModuleReference reference) { .map(this::className) .filter(name -> !name.equals("module-info")) .filter(classFilter::match) - .map(this::loadClassUnchecked) + .> map(this::loadClassUnchecked) .filter(classFilter::match) - // We do not use Stream#toList() due to an issue with the Eclipse compiler. - .collect(toList()); + .toList(); // @formatter:on } } 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 bde08e228967..aa3f340df281 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 @@ -11,7 +11,6 @@ package org.junit.platform.engine.discovery; 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.STABLE; @@ -102,8 +101,7 @@ public List getEnclosingClassNames() { * {@link PreconditionViolationException} if the classes cannot be loaded. */ public List> getEnclosingClasses() { - // We do not use Stream#toList() due to an issue with the Eclipse compiler. - return this.enclosingClassSelectors.stream().map(ClassSelector::getJavaClass).collect(toList()); + return this.enclosingClassSelectors.stream().> map(ClassSelector::getJavaClass).toList(); } /** From 35742e5bb2ecf3232314d59ca6d94e6981c2f198 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 08:31:03 +0200 Subject: [PATCH 189/521] Remove duplicate `package-info.java` file showing as error in Eclipse --- .../test/java/example/registration/DocumentationDemo.java | 2 ++ .../src/test/java/example/registration/package-info.java | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) delete mode 100644 documentation/src/test/java/example/registration/package-info.java diff --git a/documentation/src/test/java/example/registration/DocumentationDemo.java b/documentation/src/test/java/example/registration/DocumentationDemo.java index 7512235d9dc3..36bc544a4e7a 100644 --- a/documentation/src/test/java/example/registration/DocumentationDemo.java +++ b/documentation/src/test/java/example/registration/DocumentationDemo.java @@ -12,6 +12,7 @@ import java.nio.file.Path; +import org.jspecify.annotations.NullMarked; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.AfterEachCallback; @@ -41,6 +42,7 @@ void generateDocumentation() { } //end::user_guide[] +@NullMarked class DocumentationExtension implements AfterEachCallback { @SuppressWarnings("unused") diff --git a/documentation/src/test/java/example/registration/package-info.java b/documentation/src/test/java/example/registration/package-info.java deleted file mode 100644 index ceb3eb919fc2..000000000000 --- a/documentation/src/test/java/example/registration/package-info.java +++ /dev/null @@ -1,5 +0,0 @@ - -@NullMarked -package example.registration; - -import org.jspecify.annotations.NullMarked; From bf1fe18138f21a6fda1c11faced0acddfca8f1cc Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 08:32:29 +0200 Subject: [PATCH 190/521] Make deserialization exception declarations consistent --- .../main/java/org/junit/platform/launcher/TestIdentifier.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index 4e96c47cb659..b5918cf6f365 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -332,7 +332,7 @@ private static class SerializedForm implements Serializable { } @SuppressWarnings("unchecked") - private SerializedForm(ObjectInputStream.GetField fields) throws IOException { + private SerializedForm(ObjectInputStream.GetField fields) throws IOException, ClassNotFoundException { this.uniqueId = (String) fields.get("uniqueId", null); this.parentId = (String) fields.get("parentId", null); this.displayName = (String) fields.get("displayName", null); @@ -354,7 +354,7 @@ void serialize(ObjectOutputStream s) throws IOException { s.writeFields(); } - static SerializedForm deserialize(ObjectInputStream s) throws ClassNotFoundException, IOException { + static SerializedForm deserialize(ObjectInputStream s) throws IOException, ClassNotFoundException { ObjectInputStream.GetField fields = s.readFields(); return new SerializedForm(fields); } From 438706cce5283edd3412b90608bdb06c442561a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 06:33:09 +0000 Subject: [PATCH 191/521] Update plugin spotless to v7.0.4 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 955cadcfdd43..bfb532add30c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -110,5 +110,5 @@ nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } -spotless = { id = "com.diffplug.spotless", version = "7.0.3" } +spotless = { id = "com.diffplug.spotless", version = "7.0.4" } versions = { id = "com.github.ben-manes.versions", version = "0.52.0" } From 3c0c32fad4b8e746408c09f74a75ca10dd6ff79b Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 10:49:49 +0200 Subject: [PATCH 192/521] Add Eclipse output folders to .gitignore --- gradle/base/code-generator-model/.gitignore | 1 + gradle/base/dsl-extensions/.gitignore | 1 + 2 files changed, 2 insertions(+) create mode 100644 gradle/base/code-generator-model/.gitignore create mode 100644 gradle/base/dsl-extensions/.gitignore diff --git a/gradle/base/code-generator-model/.gitignore b/gradle/base/code-generator-model/.gitignore new file mode 100644 index 000000000000..ae3c1726048c --- /dev/null +++ b/gradle/base/code-generator-model/.gitignore @@ -0,0 +1 @@ +/bin/ diff --git a/gradle/base/dsl-extensions/.gitignore b/gradle/base/dsl-extensions/.gitignore new file mode 100644 index 000000000000..ae3c1726048c --- /dev/null +++ b/gradle/base/dsl-extensions/.gitignore @@ -0,0 +1 @@ +/bin/ From f4ac7cc4996c3a690fa9c73d8930ebea3e89b660 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 10:52:04 +0200 Subject: [PATCH 193/521] Clean up warnings and polish --- .../descriptor/AbstractExtensionContext.java | 2 +- .../JupiterEngineExecutionContext.java | 2 +- .../engine/extension/AutoCloseExtension.java | 11 ++-- .../PreInterruptThreadDumpPrinter.java | 50 +++++++++---------- .../rules/TestRuleSupport.java | 2 +- 5 files changed, 34 insertions(+), 33 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index b35768ca74a6..a7aa5fe248c0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -95,7 +95,7 @@ private NamespacedHierarchicalStore.CloseAction { boolean isAutoCloseEnabled = this.configuration.isClosingStoredAutoCloseablesEnabled(); - if (value instanceof AutoCloseable closeable && isAutoCloseEnabled) { + if (value instanceof @SuppressWarnings("resource") AutoCloseable closeable && isAutoCloseEnabled) { closeable.close(); return; } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java index d09caed6ad1f..a70ae7c2d38d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/JupiterEngineExecutionContext.java @@ -47,7 +47,7 @@ private JupiterEngineExecutionContext(State state) { public void close() throws Exception { ExtensionContext extensionContext = getExtensionContext(); - if (extensionContext instanceof AutoCloseable closeable) { + if (extensionContext instanceof @SuppressWarnings("resource") AutoCloseable closeable) { try { closeable.close(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java index c3bf48d99ec9..17652eef18ef 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/AutoCloseExtension.java @@ -62,9 +62,10 @@ public void afterAll(ExtensionContext context) { private static void closeFields(Class testClass, @Nullable Object testInstance, ThrowableCollector throwableCollector) { + Predicate predicate = (testInstance == null ? ModifierSupport::isStatic : ModifierSupport::isNotStatic); - AnnotationSupport.findAnnotatedFields(testClass, AutoClose.class, predicate, BOTTOM_UP).forEach( - field -> throwableCollector.execute(() -> closeField(field, testInstance))); + AnnotationSupport.findAnnotatedFields(testClass, AutoClose.class, predicate, BOTTOM_UP)// + .forEach(field -> throwableCollector.execute(() -> closeField(field, testInstance))); } private static void closeField(Field field, @Nullable Object testInstance) throws Exception { @@ -86,7 +87,7 @@ private static void closeField(Field field, @Nullable Object testInstance) throw private static void invokeCloseMethod(Field field, Object target, String methodName) throws Exception { // Avoid reflection if we can directly invoke close() via AutoCloseable. - if (target instanceof AutoCloseable closeable && "close".equals(methodName)) { + if (target instanceof @SuppressWarnings("resource") AutoCloseable closeable && "close".equals(methodName)) { closeable.close(); return; } @@ -94,8 +95,8 @@ private static void invokeCloseMethod(Field field, Object target, String methodN Class targetType = target.getClass(); Method closeMethod = ReflectionSupport.findMethod(targetType, methodName).orElseThrow( () -> new ExtensionConfigurationException( - "Cannot @AutoClose field %s because %s does not define method %s().".formatted(getQualifiedName(field), - targetType.getName(), methodName))); + "Cannot @AutoClose field %s because %s does not define method %s()."// + .formatted(getQualifiedName(field), targetType.getName(), methodName))); closeMethod = ReflectionUtils.getInterfaceMethodIfPossible(closeMethod, targetType); ReflectionSupport.invokeMethod(closeMethod, target); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java index 40fa9e03e3bf..283710eb1f1e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/PreInterruptThreadDumpPrinter.java @@ -18,24 +18,23 @@ import org.junit.jupiter.engine.Constants; /** - * The default implementation for {@link PreInterruptCallback}, - * which will print the stacks of all {@link Thread}s to {@code System.out}. + * Default implementation of {@link PreInterruptCallback}, which prints the stacks + * of all {@link Thread}s to {@code System.out}. * - *

    Note: This is disabled by default, and must be enabled with - * {@link Constants#EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME} + *

    Note: This is disabled by default and must be enabled via + * {@link Constants#EXTENSIONS_TIMEOUT_THREAD_DUMP_ENABLED_PROPERTY_NAME}. * * @since 5.12 */ final class PreInterruptThreadDumpPrinter implements PreInterruptCallback { + private static final String NL = "\n"; @Override public void beforeThreadInterrupt(PreInterruptContext preInterruptContext, ExtensionContext extensionContext) { - Map stackTraces = Thread.getAllStackTraces(); - StringBuilder sb = new StringBuilder(); - sb.append("Thread "); + StringBuilder sb = new StringBuilder("Thread "); appendThreadName(sb, preInterruptContext.getThreadToInterrupt()); sb.append(" will be interrupted."); sb.append(NL); @@ -48,10 +47,9 @@ public void beforeThreadInterrupt(PreInterruptContext preInterruptContext, Exten appendThreadName(sb, thread); for (StackTraceElement stackTraceElement : stack) { sb.append(NL); - //Do the same prefix as java.lang.Throwable.printStackTrace(java.lang.Throwable.PrintStreamOrWriter) + // Use the same prefix as java.lang.Throwable.printStackTrace(PrintStreamOrWriter) sb.append("\tat "); sb.append(stackTraceElement.toString()); - } sb.append(NL); } @@ -61,23 +59,25 @@ public void beforeThreadInterrupt(PreInterruptContext preInterruptContext, Exten } /** - * Appends the {@link Thread} name and ID in a similar fashion as {@code jstack}. - * @param sb the buffer - * @param th the thread to append + * Append the {@link Thread} name and ID in a similar fashion as {@code jstack}. + * @param builder the builder to append to + * @param thread the thread whose information should be appended */ - private void appendThreadName(StringBuilder sb, Thread th) { - // Use same format as java.lang.management.ThreadInfo.toString - sb.append("\""); - sb.append(th.getName()); - sb.append("\""); - if (th.isDaemon()) { - sb.append(" daemon"); + @SuppressWarnings("deprecation") // Thread.getId() is deprecated on JDK 19+ + private static void appendThreadName(StringBuilder builder, Thread thread) { + // Use same format as java.lang.management.ThreadInfo.toString() + builder.append("\""); + builder.append(thread.getName()); + builder.append("\""); + if (thread.isDaemon()) { + builder.append(" daemon"); } - sb.append(" prio="); - sb.append(th.getPriority()); - sb.append(" Id="); - sb.append(th.getId()); - sb.append(" "); - sb.append(th.getState()); + builder.append(" prio="); + builder.append(thread.getPriority()); + builder.append(" Id="); + builder.append(thread.getId()); + builder.append(" "); + builder.append(thread.getState()); } + } diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java index a749d1f825a0..8ef8b97b8b61 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/TestRuleSupport.java @@ -147,7 +147,7 @@ private List getRuleAnnotatedMembers(ExtensionContext c Object testInstance = context.getRequiredTestInstance(); Namespace namespace = Namespace.create(TestRuleSupport.class, context.getRequiredTestClass()); // @formatter:off - return new ArrayList(requireNonNull(context.getStore(namespace) + return new ArrayList<>(requireNonNull(context.getStore(namespace) .getOrComputeIfAbsent("rule-annotated-members", key -> findRuleAnnotatedMembers(testInstance), List.class))); // @formatter:on } From a4f2f60f121de0d3c7bbd8075e727fc25b00b18f Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 11:07:05 +0200 Subject: [PATCH 194/521] Tweak Eclipse settings and disable test in platform-tests in Eclipse --- .../junitbuild.java-library-conventions.gradle.kts | 5 ++++- .../scanning/DefaultClasspathScannerTests.java | 13 +++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) 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 c28eff9f26e9..3801c5fe3a50 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 @@ -1,4 +1,3 @@ - import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar import junitbuild.extensions.isSnapshot import org.gradle.plugins.ide.eclipse.model.Classpath @@ -54,6 +53,10 @@ eclipse { entries.removeIf { it is ProjectDependency && it.path.equals("/code-generator-model") } entries.filterIsInstance().forEach { it.excludes.add("**/module-info.java") + if (project.name == "platform-tests" && it.path == "src/test/resources") { + // Exclude Foo.java and FooBar.java in the modules-2500 folder. + it.excludes.add("**/Foo*.java") + } } entries.filterIsInstance().forEach { it.entryAttributes.remove("module") 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 d407c2f0401c..c2515661ffe0 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 @@ -42,6 +42,7 @@ import java.util.spi.ToolProvider; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIf; import org.junit.jupiter.api.fixtures.TrackLogRecords; import org.junit.jupiter.api.io.TempDir; import org.junit.platform.commons.PreconditionViolationException; @@ -299,8 +300,8 @@ void scanForResourcesInPackage() { uriOf("/org/junit/platform/commons/other-example.resource")); } - @Test - // #2500 + @Test // #2500 + @DisabledIf("runningInEclipse") 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()); @@ -629,4 +630,12 @@ public Enumeration getResources(String name) throws IOException { } } + /** + * Determine if the current code is running in the Eclipse IDE. + */ + static boolean runningInEclipse() { + return StackWalker.getInstance().walk( + stream -> stream.anyMatch(stackFrame -> stackFrame.getClassName().startsWith("org.eclipse.jdt"))); + } + } From 48096bd78815afd98a3edfb6e3ad428dd3a07321 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 11:16:52 +0200 Subject: [PATCH 195/521] Hide test classes that depend on compiled Kotlin classes in Eclipse --- .../kotlin/junitbuild.java-library-conventions.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) 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 3801c5fe3a50..39550d718473 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 @@ -57,6 +57,11 @@ eclipse { // Exclude Foo.java and FooBar.java in the modules-2500 folder. it.excludes.add("**/Foo*.java") } + if (project.name == "jupiter-tests" && it.path == "src/test/java") { + // Exclude test classes that depend on compiled Kotlin code. + it.excludes.add("**/AtypicalJvmMethodNameTests.java") + it.excludes.add("**/TestInstanceLifecycleKotlinTests.java") + } } entries.filterIsInstance().forEach { it.entryAttributes.remove("module") From dff5133efee398759b1ecdc23f20c031fe12c6c2 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 11:22:36 +0200 Subject: [PATCH 196/521] =?UTF-8?q?Add=20missing=20@=E2=81=A0ExcludeTags?= =?UTF-8?q?=20declaration=20to=20VintageTestEngineTestSuite?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/junit/vintage/engine/VintageTestEngineTestSuite.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineTestSuite.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineTestSuite.java index d45ca3b2139b..12f94fae817b 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineTestSuite.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineTestSuite.java @@ -10,6 +10,7 @@ package org.junit.vintage.engine; +import org.junit.platform.suite.api.ExcludeTags; import org.junit.platform.suite.api.IncludeClassNamePatterns; import org.junit.platform.suite.api.IncludeEngines; import org.junit.platform.suite.api.SelectPackages; @@ -34,5 +35,6 @@ @SelectPackages("org.junit.vintage.engine") @IncludeClassNamePatterns(".*Tests?") @IncludeEngines("junit-jupiter") +@ExcludeTags("missing-junit4") class VintageTestEngineTestSuite { } From bbfbdcba26ecdc01aff388b504009307dd9b985b Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Wed, 28 May 2025 11:23:35 +0200 Subject: [PATCH 197/521] Disable tests that depend on compiled Groovy code in Eclipse --- .../engine/JUnit4VersionCheckTests.java | 1 + .../VintageTestEngineExecutionTests.java | 23 +++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4VersionCheckTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4VersionCheckTests.java index fc3416f404af..cc5a828928ed 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4VersionCheckTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4VersionCheckTests.java @@ -84,4 +84,5 @@ void handlesMissingJUnit() { + "an excludeEngines(\"junit-vintage\") filter.", exception.getMessage()); } + } 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..3e6f5c7e7f75 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,8 @@ import org.assertj.core.api.Condition; import org.junit.AssumptionViolatedException; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.DisabledIf; +import org.junit.platform.commons.util.ReflectionUtils; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -98,7 +100,6 @@ import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichFails; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithSingleTestWhichIsIgnored; import org.junit.vintage.engine.samples.junit4.PlainJUnit4TestCaseWithTwoTestMethods; -import org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods; import org.opentest4j.MultipleFailuresError; /** @@ -862,13 +863,16 @@ void executesJUnit4TestCaseWithRunnerWithDuplicateChangingChildDescriptions() { } @Test + @DisabledIf("runningInEclipse") void executesUnrolledSpockFeatureMethod() { - Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; + // Load Groovy class via reflection to avoid compilation errors in Eclipse IDE. + String testClassName = "org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods"; + Class testClass = ReflectionUtils.loadRequiredClass(testClassName, getClass().getClassLoader()); var request = LauncherDiscoveryRequestBuilder.request().selectors( selectMethod(testClass, "unrolled feature for #input")).build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // - event(uniqueIdSubstring(testClass.getName()), started()), // + event(uniqueIdSubstring(testClassName), started()), // event(dynamicTestRegistered("unrolled feature for 23")), // event(test("unrolled feature for 23"), started()), // event(test("unrolled feature for 23"), finishedWithFailure()), // @@ -880,8 +884,11 @@ void executesUnrolledSpockFeatureMethod() { } @Test + @DisabledIf("runningInEclipse") void executesRegularSpockFeatureMethod() { - Class testClass = SpockTestCaseWithUnrolledAndRegularFeatureMethods.class; + // Load Groovy class via reflection to avoid compilation errors in Eclipse IDE. + String testClassName = "org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods"; + Class testClass = ReflectionUtils.loadRequiredClass(testClassName, getClass().getClassLoader()); var request = LauncherDiscoveryRequestBuilder.request().selectors(selectMethod(testClass, "regular")).build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // @@ -938,4 +945,12 @@ private static boolean atLeastJUnit4_13() { return JUnit4VersionCheck.parseVersion(Version.id()).compareTo(new BigDecimal("4.13")) >= 0; } + /** + * Determine if the current code is running in the Eclipse IDE. + */ + static boolean runningInEclipse() { + return StackWalker.getInstance().walk( + stream -> stream.anyMatch(stackFrame -> stackFrame.getClassName().startsWith("org.eclipse.jdt"))); + } + } From acc638509baaf973c738b569cea694ce17c460d2 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 12:56:00 +0200 Subject: [PATCH 198/521] Allow publishing files to an existing directory Prior to this commit, both `TestReporter` and `ExtensionContext` threw an exception when `publishDirectory` was called with an existing directory. Now, they only attempt to create the directory if it doesn't already exist. --- .../release-notes/release-notes-5.13.0.adoc | 2 ++ .../jupiter/api/extension/ExtensionContext.java | 2 +- .../engine/descriptor/AbstractExtensionContext.java | 4 +++- .../engine/descriptor/ExtensionContextTests.java | 13 +++++++++++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index 35efebf70ac0..11135967b332 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -188,6 +188,8 @@ to start reporting discovery issues. failures. * Add support for Kotlin `Sequence` to `@MethodSource`, `@FieldSource`, and `@TestFactory`. +* Allow publishing files to an existing directory via `TestReporter` and + `ExtensionContext`, for example, when re-running a test class. [[release-notes-5.13.0-junit-vintage]] 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 a4f2a09a56b2..fd09f1d47de3 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 @@ -419,7 +419,7 @@ default void publishReportEntry(String value) { * and attach it to the current test or container. * *

    The directory will be resolved and created in the report output directory - * prior to invoking the supplied action. + * prior to invoking the supplied action, if it doesn't already exist. * * @param name the name of the directory to be attached; never {@code null} * or blank and must not contain any path separators diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index a7aa5fe248c0..b3497dfc0c80 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -161,7 +161,9 @@ public void publishDirectory(String name, ThrowingConsumer action) { Preconditions.notNull(action, "action must not be null"); ThrowingConsumer enhancedAction = path -> { - Files.createDirectory(path); + if (!Files.isDirectory(path)) { + Files.createDirectory(path); + } action.accept(path); }; publishFileEntry(name, enhancedAction, file -> { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java index f48979ec7dff..2599244c739c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/descriptor/ExtensionContextTests.java @@ -382,6 +382,19 @@ void failsWhenAttemptingToPublishRegularFilesAsDirectories(@TempDir Path tempDir "Published path must be a directory: " + tempDir.resolve("OuterClass").resolve("test")); } + @Test + void allowsPublishingToTheSameDirectoryTwice(@TempDir Path tempDir) { + var extensionContext = createExtensionContextForFilePublishing(tempDir); + + extensionContext.publishDirectory("test", + dir -> Files.writeString(dir.resolve("nested1.txt"), "Nested content 1")); + extensionContext.publishDirectory("test", + dir -> Files.writeString(dir.resolve("nested2.txt"), "Nested content 2")); + + assertThat(tempDir.resolve("OuterClass/test/nested1.txt")).hasContent("Nested content 1"); + assertThat(tempDir.resolve("OuterClass/test/nested2.txt")).hasContent("Nested content 2"); + } + private ExtensionContext createExtensionContextForFilePublishing(Path tempDir) { return createExtensionContextForFilePublishing(tempDir, mock(EngineExecutionListener.class), outerClassDescriptor(null)); From a7b02df53bed0b3daddb8ae3727603abcd635292 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 11:16:40 +0000 Subject: [PATCH 199/521] Update oracle-actions/setup-java action to v1.4.2 (#4592) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/cross-version.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 7c51412feaaf..6178ae7d2a05 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -37,7 +37,7 @@ jobs: uses: ./.github/actions/setup-test-jdk - name: "Set up JDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || 'ea' }})" if: matrix.jdk.type == 'ea' - uses: oracle-actions/setup-java@8fb9d7717810ccde9f8d4bef1e6f43d180f506b5 # v1.4.1 + uses: oracle-actions/setup-java@b1546e588c27008e88bfcabda44d11c22316b9b8 # v1.4.2 with: website: jdk.java.net release: ${{ matrix.jdk.release || matrix.jdk.version }} From 0855a7e0b94cc077a1156e7d4ace2adc943671b1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 13:22:34 +0200 Subject: [PATCH 200/521] Move subproject-specific configuration to subprojects --- ...junitbuild.java-library-conventions.gradle.kts | 9 --------- jupiter-tests/jupiter-tests.gradle.kts | 15 +++++++++++++++ platform-tests/platform-tests.gradle.kts | 11 +++++++++++ 3 files changed, 26 insertions(+), 9 deletions(-) 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 39550d718473..7fbb29c02acb 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 @@ -53,15 +53,6 @@ eclipse { entries.removeIf { it is ProjectDependency && it.path.equals("/code-generator-model") } entries.filterIsInstance().forEach { it.excludes.add("**/module-info.java") - if (project.name == "platform-tests" && it.path == "src/test/resources") { - // Exclude Foo.java and FooBar.java in the modules-2500 folder. - it.excludes.add("**/Foo*.java") - } - if (project.name == "jupiter-tests" && it.path == "src/test/java") { - // Exclude test classes that depend on compiled Kotlin code. - it.excludes.add("**/AtypicalJvmMethodNameTests.java") - it.excludes.add("**/TestInstanceLifecycleKotlinTests.java") - } } entries.filterIsInstance().forEach { it.entryAttributes.remove("module") diff --git a/jupiter-tests/jupiter-tests.gradle.kts b/jupiter-tests/jupiter-tests.gradle.kts index 8c4526753061..8b461d4e1c7e 100644 --- a/jupiter-tests/jupiter-tests.gradle.kts +++ b/jupiter-tests/jupiter-tests.gradle.kts @@ -1,4 +1,6 @@ import org.gradle.api.tasks.PathSensitivity.RELATIVE +import org.gradle.plugins.ide.eclipse.model.Classpath +import org.gradle.plugins.ide.eclipse.model.SourceFolder plugins { id("junitbuild.code-generator") @@ -41,3 +43,16 @@ tasks { } } } + +eclipse { + classpath.file.whenMerged { + this as Classpath + entries.filterIsInstance().forEach { + if (it.path == "src/test/java") { + // Exclude test classes that depend on compiled Kotlin code. + it.excludes.add("**/AtypicalJvmMethodNameTests.java") + it.excludes.add("**/TestInstanceLifecycleKotlinTests.java") + } + } + } +} diff --git a/platform-tests/platform-tests.gradle.kts b/platform-tests/platform-tests.gradle.kts index 629b68107c0b..35bf44a50873 100644 --- a/platform-tests/platform-tests.gradle.kts +++ b/platform-tests/platform-tests.gradle.kts @@ -2,6 +2,8 @@ import junitbuild.extensions.capitalized import junitbuild.extensions.dependencyProject import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.internal.os.OperatingSystem +import org.gradle.plugins.ide.eclipse.model.Classpath +import org.gradle.plugins.ide.eclipse.model.SourceFolder plugins { id("junitbuild.java-library-conventions") @@ -143,6 +145,15 @@ eclipse { classpath { plusConfigurations.add(dependencyProject(projects.junitPlatformConsole).configurations["shadowedClasspath"]) } + classpath.file.whenMerged { + this as Classpath + entries.filterIsInstance().forEach { + if (it.path == "src/test/resources") { + // Exclude Foo.java and FooBar.java in the modules-2500 folder. + it.excludes.add("**/Foo*.java") + } + } + } } idea { From e806e6578cf82c8d672afa8e63a78c279917fcc7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 19:35:26 +0200 Subject: [PATCH 201/521] Remove unused Gradle plugin --- build.gradle.kts | 1 - gradle/libs.versions.toml | 1 - gradle/plugins/common/build.gradle.kts | 1 - ...itbuild.dependency-update-check.gradle.kts | 19 ------------------- 4 files changed, 22 deletions(-) delete mode 100644 gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts diff --git a/build.gradle.kts b/build.gradle.kts index 894df845d9b8..226115834bbc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,6 @@ plugins { id("junitbuild.base-conventions") id("junitbuild.build-metadata") id("junitbuild.checkstyle-nohttp") - id("junitbuild.dependency-update-check") id("junitbuild.jacoco-aggregation-conventions") id("junitbuild.maven-central-publishing") id("junitbuild.temp-maven-repo") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bfb532add30c..e48853bd23ac 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -111,4 +111,3 @@ openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "7.0.4" } -versions = { id = "com.github.ben-manes.versions", version = "0.52.0" } diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index ded9ec6a99bb..c8b07ca033d6 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -19,5 +19,4 @@ dependencies { implementation(libs.plugins.openrewrite.markerCoordinates) implementation(libs.plugins.shadow.markerCoordinates) implementation(libs.plugins.spotless.markerCoordinates) - implementation(libs.plugins.versions.markerCoordinates) } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts deleted file mode 100644 index f7bac1fb8efc..000000000000 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.dependency-update-check.gradle.kts +++ /dev/null @@ -1,19 +0,0 @@ -plugins { - id("com.github.ben-manes.versions") -} - -tasks.dependencyUpdates { - checkConstraints = true - resolutionStrategy { - componentSelection { - all { - val rejected = listOf("alpha", "beta", "rc", "cr", "m", "preview", "b", "ea") - .map { qualifier -> Regex("(?i).*[.-]$qualifier[.\\d-+]*") } - .any { it.matches(candidate.version) } - if (rejected) { - reject("Release candidate") - } - } - } - } -} From 6a2b64ea9c3faa70fe3a60abb4ff87ebb313c2ce Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 28 May 2025 19:36:43 +0200 Subject: [PATCH 202/521] Remove usage of removed plugin --- gradle/plugins/build.gradle.kts | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 gradle/plugins/build.gradle.kts diff --git a/gradle/plugins/build.gradle.kts b/gradle/plugins/build.gradle.kts deleted file mode 100644 index f64d71d4260c..000000000000 --- a/gradle/plugins/build.gradle.kts +++ /dev/null @@ -1,3 +0,0 @@ -plugins { - alias(libs.plugins.versions) -} From b14ea155cb95669cfa2e5ddba5f48993f47f2205 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 02:01:58 +0000 Subject: [PATCH 203/521] Update dependency com.fasterxml.woodstox:woodstox-core to v7.1.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e48853bd23ac..3d90ddbfa918 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,7 @@ univocity-parsers = { module = "com.sonofab1rd:univocity-parsers", version = "2. xmlunit-assertj = { module = "org.xmlunit:xmlunit-assertj3", version.ref = "xmlunit" } xmlunit-placeholders = { module = "org.xmlunit:xmlunit-placeholders", version.ref = "xmlunit" } testingAnnotations = { module = "com.gradle:develocity-testing-annotations", version = "2.0.1" } -woodstox = { module = "com.fasterxml.woodstox:woodstox-core", version = "7.1.0" } +woodstox = { module = "com.fasterxml.woodstox:woodstox-core", version = "7.1.1" } # Only declared here so Dependabot knows when to update the referenced versions asciidoctorj-pdf = { module = "org.asciidoctor:asciidoctorj-pdf", version.ref = "asciidoctorj-pdf" } From 3d61b7aa3f188fa9b81ed232b6fc2c8ed4cb0b74 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 11:03:51 +0200 Subject: [PATCH 204/521] Avoid publishing Gradle Module Metadata for `shadowRuntimeElements` --- .../src/main/kotlin/junitbuild.shadow-conventions.gradle.kts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts index a9a7716bc91e..6962f80c3ca3 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.shadow-conventions.gradle.kts @@ -24,6 +24,9 @@ configurations { } } +val javaComponent = components["java"] as AdhocComponentWithVariants +javaComponent.withVariantsFromConfiguration(configurations.shadowRuntimeElements.get()) { skip() } + tasks { javadoc { classpath += shadowedClasspath.get() From a797fd8473c26aee186ab02fd7bcb54155bd0907 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 11:04:38 +0200 Subject: [PATCH 205/521] Set source/target compatibility on `JavaPluginExtension` So plugins like Groovy and Shadow can read it from there. --- gradle/base/code-generator-model/build.gradle.kts | 11 +++++++++++ .../junitbuild.java-library-conventions.gradle.kts | 12 ++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/gradle/base/code-generator-model/build.gradle.kts b/gradle/base/code-generator-model/build.gradle.kts index bc0172f0f072..4bf50672a124 100644 --- a/gradle/base/code-generator-model/build.gradle.kts +++ b/gradle/base/code-generator-model/build.gradle.kts @@ -1,3 +1,14 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { `kotlin-dsl` } + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +kotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_17 +} 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 7fbb29c02acb..4064b58bdadd 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 @@ -253,13 +253,13 @@ tasks { } afterEvaluate { + java { + // For Groovy and Shadow plugins + sourceCompatibility = extension.mainJavaVersion.get() + targetCompatibility = extension.mainJavaVersion.get() + } pluginManager.withPlugin("groovy") { - tasks.named("compileGroovy").configure { - // Groovy compiler does not support the --release flag. - sourceCompatibility = extension.mainJavaVersion.get().majorVersion - targetCompatibility = extension.mainJavaVersion.get().majorVersion - } - tasks.named("compileTestGroovy").configure { + tasks.withType().named { it.startsWith("compileTest") }.configureEach { // Groovy compiler does not support the --release flag. sourceCompatibility = extension.testJavaVersion.get().majorVersion targetCompatibility = extension.testJavaVersion.get().majorVersion From f8037e73977422c54f2a8f452b39be3a4a1f6809 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 11:45:43 +0200 Subject: [PATCH 206/521] Clean up code-generator plugin --- .../kotlin/junitbuild.code-generator.gradle.kts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gradle/plugins/code-generator/src/main/kotlin/junitbuild.code-generator.gradle.kts b/gradle/plugins/code-generator/src/main/kotlin/junitbuild.code-generator.gradle.kts index 1846eb6ae728..63c33d1a401f 100644 --- a/gradle/plugins/code-generator/src/main/kotlin/junitbuild.code-generator.gradle.kts +++ b/gradle/plugins/code-generator/src/main/kotlin/junitbuild.code-generator.gradle.kts @@ -5,10 +5,12 @@ plugins { java } -val templates by sourceSets.registering +val templates by sourceSets.creating +val templatesCompileOnly = configurations[templates.compileOnlyConfigurationName] + dependencies { - add(templates.get().compileOnlyConfigurationName, dependencyFromLibs("jte")) - add(templates.get().compileOnlyConfigurationName, "junitbuild.base:code-generator-model") + templatesCompileOnly(dependencyFromLibs("jte")) + templatesCompileOnly("junitbuild.base:code-generator-model") } val license: License by rootProject.extra @@ -18,17 +20,16 @@ val generateCode by tasks.registering sourceSets.named { it != templates.name }.configureEach { val sourceSetName = name - val sourceSetTargetDir = rootTargetDir.map { it.dir(sourceSetName) } val task = tasks.register(getTaskName("generateJreRelated", "SourceCode"), GenerateJreRelatedSourceCode::class) { - templateDir.convention(layout.dir(templates.map { - it.resources.srcDirs.single().resolve(sourceSetName) + templateDir.convention(layout.dir(provider { + templates.resources.srcDirs.single().resolve(sourceSetName) })) - targetDir.convention(sourceSetTargetDir) + targetDir.convention(rootTargetDir.map { it.dir(sourceSetName) }) licenseHeaderFile.convention(license.headerFile) } - java.srcDir(files(sourceSetTargetDir).builtBy(task)) + java.srcDir(task.map { it.targetDir }) generateCode { dependsOn(task) From f3180a53d8a99e4913302e7046720dac3e9df924 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 29 May 2025 09:27:24 +0000 Subject: [PATCH 207/521] Update plugin openrewrite to v7.7.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3d90ddbfa918..7b0772e73597 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -107,7 +107,7 @@ jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC" } nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } -openrewrite = { id = "org.openrewrite.rewrite", version = "7.6.2" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.7.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "7.0.4" } From 050f42814803294d2bbf2bfe5799924a465c2d9e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 15:52:35 +0200 Subject: [PATCH 208/521] Work around CVE-2025-48734 --- .../src/main/kotlin/junitbuild.checkstyle-nohttp.gradle.kts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.checkstyle-nohttp.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.checkstyle-nohttp.gradle.kts index 0bcb0ce67641..b993fedf65fe 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.checkstyle-nohttp.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.checkstyle-nohttp.gradle.kts @@ -16,6 +16,10 @@ configurations.checkstyle { if (requested.group == "ch.qos.logback") { useVersion(requiredVersionFromLibs("logback")) } + // Workaround for CVE-2025-48734 + if (requested.group == "commons-beanutils") { + useVersion("1.11.0") + } } } } From d0136e0c210e0d3fe29f80982fdc104da80657da Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 15:53:31 +0200 Subject: [PATCH 209/521] Update transitive JReleaser dependencies to work around CVEs --- gradle/plugins/publishing/build.gradle.kts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/gradle/plugins/publishing/build.gradle.kts b/gradle/plugins/publishing/build.gradle.kts index e010a00708d4..79f65b980991 100644 --- a/gradle/plugins/publishing/build.gradle.kts +++ b/gradle/plugins/publishing/build.gradle.kts @@ -8,3 +8,18 @@ dependencies { implementation("junitbuild.base:dsl-extensions") implementation(libs.plugins.jreleaser.markerCoordinates) } + +configurations.configureEach { + resolutionStrategy { + eachDependency { + // Workaround for CVE-2025-4949 + if (requested.name == "org.eclipse.jgit") { + useVersion("6.10.1.202505221210-r") + } + // Workaround for CVE-2020-36843 + if (requested.name == "sshj") { + useVersion("0.40.0") + } + } + } +} From d7ca58c7a1be3b23d44da2fdcdf8e07fc0882590 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 15:53:45 +0200 Subject: [PATCH 210/521] Remove unused dependency --- gradle/plugins/common/build.gradle.kts | 1 - 1 file changed, 1 deletion(-) diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index c8b07ca033d6..c5f794080724 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -14,7 +14,6 @@ dependencies { implementation(libs.plugins.errorProne.markerCoordinates) implementation(libs.plugins.foojayResolver.markerCoordinates) implementation(libs.plugins.jmh.markerCoordinates) - implementation(libs.plugins.jreleaser.markerCoordinates) implementation(libs.plugins.nullaway.markerCoordinates) implementation(libs.plugins.openrewrite.markerCoordinates) implementation(libs.plugins.shadow.markerCoordinates) From ac0b9c1551a828d741aa9e0c1904724c83bea7ad Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 29 May 2025 15:30:08 +0200 Subject: [PATCH 211/521] Set Java source & target compatibility to JDK 21 in Eclipse This ensures that all code (including tests and the API tools in the 'documentation' project that make use of JDK 21 language features) is compiled as if we were targeting JDK 21 instead of JDK 17. Note, however, that this only affects the projects within Eclipse. The standard Gradle build will still fail if somebody inadvertently uses language features or APIs post JDK 17. --- .../main/kotlin/junitbuild.java-library-conventions.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) 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 4064b58bdadd..3b0574f5eb73 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 @@ -34,6 +34,8 @@ val extension = extensions.create("javaLibrary") eclipse { jdt { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 file { // Set properties for org.eclipse.jdt.core.prefs withProperties { From 3194419063e455453963c8825153d25d6e25d2c3 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 29 May 2025 15:47:47 +0200 Subject: [PATCH 212/521] Remove Groovy Nature from Eclipse projects This commit removes the Groovy Nature from Eclipse projects, since we do not want to require that the Groovy plugin is installed in order for developers to work with the code base in Eclipse IDE. --- junit-vintage-engine/junit-vintage-engine.gradle.kts | 5 +++++ jupiter-tests/jupiter-tests.gradle.kts | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/junit-vintage-engine/junit-vintage-engine.gradle.kts b/junit-vintage-engine/junit-vintage-engine.gradle.kts index 9eef3cf490fc..748cb2749da6 100644 --- a/junit-vintage-engine/junit-vintage-engine.gradle.kts +++ b/junit-vintage-engine/junit-vintage-engine.gradle.kts @@ -103,4 +103,9 @@ eclipse { // Avoid exposing test resources to dependent projects containsTestFixtures = false } + project { + // Remove Groovy Nature, since we don't require a Groovy plugin for Eclipse + // in order for developers to work with the code base. + natures.removeAll { it == "org.eclipse.jdt.groovy.core.groovyNature" } + } } diff --git a/jupiter-tests/jupiter-tests.gradle.kts b/jupiter-tests/jupiter-tests.gradle.kts index 8b461d4e1c7e..9b1baaf781a7 100644 --- a/jupiter-tests/jupiter-tests.gradle.kts +++ b/jupiter-tests/jupiter-tests.gradle.kts @@ -55,4 +55,9 @@ eclipse { } } } + project { + // Remove Groovy Nature, since we don't require a Groovy plugin for Eclipse + // in order for developers to work with the code base. + natures.removeAll { it == "org.eclipse.jdt.groovy.core.groovyNature" } + } } From 77b59e2bd0688f3f0e8ddf11cbcfb5d237718c3e Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 29 May 2025 16:19:05 +0200 Subject: [PATCH 213/521] Ensure LauncherConfigurationParametersTests runs in all environments Prior to this commit, the warnsOnMultiplePropertyResources() test in LauncherConfigurationParametersTests only ran within the Gradle build or within IntelliJ IDEA when configured with "build" as the target build directory. However, other environments might not use a "build" directory. For example, Eclipse uses a "bin" directory. This commit therefore removes the hardcoded "build/resources/test" path from the assertion and instead determines the URL for the resource by loading it via the ClassLoader. This commit also refactors the assertion to make it easier to follow. --- .../LauncherConfigurationParametersTests.java | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java index 05a74b2bb9ee..9d8899b9402a 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherConfigurationParametersTests.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.core; +import static org.assertj.core.api.Assertions.as; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -18,12 +19,12 @@ import java.net.URLClassLoader; import java.nio.file.Files; import java.nio.file.Path; -import java.util.List; import java.util.Map; import java.util.Properties; import java.util.logging.Level; import java.util.logging.LogRecord; +import org.assertj.core.api.InstanceOfAssertFactories; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -204,31 +205,32 @@ void ignoresSystemPropertyAndConfigFileWhenImplicitLookupsAreDisabled() { @Test void warnsOnMultiplePropertyResources(@TempDir Path tempDir, @TrackLogRecords LogRecordListener logRecordListener) throws Exception { + Properties properties = new Properties(); properties.setProperty(KEY, "from second config file"); try (var out = Files.newOutputStream(tempDir.resolve(CONFIG_FILE_NAME))) { properties.store(out, ""); } + ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader(); + URL originalResource = originalClassLoader.getResource(CONFIG_FILE_NAME); + try (var customClassLoader = new URLClassLoader(new URL[] { tempDir.toUri().toURL() }, originalClassLoader)) { Thread.currentThread().setContextClassLoader(customClassLoader); ConfigurationParameters configParams = fromMapAndFile(Map.of(), CONFIG_FILE_NAME); assertThat(configParams.get(KEY)).contains(CONFIG_FILE); - List loggedWarnings = logRecordListener.stream(Level.WARNING) // - .map(LogRecord::getMessage) // - .toList(); - assertThat(loggedWarnings) // - .hasSize(1); - assertThat(loggedWarnings.getFirst()) // - .contains("Discovered 2 '" + CONFIG_FILE_NAME - + "' configuration files on the classpath (see below); only the first (*) will be used.") // - .contains("- " - + Path.of( - "build/resources/test/test-junit-platform.properties").toAbsolutePath().toUri().toURL() - + " (*)") // - .contains("- " + tempDir.resolve(CONFIG_FILE_NAME).toUri().toURL()); + assertThat(logRecordListener.stream(Level.WARNING).map(LogRecord::getMessage)) // + .hasSize(1) // + .first(as(InstanceOfAssertFactories.STRING)) // + .contains(""" + Discovered 2 '%s' configuration files on the classpath (see below); \ + only the first (*) will be used. + - %s (*) + - %s"""// + .formatted(CONFIG_FILE_NAME, originalResource, + tempDir.resolve(CONFIG_FILE_NAME).toUri().toURL())); } finally { Thread.currentThread().setContextClassLoader(originalClassLoader); From b67b1773b6c699433ae958b1fdb828bbe20c51af Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 29 May 2025 16:28:03 +0200 Subject: [PATCH 214/521] Move Jupiter-specific tests to the jupiter-tests module --- .../java/org/junit/jupiter/api/condition/OSTests.java | 2 ++ .../org/junit/jupiter/api/extension}/Heavyweight.java | 9 ++------- .../junit/jupiter/api/extension}/HeavyweightTests.java | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) rename {platform-tests => jupiter-tests}/src/test/java/org/junit/jupiter/api/condition/OSTests.java (99%) rename {platform-tests/src/test/java/org/junit/jupiter/extensions => jupiter-tests/src/test/java/org/junit/jupiter/api/extension}/Heavyweight.java (87%) rename {platform-tests/src/test/java/org/junit/jupiter/extensions => jupiter-tests/src/test/java/org/junit/jupiter/api/extension}/HeavyweightTests.java (96%) diff --git a/platform-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java similarity index 99% rename from platform-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java rename to jupiter-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java index 70a0c42350e1..6a0c582fb354 100644 --- a/platform-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/OSTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.params.provider.ValueSource; class OSTests { + @ParameterizedTest @NullAndEmptySource @ValueSource(strings = { " ", "\t" }) @@ -76,4 +77,5 @@ void windows(String name) { assertEquals(OS.WINDOWS, OS.parse(name)); } } + } diff --git a/platform-tests/src/test/java/org/junit/jupiter/extensions/Heavyweight.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java similarity index 87% rename from platform-tests/src/test/java/org/junit/jupiter/extensions/Heavyweight.java rename to jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java index ab9207301eff..2ababf8d4145 100644 --- a/platform-tests/src/test/java/org/junit/jupiter/extensions/Heavyweight.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java @@ -8,7 +8,7 @@ * https://www.eclipse.org/legal/epl-v20.html */ -package org.junit.jupiter.extensions; +package org.junit.jupiter.api.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -16,12 +16,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; -import org.junit.jupiter.api.extension.BeforeEachCallback; -import org.junit.jupiter.api.extension.ExtensionContext; -import org.junit.jupiter.api.extension.ParameterContext; -import org.junit.jupiter.api.extension.ParameterResolver; - -public class Heavyweight implements ParameterResolver, BeforeEachCallback { +class Heavyweight implements ParameterResolver, BeforeEachCallback { @Override public void beforeEach(ExtensionContext context) { diff --git a/platform-tests/src/test/java/org/junit/jupiter/extensions/HeavyweightTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/HeavyweightTests.java similarity index 96% rename from platform-tests/src/test/java/org/junit/jupiter/extensions/HeavyweightTests.java rename to jupiter-tests/src/test/java/org/junit/jupiter/api/extension/HeavyweightTests.java index 6c278c9ae8c2..872a00f44d81 100644 --- a/platform-tests/src/test/java/org/junit/jupiter/extensions/HeavyweightTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/HeavyweightTests.java @@ -8,7 +8,7 @@ * https://www.eclipse.org/legal/epl-v20.html */ -package org.junit.jupiter.extensions; +package org.junit.jupiter.api.extension; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -25,7 +25,6 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.TestInstance; -import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.parallel.ResourceLock; /** @@ -107,4 +106,5 @@ void afterAll(Heavyweight.Resource resource) { } } + } From b0a1a1ecb42ac9b0fc0c60ba2c850eda710361b7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 29 May 2025 16:41:29 +0200 Subject: [PATCH 215/521] Fix resolution of `jmhRuntimeClasspath` configurations --- .../junitbuild.java-library-conventions.gradle.kts | 10 +++++----- .../kotlin/junitbuild.testing-conventions.gradle.kts | 8 ++++++-- 2 files changed, 11 insertions(+), 7 deletions(-) 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 3b0574f5eb73..35752e82b589 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 @@ -255,12 +255,12 @@ tasks { } afterEvaluate { - java { - // For Groovy and Shadow plugins - sourceCompatibility = extension.mainJavaVersion.get() - targetCompatibility = extension.mainJavaVersion.get() - } pluginManager.withPlugin("groovy") { + tasks.named("compileGroovy").configure { + // Groovy compiler does not support the --release flag. + sourceCompatibility = extension.mainJavaVersion.get().majorVersion + targetCompatibility = extension.mainJavaVersion.get().majorVersion + } tasks.withType().named { it.startsWith("compileTest") }.configureEach { // Groovy compiler does not support the --release flag. sourceCompatibility = extension.testJavaVersion.get().majorVersion 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 b79be1dbbeed..dd333c70161c 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 @@ -1,8 +1,8 @@ import com.gradle.develocity.agent.gradle.internal.test.PredictiveTestSelectionConfigurationInternal import com.gradle.develocity.agent.gradle.test.PredictiveTestSelectionMode -import junitbuild.extensions.trackOperationSystemAsInput -import junitbuild.extensions.dependencyFromLibs import junitbuild.extensions.bundleFromLibs +import junitbuild.extensions.dependencyFromLibs +import junitbuild.extensions.trackOperationSystemAsInput import org.gradle.api.tasks.PathSensitivity.RELATIVE import org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL import org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED @@ -22,6 +22,10 @@ var javaAgentClasspath = configurations.resolvable("javaAgentClasspath") { var openTestReportingCli = configurations.dependencyScope("openTestReportingCli") var openTestReportingCliClasspath = configurations.resolvable("openTestReportingCliClasspath") { extendsFrom(openTestReportingCli.get()) + attributes { + // Avoid using the shadowed variant of junit-platform-reporting + attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling::class, Bundling.EXTERNAL)) + } } val generateOpenTestHtmlReport by tasks.registering(JavaExec::class) { From 3c5b457564d559fb0f396d7f303f8effe291daa3 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Thu, 29 May 2025 17:40:21 +0200 Subject: [PATCH 216/521] Improve assertion failure message in TestClassPredicatesTests The recursiveHierarchies() test currently fails when running in Eclipse IDE, but the failure message does not indicate what the expected message is for the expected JUnitException. This commit therefore updates the assertion to check the exception message to help with diagnostics. --- .../discovery/predicates/TestClassPredicatesTests.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 757d4a8cfa6c..30ea70b31b54 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 @@ -11,8 +11,8 @@ package org.junit.jupiter.engine.discovery.predicates; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; @@ -218,7 +218,11 @@ void privateStaticTestClassEvaluatesToFalse() { */ @Test void recursiveHierarchies() { - assertThrows(JUnitException.class, () -> predicates.looksLikeIntendedTestClass(TestCases.OuterClass.class)); + assertThatExceptionOfType(JUnitException.class)// + .isThrownBy(() -> predicates.looksLikeIntendedTestClass(TestCases.OuterClass.class))// + .withMessage("Detected cycle in inner class hierarchy between %s and %s", + TestCases.OuterClass.RecursiveInnerClass.class.getName(), TestCases.OuterClass.class.getName()); + assertTrue(predicates.isValidStandaloneTestClass(TestCases.OuterClass.class)); assertThat(discoveryIssues).isEmpty(); @@ -404,6 +408,7 @@ void test() { @SuppressWarnings("InnerClassMayBeStatic") class RecursiveInnerClass extends OuterClass { } + } private static class NestedClassesTestCase { From 8387b448a4b92694be42ab74873ba5934cb7dd24 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 11:07:44 +0200 Subject: [PATCH 217/521] Remove short-circuiting to ensure all classes are checked for cycles (#4598) Resolves #4597. --- .../commons/util/ReflectionUtils.java | 50 +++++++------------ 1 file changed, 17 insertions(+), 33 deletions(-) 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 8394fc2ebc27..5973b183d3fb 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 @@ -49,6 +49,8 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.Consumer; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -1119,10 +1121,7 @@ public static List> findNestedClasses(Class clazz, Predicate> candidates = new LinkedHashSet<>(); - visitNestedClasses(clazz, predicate, nestedClass -> { - candidates.add(nestedClass); - return true; - }); + visitAllNestedClasses(clazz, predicate, candidates::add); return List.copyOf(candidates); } @@ -1144,8 +1143,9 @@ public static boolean isNestedClassPresent(Class clazz, Predicate> p Preconditions.notNull(clazz, "Class must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); - boolean visitorWasNotCalled = visitNestedClasses(clazz, predicate, __ -> false); - return !visitorWasNotCalled; + AtomicBoolean foundNestedClass = new AtomicBoolean(false); + visitAllNestedClasses(clazz, predicate, __ -> foundNestedClass.setPlain(true)); + return foundNestedClass.getPlain(); } /** @@ -1156,10 +1156,15 @@ public static Stream> streamNestedClasses(Class clazz, Predicate clazz, Predicate> predicate, - Visitor> visitor) { + /** + * Visit all nested classes without support for short-circuiting + * in order to ensure all of them are checked for class cycles. + */ + private static void visitAllNestedClasses(Class clazz, Predicate> predicate, + Consumer> consumer) { + if (!isSearchable(clazz)) { - return true; + return; } if (isInnerClass(clazz) && predicate.test(clazz)) { @@ -1171,10 +1176,7 @@ private static boolean visitNestedClasses(Class clazz, Predicate> pr for (Class nestedClass : clazz.getDeclaredClasses()) { if (predicate.test(nestedClass)) { detectInnerClassCycle(nestedClass); - boolean shouldContinue = visitor.accept(nestedClass); - if (!shouldContinue) { - return false; - } + consumer.accept(nestedClass); } } } @@ -1183,20 +1185,12 @@ private static boolean visitNestedClasses(Class clazz, Predicate> pr } // Search class hierarchy - boolean shouldContinue = visitNestedClasses(clazz.getSuperclass(), predicate, visitor); - if (!shouldContinue) { - return false; - } + visitAllNestedClasses(clazz.getSuperclass(), predicate, consumer); // Search interface hierarchy for (Class ifc : clazz.getInterfaces()) { - shouldContinue = visitNestedClasses(ifc, predicate, visitor); - if (!shouldContinue) { - return false; - } + visitAllNestedClasses(ifc, predicate, consumer); } - - return true; } /** @@ -1936,14 +1930,4 @@ static Throwable getUnderlyingCause(Throwable t) { return t; } - private interface Visitor { - - /** - * @return {@code true} if the visitor should continue searching; - * {@code false} if the visitor should stop - */ - boolean accept(T value); - - } - } From 2eaf488b7be163d7842f09bce6f988ccc15d44d7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 11:09:08 +0200 Subject: [PATCH 218/521] Finalize 5.13.0 release notes --- .../asciidoc/release-notes/release-notes-5.13.0.adoc | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc index 11135967b332..c8a7dfa56ab2 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.0.adoc @@ -54,11 +54,6 @@ repository on GitHub. `ClassNotFoundException` when loading classes during shutdown. * Fix support of `--uid` and `--select-unique-id` options in the console launcher. -[[release-notes-5.13.0-junit-platform-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - [[release-notes-5.13.0-junit-platform-new-features-and-improvements]] ==== New Features and Improvements @@ -116,11 +111,6 @@ to start reporting discovery issues. failure happens prior to invoking the parameterized method. * Validate _all_ versions specified in `@EnabledOnJre` and `@DisabledOnJre` annotations. -[[release-notes-5.13.0-junit-jupiter-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - [[release-notes-5.13.0-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements From e2044de37388a375392782c23ff138a1c07da2e3 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:20:39 +0200 Subject: [PATCH 219/521] Polish Javadoc for ReflectionUtils.isNestedClassPresent() This commit reuses the text I wrote for ReflectionSupport.findNestedClasses(). --- .../org/junit/platform/commons/util/ReflectionUtils.java | 6 ++++++ 1 file changed, 6 insertions(+) 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 5973b183d3fb..cac9bbffc86f 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 @@ -1132,6 +1132,12 @@ public static List> findNestedClasses(Class clazz, PredicateThis method does not search for nested classes * recursively. * + *

    This method detects cycles in inner class hierarchies — + * from the supplied class up to the outermost enclosing class — and + * throws a {@link JUnitException} if such a cycle is detected. Cycles within + * inner class hierarchies below the supplied class are not detected + * by this method. + * * @param clazz the class to be searched; never {@code null} * @param predicate the predicate against which the list of nested classes is * checked; never {@code null} From 1e562ef3f779d914969e54b1225b95b7df61bc6c Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:42:38 +0200 Subject: [PATCH 220/521] =?UTF-8?q?Add=20missing=20@=E2=81=A0Override=20an?= =?UTF-8?q?notations?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../jupiter/engine/execution/ExtensionContextSupplier.java | 1 + .../ForkJoinPoolHierarchicalTestExecutorService.java | 2 ++ .../launcher/core/DelegatingLauncherDiscoveryRequest.java | 7 +++++++ 3 files changed, 10 insertions(+) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ExtensionContextSupplier.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ExtensionContextSupplier.java index c813687bb8b4..5a3ed9a9d09d 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ExtensionContextSupplier.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/ExtensionContextSupplier.java @@ -51,6 +51,7 @@ private ScopeBasedExtensionContextSupplier(ExtensionContext currentExtensionCont this.legacyExtensionContext = legacyExtensionContext; } + @Override public ExtensionContext get(TestInstantiationAwareExtension extension) { return isTestScoped(extension) ? currentExtensionContext : legacyExtensionContext; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java index 5d6979cf8b32..3f64d3cd4493 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java @@ -234,6 +234,7 @@ class ExclusiveTask extends ForkJoinTask { * * @return {@code null} always */ + @Override public final Void getRawResult() { return null; } @@ -241,6 +242,7 @@ public final Void getRawResult() { /** * Requires null completion value. */ + @Override protected final void setRawResult(Void mustBeNull) { } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncherDiscoveryRequest.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncherDiscoveryRequest.java index 4a8c8d5cad97..55d2ba094df2 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncherDiscoveryRequest.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/DelegatingLauncherDiscoveryRequest.java @@ -32,30 +32,37 @@ class DelegatingLauncherDiscoveryRequest implements LauncherDiscoveryRequest { this.request = request; } + @Override public List getEngineFilters() { return this.request.getEngineFilters(); } + @Override public List getPostDiscoveryFilters() { return this.request.getPostDiscoveryFilters(); } + @Override public LauncherDiscoveryListener getDiscoveryListener() { return this.request.getDiscoveryListener(); } + @Override public List getSelectorsByType(Class selectorType) { return this.request.getSelectorsByType(selectorType); } + @Override public > List getFiltersByType(Class filterType) { return this.request.getFiltersByType(filterType); } + @Override public ConfigurationParameters getConfigurationParameters() { return this.request.getConfigurationParameters(); } + @Override public OutputDirectoryProvider getOutputDirectoryProvider() { return this.request.getOutputDirectoryProvider(); } From 0641ab37e3de412fddde5c6e3f46aff87d8ebad4 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:44:31 +0200 Subject: [PATCH 221/521] Use method references and/or simplify lambda expressions --- .../org/junit/jupiter/params/ResolverFacade.java | 2 +- .../org/junit/platform/engine/CompositeFilter.java | 2 +- .../platform/launcher/AbstractMethodFilter.java | 2 +- .../launcher/core/EngineDiscoveryOrchestrator.java | 4 ++-- .../junit/jupiter/api/AssertAllAssertionsTests.java | 13 ++++++------- .../api/AssertDoesNotThrowAssertionsTests.java | 4 +--- .../jupiter/engine/extension/TestWatcherTests.java | 3 ++- .../console/ConsoleLauncherWrapperResult.java | 2 +- .../launcher/tagexpression/ParserTests.java | 2 +- .../launcher/tagexpression/TokenizerTests.java | 4 ++-- 10 files changed, 18 insertions(+), 20 deletions(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index bdec2d6af084..594c3a7bfd49 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -414,7 +414,7 @@ else if (declarations.size() > 1) { } fields.stream() // .filter(ModifierSupport::isFinal) // - .map(field -> "@Parameter field [%s] must not be declared as final".formatted(field)) // + .map("@Parameter field [%s] must not be declared as final"::formatted) // .forEach(errors::add); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java index 2083d4d2800f..de40e2256c9b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/CompositeFilter.java @@ -81,7 +81,7 @@ public String toString() { // @formatter:off return filters.stream() .map(Object::toString) - .map(value -> "(%s)".formatted(value)) + .map("(%s)"::formatted) .collect(joining(" and ")); // @formatter:on } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java index 83d02375b47b..74792aa35e86 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/AbstractMethodFilter.java @@ -51,7 +51,7 @@ protected Optional findMatchingPattern(@Nullable String methodName) { protected @Nullable String getFullyQualifiedMethodNameFromDescriptor(TestDescriptor descriptor) { return descriptor.getSource() // - .filter(source -> source instanceof MethodSource) // + .filter(MethodSource.class::isInstance) // .map(methodSource -> getFullyQualifiedMethodNameWithoutParameters(((MethodSource) methodSource))) // .orElse(null); } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java index 026cefeeba9d..7d2e7c529d4e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/EngineDiscoveryOrchestrator.java @@ -164,12 +164,12 @@ private Map discoverSafely(LauncherDiscoveryReques if (engineIsExcluded) { logger.debug(() -> "Test discovery for engine '%s' was skipped due to an EngineFilter%s.".formatted( - testEngine.getId(), phase.map(it -> " in %s phase".formatted(it)).orElse(""))); + testEngine.getId(), phase.map(" in %s phase"::formatted).orElse(""))); continue; } logger.debug(() -> "Discovering tests%s in engine '%s'.".formatted( - phase.map(it -> " during Launcher %s phase".formatted(it)).orElse(""), testEngine.getId())); + phase.map(" during Launcher %s phase"::formatted).orElse(""), testEngine.getId())); EngineResultInfo engineResult = discoverEngineRoot(testEngine, request, issueCollector, uniqueIdCreator); testEngineDescriptors.put(testEngine, engineResult); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java index f87e109281cf..1081fd79459c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java @@ -19,7 +19,6 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.util.Collection; @@ -109,8 +108,8 @@ void assertAllWithExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll( - () -> fail(), - () -> fail() + Assertions::fail, + Assertions::fail ) ); // @formatter:on @@ -123,8 +122,8 @@ void assertAllWithCollectionOfExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(asList( - () -> fail(), - () -> fail() + Assertions::fail, + Assertions::fail )) ); // @formatter:on @@ -137,8 +136,8 @@ void assertAllWithStreamOfExecutablesThatThrowAssertionErrors() { // @formatter:off MultipleFailuresError multipleFailuresError = assertThrows(MultipleFailuresError.class, () -> assertAll(Stream.of( - () -> fail(), - () -> fail() + Assertions::fail, + Assertions::fail )) ); // @formatter:on diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertDoesNotThrowAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertDoesNotThrowAssertionsTests.java index 260be584308a..90eafaf27f87 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertDoesNotThrowAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertDoesNotThrowAssertionsTests.java @@ -36,9 +36,7 @@ class AssertDoesNotThrowAssertionsTests { @Test void assertDoesNotThrowWithMethodReferenceForNonVoidReturnType() { - FutureTask future = new FutureTask<>(() -> { - return "foo"; - }); + FutureTask future = new FutureTask<>(() -> "foo"); future.run(); String result; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java index 49a3bb073554..dbacb6dd6d9a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TestWatcherTests.java @@ -31,6 +31,7 @@ import java.util.stream.Stream; import org.jspecify.annotations.Nullable; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.DynamicTest; @@ -305,7 +306,7 @@ Stream abortedTest() { @TestFactory @Disabled Stream skippedTest() { - return Stream.of("A", "B").map(text -> dynamicTest(text, () -> fail())); + return Stream.of("A", "B").map(text -> dynamicTest(text, Assertions::fail)); } } diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java index 972496c23fa6..ca6e410147b7 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java @@ -38,7 +38,7 @@ class ConsoleLauncherWrapperResult implements TestExecutionSummary { this.err = err; this.code = result.getExitCode(); this.summary = (TestExecutionSummary) result.getValue() // - .filter(it -> it instanceof TestExecutionSummary) // + .filter(TestExecutionSummary.class::isInstance) // .orElse(null); } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserTests.java index 4d3133f66f27..dd036b1ffb70 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/ParserTests.java @@ -76,7 +76,7 @@ private static Stream data() { private TagExpression tagExpressionParsedFrom(String tagExpression) { return parser.parse(tagExpression).tagExpressionOrThrow( - (error) -> new RuntimeException("[" + tagExpression + "] should be parsable")); + error -> new RuntimeException("[" + tagExpression + "] should be parsable")); } } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java index 659174d43310..9682e8ee6f21 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/tagexpression/TokenizerTests.java @@ -79,11 +79,11 @@ void extractStartPositionOfRawString() { } private Stream startIndicesExtractedFrom(String expression) { - return tokensExtractedFrom(expression).map(token -> token.startIndex()); + return tokensExtractedFrom(expression).map(Token::startIndex); } private Stream rawStringsExtractedFrom(String expression) { - return tokensExtractedFrom(expression).map(token -> token.rawString()); + return tokensExtractedFrom(expression).map(Token::rawString); } private List tokenStringsExtractedFrom(@Nullable String expression) { From c848ed31f590e4ee7384ce67d46a1117ae881464 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:45:19 +0200 Subject: [PATCH 222/521] Avoid unnecessary static imports --- .../junit/jupiter/api/parallel/LockTests.java | 2 +- .../parallel/ResourceLockAnnotationTests.java | 2 +- .../AbstractExecutableInvokerTests.java | 10 +++---- .../engine/BeforeAndAfterSuiteTests.java | 28 +++++++++---------- 4 files changed, 21 insertions(+), 21 deletions(-) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/LockTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/LockTests.java index f0e54f73424f..a311d83bd702 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/LockTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/LockTests.java @@ -14,9 +14,9 @@ import static org.junit.jupiter.api.EqualsAndHashCodeAssertions.assertEqualsAndHashCode; import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ; import static org.junit.jupiter.api.parallel.ResourceAccessMode.READ_WRITE; -import static org.junit.jupiter.api.parallel.ResourceLocksProvider.Lock; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.parallel.ResourceLocksProvider.Lock; /** * Unit tests for {@link Lock}. diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLockAnnotationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLockAnnotationTests.java index cc300beee64e..73c01e8ec3e3 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLockAnnotationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/parallel/ResourceLockAnnotationTests.java @@ -16,7 +16,6 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectIteration; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; -import static org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode; import static org.junit.platform.testkit.engine.EventConditions.finishedWithFailure; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.instanceOf; import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; @@ -50,6 +49,7 @@ import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.hierarchical.ExclusiveResource; +import org.junit.platform.engine.support.hierarchical.ExclusiveResource.LockMode; import org.junit.platform.testkit.engine.Event; /** diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java index 18291aefb8d6..683c5c212f9a 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java @@ -12,11 +12,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConfigurableParameterResolver; -import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConstructorInjectionTestCase; -import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.MethodSource; -import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.NumberParameterResolver; -import static org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.StringParameterResolver; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -28,6 +23,11 @@ import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.engine.config.JupiterConfiguration; +import org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConfigurableParameterResolver; +import org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.ConstructorInjectionTestCase; +import org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.MethodSource; +import org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.NumberParameterResolver; +import org.junit.jupiter.engine.execution.ParameterResolutionUtilsTests.StringParameterResolver; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.commons.support.ReflectionSupport; import org.junit.platform.commons.util.ReflectionUtils; diff --git a/platform-tests/src/test/java/org/junit/platform/suite/engine/BeforeAndAfterSuiteTests.java b/platform-tests/src/test/java/org/junit/platform/suite/engine/BeforeAndAfterSuiteTests.java index 186cd71304f3..bcfb56f8ecc0 100644 --- a/platform-tests/src/test/java/org/junit/platform/suite/engine/BeforeAndAfterSuiteTests.java +++ b/platform-tests/src/test/java/org/junit/platform/suite/engine/BeforeAndAfterSuiteTests.java @@ -16,20 +16,6 @@ import static org.junit.platform.commons.util.CollectionUtils.getOnlyElement; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.suite.engine.SuiteEngineDescriptor.ENGINE_ID; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingBeforeAndAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingBeforeSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonStaticAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonStaticBeforeSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonVoidAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonVoidBeforeSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.ParameterAcceptingAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.ParameterAcceptingBeforeSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.PrivateAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.PrivateBeforeSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SeveralFailingBeforeAndAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SubclassWithBeforeAndAfterSuite; -import static org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SuccessfulBeforeAndAfterSuite; import static org.junit.platform.testkit.engine.EventConditions.container; import static org.junit.platform.testkit.engine.EventConditions.event; import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; @@ -52,6 +38,20 @@ import org.junit.platform.suite.api.AfterSuite; import org.junit.platform.suite.api.BeforeSuite; import org.junit.platform.suite.engine.testcases.StatefulTestCase; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingBeforeAndAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.FailingBeforeSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonStaticAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonStaticBeforeSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonVoidAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.NonVoidBeforeSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.ParameterAcceptingAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.ParameterAcceptingBeforeSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.PrivateAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.PrivateBeforeSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SeveralFailingBeforeAndAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SubclassWithBeforeAndAfterSuite; +import org.junit.platform.suite.engine.testsuites.LifecycleMethodsSuites.SuccessfulBeforeAndAfterSuite; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.EngineTestKit; From 6511e30c589a66dfd3bbf1abc04c8f8e058795a5 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:46:28 +0200 Subject: [PATCH 223/521] Consistent declaration of if-blocks --- .../params/converter/AnnotationBasedArgumentConverter.java | 2 +- .../org/junit/platform/engine/DefaultDiscoveryIssue.java | 3 ++- .../EnableRuleMigrationSupportWithBothRuleTypesTests.java | 6 ++++-- ...rceSupportForDifferentDeclaredReturnTypesRulesTests.java | 6 ++++-- ...rnalResourceSupportForMixedMethodAndFieldRulesTests.java | 3 ++- .../ExternalResourceSupportForMultipleFieldRulesTests.java | 6 ++++-- .../ExternalResourceSupportForMultipleMethodRulesTests.java | 6 ++++-- .../VerifierSupportForMixedMethodAndFieldRulesTests.java | 6 ++++-- .../rules/WrongExtendWithForVerifierFieldTests.java | 3 ++- .../rules/WrongExtendWithForVerifierMethodTests.java | 3 ++- .../jupiter/params/ParameterizedTestIntegrationTests.java | 3 ++- .../support/descriptor/AbstractTestDescriptorTests.java | 6 ++++-- 12 files changed, 35 insertions(+), 18 deletions(-) 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 b36a604e86e7..ca1d68bb6aca 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 @@ -45,7 +45,7 @@ public AnnotationBasedArgumentConverter() { @Override public final void accept(A annotation) { this.annotation = Preconditions.notNull(annotation, "annotation must not be null"); - ; + } @Override diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java index f722facb7fa0..c0c2b7647d8d 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java @@ -59,8 +59,9 @@ public Optional cause() { @Override public boolean equals(Object o) { - if (o == null || getClass() != o.getClass()) + if (o == null || getClass() != o.getClass()) { return false; + } DefaultDiscoveryIssue that = (DefaultDiscoveryIssue) o; return this.severity == that.severity // && Objects.equals(this.message, that.message) // diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java index 1ad5ee93778d..36a76e0442a0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java @@ -80,10 +80,12 @@ void beforeMethodOfBothRule2WasExecuted() { static void afterMethodsOfBothRulesWereExecuted() { assertEquals(1, numberOfRule1InstancesCreated); assertEquals(1, numberOfRule2InstancesCreated); - if (!afterOfRule1WasExecuted) + if (!afterOfRule1WasExecuted) { fail(); - if (!afterOfRule2WasExecuted) + } + if (!afterOfRule2WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java index c71f63ac9178..88175349a909 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java @@ -57,10 +57,12 @@ void beforeMethodsOfBothRulesWereExecuted() { @AfterAll static void afterMethodsOfBothRulesWereExecuted() { - if (!afterOfRule1WasExecuted) + if (!afterOfRule1WasExecuted) { fail(); - if (!afterOfRule2WasExecuted) + } + if (!afterOfRule2WasExecuted) { fail(); + } } private static class MyExternalResource1 extends ExternalResource { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java index c4fc1b66a0d3..9cfaa726f49b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java @@ -70,8 +70,9 @@ void constructorsAndBeforeEachMethodsOfAllRulesWereExecuted() { @AfterAll static void afterMethodsOfAllRulesWereExecuted() { // beforeEach methods of rules from methods are run before those from fields but in reverse order - if (!asList(initEvents.get(2), initEvents.get(3), initEvents.get(0), initEvents.get(1)).equals(afterEvents)) + if (!asList(initEvents.get(2), initEvents.get(3), initEvents.get(0), initEvents.get(1)).equals(afterEvents)) { fail(); + } } static class MyExternalResource extends ExternalResource { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java index f2ba8354f6cc..4dcbc190b533 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java @@ -62,10 +62,12 @@ void beforeMethodsOfBothRulesWereExecuted() { @AfterAll static void afterMethodsOfBothRulesWereExecuted() { - if (!afterOfRule1WasExecuted) + if (!afterOfRule1WasExecuted) { fail(); - if (!afterOfRule2WasExecuted) + } + if (!afterOfRule2WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java index e5ad795f43c0..ba9dd82fafb5 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java @@ -66,10 +66,12 @@ void beforeMethodsOfBothRulesWereExecuted() { @AfterAll static void afterMethodsOfBothRulesWereExecuted() { - if (!afterOfRule1WasExecuted) + if (!afterOfRule1WasExecuted) { fail(); - if (!afterOfRule2WasExecuted) + } + if (!afterOfRule2WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java index 42a292c7e860..d195ae72a7d7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java @@ -53,10 +53,12 @@ void testNothing() { @AfterAll static void afterMethodsOfBothRulesWereExecuted() { - if (!afterOfRule1WasExecuted) + if (!afterOfRule1WasExecuted) { fail(); - if (!afterOfRule2WasExecuted) + } + if (!afterOfRule2WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java index ec4c7871fdb3..03f19dd584a5 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java @@ -39,8 +39,9 @@ void testNothing() { @AfterAll static void afterMethodOfRuleWasNotExecuted() { - if (afterOfRule1WasExecuted) + if (afterOfRule1WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java index 77d89f7bddb7..02741f9831dc 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java @@ -43,8 +43,9 @@ void testNothing() { @AfterAll static void afterMethodsOfBothRulesWereExecuted() { - if (afterOfRule1WasExecuted) + if (afterOfRule1WasExecuted) { fail(); + } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index 379efee6ca38..f9edc394c990 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -2667,8 +2667,9 @@ static class ExceptionInStaticInitializerTestCase { static { //noinspection ConstantValue - if (true) + if (true) { throw new RuntimeException("boom"); + } } private static Stream getArguments() { diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptorTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptorTests.java index bfa105bf1168..9f2954636e74 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptorTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptorTests.java @@ -111,8 +111,9 @@ void visitAllNodes() { @Test void pruneLeaf() { TestDescriptor.Visitor visitor = descriptor -> { - if (descriptor.getUniqueId().equals(UniqueId.root("leaf", "leaf1-1"))) + if (descriptor.getUniqueId().equals(UniqueId.root("leaf", "leaf1-1"))) { descriptor.removeFromHierarchy(); + } }; engineDescriptor.accept(visitor); @@ -128,8 +129,9 @@ void pruneLeaf() { void pruneGroup() { final var countVisited = new AtomicInteger(); TestDescriptor.Visitor visitor = descriptor -> { - if (descriptor.getUniqueId().equals(UniqueId.root("group", "group1"))) + if (descriptor.getUniqueId().equals(UniqueId.root("group", "group1"))) { descriptor.removeFromHierarchy(); + } countVisited.incrementAndGet(); }; engineDescriptor.accept(visitor); From a721bd0953946875a4da318e6065302e9aa71c8c Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 11:47:20 +0200 Subject: [PATCH 224/521] Use switch expression --- .../execution/ParameterResolutionUtilsTests.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index fbf2f4a9fb39..6612530bb977 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -120,14 +120,11 @@ void resolveArgumentsViaParameterResolver() { void resolveMultipleArguments() { testMethodWith("multipleParameters", String.class, Integer.class, Double.class); register(ConfigurableParameterResolver.supportsAndResolvesTo(parameterContext -> { - switch (parameterContext.getIndex()) { - case 0: - return "0"; - case 1: - return 1; - default: - return 2.0; - } + return switch (parameterContext.getIndex()) { + case 0 -> "0"; + case 1 -> 1; + default -> 2.0; + }; })); Object[] arguments = resolveMethodParameters(); From 5802530ab770f8f01e3e01df30c251a2eeb0178a Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 12:24:06 +0200 Subject: [PATCH 225/521] Consistent use of "instanceof pattern matching" --- .../jupiter/engine/descriptor/JupiterTestDescriptor.java | 4 ++-- .../engine/descriptor/NestedClassTestDescriptor.java | 6 +++--- .../junit/jupiter/engine/descriptor/ResourceLockAware.java | 4 ++-- .../engine/execution/InterceptingExecutableInvoker.java | 4 ++-- .../org/junit/platform/commons/util/CollectionUtils.java | 4 ++-- .../org/junit/platform/commons/util/ReflectionUtils.java | 4 ++-- .../platform/engine/support/hierarchical/NodeUtils.java | 4 ++-- .../injection/sample/MapOfStringsParameterResolver.java | 4 ++-- 8 files changed, 17 insertions(+), 17 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java index 028450c8cbfe..8bd1c7941b5a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/JupiterTestDescriptor.java @@ -177,8 +177,8 @@ public static ExecutionMode toExecutionMode(org.junit.jupiter.api.parallel.Execu @Override public Set getExclusiveResources() { - if (this instanceof ResourceLockAware aware) { - return aware.determineExclusiveResources().collect(toSet()); + if (this instanceof ResourceLockAware resourceLockAware) { + return resourceLockAware.determineExclusiveResources().collect(toSet()); } return emptySet(); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java index 43b397df42d0..d4b354b09d0e 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/NestedClassTestDescriptor.java @@ -89,9 +89,9 @@ public List> getEnclosingTestClasses() { @API(status = INTERNAL, since = "5.12") public static List> getEnclosingTestClasses(@Nullable TestDescriptor parent) { - if (parent instanceof TestClassAware parentClassDescriptor) { - List> result = new ArrayList<>(parentClassDescriptor.getEnclosingTestClasses()); - result.add(parentClassDescriptor.getTestClass()); + if (parent instanceof TestClassAware testClassAwareParent) { + List> result = new ArrayList<>(testClassAwareParent.getEnclosingTestClasses()); + result.add(testClassAwareParent.getTestClass()); return result; } return emptyList(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java index 664462e45d6a..d7d5a85e6cbf 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ResourceLockAware.java @@ -35,8 +35,8 @@ default Stream determineExclusiveResources() { Deque ancestors = new ArrayDeque<>(); TestDescriptor parent = this.getParent().orElse(null); - while (parent instanceof ResourceLockAware) { - ancestors.addFirst((ResourceLockAware) parent); + while (parent instanceof ResourceLockAware resourceLockAwareParent) { + ancestors.addFirst(resourceLockAwareParent); parent = parent.getParent().orElse(null); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java index 8dc93f242fa0..8a9a25968973 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java @@ -81,8 +81,8 @@ public T invoke(Constructor constructor, Optional outerInstance, public T invoke(Method method, @Nullable Object target, ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall interceptorCall) { - @SuppressWarnings("unchecked") - Optional optionalTarget = (target instanceof Optional ? (Optional) target + @SuppressWarnings({ "unchecked", "rawtypes" }) + Optional optionalTarget = (target instanceof Optional optional ? optional : Optional.ofNullable(target)); @Nullable Object[] arguments = resolveParameters(method, optionalTarget, extensionContext, extensionRegistry); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java index 2305526dd882..3ebbd28e9b99 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/util/CollectionUtils.java @@ -85,8 +85,8 @@ private CollectionUtils() { } private static T firstElement(Collection collection) { - return collection instanceof List // - ? ((List) collection).get(0) // + return collection instanceof List list // + ? list.get(0) // : collection.iterator().next(); } 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 cac9bbffc86f..2d7c11e3eace 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 @@ -1930,8 +1930,8 @@ private static boolean isSearchable(@Nullable Class clazz) { * exception}; otherwise, this method returns the supplied {@code Throwable}. */ static Throwable getUnderlyingCause(Throwable t) { - if (t instanceof InvocationTargetException) { - return getUnderlyingCause(((InvocationTargetException) t).getTargetException()); + if (t instanceof InvocationTargetException ite) { + return getUnderlyingCause(ite.getTargetException()); } return t; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeUtils.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeUtils.java index 4f916837c32c..a624f2300efa 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeUtils.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeUtils.java @@ -21,9 +21,9 @@ private NodeUtils() { /* no-op */ } - @SuppressWarnings("unchecked") + @SuppressWarnings({ "unchecked", "rawtypes" }) static Node asNode(TestDescriptor testDescriptor) { - return (testDescriptor instanceof Node ? (Node) testDescriptor : noOpNode); + return (testDescriptor instanceof Node node ? node : noOpNode); } @SuppressWarnings("rawtypes") diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/MapOfStringsParameterResolver.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/MapOfStringsParameterResolver.java index e669fe26b07b..d0e2ddf96462 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/MapOfStringsParameterResolver.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/injection/sample/MapOfStringsParameterResolver.java @@ -29,10 +29,10 @@ public class MapOfStringsParameterResolver implements ParameterResolver { @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Type type = parameterContext.getParameter().getParameterizedType(); - if (!(type instanceof ParameterizedType)) { + if (!(type instanceof ParameterizedType parameterizedType)) { return false; } - Type[] actualTypeArguments = ((ParameterizedType) type).getActualTypeArguments(); + Type[] actualTypeArguments = parameterizedType.getActualTypeArguments(); if (actualTypeArguments.length != 2) { return false; } From df6fe916d66e850a4755b4a5070614630aaf280a Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 12:24:32 +0200 Subject: [PATCH 226/521] Inline method --- .../tasks/CustomClassLoaderCloseStrategy.java | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java index f859e2bb687a..a5221b569334 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/CustomClassLoaderCloseStrategy.java @@ -31,17 +31,13 @@ public enum CustomClassLoaderCloseStrategy { @Override public void handle(ClassLoader customClassLoader) { - if (customClassLoader instanceof AutoCloseable closeable) { - close(closeable); - } - } - - private void close(AutoCloseable customClassLoader) { - try { - customClassLoader.close(); - } - catch (Exception e) { - throw new JUnitException("Failed to close custom class loader", e); + if (customClassLoader instanceof @SuppressWarnings("resource") AutoCloseable closeable) { + try { + closeable.close(); + } + catch (Exception ex) { + throw new JUnitException("Failed to close custom class loader", ex); + } } } }, @@ -54,6 +50,7 @@ private void close(AutoCloseable customClassLoader) { * afterward. */ KEEP_OPEN { + @Override public void handle(ClassLoader customClassLoader) { // do nothing From 7ed841b894b58590e9319085655614663a1d9fed Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 12:28:58 +0200 Subject: [PATCH 227/521] Consistent equals() implementations using this/that and pattern matching --- .../org/junit/platform/engine/TestTag.java | 5 +--- .../platform/launcher/TestIdentifier.java | 5 +--- .../FallbackStringToObjectConverterTests.java | 24 +++---------------- 3 files changed, 5 insertions(+), 29 deletions(-) diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java index 979278134116..0a2e7002a330 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestTag.java @@ -132,10 +132,7 @@ public String getName() { @Override public boolean equals(Object obj) { - if (obj instanceof TestTag that) { - return Objects.equals(this.name, that.name); - } - return false; + return (obj instanceof TestTag that && Objects.equals(this.name, that.name)); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index b5918cf6f365..f2700882724f 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -251,10 +251,7 @@ public Set getTags() { @Override public boolean equals(Object obj) { - if (obj instanceof TestIdentifier that) { - return Objects.equals(this.uniqueId, that.uniqueId); - } - return false; + return (obj instanceof TestIdentifier that && Objects.equals(this.uniqueId, that.uniqueId)); } @Override diff --git a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java index cc2e8b38469d..5bfc428ec8d7 100644 --- a/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java +++ b/platform-tests/src/test/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverterTests.java @@ -158,13 +158,7 @@ Book nonStaticFactory(String title) { @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Book that)) { - return false; - } - return Objects.equals(this.title, that.title); + return (this == obj) || (obj instanceof Book that && Objects.equals(this.title, that.title)); } @Override @@ -184,13 +178,7 @@ static class Journal { @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Journal that)) { - return false; - } - return Objects.equals(this.title, that.title); + return (this == obj) || (obj instanceof Journal that && Objects.equals(this.title, that.title)); } @Override @@ -218,13 +206,7 @@ static Newspaper of(String title) { @Override public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (!(obj instanceof Newspaper that)) { - return false; - } - return Objects.equals(this.title, that.title); + return (this == obj) || (obj instanceof Newspaper that && Objects.equals(this.title, that.title)); } @Override From 037d4df2881e038d92a0dbb0a71532356fba460a Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 30 May 2025 12:55:45 +0200 Subject: [PATCH 228/521] Consistently use switch expressions --- .../descriptor/TestMethodTestDescriptor.java | 12 +++--------- .../params/ArgumentCountValidationMode.java | 3 ++- .../jupiter/params/ArgumentCountValidator.java | 14 ++++++-------- .../listeners/SummaryGeneratingListener.java | 14 +++++--------- .../LoggingLauncherDiscoveryListener.java | 14 +++++--------- .../junit/platform/testkit/engine/Executions.java | 14 ++++---------- .../engine/extension/RepeatedTestTests.java | 6 ++---- .../tooling/support/tests/MavenRepoProxy.java | 11 ++++------- 8 files changed, 31 insertions(+), 57 deletions(-) diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java index bcf5a5fc21d7..674761ffb1ba 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java @@ -285,15 +285,9 @@ public void nodeFinished(JupiterEngineExecutionContext context, TestDescriptor d invokeTestWatchers(context, true, watcher -> { switch (status) { - case SUCCESSFUL: - watcher.testSuccessful(extensionContext); - break; - case ABORTED: - watcher.testAborted(extensionContext, result.getThrowable().orElse(null)); - break; - case FAILED: - watcher.testFailed(extensionContext, result.getThrowable().orElse(null)); - break; + case SUCCESSFUL -> watcher.testSuccessful(extensionContext); + case ABORTED -> watcher.testAborted(extensionContext, result.getThrowable().orElse(null)); + case FAILED -> watcher.testFailed(extensionContext, result.getThrowable().orElse(null)); } }); } 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..6aa5a092eb9b 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 @@ -55,5 +55,6 @@ public enum ArgumentCountValidationMode { *

    When there are more arguments provided than declared by the * parameterized class or method, this raises an error. */ - STRICT, + STRICT + } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java index 4495eec648c0..135b4986a03c 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ArgumentCountValidator.java @@ -40,10 +40,9 @@ class ArgumentCountValidator { void validate(ExtensionContext extensionContext) { ArgumentCountValidationMode argumentCountValidationMode = getArgumentCountValidationMode(extensionContext); switch (argumentCountValidationMode) { - case DEFAULT: - case NONE: - return; - case STRICT: + case DEFAULT, NONE -> { + } + case STRICT -> { int consumedCount = this.declarationContext.getResolverFacade().determineConsumedArgumentCount( this.arguments); int totalCount = this.arguments.getTotalLength(); @@ -53,10 +52,9 @@ void validate(ExtensionContext extensionContext) { pluralize(consumedCount, "parameter", "parameters"), pluralize(totalCount, "was", "were"), totalCount, pluralize(totalCount, "argument", "arguments"), Arrays.toString(this.arguments.getAllPayloads()))); - break; - default: - throw new ExtensionConfigurationException( - "Unsupported argument count validation mode: " + argumentCountValidationMode); + } + default -> throw new ExtensionConfigurationException( + "Unsupported argument count validation mode: " + argumentCountValidationMode); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java index 49d20e0331aa..c972b968a925 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java @@ -113,27 +113,25 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult switch (testExecutionResult.getStatus()) { - case SUCCESSFUL: { + case SUCCESSFUL -> { if (testIdentifier.isContainer()) { summary.containersSucceeded.incrementAndGet(); } if (testIdentifier.isTest()) { summary.testsSucceeded.incrementAndGet(); } - break; } - case ABORTED: { + case ABORTED -> { if (testIdentifier.isContainer()) { summary.containersAborted.incrementAndGet(); } if (testIdentifier.isTest()) { summary.testsAborted.incrementAndGet(); } - break; } - case FAILED: { + case FAILED -> { if (testIdentifier.isContainer()) { summary.containersFailed.incrementAndGet(); } @@ -142,12 +140,10 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult } testExecutionResult.getThrowable().ifPresent( throwable -> summary.addFailure(testIdentifier, throwable)); - break; } - default: - throw new PreconditionViolationException( - "Unsupported execution status:" + testExecutionResult.getStatus()); + default -> throw new PreconditionViolationException( + "Unsupported execution status:" + testExecutionResult.getStatus()); } } diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java index ed175537540d..922b9068b2e4 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/discovery/LoggingLauncherDiscoveryListener.java @@ -69,14 +69,10 @@ public void engineDiscoveryFinished(UniqueId engineId, EngineDiscoveryResult res @Override public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, SelectorResolutionResult result) { switch (result.getStatus()) { - case RESOLVED: - logger.debug(() -> selector + " was resolved by " + engineId); - break; - case FAILED: - logger.error(result.getThrowable().orElse(null), - () -> "Resolution of " + selector + " by " + engineId + " failed"); - break; - case UNRESOLVED: + case RESOLVED -> logger.debug(() -> selector + " was resolved by " + engineId); + case FAILED -> logger.error(result.getThrowable().orElse(null), + () -> "Resolution of " + selector + " by " + engineId + " failed"); + case UNRESOLVED -> { Consumer> loggingConsumer = logger::debug; if (selector instanceof UniqueIdSelector uniqueIdSelector) { UniqueId uniqueId = uniqueIdSelector.getUniqueId(); @@ -85,7 +81,7 @@ public void selectorProcessed(UniqueId engineId, DiscoverySelector selector, Sel } } loggingConsumer.accept(() -> selector + " could not be resolved by " + engineId); - break; + } } } diff --git a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java index d17173d11c79..edfd4311fd67 100644 --- a/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java +++ b/junit-platform-testkit/src/main/java/org/junit/platform/testkit/engine/Executions.java @@ -254,11 +254,8 @@ private static List createExecutions(List events) { for (Event event : events) { switch (event.getType()) { - case STARTED: { - executionStarts.put(event.getTestDescriptor(), event.getTimestamp()); - break; - } - case SKIPPED: { + case STARTED -> executionStarts.put(event.getTestDescriptor(), event.getTimestamp()); + case SKIPPED -> { // Based on the Javadoc for EngineExecutionListener.executionSkipped(...), // a skipped descriptor must never be reported as started or finished, // but just in case a TestEngine does not adhere to that contract, we @@ -271,9 +268,8 @@ private static List createExecutions(List events) { Execution skippedEvent = Execution.skipped(event.getTestDescriptor(), timestamp, timestamp, event.getRequiredPayload(String.class)); executions.add(skippedEvent); - break; } - case FINISHED: { + case FINISHED -> { Instant startInstant = executionStarts.remove(event.getTestDescriptor()); Instant endInstant = event.getTimestamp(); @@ -285,11 +281,9 @@ private static List createExecutions(List events) { endInstant, event.getRequiredPayload(TestExecutionResult.class)); executions.add(finishedEvent); } - break; } - default: { + default -> { // Ignore other events - break; } } } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/RepeatedTestTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/RepeatedTestTests.java index bed689112b13..23750bfc0d4d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/RepeatedTestTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/RepeatedTestTests.java @@ -136,15 +136,13 @@ public LifecycleMethodTests(RepetitionInfo repetitionInfo) { @AfterEach void beforeAndAfterEach(TestInfo testInfo, RepetitionInfo repetitionInfo) { switch (testInfo.getTestMethod().get().getName()) { - case "repeatedOnce": { + case "repeatedOnce" -> { assertThat(repetitionInfo.getCurrentRepetition()).isEqualTo(1); assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(1); - break; } - case "repeatedFortyTwoTimes": { + case "repeatedFortyTwoTimes" -> { assertThat(repetitionInfo.getCurrentRepetition()).isBetween(1, 42); assertThat(repetitionInfo.getTotalRepetitions()).isEqualTo(42); - break; } } } diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenRepoProxy.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenRepoProxy.java index 2525a5c8c588..b9c85d6ddaed 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenRepoProxy.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/MavenRepoProxy.java @@ -40,19 +40,16 @@ private MavenRepoProxy(String proxiedUrl, int port) throws IOException { httpServer.createContext("/", exchange -> { try (exchange) { switch (exchange.getRequestMethod()) { - case "HEAD": - case "GET": - if (FORBIDDEN_PATHS.stream().anyMatch( - it -> exchange.getRequestURI().getPath().startsWith(it))) { + case "HEAD", "GET" -> { + if (FORBIDDEN_PATHS.stream().anyMatch(exchange.getRequestURI().getPath()::startsWith)) { exchange.sendResponseHeaders(404, -1); break; } var redirectUrl = proxiedUrl + exchange.getRequestURI().getPath(); exchange.getResponseHeaders().add("Location", redirectUrl); exchange.sendResponseHeaders(302, -1); - break; - default: - exchange.sendResponseHeaders(405, -1); + } + default -> exchange.sendResponseHeaders(405, -1); } } catch (Exception e) { From 217a55893c85726ec7b1226eeae578806c52966c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 12:00:25 +0200 Subject: [PATCH 229/521] Release 5.13.0 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3f1c7842bbc4..49bb5adf6d05 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository is the home of JUnit Platform, Jupiter, and Vintage. ## Latest Releases -- General Availability (GA): [JUnit 5.12.2](https://github.com/junit-team/junit5/releases/tag/r5.12.2) (April 11, 2025) +- General Availability (GA): [JUnit 5.13.0](https://github.com/junit-team/junit5/releases/tag/r5.13.0) (May 30, 2025) - Preview (Milestone/Release Candidate): [JUnit 5.13.0-RC1](https://github.com/junit-team/junit5/releases/tag/r5.13.0-RC1) (May 16, 2025) ## Documentation From 6def414df865e5a887de4744d4e4ef583c99b06d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 12:18:15 +0200 Subject: [PATCH 230/521] Revert "Don't error on already closed milestones" This reverts commit 52ae1126 --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc3320b3039f..e0ff6eea2e5d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -119,12 +119,12 @@ jobs: with: result-encoding: string script: | - const milestones = await github.rest.issues.listMilestones({ + const openMilestones = await github.rest.issues.listMilestones({ owner: context.repo.owner, repo: context.repo.repo, - state: 'all' + state: 'open' }); - const [milestone] = milestones.data.filter(x => x.title === "${{ inputs.releaseVersion }}") + const [milestone] = openMilestones.data.filter(x => x.title === "${{ inputs.releaseVersion }}") if (!milestone) { throw new Error('Milestone "${{ inputs.releaseVersion }}" not found'); } From 357f8fb6b629ec8324775bf84c78a1daf4e1f8b3 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 13:46:33 +0200 Subject: [PATCH 231/521] Update supported versions --- SECURITY.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SECURITY.md b/SECURITY.md index 4d4bad5f6641..90102e191264 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -11,8 +11,8 @@ You'll find more information about the key here: [KEYS](./KEYS) | Version | Supported | |---------| ------------------ | -| 5.12.x | :white_check_mark: | -| < 5.12 | :x: | +| 5.13.x | :white_check_mark: | +| < 5.13 | :x: | ## Reporting a Vulnerability From 5631ae577deb826ba2a5f8d3e1a7f6b8b68d379e Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 14:08:19 +0200 Subject: [PATCH 232/521] Use GraphQL API to list matching milestones to avoid pagination issues --- .github/workflows/release.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e0ff6eea2e5d..c7096aa4e1d5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -119,17 +119,30 @@ jobs: with: result-encoding: string script: | - const openMilestones = await github.rest.issues.listMilestones({ + const query = ` + query ($owner: String!, $repo: String!, $title: String!) { + repository(owner: $owner, name: $repo) { + milestones(first: 100, query: $title) { + nodes { + title + number + openIssueCount + } + } + } + } + `; + const {repository} = await github.graphql(query, { owner: context.repo.owner, repo: context.repo.repo, - state: 'open' + title: "${{ inputs.releaseVersion }}" }); - const [milestone] = openMilestones.data.filter(x => x.title === "${{ inputs.releaseVersion }}") + const [milestone] = repository.milestones.nodes.filter(it => it.title === "${{ inputs.releaseVersion }}") if (!milestone) { throw new Error('Milestone "${{ inputs.releaseVersion }}" not found'); } - if (milestone.open_issues > 0) { - throw new Error(`Milestone "${{ inputs.releaseVersion }}" has ${milestone.open_issues} open issue(s)`); + if (milestone.openIssueCount > 0) { + throw new Error(`Milestone "${{ inputs.releaseVersion }}" has ${milestone.openIssueCount} open issue(s)`); } const requestBody = { owner: context.repo.owner, From c571ba34230451f3ab2ef2f7047741b465d2e6a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 30 May 2025 18:02:21 +0000 Subject: [PATCH 233/521] Update ossf/scorecard-action action to v2.4.2 --- .github/workflows/ossf-scorecard.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index c24ae2e85e54..3e6d58b6a42b 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -26,7 +26,7 @@ jobs: persist-credentials: false - name: "Run analysis" - uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1 + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif From 0e2ff3a7f2a74823d49352d8c96b651c33d2c380 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 31 May 2025 09:55:02 +0200 Subject: [PATCH 234/521] Create initial 5.13.1 release notes from template --- .../docs/asciidoc/release-notes/index.adoc | 4 +- .../release-notes/release-notes-5.13.1.adoc | 67 +++++++++++++++++++ 2 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index 921e3dac46df..a4f401543146 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-6.0.0-M1.adoc[] +include::{basedir}/release-notes-6.0.0-M1.adoc[ + +include::{basedir}/release-notes-5.13.1.adoc[] include::{basedir}/release-notes-5.13.0.adoc[] diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc new file mode 100644 index 000000000000..abb783ac56e4 --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc @@ -0,0 +1,67 @@ +[[release-notes-5.13.1]] +== 5.13.1 + +*Date of Release:* ❓ + +*Scope:* ❓ + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit5-repo}+/milestone/97?closed=1+[5.13.1] milestone page in the JUnit repository +on GitHub. + + +[[release-notes-5.13.1-junit-platform]] +=== JUnit Platform + +[[release-notes-5.13.1-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.1-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.1-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.13.1-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-5.13.1-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.1-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.1-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.13.1-junit-vintage]] +=== JUnit Vintage + +[[release-notes-5.13.1-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.1-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.1-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ From d8c3f99a1378a2147b3fdac266f08853eb252266 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 31 May 2025 17:23:19 +0000 Subject: [PATCH 235/521] Update dependency com.puppycrawl.tools:checkstyle to v10.25.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7b0772e73597..9adce7a6ba81 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.24.0" +checkstyle = "10.25.0" eclipse = "4.35.0" jackson = "2.19.0" jacoco = "0.8.13" From 50ec93961fcf063848dd7b67314eb4c346d41848 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 2 Jun 2025 16:36:36 +0200 Subject: [PATCH 236/521] Update CI status badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49bb5adf6d05..a19f198286e6 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Ask JUnit-related questions on [StackOverflow] or use the Q&A category on [GitHu ## Continuous Integration Builds -[![CI Status](https://github.com/junit-team/junit5/workflows/CI/badge.svg)](https://github.com/junit-team/junit5/actions) [![Cross-Version Status](https://github.com/junit-team/junit5/workflows/Cross-Version/badge.svg)](https://github.com/junit-team/junit5/actions) +[![CI](https://github.com/junit-team/junit5/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/junit-team/junit5/actions/workflows/main.yml) [![Cross-Version](https://github.com/junit-team/junit5/actions/workflows/cross-version.yml/badge.svg?branch=main)](https://github.com/junit-team/junit5/actions/workflows/cross-version.yml) Official CI build server used to perform quick checks on submitted pull requests and for build matrices including the latest released OpenJDK and early access builds of the next From 2196d97edc152c2b0a8dda2d6ddffe66ab516d81 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 30 May 2025 14:37:03 +0200 Subject: [PATCH 237/521] Deprecate junit-jupiter-migrationsupport for removal in 7.0 --- .../asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 2 ++ .../src/docs/asciidoc/user-guide/appendix.adoc | 4 ++-- .../asciidoc/user-guide/migration-from-junit4.adoc | 6 ++++++ .../src/test/java/example/IgnoredTestsDemo.java | 1 + .../migrationsupport/EnableJUnit4MigrationSupport.java | 8 ++++++-- .../migrationsupport/conditions/IgnoreCondition.java | 6 ++++-- .../migrationsupport/conditions/package-info.java | 6 +++--- .../junit/jupiter/migrationsupport/package-info.java | 2 +- .../rules/EnableRuleMigrationSupport.java | 7 +++++-- .../rules/ExpectedExceptionSupport.java | 10 ++++++++-- .../rules/ExternalResourceSupport.java | 7 +++++-- .../migrationsupport/rules/VerifierSupport.java | 7 +++++-- .../migrationsupport/rules/adapter/package-info.java | 3 ++- .../rules/member/TestRuleAnnotatedMember.java | 2 +- .../migrationsupport/rules/member/package-info.java | 2 +- .../jupiter/migrationsupport/rules/package-info.java | 3 ++- .../conditions/IgnoreAnnotationIntegrationTests.java | 1 + .../conditions/IgnoreConditionTests.java | 1 + .../rules/AbstractTestRuleAdapterTests.java | 1 + ...ableRuleMigrationSupportWithBothRuleTypesTests.java | 1 + .../rules/ExpectedExceptionSupportTests.java | 1 + ...pportForDifferentDeclaredReturnTypesRulesTests.java | 1 + ...esourceSupportForMixedMethodAndFieldRulesTests.java | 1 + ...ernalResourceSupportForMultipleFieldRulesTests.java | 1 + ...rnalResourceSupportForMultipleMethodRulesTests.java | 1 + ...nalResourceSupportForTemporaryFolderFieldTests.java | 1 + .../LauncherBasedEnableRuleMigrationSupportTests.java | 1 + ...erifierSupportForMixedMethodAndFieldRulesTests.java | 1 + .../rules/WrongExtendWithForVerifierFieldTests.java | 1 + .../rules/WrongExtendWithForVerifierMethodTests.java | 1 + 30 files changed, 68 insertions(+), 22 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 626753edd77e..128ede0a735d 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -110,6 +110,8 @@ repository on GitHub. * The contracts for the `Executable` parameters of Kotlin-specific `assertTimeout` functions were changed from `callsInPlace(executable, EXACTLY_ONCE)` to `callsInPlace(executable, AT_MOST_ONCE)` which might result in compilation errors. +* The `junit-jupiter-migrationsupport` artifact and its contained classes are now + deprecated and will be removed in the next major version. [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/appendix.adoc b/documentation/src/docs/asciidoc/user-guide/appendix.adoc index ef8c60dd4385..75744b243609 100644 --- a/documentation/src/docs/asciidoc/user-guide/appendix.adoc +++ b/documentation/src/docs/asciidoc/user-guide/appendix.adoc @@ -108,8 +108,8 @@ Please refer to the corresponding sections for <> in JUnit Jupiter. `junit-jupiter-migrationsupport`:: - Support for migrating from JUnit 4 to JUnit Jupiter; only required for support for - JUnit 4's `@Ignore` annotation and for running selected JUnit 4 rules. + _Deprecated_ support for migrating from JUnit 4 to JUnit Jupiter; only required for + support for JUnit 4's `@Ignore` annotation and for running selected JUnit 4 rules. [[dependency-metadata-junit-vintage]] ==== JUnit Vintage diff --git a/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc b/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc index da24b1665ada..16ef3371a1d1 100644 --- a/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc +++ b/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc @@ -256,6 +256,9 @@ include::{testDir}/example/ParameterizedMigrationDemo.java[tags=after] [[migrating-from-junit4-rule-support]] === Limited JUnit 4 Rule Support +WARNING: _JUnit 4 rule support_ is deprecated for removal since version 6.0.0. Please +migrate to the corresponding APIs and extensions provided by JUnit Jupiter. + As stated above, JUnit Jupiter does not and will not support JUnit 4 rules natively. The JUnit team realizes, however, that many organizations, especially large ones, are likely to have large JUnit 4 code bases that make use of custom rules. To serve these @@ -290,6 +293,9 @@ extension model of JUnit Jupiter instead of the rule-based model of JUnit 4. [[migrating-from-junit4-ignore-annotation-support]] === JUnit 4 @Ignore Support +WARNING: _JUnit 4 `@Ignore` support_ is deprecated for removal since version 6.0.0. Please +use JUnit Jupiter's `@Disabled` annotation instead. + In order to provide a smooth migration path from JUnit 4 to JUnit Jupiter, the `junit-jupiter-migrationsupport` module provides support for JUnit 4's `@Ignore` annotation analogous to Jupiter's `{Disabled}` annotation. diff --git a/documentation/src/test/java/example/IgnoredTestsDemo.java b/documentation/src/test/java/example/IgnoredTestsDemo.java index 4718c922ca9f..3daf582d6f90 100644 --- a/documentation/src/test/java/example/IgnoredTestsDemo.java +++ b/documentation/src/test/java/example/IgnoredTestsDemo.java @@ -16,6 +16,7 @@ import org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport; // @ExtendWith(IgnoreCondition.class) +@SuppressWarnings("removal") @EnableJUnit4MigrationSupport class IgnoredTestsDemo { diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/EnableJUnit4MigrationSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/EnableJUnit4MigrationSupport.java index 0c9c04778493..540b42ad5150 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/EnableJUnit4MigrationSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/EnableJUnit4MigrationSupport.java @@ -10,7 +10,7 @@ package org.junit.jupiter.migrationsupport; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -47,10 +47,14 @@ * @see ExpectedExceptionSupport * @see IgnoreCondition * @see EnableRuleMigrationSupport + * @deprecated Please migrate to Jupiter extensions and use + * {@link org.junit.jupiter.api.Disabled @Disabled} instead. */ +@SuppressWarnings("removal") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -@API(status = STABLE, since = "5.7") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) @EnableRuleMigrationSupport @ExtendWith(IgnoreCondition.class) public @interface EnableJUnit4MigrationSupport { diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java index efceb5723117..ed8e2e434b37 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/IgnoreCondition.java @@ -10,7 +10,7 @@ package org.junit.jupiter.migrationsupport.conditions; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import java.lang.reflect.AnnotatedElement; @@ -32,8 +32,10 @@ * @see org.junit.jupiter.api.Disabled @Disabled * @see #evaluateExecutionCondition(ExtensionContext) * @see org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport + * @deprecated Please use {@link org.junit.jupiter.api.Disabled @Disabled} instead. */ -@API(status = STABLE, since = "5.7") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) public class IgnoreCondition implements ExecutionCondition { private static final ConditionEvaluationResult ENABLED = // diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java index 27c646ec3448..198cf1d1c686 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/conditions/package-info.java @@ -1,7 +1,7 @@ /** - * Extensions which provide support for conditional test execution features of - * JUnit 4 (e.g., the {@link org.junit.Ignore @Ignore} annotation) within JUnit - * Jupiter. + * Deprecated extensions that provide support for conditional test + * execution features of JUnit 4 (e.g., the {@link org.junit.Ignore @Ignore} + * annotation) within JUnit Jupiter. */ @NullMarked diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java index 1f14ec941a3c..ad4c3815a608 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/package-info.java @@ -1,5 +1,5 @@ /** - * Support for migrating from JUnit 4 to JUnit Jupiter. + * Deprecated support for migrating from JUnit 4 to JUnit Jupiter. */ @NullMarked diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupport.java index 243874b8265e..88d713067c3e 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupport.java @@ -10,7 +10,7 @@ package org.junit.jupiter.migrationsupport.rules; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -36,10 +36,13 @@ * @see VerifierSupport * @see ExpectedExceptionSupport * @see org.junit.jupiter.migrationsupport.EnableJUnit4MigrationSupport + * @deprecated Please migrate to Jupiter extensions. */ +@SuppressWarnings("removal") @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) -@API(status = STABLE, since = "5.7") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) @ExtendWith(ExternalResourceSupport.class) @ExtendWith(VerifierSupport.class) @ExtendWith(ExpectedExceptionSupport.class) diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java index bf6abc2bcf39..ec84443b488d 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupport.java @@ -12,7 +12,7 @@ import static java.lang.Boolean.FALSE; import static java.lang.Boolean.TRUE; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; @@ -20,6 +20,7 @@ import org.junit.jupiter.api.extension.ExtensionContext.Namespace; import org.junit.jupiter.api.extension.ExtensionContext.Store; import org.junit.jupiter.api.extension.TestExecutionExceptionHandler; +import org.junit.jupiter.api.function.Executable; import org.junit.jupiter.migrationsupport.rules.adapter.ExpectedExceptionAdapter; import org.junit.rules.ExpectedException; @@ -38,8 +39,13 @@ * @see org.junit.rules.ExpectedException * @see org.junit.rules.TestRule * @see org.junit.Rule + * @deprecated Please use + * {@link org.junit.jupiter.api.Assertions#assertThrows(Class, Executable)} + * instead. */ -@API(status = STABLE, since = "5.7") +@SuppressWarnings("removal") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) public class ExpectedExceptionSupport implements AfterEachCallback, TestExecutionExceptionHandler { private static final String EXCEPTION_WAS_HANDLED = "exceptionWasHandled"; diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java index de134f2a4d44..b5d77cfc6a7e 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupport.java @@ -10,7 +10,7 @@ package org.junit.jupiter.migrationsupport.rules; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; @@ -37,8 +37,11 @@ * @see org.junit.rules.ExternalResource * @see org.junit.rules.TestRule * @see org.junit.Rule + * @deprecated Please use {@link org.junit.jupiter.api.AutoClose @AutoClose} instead. */ -@API(status = STABLE, since = "5.7") +@SuppressWarnings("removal") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) public class ExternalResourceSupport implements BeforeEachCallback, AfterEachCallback { private final TestRuleSupport support = new TestRuleSupport(ExternalResourceAdapter::new, ExternalResource.class); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java index ac22ac1b2a0a..1892be971501 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/VerifierSupport.java @@ -10,7 +10,7 @@ package org.junit.jupiter.migrationsupport.rules; -import static org.apiguardian.api.API.Status.STABLE; +import static org.apiguardian.api.API.Status.DEPRECATED; import org.apiguardian.api.API; import org.junit.jupiter.api.extension.AfterEachCallback; @@ -36,8 +36,11 @@ * @see org.junit.rules.Verifier * @see org.junit.rules.TestRule * @see org.junit.Rule + * @deprecated Please implement {@link org.junit.jupiter.api.extension.AfterTestExecutionCallback} instead. */ -@API(status = STABLE, since = "5.7") +@SuppressWarnings("removal") +@API(status = DEPRECATED, since = "6.0") +@Deprecated(since = "6.0", forRemoval = true) public class VerifierSupport implements AfterEachCallback { private final TestRuleSupport support = new TestRuleSupport(VerifierAdapter::new, Verifier.class); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java index 8353b255297f..043282b12ce0 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/adapter/package-info.java @@ -1,5 +1,6 @@ /** - * Simple wrappers for JUnit 4 rules to overcome visibility limitations of the JUnit 4 implementations. + * Internal wrappers for JUnit 4 rules to overcome visibility + * limitations of the JUnit 4 implementations. */ @NullMarked diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/TestRuleAnnotatedMember.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/TestRuleAnnotatedMember.java index 0b959f53bdaf..de68d64d1d15 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/TestRuleAnnotatedMember.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/TestRuleAnnotatedMember.java @@ -18,7 +18,7 @@ /** * @since 5.0 */ -@API(status = INTERNAL, since = "5.0") +@API(status = INTERNAL, since = "5.1") public interface TestRuleAnnotatedMember { TestRule getTestRule(); diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java index d60c3221db07..3d68cd8f27e4 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/member/package-info.java @@ -1,5 +1,5 @@ /** - * Abstractions for members which can be targets of JUnit 4 rule annotations. + * Internal abstractions for members which can be targets of JUnit 4 rule annotations. */ @NullMarked diff --git a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java index 6532d84fcb78..fa87e3fa0f3a 100644 --- a/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java +++ b/junit-jupiter-migrationsupport/src/main/java/org/junit/jupiter/migrationsupport/rules/package-info.java @@ -1,5 +1,6 @@ /** - * Extensions which provide (limited) support for JUnit 4 rules within JUnit Jupiter. + * Deprecated extensions which provide (limited) support for JUnit 4 + * rules within JUnit Jupiter. */ @NullMarked diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreAnnotationIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreAnnotationIntegrationTests.java index 532703006296..20d523c6dc05 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreAnnotationIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreAnnotationIntegrationTests.java @@ -36,6 +36,7 @@ * @since 5.4 * @see IgnoreConditionTests */ +@SuppressWarnings("removal") class IgnoreAnnotationIntegrationTests { @Nested diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreConditionTests.java index d1c3556cec40..620569b75e3e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/conditions/IgnoreConditionTests.java @@ -35,6 +35,7 @@ * @since 5.4 * @see IgnoreAnnotationIntegrationTests */ +@SuppressWarnings("removal") class IgnoreConditionTests { @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java index 40fb18c29adf..31adeb6039a0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/AbstractTestRuleAdapterTests.java @@ -26,6 +26,7 @@ /** * @since 5.0 */ +@SuppressWarnings("removal") public class AbstractTestRuleAdapterTests { @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java index 36a76e0442a0..e998ddb498f3 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/EnableRuleMigrationSupportWithBothRuleTypesTests.java @@ -23,6 +23,7 @@ import org.junit.rules.ExternalResource; import org.junit.rules.Verifier; +@SuppressWarnings("removal") @EnableRuleMigrationSupport public class EnableRuleMigrationSupportWithBothRuleTypesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupportTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupportTests.java index 2ee4f9155881..9d35bb93ccaa 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupportTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExpectedExceptionSupportTests.java @@ -34,6 +34,7 @@ * * @since 5.0 */ +@SuppressWarnings("removal") class ExpectedExceptionSupportTests { @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java index 88175349a909..c92bcacfff7e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests.java @@ -20,6 +20,7 @@ import org.junit.rules.ExternalResource; import org.junit.rules.TestRule; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) class ExternalResourceSupportForDifferentDeclaredReturnTypesRulesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java index 9cfaa726f49b..81a66eaea2b6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMixedMethodAndFieldRulesTests.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMixedMethodAndFieldRulesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java index 4dcbc190b533..4b43744c926b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleFieldRulesTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMultipleFieldRulesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java index ba9dd82fafb5..628fd3abc2e6 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForMultipleMethodRulesTests.java @@ -19,6 +19,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.ExternalResource; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForMultipleMethodRulesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForTemporaryFolderFieldTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForTemporaryFolderFieldTests.java index c58690716548..7750eeda31cd 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForTemporaryFolderFieldTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/ExternalResourceSupportForTemporaryFolderFieldTests.java @@ -21,6 +21,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.TemporaryFolder; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class ExternalResourceSupportForTemporaryFolderFieldTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/LauncherBasedEnableRuleMigrationSupportTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/LauncherBasedEnableRuleMigrationSupportTests.java index 1a022944706b..116f9d0c5c4d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/LauncherBasedEnableRuleMigrationSupportTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/LauncherBasedEnableRuleMigrationSupportTests.java @@ -23,6 +23,7 @@ import org.junit.rules.ExternalResource; import org.junit.rules.Verifier; +@SuppressWarnings("removal") class LauncherBasedEnableRuleMigrationSupportTests { @Test diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java index d195ae72a7d7..1d533866f38e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/VerifierSupportForMixedMethodAndFieldRulesTests.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; +@SuppressWarnings("removal") @ExtendWith(VerifierSupport.class) public class VerifierSupportForMixedMethodAndFieldRulesTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java index 03f19dd584a5..e3b2224b11a7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierFieldTests.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class WrongExtendWithForVerifierFieldTests { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java index 02741f9831dc..aa67381f3ac2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/migrationsupport/rules/WrongExtendWithForVerifierMethodTests.java @@ -18,6 +18,7 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.rules.Verifier; +@SuppressWarnings("removal") @ExtendWith(ExternalResourceSupport.class) public class WrongExtendWithForVerifierMethodTests { From ccfdbd1e3f78e7ca9fea5de16075c183488b3cdc Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Mon, 2 Jun 2025 15:18:09 +0200 Subject: [PATCH 238/521] Deprecate junit-vintage-engine to clarify its purpose --- documentation/documentation.gradle.kts | 3 +- .../release-notes/release-notes-6.0.0-M1.adoc | 6 +++- .../user-guide/migration-from-junit4.adoc | 4 +++ .../src/main/java/module-info.java | 1 + .../org/junit/vintage/engine/Constants.java | 8 +++-- .../vintage/engine/VintageTestEngine.java | 7 ++-- .../engine/discovery/VintageDiscoverer.java | 8 +++++ .../engine/execution/VintageExecutor.java | 16 ++++----- .../engine/JUnit4ParameterizedTests.java | 1 + .../VintageLauncherIntegrationTests.java | 4 ++- .../engine/VintageTestEngineBasicTests.java | 1 + .../VintageTestEngineDiscoveryTests.java | 34 +++++++++++++++++-- .../VintageTestEngineExecutionTests.java | 24 +++++++++---- .../ParallelExecutionIntegrationTests.java | 16 ++++----- .../launcher/core/LauncherFactoryTests.java | 1 + .../projects/graalvm-starter/build.gradle.kts | 1 + .../projects/standalone/expected-err.txt | 4 +++ 17 files changed, 106 insertions(+), 33 deletions(-) diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index fffaa8355287..6c1a6ac520e3 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -165,7 +165,7 @@ tasks { args.addAll("--config=junit.platform.reporting.open.xml.enabled=true") args.addAll("--config=junit.platform.output.capture.stdout=true") args.addAll("--config=junit.platform.output.capture.stderr=true") - args.addAll("--config=junit.platform.discovery.issue.severity.critical=info") + args.addAll("--config=junit.platform.discovery.issue.severity.critical=warn") outputs.dir(consoleLauncherTestReportsDir) argumentProviders.add(CommandLineArgumentProvider { listOf( @@ -202,6 +202,7 @@ tasks { (options as JUnitPlatformOptions).apply { includeEngines("junit-vintage") includeTags("timeout") + systemProperty("junit.platform.discovery.issue.severity.critical", "warn") } } diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 128ede0a735d..5b649daa7d71 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -132,7 +132,11 @@ repository on GitHub. [[release-notes-6.0.0-M1-junit-vintage-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes -* ❓ +* The JUnit Vintage engine is now deprecated and will report an INFO level discovery issue + when it finds at least one JUnit 4 test class. For now, the intent of the deprecation is + not to signal removal in the next major version but to clarify the intended purpose of + the engine. It should only be used temporarily while migrating tests to JUnit Jupiter or + another testing framework with native JUnit Platform support. [[release-notes-6.0.0-M1-junit-vintage-new-features-and-improvements]] ==== New Features and Improvements diff --git a/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc b/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc index 16ef3371a1d1..48d721c9834f 100644 --- a/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc +++ b/documentation/src/docs/asciidoc/user-guide/migration-from-junit4.adoc @@ -21,6 +21,10 @@ plenty of time to migrate to JUnit Jupiter on their own schedule. [[migrating-from-junit4-running]] === Running JUnit 4 Tests on the JUnit Platform +WARNING: The JUnit Vintage engine is deprecated and should only be used temporarily while +migrating tests to JUnit Jupiter or another testing framework with native JUnit Platform +support. + Make sure that the `junit-vintage-engine` artifact is in your test runtime path. In that case JUnit 3 and JUnit 4 tests will automatically be picked up by the JUnit Platform launcher. diff --git a/junit-vintage-engine/src/main/java/module-info.java b/junit-vintage-engine/src/main/java/module-info.java index 9c982e4cfa62..c6e3e02fe161 100644 --- a/junit-vintage-engine/src/main/java/module-info.java +++ b/junit-vintage-engine/src/main/java/module-info.java @@ -16,6 +16,7 @@ * @provides org.junit.platform.engine.TestEngine The {@code VintageTestEngine} * runs JUnit 3 and 4 based tests on the platform. */ +@SuppressWarnings("deprecation") module org.junit.vintage.engine { requires static org.apiguardian.api; 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..4d7b98a0193e 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,17 +10,19 @@ package org.junit.vintage.engine; +import static org.apiguardian.api.API.Status.DEPRECATED; import static org.apiguardian.api.API.Status.EXPERIMENTAL; -import static org.apiguardian.api.API.Status.STABLE; import org.apiguardian.api.API; /** * Collection of constants related to the {@link VintageTestEngine}. * - * @since 5.12 + * @deprecated Should only be used temporarily while migrating tests to JUnit + * Jupiter or another testing framework with native JUnit Platform support */ -@API(status = STABLE, since = "5.12") +@Deprecated(since = "6.0") +@API(status = DEPRECATED, since = "6.0") public final class Constants { /** diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/VintageTestEngine.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/VintageTestEngine.java index 8d9279ae108e..fdb8e4c8c2de 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/VintageTestEngine.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/VintageTestEngine.java @@ -10,7 +10,7 @@ package org.junit.vintage.engine; -import static org.apiguardian.api.API.Status.INTERNAL; +import static org.apiguardian.api.API.Status.DEPRECATED; import static org.junit.platform.engine.TestExecutionResult.successful; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.ENGINE_ID; @@ -31,8 +31,11 @@ * The JUnit Vintage {@link TestEngine}. * * @since 4.12 + * @deprecated Should only be used temporarily while migrating tests to JUnit + * Jupiter or another testing framework with native JUnit Platform support */ -@API(status = INTERNAL, since = "4.12") +@Deprecated(since = "6.0") +@API(status = DEPRECATED, since = "6.0") public final class VintageTestEngine implements TestEngine { @Override diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/VintageDiscoverer.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/VintageDiscoverer.java index 5f50c2c439f0..df0e99c50462 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/VintageDiscoverer.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/VintageDiscoverer.java @@ -14,6 +14,7 @@ import org.apiguardian.api.API; import org.junit.platform.commons.support.scanning.ClassFilter; +import org.junit.platform.engine.DiscoveryIssue; import org.junit.platform.engine.EngineDiscoveryRequest; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; @@ -45,6 +46,13 @@ public VintageEngineDescriptor discover(EngineDiscoveryRequest discoveryRequest, RunnerTestDescriptor runnerTestDescriptor = (RunnerTestDescriptor) testDescriptor; postProcessor.applyFiltersAndCreateDescendants(runnerTestDescriptor); } + if (!engineDescriptor.getChildren().isEmpty()) { + var issue = DiscoveryIssue.create(DiscoveryIssue.Severity.INFO, // + "The JUnit Vintage engine is deprecated and should only be " // + + "used temporarily while migrating tests to JUnit Jupiter or another testing " // + + "framework with native JUnit Platform support."); + discoveryRequest.getDiscoveryListener().issueEncountered(uniqueId, issue); + } return engineDescriptor; } diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java index 6ba96f93bbfd..450dc4fde4dd 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/execution/VintageExecutor.java @@ -12,10 +12,6 @@ import static java.util.Objects.requireNonNullElse; import static org.apiguardian.api.API.Status.INTERNAL; -import static org.junit.vintage.engine.Constants.PARALLEL_CLASS_EXECUTION; -import static org.junit.vintage.engine.Constants.PARALLEL_EXECUTION_ENABLED; -import static org.junit.vintage.engine.Constants.PARALLEL_METHOD_EXECUTION; -import static org.junit.vintage.engine.Constants.PARALLEL_POOL_SIZE; import java.util.ArrayList; import java.util.Iterator; @@ -34,12 +30,14 @@ import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; +import org.junit.vintage.engine.Constants; import org.junit.vintage.engine.descriptor.RunnerTestDescriptor; import org.junit.vintage.engine.descriptor.VintageEngineDescriptor; /** * @since 5.12 */ +@SuppressWarnings({ "deprecation", "RedundantSuppression" }) @API(status = INTERNAL, since = "5.12") public class VintageExecutor { @@ -62,9 +60,11 @@ public VintageExecutor(VintageEngineDescriptor engineDescriptor, EngineExecution this.engineExecutionListener = engineExecutionListener; this.request = request; this.parallelExecutionEnabled = request.getConfigurationParameters().getBoolean( - PARALLEL_EXECUTION_ENABLED).orElse(false); - this.classes = request.getConfigurationParameters().getBoolean(PARALLEL_CLASS_EXECUTION).orElse(false); - this.methods = request.getConfigurationParameters().getBoolean(PARALLEL_METHOD_EXECUTION).orElse(false); + Constants.PARALLEL_EXECUTION_ENABLED).orElse(false); + this.classes = request.getConfigurationParameters().getBoolean(Constants.PARALLEL_CLASS_EXECUTION).orElse( + false); + this.methods = request.getConfigurationParameters().getBoolean(Constants.PARALLEL_METHOD_EXECUTION).orElse( + false); } public void executeAllChildren() { @@ -110,7 +110,7 @@ private boolean executeInParallel() { } private int getThreadPoolSize() { - Optional optionalPoolSize = request.getConfigurationParameters().get(PARALLEL_POOL_SIZE); + Optional optionalPoolSize = request.getConfigurationParameters().get(Constants.PARALLEL_POOL_SIZE); if (optionalPoolSize.isPresent()) { try { int poolSize = Integer.parseInt(optionalPoolSize.get()); diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4ParameterizedTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4ParameterizedTests.java index 5ac12b0a1f26..99253ff128c4 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4ParameterizedTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/JUnit4ParameterizedTests.java @@ -63,6 +63,7 @@ private void executeTests(DiscoverySelector selector) { request() .selectors(selector) .filters(includeEngines("junit-vintage")) + .enableImplicitConfigurationParameters(false) .build() ); // @formatter:on diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageLauncherIntegrationTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageLauncherIntegrationTests.java index 975752edee61..9b6e3bb4811b 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageLauncherIntegrationTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageLauncherIntegrationTests.java @@ -280,7 +280,9 @@ public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult } private LauncherDiscoveryRequest toRequest(LauncherDiscoveryRequestBuilder requestBuilder) { - return requestBuilder.filters(includeEngines(ENGINE_ID)).build(); + return requestBuilder.filters(includeEngines(ENGINE_ID)) // + .enableImplicitConfigurationParameters(false) // + .build(); } } diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineBasicTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineBasicTests.java index 3f6fa7b5e5d7..1a1efcdb0bd1 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineBasicTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineBasicTests.java @@ -20,6 +20,7 @@ * * @since 4.12 */ +@SuppressWarnings("deprecation") class VintageTestEngineBasicTests { private final VintageTestEngine vintage = new VintageTestEngine(); diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java index 5ae829c9b873..26b6eeb12d63 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/VintageTestEngineDiscoveryTests.java @@ -40,12 +40,15 @@ import org.junit.jupiter.api.Test; import org.junit.platform.commons.util.ClassUtils; +import org.junit.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.TestTag; import org.junit.platform.engine.UniqueId; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.engine.support.descriptor.MethodSource; import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.testkit.engine.EngineDiscoveryResults; +import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.runner.manipulation.Filter; import org.junit.vintage.engine.samples.PlainOldJavaClassWithoutAnyTestsTestCase; import org.junit.vintage.engine.samples.junit3.JUnit3SuiteWithSingleTestCaseWithSingleTestWhichFails; @@ -76,8 +79,6 @@ */ class VintageTestEngineDiscoveryTests { - VintageTestEngine engine = new VintageTestEngine(); - @Test void resolvesSimpleJUnit4TestClass() throws Exception { Class testClass = PlainJUnit4TestCaseWithSingleTestWhichFails.class; @@ -702,6 +703,28 @@ void resolvesTestSourceForParameterizedTests() throws Exception { assertMethodSource(testClass.getMethod("test"), testMethodDescriptor); } + @Test + void reportsNoDiscoveryIssuesWhenNoTestsAreFound() { + var request = discoveryRequestForClass(PlainOldJavaClassWithoutAnyTestsTestCase.class); + + var results = discover(request); + + assertThat(results.getDiscoveryIssues()).isEmpty(); + } + + @Test + void reportDiscoveryIssueWhenTestsAreFound() { + var request = discoveryRequestForClass(PlainJUnit4TestCaseWithSingleTestWhichFails.class); + + var results = discover(request); + + assertThat(results.getDiscoveryIssues()).hasSize(1); + + var issue = results.getDiscoveryIssues().getFirst(); + assertThat(issue.severity()).isEqualTo(Severity.INFO); + assertThat(issue.message()).contains("JUnit Vintage engine is deprecated"); + } + private TestDescriptor findChildByDisplayName(TestDescriptor runnerDescriptor, String displayName) { // @formatter:off var children = runnerDescriptor.getChildren(); @@ -715,7 +738,12 @@ private TestDescriptor findChildByDisplayName(TestDescriptor runnerDescriptor, S } private TestDescriptor discoverTests(LauncherDiscoveryRequest discoveryRequest) { - return engine.discover(discoveryRequest, UniqueId.forEngine(engine.getId())); + return discover(discoveryRequest).getEngineDescriptor(); + } + + @SuppressWarnings("deprecation") + private static EngineDiscoveryResults discover(LauncherDiscoveryRequest discoveryRequest) { + return EngineTestKit.discover(new VintageTestEngine(), discoveryRequest); } private Path getClasspathRoot(Class testClass) throws Exception { 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 3e6f5c7e7f75..ab66653d0879 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 @@ -787,8 +787,10 @@ void executesJUnit4SuiteWithJUnit4TestCaseWithFailingDescriptionThatIsNotReporte @Test void executesCompletelyDynamicTestCaseDiscoveredByUniqueId() { Class testClass = CompletelyDynamicTestCase.class; - var request = LauncherDiscoveryRequestBuilder.request().selectors( - selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClass(testClass))).build(); + var request = LauncherDiscoveryRequestBuilder.request() // + .selectors(selectUniqueId(VintageUniqueIdBuilder.uniqueIdForClass(testClass))) // + .enableImplicitConfigurationParameters(false) // + .build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // @@ -868,8 +870,10 @@ void executesUnrolledSpockFeatureMethod() { // Load Groovy class via reflection to avoid compilation errors in Eclipse IDE. String testClassName = "org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods"; Class testClass = ReflectionUtils.loadRequiredClass(testClassName, getClass().getClassLoader()); - var request = LauncherDiscoveryRequestBuilder.request().selectors( - selectMethod(testClass, "unrolled feature for #input")).build(); + var request = LauncherDiscoveryRequestBuilder.request() // + .selectors(selectMethod(testClass, "unrolled feature for #input"))// + .enableImplicitConfigurationParameters(false) // + .build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(uniqueIdSubstring(testClassName), started()), // @@ -889,7 +893,10 @@ void executesRegularSpockFeatureMethod() { // Load Groovy class via reflection to avoid compilation errors in Eclipse IDE. String testClassName = "org.junit.vintage.engine.samples.spock.SpockTestCaseWithUnrolledAndRegularFeatureMethods"; Class testClass = ReflectionUtils.loadRequiredClass(testClassName, getClass().getClassLoader()); - var request = LauncherDiscoveryRequestBuilder.request().selectors(selectMethod(testClass, "regular")).build(); + var request = LauncherDiscoveryRequestBuilder.request() // + .selectors(selectMethod(testClass, "regular")) // + .enableImplicitConfigurationParameters(false) // + .build(); execute(request).allEvents().assertEventsMatchExactly( // event(engine(), started()), // event(container(testClass), started()), // @@ -924,10 +931,12 @@ private static EngineExecutionResults execute(Class testClass) { return execute(request(testClass)); } + @SuppressWarnings("deprecation") private static EngineExecutionResults execute(LauncherDiscoveryRequest request) { return EngineTestKit.execute(new VintageTestEngine(), request); } + @SuppressWarnings("deprecation") private static void execute(Class testClass, EngineExecutionListener listener) { TestEngine testEngine = new VintageTestEngine(); var discoveryRequest = request(testClass); @@ -938,7 +947,10 @@ private static void execute(Class testClass, EngineExecutionListener listener } private static LauncherDiscoveryRequest request(Class testClass) { - return LauncherDiscoveryRequestBuilder.request().selectors(selectClass(testClass)).build(); + return LauncherDiscoveryRequestBuilder.request() // + .selectors(selectClass(testClass)) // + .enableImplicitConfigurationParameters(false) // + .build(); } private static boolean atLeastJUnit4_13() { diff --git a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/ParallelExecutionIntegrationTests.java b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/ParallelExecutionIntegrationTests.java index 41b96da2c5cb..ce3efd137e42 100644 --- a/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/ParallelExecutionIntegrationTests.java +++ b/junit-vintage-engine/src/test/java/org/junit/vintage/engine/execution/ParallelExecutionIntegrationTests.java @@ -17,10 +17,6 @@ import static org.junit.platform.testkit.engine.EventConditions.finishedSuccessfully; import static org.junit.platform.testkit.engine.EventConditions.started; import static org.junit.platform.testkit.engine.EventConditions.test; -import static org.junit.vintage.engine.Constants.PARALLEL_CLASS_EXECUTION; -import static org.junit.vintage.engine.Constants.PARALLEL_EXECUTION_ENABLED; -import static org.junit.vintage.engine.Constants.PARALLEL_METHOD_EXECUTION; -import static org.junit.vintage.engine.Constants.PARALLEL_POOL_SIZE; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_RUNNER; import static org.junit.vintage.engine.descriptor.VintageTestDescriptor.SEGMENT_TYPE_TEST; import static org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase.FirstClassTestCase; @@ -51,6 +47,7 @@ import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.Event; import org.junit.platform.testkit.engine.Events; +import org.junit.vintage.engine.Constants; import org.junit.vintage.engine.VintageTestEngine; import org.junit.vintage.engine.samples.junit4.JUnit4ParallelClassesTestCase; import org.junit.vintage.engine.samples.junit4.JUnit4ParallelMethodsTestCase; @@ -180,12 +177,14 @@ private Events executeInParallelSuccessfully(int poolSize, boolean parallelClass } } + @SuppressWarnings("deprecation") private static EngineExecutionResults execute(int poolSize, boolean parallelClasses, boolean parallelMethods, Class... testClass) { return EngineTestKit.execute(new VintageTestEngine(), request(poolSize, parallelClasses, parallelMethods, testClass)); } + @SuppressWarnings("deprecation") private static LauncherDiscoveryRequest request(int poolSize, boolean parallelClasses, boolean parallelMethods, Class... testClasses) { var classSelectors = Arrays.stream(testClasses) // @@ -194,10 +193,11 @@ private static LauncherDiscoveryRequest request(int poolSize, boolean parallelCl return LauncherDiscoveryRequestBuilder.request() // .selectors(classSelectors) // - .configurationParameter(PARALLEL_EXECUTION_ENABLED, String.valueOf(true)) // - .configurationParameter(PARALLEL_POOL_SIZE, String.valueOf(poolSize)) // - .configurationParameter(PARALLEL_CLASS_EXECUTION, String.valueOf(parallelClasses)) // - .configurationParameter(PARALLEL_METHOD_EXECUTION, String.valueOf(parallelMethods)) // + .configurationParameter(Constants.PARALLEL_EXECUTION_ENABLED, String.valueOf(true)) // + .configurationParameter(Constants.PARALLEL_POOL_SIZE, String.valueOf(poolSize)) // + .configurationParameter(Constants.PARALLEL_CLASS_EXECUTION, String.valueOf(parallelClasses)) // + .configurationParameter(Constants.PARALLEL_METHOD_EXECUTION, String.valueOf(parallelMethods)) // + .enableImplicitConfigurationParameters(false) // .build(); } diff --git a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java index 99c2f2ecc599..9ce3bb561f58 100644 --- a/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java +++ b/platform-tests/src/test/java/org/junit/platform/launcher/core/LauncherFactoryTests.java @@ -441,6 +441,7 @@ private LauncherDiscoveryRequest createLauncherDiscoveryRequestForBothStandardEn return request() .selectors(selectClass(JUnit4Example.class)) .selectors(selectClass(JUnit5Example.class)) + .enableImplicitConfigurationParameters(false) .build(); // @formatter:on } diff --git a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts index 09fe0465d37a..da1548337dea 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/build.gradle.kts @@ -52,6 +52,7 @@ val initializeAtBuildTime = mapOf( // These need to be added to native-build-tools "6.0" to listOf( "org.junit.platform.commons.util.KotlinReflectionUtils", + "org.junit.platform.launcher.core.DiscoveryIssueNotifier\$1", ) ) diff --git a/platform-tooling-support-tests/projects/standalone/expected-err.txt b/platform-tooling-support-tests/projects/standalone/expected-err.txt index 53ca33b7f6f0..23779eeaa528 100644 --- a/platform-tooling-support-tests/projects/standalone/expected-err.txt +++ b/platform-tooling-support-tests/projects/standalone/expected-err.txt @@ -18,3 +18,7 @@ - junit-platform-suite .+ - junit-jupiter .+ - junit-vintage .+ +>> LOGGER >> +INFO: TestEngine with ID 'junit-vintage' encountered a non-critical issue during test discovery: + +(1) [INFO] The JUnit Vintage engine is deprecated and should only be used temporarily while migrating tests to JUnit Jupiter or another testing framework with native JUnit Platform support. From 5cfbbfaba4ff7fabb190eeebd499fcaeb3230757 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 21:40:02 +0000 Subject: [PATCH 239/521] Update github/codeql-action action to v3.28.19 (#4614) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/ossf-scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 7a3567c7e3ec..a951c049cd72 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,7 +34,7 @@ jobs: - name: Check out repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Initialize CodeQL - uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: languages: ${{ matrix.language }} tools: linked @@ -47,4 +47,4 @@ jobs: -Dscan.tag.CodeQL \ classes - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index 3e6d58b6a42b..dab9a2cff69b 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -57,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18 + uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 with: sarif_file: results.sarif From d0d6071a368aaa945307d27cfad7de8d3f3b6e8d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 4 Jun 2025 11:44:16 +0200 Subject: [PATCH 240/521] Ensure `@Nested` classes are executed after sibling test methods (#4603) In order to validate them, classpath scanning was changed to find them in 5.13.0. However, that caused `@Nested` classes to be added to their parent descriptors before their sibling test methods. This made the order of execution in classes containing nested test classes dependent on how they were discovered unless a `MethodOrderer` was configured in which case `MethodOrderingVisitor` ensured test methods came before `@Nested` test classes on the same level. This commit changes `MethodOrderingVisitor` to also ensure this ordering constraint in case no `MethodOrderer` is configured. Resolves #4600. --- .../release-notes/release-notes-5.13.1.adoc | 8 ++++- .../discovery/MethodOrderingVisitor.java | 20 +++++++++++ .../engine/NestedTestClassesTests.java | 34 ++++++++++++++++--- 3 files changed, 56 insertions(+), 6 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc index abb783ac56e4..505bdb10b39b 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc @@ -35,7 +35,13 @@ on GitHub. [[release-notes-5.13.1-junit-jupiter-bug-fixes]] ==== Bug Fixes -* ❓ +* The 5.13.0 release introduced a regression regarding the execution order in test classes + containing both test methods and `@Nested` test classes. When classpath scanning was + used during test discovery -- for example, when resolving a package selector for a + `@Suite` class -- test methods in `@Nested` classes were executed _before_ test methods + in their enclosing class. This undesired change in behavior has now been reverted so + that tests in `@Nested` test classes are always executed _after_ tests in enclosing test + classes again. [[release-notes-5.13.1-junit-jupiter-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes 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 052f4cb822e9..de4646820d37 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 @@ -10,12 +10,14 @@ package org.junit.jupiter.engine.discovery; +import static java.util.Comparator.comparing; import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation; import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated; import java.util.List; import java.util.Optional; import java.util.function.Consumer; +import java.util.function.UnaryOperator; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; @@ -40,6 +42,9 @@ class MethodOrderingVisitor extends AbstractOrderingVisitor { private final JupiterConfiguration configuration; private final Condition noOrderAnnotation; + // Not a static field to avoid initialization at build time for GraalVM + private final UnaryOperator> methodsBeforeNestedClassesOrderer; + MethodOrderingVisitor(JupiterConfiguration configuration, DiscoveryIssueReporter issueReporter) { super(issueReporter); this.configuration = configuration; @@ -51,6 +56,7 @@ class MethodOrderingVisitor extends AbstractOrderingVisitor { .source(MethodSource.from(testDescriptor.getTestMethod())) // .build(); }); + this.methodsBeforeNestedClassesOrderer = createMethodsBeforeNestedClassesOrderer(); } @Override @@ -80,6 +86,7 @@ private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescri private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescriptor, Class testClass, Optional methodOrderer) { + DescriptorWrapperOrderer descriptorWrapperOrderer = createDescriptorWrapperOrderer( testClass, methodOrderer); @@ -89,6 +96,11 @@ private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescri DefaultMethodDescriptor::new, // descriptorWrapperOrderer); + if (methodOrderer.isEmpty()) { + // If there is an orderer, this is ensured by the call above + classBasedTestDescriptor.orderChildren(methodsBeforeNestedClassesOrderer); + } + // Note: MethodOrderer#getDefaultExecutionMode() is guaranteed // to be invoked after MethodOrderer#orderMethods(). methodOrderer // @@ -126,4 +138,12 @@ private Optional> toValidationAction(Optiona return Optional.of(noOrderAnnotation::check); } + private static UnaryOperator> createMethodsBeforeNestedClassesOrderer() { + var methodsFirst = comparing(MethodBasedTestDescriptor.class::isInstance).reversed(); + return children -> { + children.sort(methodsFirst); + return children; + }; + } + } 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 60eea16c0028..d1ebc1001ed7 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 @@ -13,8 +13,10 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertAll; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectMethod; +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; @@ -22,19 +24,25 @@ import static org.junit.platform.testkit.engine.TestExecutionResultConditions.message; import java.util.List; +import java.util.function.Consumer; +import java.util.regex.Pattern; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass; import org.junit.jupiter.engine.NestedTestClassesTests.OuterClass.NestedClass.RecursiveNestedClass; 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.platform.engine.DiscoveryIssue.Severity; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.support.descriptor.ClassSource; import org.junit.platform.launcher.LauncherDiscoveryRequest; +import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder; import org.junit.platform.testkit.engine.EngineExecutionResults; import org.junit.platform.testkit.engine.Events; @@ -53,20 +61,36 @@ void nestedTestsAreCorrectlyDiscovered() { assertEquals(5, engineDescriptor.getDescendants().size(), "# resolved test descriptors"); } - @Test - void nestedTestsAreExecuted() { - EngineExecutionResults executionResults = executeTestsForClass(TestCaseWithNesting.class); - Events containers = executionResults.containerEvents(); - Events tests = executionResults.testEvents(); + @ParameterizedTest(name = "{0}") + @MethodSource + void nestedTestsAreExecutedInTheRightOrder(Consumer configurer) { + EngineExecutionResults executionResults = executeTests(configurer); + Events tests = executionResults.testEvents(); assertEquals(3, tests.started().count(), "# tests started"); assertEquals(2, tests.succeeded().count(), "# tests succeeded"); assertEquals(1, tests.failed().count(), "# tests failed"); + assertThat(tests.started().map(it -> it.getTestDescriptor().getDisplayName())) // + .containsExactlyInAnyOrder("someTest()", "successful()", "failing()") // + .containsSubsequence("someTest()", "successful()") // + .containsSubsequence("someTest()", "failing()"); + + Events containers = executionResults.containerEvents(); assertEquals(3, containers.started().count(), "# containers started"); assertEquals(3, containers.finished().count(), "# containers finished"); } + static List>> nestedTestsAreExecutedInTheRightOrder() { + return List.of( // + Named.of("class selector", request -> request // + .selectors(selectClass(TestCaseWithNesting.class))), + Named.of("package selector", request -> request // + .selectors(selectPackage(TestCaseWithNesting.class.getPackageName())) // + .filters(includeClassNamePatterns(Pattern.quote(TestCaseWithNesting.class.getName()) + ".*"))) // + ); + } + @Test void doublyNestedTestsAreCorrectlyDiscovered() { LauncherDiscoveryRequest request = request().selectors(selectClass(TestCaseWithDoubleNesting.class)).build(); From 78f481f2fdf6b6fabe9e45533df5d54285a20bf0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 15:44:06 +0000 Subject: [PATCH 241/521] Update plugin kotlin to v2.2.0-RC2 --- gradle/libs.versions.toml | 2 +- .../projects/gradle-kotlin-extensions/build.gradle.kts | 2 +- .../projects/kotlin-coroutines/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9adce7a6ba81..cddb564f52eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -105,7 +105,7 @@ gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating -kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC" } +kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC2" } nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.7.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index 76d33e06b27d..facdb0179c8d 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 plugins { - kotlin("jvm") version "2.2.0-RC" + kotlin("jvm") version "2.2.0-RC2" } repositories { diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts index 64410c4e7759..783bae5fddbb 100644 --- a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.2.0-RC" + kotlin("jvm") version "2.2.0-RC2" } val junitVersion: String by project From 771bcc98a88a9368a3e5daea0c65991ace262d1c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 5 Jun 2025 10:12:59 +0200 Subject: [PATCH 242/521] Fix value of severity configuration parameter --- documentation/documentation.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/documentation/documentation.gradle.kts b/documentation/documentation.gradle.kts index 6c1a6ac520e3..f7bdaa0c2c50 100644 --- a/documentation/documentation.gradle.kts +++ b/documentation/documentation.gradle.kts @@ -165,7 +165,7 @@ tasks { args.addAll("--config=junit.platform.reporting.open.xml.enabled=true") args.addAll("--config=junit.platform.output.capture.stdout=true") args.addAll("--config=junit.platform.output.capture.stderr=true") - args.addAll("--config=junit.platform.discovery.issue.severity.critical=warn") + args.addAll("--config=junit.platform.discovery.issue.severity.critical=warning") outputs.dir(consoleLauncherTestReportsDir) argumentProviders.add(CommandLineArgumentProvider { listOf( @@ -202,7 +202,7 @@ tasks { (options as JUnitPlatformOptions).apply { includeEngines("junit-vintage") includeTags("timeout") - systemProperty("junit.platform.discovery.issue.severity.critical", "warn") + systemProperty("junit.platform.discovery.issue.severity.critical", "warning") } } From e5d6e11f427d9b91502ccdc7a07b4234fcef968d Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Thu, 5 Jun 2025 15:13:16 +0300 Subject: [PATCH 243/521] Add trim_trailing_whitespace and insert_final_newline to .editorconfig It enables IDEs to trim the whitespace automatically --- .editorconfig | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.editorconfig b/.editorconfig index 2a4ad4ec1b55..b49a2d432075 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,3 +1,17 @@ +root = true + +[*] +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.bat] +end_of_line = crlf + +[*.md] +# Trailing whitespace is important in Markdown (they distinguish a new line from a new paragraph) +trim_trailing_whitespace = false + [*.{kt,kts}] ij_kotlin_allow_trailing_comma = false ij_kotlin_allow_trailing_comma_on_call_site = false From 7d02a6a2521617ab8502f8614794b7bb0a568603 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 15:29:48 +0000 Subject: [PATCH 244/521] Update dependency gradle to v8.14.2 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 9128c7d428d8..3735f265b953 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=845952a9d6afa783db70bb3b0effaae45ae5542ca2bb7929619e8af49cb634cf -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip +distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999 +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From 483fcc90c3cb1852c4c475ccdefeb298a35f5161 Mon Sep 17 00:00:00 2001 From: Sam Brannen <104798+sbrannen@users.noreply.github.com> Date: Fri, 6 Jun 2025 13:19:40 +0200 Subject: [PATCH 245/521] Remove annotationName fields from AbstractJre[Range]Condition This commit removes the annotationName fields from AbstractJreCondition and AbstractJreRangeCondition and replaces them with local variables. See #4619 --- .../api/condition/AbstractJreCondition.java | 11 +++++------ .../condition/AbstractJreRangeCondition.java | 17 ++++++++--------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java index 877635633656..84811acee7d3 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java @@ -33,21 +33,20 @@ abstract class AbstractJreCondition extends BooleanExecuti static final String DISABLED_ON_CURRENT_JRE = // "Disabled on JRE version: " + System.getProperty("java.version"); - private final String annotationName; - AbstractJreCondition(Class annotationType, Function customDisabledReason) { super(annotationType, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, customDisabledReason); - this.annotationName = annotationType.getSimpleName(); } protected final IntStream validatedVersions(JRE[] jres, int[] versions) { + String annotationName = super.annotationType.getSimpleName(); + Preconditions.condition(jres.length > 0 || versions.length > 0, - () -> "You must declare at least one JRE or version in @" + this.annotationName); + () -> "You must declare at least one JRE or version in @" + annotationName); Preconditions.condition(Arrays.stream(jres).noneMatch(isEqual(JRE.UNDEFINED)), - () -> "JRE.UNDEFINED is not supported in @" + this.annotationName); + () -> "JRE.UNDEFINED is not supported in @" + annotationName); Arrays.stream(versions).min().ifPresent(version -> Preconditions.condition(version >= JRE.MINIMUM_VERSION, - () -> "Version [%d] in @%s must be greater than or equal to %d".formatted(version, this.annotationName, + () -> "Version [%d] in @%s must be greater than or equal to %d".formatted(version, annotationName, JRE.MINIMUM_VERSION))); return IntStream.concat(// diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java index c33d8e4a4ccd..342d25e9a266 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java @@ -29,14 +29,13 @@ abstract class AbstractJreRangeCondition extends BooleanEx private static final JRE DEFAULT_MINIMUM_JRE = JRE.JAVA_17; private static final JRE DEFAULT_MAXIMUM_JRE = JRE.OTHER; - private final String annotationName; - AbstractJreRangeCondition(Class annotationType, Function customDisabledReason) { super(annotationType, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, customDisabledReason); - this.annotationName = annotationType.getSimpleName(); } protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int minVersion, int maxVersion) { + String annotationName = super.annotationType.getSimpleName(); + boolean minJreSet = minJre != JRE.UNDEFINED; boolean maxJreSet = maxJre != JRE.UNDEFINED; boolean minVersionSet = minVersion != JRE.UNDEFINED_VERSION; @@ -45,17 +44,17 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int // Users must choose between JRE enum constants and version numbers. Preconditions.condition(!minJreSet || !minVersionSet, () -> "@%s's minimum value must be configured with either a JRE enum constant or numeric version, but not both".formatted( - this.annotationName)); + annotationName)); Preconditions.condition(!maxJreSet || !maxVersionSet, () -> "@%s's maximum value must be configured with either a JRE enum constant or numeric version, but not both".formatted( - this.annotationName)); + annotationName)); // Users must supply valid values for minVersion and maxVersion. Preconditions.condition(!minVersionSet || (minVersion >= JRE.MINIMUM_VERSION), - () -> "@%s's minVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, minVersion, + () -> "@%s's minVersion [%d] must be greater than or equal to %d".formatted(annotationName, minVersion, JRE.MINIMUM_VERSION)); Preconditions.condition(!maxVersionSet || (maxVersion >= JRE.MINIMUM_VERSION), - () -> "@%s's maxVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, maxVersion, + () -> "@%s's maxVersion [%d] must be greater than or equal to %d".formatted(annotationName, maxVersion, JRE.MINIMUM_VERSION)); // Now that we have checked the basic preconditions, we need to ensure that we are @@ -72,10 +71,10 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int // Finally, we need to validate the effective minimum and maximum values. Preconditions.condition((min != DEFAULT_MINIMUM_JRE.version() || max != DEFAULT_MAXIMUM_JRE.version()), - () -> "You must declare a non-default value for the minimum or maximum value in @" + this.annotationName); + () -> "You must declare a non-default value for the minimum or maximum value in @" + annotationName); Preconditions.condition(min <= max, () -> "@%s's minimum value [%d] must be less than or equal to its maximum value [%d]".formatted( - this.annotationName, min, max)); + annotationName, min, max)); return JRE.isCurrentVersionWithinRange(min, max); } From 7e964ab93afd7aafd8bffac854623dc1adcc5c08 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 08:48:06 +0000 Subject: [PATCH 246/521] Update dependency org.apache.maven:apache-maven to v3.9.10 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cddb564f52eb..a839cd6e3fe1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -53,7 +53,7 @@ junit4 = { module = "junit:junit", version = { require = "[4.12,)", prefer = "4. kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.10.2" } log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" } log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4j" } -maven = { module = "org.apache.maven:apache-maven", version = "3.9.9" } +maven = { module = "org.apache.maven:apache-maven", version = "3.9.10" } mavenSurefirePlugin = { module = "org.apache.maven.plugins:maven-surefire-plugin", version.ref = "surefire" } memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.8.1" } mockito-bom = { module = "org.mockito:mockito-bom", version = "5.18.0" } From 934d05e602892b438c390690f0e16a483bd11fbb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 08:48:11 +0000 Subject: [PATCH 247/521] Update plugin commonCustomUserData to v2.3 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a839cd6e3fe1..c48781d6ce53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -96,7 +96,7 @@ asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciid asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor-plugins" } bnd = { id = "biz.aQute.bnd", version.ref = "bnd" } buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" } -commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" } +commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.3" } develocity = { id = "com.gradle.develocity", version = "4.0.2" } errorProne = { id = "net.ltgt.errorprone", version = "4.2.0" } extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" } From bdcb7ee9e155d264e7955992aef163e8fbe1ca64 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 5 Jun 2025 13:49:11 +0200 Subject: [PATCH 248/521] Use JDK 24 toolchain to run Gradle and Java-related tasks --- .github/actions/run-gradle/action.yml | 2 +- .github/workflows/cross-version.yml | 4 +--- .github/workflows/gradle-dependency-submission.yml | 2 +- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 4 ++-- README.md | 4 ++-- gradle/base/dsl-extensions/build.gradle.kts | 11 +++++++++++ gradle/gradle-daemon-jvm.properties | 2 +- gradle/plugins/build-parameters/build.gradle.kts | 5 +++++ gradle/plugins/code-generator/build.gradle.kts | 11 +++++++++++ gradle/plugins/common/build.gradle.kts | 10 ++++++++++ .../junitbuild.java-toolchain-conventions.gradle.kts | 2 +- gradle/plugins/publishing/build.gradle.kts | 10 ++++++++++ .../platform-tooling-support-tests.gradle.kts | 2 +- .../tooling/support/tests/GraalVmStarterTests.java | 5 ++--- 15 files changed, 60 insertions(+), 16 deletions(-) diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index 90bd8082b59c..00e36b096d47 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -15,7 +15,7 @@ runs: id: setup-gradle-jdk with: distribution: temurin - java-version: 21 + java-version: 24 check-latest: true - uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 with: diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 6178ae7d2a05..9cae65c78f66 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -22,8 +22,6 @@ jobs: fail-fast: false matrix: jdk: - - version: 24 - type: ga - version: 25 type: ea name: "OpenJDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || matrix.jdk.type }})" @@ -71,7 +69,7 @@ jobs: strategy: fail-fast: false matrix: - jdk: [ 21 ] + jdk: [ 24 ] name: "OpenJ9 ${{ matrix.jdk }}" runs-on: ubuntu-latest steps: diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index eda44140d013..d71f044b604c 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -22,7 +22,7 @@ jobs: uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: distribution: temurin - java-version: 21 + java-version: 24 check-latest: true - name: Generate and submit dependency graph uses: gradle/actions/dependency-submission@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aadc10b78069..631844011063 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: with: distribution: graalvm-community version: 'latest' - java-version: '21' + java-version: '24' github-token: ${{ secrets.GITHUB_TOKEN }} - name: Build uses: ./.github/actions/main-build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c7096aa4e1d5..91c8ac3903ba 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -87,7 +87,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: - java-version: 21 + java-version: 24 distribution: temurin - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 - name: Update JUnit dependencies in samples @@ -245,7 +245,7 @@ jobs: - name: Set up JDK uses: actions/setup-java@c5195efecf7bdfc987ee8bae7a71cb8b11521c00 # v4.7.1 with: - java-version: 21 + java-version: 24 distribution: temurin - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 - name: Update JUnit dependencies in samples diff --git a/README.md b/README.md index a19f198286e6..f5de32911e7e 100644 --- a/README.md +++ b/README.md @@ -70,7 +70,7 @@ task outputs from previous CI builds. ## Building from Source -You need [JDK 21] to build JUnit. [Gradle toolchains] are used to detect and +You need [JDK 24] to build JUnit. [Gradle toolchains] are used to detect and potentially download additional JDKs for compilation and test execution. All modules can be _built_ and _tested_ with the [Gradle Wrapper] using the following command: @@ -100,7 +100,7 @@ of the JUnit Platform, JUnit Jupiter, and JUnit Vintage. [Gradle Wrapper]: https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:using_wrapper [JaCoCo]: https://www.eclemma.org/jacoco/ [Javadoc]: https://junit.org/junit5/docs/current/api/ -[JDK 21]: https://javaalmanac.io/jdk/21/ +[JDK 24]: https://javaalmanac.io/jdk/24/ [Release Notes]: https://junit.org/junit5/docs/current/release-notes/ [Samples]: https://github.com/junit-team/junit5-samples [StackOverflow]: https://stackoverflow.com/questions/tagged/junit5 diff --git a/gradle/base/dsl-extensions/build.gradle.kts b/gradle/base/dsl-extensions/build.gradle.kts index bc0172f0f072..8d698e0a8b54 100644 --- a/gradle/base/dsl-extensions/build.gradle.kts +++ b/gradle/base/dsl-extensions/build.gradle.kts @@ -1,3 +1,14 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 + plugins { `kotlin-dsl` } + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +kotlin { + compilerOptions.jvmTarget = JVM_21 +} diff --git a/gradle/gradle-daemon-jvm.properties b/gradle/gradle-daemon-jvm.properties index 63e5bbdf4845..9c554284ce79 100644 --- a/gradle/gradle-daemon-jvm.properties +++ b/gradle/gradle-daemon-jvm.properties @@ -1,2 +1,2 @@ #This file is generated by updateDaemonJvm -toolchainVersion=21 +toolchainVersion=24 diff --git a/gradle/plugins/build-parameters/build.gradle.kts b/gradle/plugins/build-parameters/build.gradle.kts index 8a1276886d14..f2b5a1b564f7 100644 --- a/gradle/plugins/build-parameters/build.gradle.kts +++ b/gradle/plugins/build-parameters/build.gradle.kts @@ -4,6 +4,11 @@ plugins { group = "junitbuild" +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + buildParameters { pluginId("junitbuild.build-parameters") bool("ci") { diff --git a/gradle/plugins/code-generator/build.gradle.kts b/gradle/plugins/code-generator/build.gradle.kts index fda16a028335..d63486fafd23 100644 --- a/gradle/plugins/code-generator/build.gradle.kts +++ b/gradle/plugins/code-generator/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 + plugins { `kotlin-dsl` } @@ -10,3 +12,12 @@ dependencies { implementation(libs.jackson.module.kotlin) implementation(libs.jte) } + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +kotlin { + compilerOptions.jvmTarget = JVM_21 +} diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index c5f794080724..1b8eaa2bdd18 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -1,4 +1,5 @@ import junitbuild.extensions.markerCoordinates +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 plugins { `kotlin-dsl` @@ -19,3 +20,12 @@ dependencies { implementation(libs.plugins.shadow.markerCoordinates) implementation(libs.plugins.spotless.markerCoordinates) } + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +kotlin { + compilerOptions.jvmTarget = JVM_21 +} diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts index 873ff64cfb1e..83902bbe5769 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-toolchain-conventions.gradle.kts @@ -5,7 +5,7 @@ plugins { } project.pluginManager.withPlugin("java") { - val defaultLanguageVersion = JavaLanguageVersion.of(21) + val defaultLanguageVersion = JavaLanguageVersion.of(24) val javaLanguageVersion = buildParameters.javaToolchain.version.map { JavaLanguageVersion.of(it) }.getOrElse(defaultLanguageVersion) val jvmImplementation = buildParameters.javaToolchain.implementation.map { when(it) { diff --git a/gradle/plugins/publishing/build.gradle.kts b/gradle/plugins/publishing/build.gradle.kts index 79f65b980991..cefaa5154de6 100644 --- a/gradle/plugins/publishing/build.gradle.kts +++ b/gradle/plugins/publishing/build.gradle.kts @@ -1,4 +1,5 @@ import junitbuild.extensions.markerCoordinates +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_21 plugins { `kotlin-dsl` @@ -23,3 +24,12 @@ configurations.configureEach { } } } + +java { + sourceCompatibility = JavaVersion.VERSION_21 + targetCompatibility = JavaVersion.VERSION_21 +} + +kotlin { + compilerOptions.jvmTarget = JVM_21 +} diff --git a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts index b321d09be1da..d2a769977d0c 100644 --- a/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts +++ b/platform-tooling-support-tests/platform-tooling-support-tests.gradle.kts @@ -225,7 +225,7 @@ val test by testing.suites.getting(JvmTestSuite::class) { jvmArgumentProviders += JavaHomeDir(project, 17, develocity.testDistribution.enabled) jvmArgumentProviders += JavaHomeDir(project, 17, develocity.testDistribution.enabled) - val gradleJavaVersion = JavaVersion.current().majorVersion.toInt() + val gradleJavaVersion = 21 jvmArgumentProviders += JavaHomeDir(project, gradleJavaVersion, develocity.testDistribution.enabled) jvmArgumentProviders += JavaHomeDir(project, gradleJavaVersion, develocity.testDistribution.enabled, nativeImage = true) systemProperty("gradle.java.version", gradleJavaVersion) diff --git a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java index 560ec627068e..35cd950de960 100644 --- a/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java +++ b/platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/GraalVmStarterTests.java @@ -46,9 +46,8 @@ void runsTestsInNativeImage(@TempDir Path workspace, @FilePrefix("gradle") Outpu var result = ProcessStarters.gradlew() // .workingDir(copyToWorkspace(Projects.GRAALVM_STARTER, workspace)) // - .putEnvironment("GRAALVM_HOME", - graalVmHome.orElseThrow(TestAbortedException::new).toString()).addArguments( - "-Dmaven.repo=" + MavenRepo.dir()) // + .putEnvironment("GRAALVM_HOME", graalVmHome.orElseThrow(TestAbortedException::new).toString()) // + .addArguments("-Dmaven.repo=" + MavenRepo.dir()) // .addArguments("javaToolchains", "nativeTest", "--no-daemon", "--stacktrace", "--no-build-cache", "--warning-mode=fail", "--refresh-dependencies") // .redirectOutput(outputFiles) // From e081684ed3ca730f4a9ab8983a31ae60ff8da1f7 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 5 Jun 2025 14:00:22 +0200 Subject: [PATCH 249/521] Avoid ByteBuddy from trying to use `Unsafe` --- .../src/main/kotlin/junitbuild.testing-conventions.gradle.kts | 2 ++ 1 file changed, 2 insertions(+) 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 dd333c70161c..60a3ec64694a 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 @@ -110,6 +110,8 @@ tasks.withType().configureEach { systemProperty("log4j2.julLoggerAdapter", "org.apache.logging.log4j.jul.CoreLoggerAdapter") // Avoid overhead (see https://logging.apache.org/log4j/2.x/manual/jmx.html#enabling-jmx) systemProperty("log4j2.disableJmx", "true") + // https://github.com/raphw/byte-buddy/issues/1803 + systemProperty("net.bytebuddy.safe", true) // Required until ASM officially supports the JDK 14 systemProperty("net.bytebuddy.experimental", true) if (buildParameters.testing.enableJFR) { From 3cf2ef5d9116dfaecabb1eafdac3ffc5d0ad56c9 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 5 Jun 2025 15:05:31 +0200 Subject: [PATCH 250/521] Enable NullAway's JSpecify mode --- .../kotlin/junitbuild.java-nullability-conventions.gradle.kts | 1 + 1 file changed, 1 insertion(+) diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index 75f0c6e70ab5..e07c8ca8297c 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -22,6 +22,7 @@ tasks.withType().configureEach { disableAllChecks = true nullaway { enable() + isJSpecifyMode = true } } } From ace4992a581d4d2622251d93ca8fadad097137be Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Thu, 5 Jun 2025 19:50:54 +0200 Subject: [PATCH 251/521] Resolve nullability issues surfaced by NullAway's JSpecify mode --- .../test/java/example/FirstCustomEngine.java | 3 ++ .../example/ParameterizedLifecycleDemo.java | 4 +- .../test/java/example/SecondCustomEngine.java | 3 ++ .../interceptor/SwingEdtInterceptor.java | 3 ++ .../org/junit/jupiter/api/AssertTimeout.java | 6 +-- .../api/extension/ExtensionContext.java | 9 ++-- .../descriptor/ClassBasedTestDescriptor.java | 12 +++-- .../descriptor/DynamicTestTestDescriptor.java | 10 ++--- .../engine/descriptor/ExtensionUtils.java | 1 + .../descriptor/TestFactoryTestDescriptor.java | 5 +-- .../descriptor/TestMethodTestDescriptor.java | 12 +++-- .../TestTemplateInvocationTestDescriptor.java | 5 +-- .../InterceptingExecutableInvoker.java | 13 ++++-- .../execution/InvocationInterceptorChain.java | 8 ++-- .../engine/execution/NamespaceAwareStore.java | 29 +++++++----- .../SeparateThreadTimeoutInvocation.java | 3 +- .../engine/extension/TimeoutExtension.java | 44 ++++++++++--------- .../extension/TimeoutInvocationFactory.java | 4 +- .../junit/jupiter/params/ResolutionCache.java | 2 +- .../aggregator/DefaultArgumentsAccessor.java | 8 ++-- .../params/provider/CsvArgumentsProvider.java | 10 +++-- .../provider/FieldArgumentsProvider.java | 1 + .../junit/platform/commons/function/Try.java | 4 +- .../commons/logging/LoggerFactory.java | 8 +--- .../commons/util/ReflectionUtils.java | 2 + .../commons/test/ConcurrencyTestingUtils.java | 5 ++- .../engine/ConfigurationParameters.java | 2 +- .../PrefixedConfigurationParameters.java | 3 +- ...inPoolHierarchicalTestExecutorService.java | 1 + .../HierarchicalTestExecutor.java | 3 +- .../support/hierarchical/NodeTestTask.java | 4 +- ...ThreadHierarchicalTestExecutorService.java | 1 + .../store/NamespacedHierarchicalStore.java | 7 +-- .../junit/platform/launcher/TagFilter.java | 8 ++-- .../launcher/core/InterceptingLauncher.java | 7 ++- .../platform/launcher/core/LauncherPhase.java | 7 ++- .../launcher/listeners/LoggingListener.java | 7 +-- .../engine/TestExecutionResultConditions.java | 11 +++-- .../engine/discovery/UniqueIdFilter.java | 7 ++- .../jupiter/api/AssertAllAssertionsTests.java | 3 +- .../api/AssertLinesMatchAssertionsTests.java | 3 +- .../api/AssertNullAssertionsTests.java | 4 +- .../jupiter/api/FailAssertionsTests.java | 3 +- .../jupiter/api/extension/Heavyweight.java | 3 +- .../api/extension/KitchenSinkExtension.java | 35 ++++++++------- .../engine/ClassTemplateInvocationTests.java | 4 +- .../ParameterResolutionUtilsTests.java | 8 ++++ .../extension/InvocationInterceptorTests.java | 41 ++++++++--------- .../engine/extension/OrderedMethodTests.java | 6 +-- ...rogrammaticExtensionRegistrationTests.java | 2 +- .../SeparateThreadTimeoutInvocationTests.java | 7 +-- .../TimeoutExceptionFactoryTests.java | 2 +- .../ParameterizedTestExtensionTests.java | 3 +- .../commons/util/ReflectionUtilsTests.java | 1 - .../TestDescriptorOrderChildrenTests.java | 1 + .../core/ClasspathAlignmentCheckerTests.java | 3 +- 56 files changed, 233 insertions(+), 178 deletions(-) diff --git a/documentation/src/test/java/example/FirstCustomEngine.java b/documentation/src/test/java/example/FirstCustomEngine.java index 5fd886fd65e8..46c66f926540 100644 --- a/documentation/src/test/java/example/FirstCustomEngine.java +++ b/documentation/src/test/java/example/FirstCustomEngine.java @@ -48,6 +48,9 @@ public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId return new EngineDescriptor(uniqueId, "First Custom Test Engine"); } + //end::user_guide[] + @SuppressWarnings("NullAway") + //tag::user_guide[] @Override public void execute(ExecutionRequest request) { request.getEngineExecutionListener() diff --git a/documentation/src/test/java/example/ParameterizedLifecycleDemo.java b/documentation/src/test/java/example/ParameterizedLifecycleDemo.java index c9c3375367d1..d06247be9518 100644 --- a/documentation/src/test/java/example/ParameterizedLifecycleDemo.java +++ b/documentation/src/test/java/example/ParameterizedLifecycleDemo.java @@ -55,7 +55,7 @@ static void beforeInvocation(TextFile textFile, @TempDir Path tempDir) throws Ex } //end::user_guide[] - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + @SuppressWarnings("DataFlowIssue") //tag::user_guide[] @AfterParameterizedClassInvocation static void afterInvocation(TextFile textFile) throws Exception { @@ -66,7 +66,7 @@ static void afterInvocation(TextFile textFile) throws Exception { } //end::user_guide[] - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + @SuppressWarnings("DataFlowIssue") //tag::user_guide[] @Test void test() { diff --git a/documentation/src/test/java/example/SecondCustomEngine.java b/documentation/src/test/java/example/SecondCustomEngine.java index ff90dfa8b983..f41223d6dfcc 100644 --- a/documentation/src/test/java/example/SecondCustomEngine.java +++ b/documentation/src/test/java/example/SecondCustomEngine.java @@ -48,6 +48,9 @@ public TestDescriptor discover(EngineDiscoveryRequest discoveryRequest, UniqueId return new EngineDescriptor(uniqueId, "Second Custom Test Engine"); } + //end::user_guide[] + @SuppressWarnings("NullAway") + //tag::user_guide[] @Override public void execute(ExecutionRequest request) { request.getEngineExecutionListener() diff --git a/documentation/src/test/java/example/interceptor/SwingEdtInterceptor.java b/documentation/src/test/java/example/interceptor/SwingEdtInterceptor.java index 348fd3607c1a..657ec3ca70a4 100644 --- a/documentation/src/test/java/example/interceptor/SwingEdtInterceptor.java +++ b/documentation/src/test/java/example/interceptor/SwingEdtInterceptor.java @@ -23,6 +23,9 @@ // tag::user_guide[] public class SwingEdtInterceptor implements InvocationInterceptor { + //end::user_guide[] + @SuppressWarnings("NullAway") + //tag::user_guide[] @Override public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java index 0d188e166197..d60b065be1bb 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertTimeout.java @@ -36,17 +36,15 @@ static void assertTimeout(Duration timeout, Executable executable) { assertTimeout(timeout, executable, (String) null); } - @SuppressWarnings("NullAway") static void assertTimeout(Duration timeout, Executable executable, @Nullable String message) { - assertTimeout(timeout, () -> { + AssertTimeout.<@Nullable Object> assertTimeout(timeout, () -> { executable.execute(); return null; }, message); } - @SuppressWarnings("NullAway") static void assertTimeout(Duration timeout, Executable executable, Supplier<@Nullable String> messageSupplier) { - assertTimeout(timeout, () -> { + AssertTimeout.<@Nullable Object> assertTimeout(timeout, () -> { executable.execute(); return null; }, messageSupplier); 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 fd09f1d47de3..51b0cccdf8cc 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 @@ -614,9 +614,9 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @API(status = STABLE, since = "5.1") - default V getOrComputeIfAbsent(Class type) { + @SuppressWarnings("NullAway") + default @Nullable V getOrComputeIfAbsent(Class type) { return getOrComputeIfAbsent(type, ReflectionSupport::newInstance, type); } @@ -650,7 +650,7 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); + @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the @@ -681,7 +681,8 @@ default V getOrComputeIfAbsent(Class type) { * @see CloseableResource * @see AutoCloseable */ - @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); + @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, + Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index 5151d5c686a7..19f89349675a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -61,7 +61,6 @@ import org.junit.jupiter.engine.execution.DefaultTestInstances; import org.junit.jupiter.engine.execution.ExtensionContextSupplier; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker; -import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.execution.TestInstancesProvider; @@ -448,8 +447,8 @@ private void invokeBeforeAllMethods(JupiterEngineExecutionContext context) { for (Method method : requireLifecycleMethods().beforeAll) { throwableCollector.execute(() -> { try { - executableInvoker.invoke(method, testInstance, extensionContext, registry, - ReflectiveInterceptorCall.ofVoidMethod(InvocationInterceptor::interceptBeforeAllMethod)); + executableInvoker.invokeVoid(method, testInstance, extensionContext, registry, + InvocationInterceptor::interceptBeforeAllMethod); } catch (Throwable throwable) { invokeBeforeAllMethodExecutionExceptionHandlers(registry, extensionContext, throwable); @@ -476,8 +475,8 @@ private void invokeAfterAllMethods(JupiterEngineExecutionContext context) { requireLifecycleMethods().afterAll.forEach(method -> throwableCollector.execute(() -> { try { - executableInvoker.invoke(method, testInstance, extensionContext, registry, - ReflectiveInterceptorCall.ofVoidMethod(InvocationInterceptor::interceptAfterAllMethod)); + executableInvoker.invokeVoid(method, testInstance, extensionContext, registry, + InvocationInterceptor::interceptAfterAllMethod); } catch (Throwable throwable) { invokeAfterAllMethodExecutionExceptionHandlers(registry, extensionContext, throwable); @@ -549,8 +548,7 @@ private void invokeMethodInExtensionContext(Method method, ExtensionContext cont Object target = testInstances.findInstance(getTestClass()).orElseThrow( () -> new JUnitException("Failed to find instance for method: " + method.toGenericString())); - executableInvoker.invoke(method, target, context, registry, - ReflectiveInterceptorCall.ofVoidMethod(interceptorCall)); + executableInvoker.invokeVoid(method, target, context, registry, interceptorCall); } private LifecycleMethods requireLifecycleMethods() { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java index b45aefc619fd..ab2b90a50dc3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/DynamicTestTestDescriptor.java @@ -65,14 +65,14 @@ public JupiterEngineExecutionContext execute(JupiterEngineExecutionContext conte requiredDynamicTest().getExecutable()); ExtensionContext extensionContext = context.getExtensionContext(); ExtensionRegistry extensionRegistry = context.getExtensionRegistry(); - interceptorChain.invoke(toInvocation(), extensionRegistry, InterceptorCall.ofVoid( - (interceptor, wrappedInvocation) -> interceptor.interceptDynamicTest(wrappedInvocation, - dynamicTestInvocationContext, extensionContext))); + interceptorChain.<@Nullable Void> invoke(toInvocation(), extensionRegistry, InterceptorCall.ofVoid(( + InvocationInterceptor interceptor, + InvocationInterceptor.Invocation<@Nullable Void> wrappedInvocation) -> interceptor.interceptDynamicTest( + wrappedInvocation, dynamicTestInvocationContext, extensionContext))); return context; } - @SuppressWarnings("NullAway") - private InvocationInterceptor.Invocation toInvocation() { + private InvocationInterceptor.Invocation<@Nullable Void> toInvocation() { return () -> { requiredDynamicTest().getExecutable().execute(); return null; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java index 4ad96e1818db..08fcb599dde0 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ExtensionUtils.java @@ -139,6 +139,7 @@ static void registerExtensionsFromInstanceFields(ExtensionRegistrar registrar, C /** * @since 5.11 */ + @SuppressWarnings("NullAway") private static Extension readAndValidateExtensionFromField(Field field, @Nullable Object instance, List> declarativeExtensionTypes) { Object value = tryToReadFieldValue(field, instance) // diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java index 7b50ac238292..5ad248efa279 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestFactoryTestDescriptor.java @@ -59,7 +59,6 @@ public class TestFactoryTestDescriptor extends TestMethodTestDescriptor implemen public static final String DYNAMIC_CONTAINER_SEGMENT_TYPE = "dynamic-container"; public static final String DYNAMIC_TEST_SEGMENT_TYPE = "dynamic-test"; - @SuppressWarnings("NullAway") private static final ReflectiveInterceptorCall interceptorCall = InvocationInterceptor::interceptTestFactoryMethod; private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); @@ -112,8 +111,8 @@ protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTe context.getThrowableCollector().execute(() -> { Object instance = extensionContext.getRequiredTestInstance(); - Object testFactoryMethodResult = executableInvoker.invoke(getTestMethod(), instance, extensionContext, - context.getExtensionRegistry(), interceptorCall); + Object testFactoryMethodResult = executableInvoker.<@Nullable Object> invoke(getTestMethod(), instance, + extensionContext, context.getExtensionRegistry(), interceptorCall); TestSource defaultTestSource = getSource().orElseThrow( () -> new JUnitException("Illegal state: TestSource must be present")); try (Stream dynamicNodeStream = toDynamicNodeStream(testFactoryMethodResult)) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java index 674761ffb1ba..885ae6d54cdd 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestMethodTestDescriptor.java @@ -39,7 +39,7 @@ import org.junit.jupiter.engine.execution.AfterEachMethodAdapter; import org.junit.jupiter.engine.execution.BeforeEachMethodAdapter; import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker; -import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; +import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.ExtensionRegistry; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; @@ -72,10 +72,8 @@ public class TestMethodTestDescriptor extends MethodBasedTestDescriptor { public static final String SEGMENT_TYPE = "method"; private static final InterceptingExecutableInvoker executableInvoker = new InterceptingExecutableInvoker(); - private static final ReflectiveInterceptorCall defaultInterceptorCall = ReflectiveInterceptorCall.ofVoidMethod( - InvocationInterceptor::interceptTestMethod); - - private final ReflectiveInterceptorCall interceptorCall; + private static final VoidMethodInterceptorCall defaultInterceptorCall = InvocationInterceptor::interceptTestMethod; + private final VoidMethodInterceptorCall interceptorCall; public TestMethodTestDescriptor(UniqueId uniqueId, Class testClass, Method testMethod, Supplier>> enclosingInstanceTypes, JupiterConfiguration configuration) { @@ -89,7 +87,7 @@ public TestMethodTestDescriptor(UniqueId uniqueId, Class testClass, Method te } TestMethodTestDescriptor(UniqueId uniqueId, String displayName, Class testClass, Method testMethod, - JupiterConfiguration configuration, ReflectiveInterceptorCall interceptorCall) { + JupiterConfiguration configuration, VoidMethodInterceptorCall interceptorCall) { super(uniqueId, displayName, testClass, testMethod, configuration); this.interceptorCall = interceptorCall; } @@ -218,7 +216,7 @@ protected void invokeTestMethod(JupiterEngineExecutionContext context, DynamicTe try { Method testMethod = getTestMethod(); Object instance = extensionContext.getRequiredTestInstance(); - executableInvoker.invoke(testMethod, instance, extensionContext, context.getExtensionRegistry(), + executableInvoker.invokeVoid(testMethod, instance, extensionContext, context.getExtensionRegistry(), interceptorCall); } catch (Throwable throwable) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java index d768a62cfa97..3bd4654732f8 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java @@ -24,7 +24,7 @@ import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.TestTemplateInvocationContext; import org.junit.jupiter.engine.config.JupiterConfiguration; -import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall; +import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.execution.JupiterEngineExecutionContext; import org.junit.jupiter.engine.extension.MutableExtensionRegistry; import org.junit.platform.engine.TestDescriptor; @@ -41,8 +41,7 @@ public class TestTemplateInvocationTestDescriptor extends TestMethodTestDescriptor { public static final String SEGMENT_TYPE = "test-template-invocation"; - private static final ReflectiveInterceptorCall interceptorCall = ReflectiveInterceptorCall.ofVoidMethod( - InvocationInterceptor::interceptTestTemplateMethod); + private static final VoidMethodInterceptorCall interceptorCall = InvocationInterceptor::interceptTestTemplateMethod; @Nullable private TestTemplateInvocationContext invocationContext; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java index 8a9a25968973..416131d853cf 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InterceptingExecutableInvoker.java @@ -25,6 +25,7 @@ import org.junit.jupiter.api.extension.InvocationInterceptor.Invocation; import org.junit.jupiter.api.extension.ParameterResolver; import org.junit.jupiter.api.extension.ReflectiveInvocationContext; +import org.junit.jupiter.engine.execution.InterceptingExecutableInvoker.ReflectiveInterceptorCall.VoidMethodInterceptorCall; import org.junit.jupiter.engine.extension.ExtensionRegistry; /** @@ -65,6 +66,12 @@ public T invoke(Constructor constructor, Optional outerInstance, return invoke(invocation, invocation, extensionContext, extensionRegistry, interceptorCall); } + public void invokeVoid(Method method, @Nullable Object target, ExtensionContext extensionContext, + ExtensionRegistry extensionRegistry, VoidMethodInterceptorCall interceptorCall) { + this.<@Nullable Void> invoke(method, target, extensionContext, extensionRegistry, + ReflectiveInterceptorCall.ofVoidMethod(interceptorCall)); + } + /** * Invoke the supplied method with dynamic parameter resolution. * @@ -78,8 +85,9 @@ public T invoke(Constructor constructor, Optional outerInstance, * @param interceptorCall the call for intercepting this method invocation * via all registered {@linkplain InvocationInterceptor interceptors} */ - public T invoke(Method method, @Nullable Object target, ExtensionContext extensionContext, - ExtensionRegistry extensionRegistry, ReflectiveInterceptorCall interceptorCall) { + public T invoke(Method method, @Nullable Object target, + ExtensionContext extensionContext, ExtensionRegistry extensionRegistry, + ReflectiveInterceptorCall interceptorCall) { @SuppressWarnings({ "unchecked", "rawtypes" }) Optional optionalTarget = (target instanceof Optional optional ? optional @@ -110,7 +118,6 @@ public interface ReflectiveInterceptorCall invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable; - @SuppressWarnings("NullAway") static ReflectiveInterceptorCall ofVoidMethod(VoidMethodInterceptorCall call) { return ((interceptorChain, invocation, invocationContext, extensionContext) -> { call.apply(interceptorChain, invocation, invocationContext, extensionContext); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java index f066298ade98..52a7fb65e12a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/InvocationInterceptorChain.java @@ -30,7 +30,8 @@ @API(status = INTERNAL, since = "5.5") public class InvocationInterceptorChain { - public T invoke(Invocation invocation, ExtensionRegistry extensionRegistry, InterceptorCall call) { + public T invoke(Invocation invocation, ExtensionRegistry extensionRegistry, + InterceptorCall call) { List interceptors = extensionRegistry.getExtensions(InvocationInterceptor.class); if (interceptors.isEmpty()) { return proceed(invocation); @@ -74,12 +75,11 @@ public interface InterceptorCall { T apply(InvocationInterceptor interceptor, Invocation invocation) throws Throwable; - @SuppressWarnings("NullAway") static InterceptorCall<@Nullable Void> ofVoid(VoidInterceptorCall call) { - return ((interceptorChain, invocation) -> { + return (InvocationInterceptor interceptorChain, Invocation<@Nullable Void> invocation) -> { call.apply(interceptorChain, invocation); return null; - }); + }; } } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java index 59897452d19d..60820ac4cea6 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java @@ -41,49 +41,58 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N @Override public @Nullable Object get(Object key) { Preconditions.notNull(key, "key must not be null"); - return accessStore(() -> this.valuesStore.get(this.namespace, key)); + Supplier<@Nullable Object> action = () -> this.valuesStore.get(this.namespace, key); + return accessStore(action); } @Override public @Nullable T get(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); - return accessStore(() -> this.valuesStore.get(this.namespace, key, requiredType)); + Supplier<@Nullable T> action = () -> this.valuesStore.get(this.namespace, key, requiredType); + return accessStore(action); } @Override - public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); - return accessStore(() -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator)); + Supplier<@Nullable Object> action = () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, + defaultCreator); + return accessStore(action); } @Override - public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { + public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, + Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); - return accessStore( - () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator, requiredType)); + Supplier<@Nullable V> action = () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, defaultCreator, + requiredType); + return accessStore(action); } @Override public void put(Object key, @Nullable Object value) { Preconditions.notNull(key, "key must not be null"); - accessStore(() -> this.valuesStore.put(this.namespace, key, value)); + Supplier<@Nullable Object> action = () -> this.valuesStore.put(this.namespace, key, value); + accessStore(action); } @Override public @Nullable Object remove(Object key) { Preconditions.notNull(key, "key must not be null"); - return accessStore(() -> this.valuesStore.remove(this.namespace, key)); + Supplier<@Nullable Object> action = () -> this.valuesStore.remove(this.namespace, key); + return accessStore(action); } @Override public @Nullable T remove(Object key, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); - return accessStore(() -> this.valuesStore.remove(this.namespace, key, requiredType)); + Supplier<@Nullable T> action = () -> this.valuesStore.remove(this.namespace, key, requiredType); + return accessStore(action); } private @Nullable T accessStore(Supplier<@Nullable T> action) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java index d9783d1b7942..03635bddcc08 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocation.java @@ -37,9 +37,10 @@ class SeparateThreadTimeoutInvocation implements Inv } @Override + @SuppressWarnings("NullAway") public T proceed() throws Throwable { return assertTimeoutPreemptively(timeout.toDuration(), delegate::proceed, descriptionSupplier, - (__, messageSupplier, cause, testThread) -> { + (__, ___, cause, testThread) -> { TimeoutException exception = TimeoutExceptionFactory.create(descriptionSupplier.get(), timeout, null); if (testThread != null) { preInterruptCallback.executePreInterruptCallback(testThread, exception::addSuppressed); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java index c0b32bf4303d..5dee4c1c2f93 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutExtension.java @@ -71,7 +71,7 @@ private void readAndStoreTimeoutSoChildrenInheritIt(ExtensionContext context) { } @Override - public void interceptBeforeAllMethod(Invocation invocation, + public void interceptBeforeAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, @@ -79,7 +79,7 @@ public void interceptBeforeAllMethod(Invocation invocation, } @Override - public void interceptBeforeEachMethod(Invocation invocation, + public void interceptBeforeEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { interceptLifecycleMethod(invocation, invocationContext, extensionContext, @@ -87,52 +87,53 @@ public void interceptBeforeEachMethod(Invocation invocation, } @Override - public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + public void interceptTestMethod(Invocation<@Nullable Void> invocation, + ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - interceptTestableMethod(invocation, invocationContext, extensionContext, + this.<@Nullable Void> interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestMethodTimeout); } @Override - public void interceptTestTemplateMethod(Invocation invocation, + public void interceptTestTemplateMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - interceptTestableMethod(invocation, invocationContext, extensionContext, + this.<@Nullable Void> interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestTemplateMethodTimeout); } @Override - public T interceptTestFactoryMethod(Invocation invocation, + public T interceptTestFactoryMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - return interceptTestableMethod(invocation, invocationContext, extensionContext, + return this. interceptTestableMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultTestFactoryMethodTimeout); } @Override - public void interceptAfterEachMethod(Invocation invocation, + public void interceptAfterEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - interceptLifecycleMethod(invocation, invocationContext, extensionContext, + this.<@Nullable Void> interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultAfterEachMethodTimeout); } @Override - public void interceptAfterAllMethod(Invocation invocation, + public void interceptAfterAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { - interceptLifecycleMethod(invocation, invocationContext, extensionContext, + this.<@Nullable Void> interceptLifecycleMethod(invocation, invocationContext, extensionContext, TimeoutConfiguration::getDefaultAfterAllMethodTimeout); } - private void interceptLifecycleMethod(Invocation invocation, + private void interceptLifecycleMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = readTimeoutFromAnnotation(Optional.of(invocationContext.getExecutable())).orElse( null); - intercept(invocation, invocationContext, extensionContext, timeout, defaultTimeoutProvider); + this.<@Nullable Void> intercept(invocation, invocationContext, extensionContext, timeout, + defaultTimeoutProvider); } @SuppressWarnings("OptionalUsedAsFieldOrParameterType") @@ -145,7 +146,7 @@ private Optional readTimeoutThreadModeFromAnnotation(Optional T interceptTestableMethod(Invocation invocation, + private T interceptTestableMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, TimeoutProvider defaultTimeoutProvider) throws Throwable { @@ -154,9 +155,9 @@ private T interceptTestableMethod(Invocation invocation, return intercept(invocation, invocationContext, extensionContext, timeout, defaultTimeoutProvider); } - private T intercept(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext, @Nullable TimeoutDuration explicitTimeout, - TimeoutProvider defaultTimeoutProvider) throws Throwable { + private T intercept(Invocation invocation, + ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, + @Nullable TimeoutDuration explicitTimeout, TimeoutProvider defaultTimeoutProvider) throws Throwable { TimeoutDuration timeout = explicitTimeout == null ? getDefaultTimeout(extensionContext, defaultTimeoutProvider) : explicitTimeout; @@ -175,8 +176,9 @@ private TimeoutConfiguration getGlobalTimeoutConfiguration(ExtensionContext exte key -> new TimeoutConfiguration(root), TimeoutConfiguration.class)); } - private Invocation decorate(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext, @Nullable TimeoutDuration timeout) { + private Invocation decorate(Invocation invocation, + ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext, + @Nullable TimeoutDuration timeout) { if (timeout == null || isTimeoutDisabled(extensionContext)) { return invocation; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java index 7843c012711b..41312b59d622 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/extension/TimeoutInvocationFactory.java @@ -10,6 +10,8 @@ package org.junit.jupiter.engine.extension; +import static java.util.Objects.requireNonNull; + import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -48,7 +50,7 @@ Invocation create(ThreadMode threadMode, TimeoutInvocationParameters t } private ScheduledExecutorService getThreadExecutorForSameThreadInvocation() { - return store.getOrComputeIfAbsent(SingleThreadExecutorResource.class).get(); + return requireNonNull(store.getOrComputeIfAbsent(SingleThreadExecutorResource.class)).get(); } @SuppressWarnings({ "deprecation", "try" }) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java index b692cb5a0e5d..4bd2321faac2 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java @@ -36,7 +36,7 @@ class Concurrent implements ResolutionCache { private final Map cache = new ConcurrentHashMap<>(); @Override - public Object resolve(ParameterDeclaration declaration, Supplier resolver) { + public @Nullable Object resolve(ParameterDeclaration declaration, Supplier<@Nullable Object> resolver) { return cache.computeIfAbsent(declaration, __ -> resolver.get()); } } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java index f33ac3dbdf0e..67a58840d000 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java @@ -53,10 +53,12 @@ public static DefaultArgumentsAccessor create(ExtensionContext context, int invo private DefaultArgumentsAccessor(BiFunction<@Nullable Object, Class, @Nullable Object> converter, int invocationIndex, @Nullable Object... arguments) { + Preconditions.notNull(converter, "Converter must not be null"); Preconditions.condition(invocationIndex >= 1, () -> "Invocation index must be >= 1"); - this.converter = Preconditions.notNull(converter, "Converter must not be null"); + Preconditions.notNull(arguments, "Arguments array must not be null"); + this.converter = converter; this.invocationIndex = invocationIndex; - this.arguments = Preconditions.notNull(arguments, "Arguments array must not be null"); + this.arguments = arguments; } @Override @@ -140,7 +142,7 @@ public int size() { @Override public List<@Nullable Object> toList() { - return Collections.unmodifiableList(Arrays.asList(this.arguments)); + return Collections.<@Nullable Object> unmodifiableList(Arrays.asList(this.arguments)); } @Override diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java index 9ec3aa038417..9a165795369e 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvArgumentsProvider.java @@ -58,7 +58,7 @@ private Stream parseTextBlock(CsvSource csvSource, CsvParser csvParse List argumentsList = new ArrayList<>(); try { - List<@Nullable String[]> csvRecords = csvParser.parseAll(new StringReader(textBlock)); + List<@Nullable String[]> csvRecords = parseAll(csvParser, textBlock); String[] headers = useHeadersInDisplayName ? getHeaders(csvParser) : null; AtomicInteger index = new AtomicInteger(0); @@ -76,6 +76,11 @@ private Stream parseTextBlock(CsvSource csvSource, CsvParser csvParse return argumentsList.stream(); } + @SuppressWarnings("NullAway") + private static List<@Nullable String[]> parseAll(CsvParser csvParser, String textBlock) { + return csvParser.parseAll(new StringReader(textBlock)); + } + private Stream parseValueArray(CsvSource csvSource, CsvParser csvParser, Set nullValues) { boolean useHeadersInDisplayName = csvSource.useHeadersInDisplayName(); List argumentsList = new ArrayList<>(); @@ -142,9 +147,8 @@ static Arguments processCsvRecord(@Nullable String[] csvRecord, Set null return Arguments.of(arguments); } - @SuppressWarnings("NullAway") private static Named<@Nullable Object> asNamed(String name, @Nullable Object column) { - return Named.of(name, column); + return Named.<@Nullable Object> of(name, column); } /** diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java index 3aaa3e8e7673..fb4b47373981 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldArgumentsProvider.java @@ -105,6 +105,7 @@ private static Field validateField(Field field, @Nullable Object testInstance) { return field; } + @SuppressWarnings("NullAway") private static Object readField(Field field, @Nullable Object testInstance) { Object value = ReflectionSupport.tryToReadFieldValue(field, testInstance).getOrThrow( cause -> new JUnitException("Could not read field [%s]".formatted(field.getName()), cause)); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java index 31f8f172efc3..115ccb8e8ef2 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/function/Try.java @@ -55,7 +55,7 @@ public abstract class Try { * @see #success(Object) * @see #failure(Exception) */ - public static Try call(Callable action) { + public static Try call(Callable action) { checkNotNull(action, "action"); return Try.of(() -> success(action.call())); } @@ -193,7 +193,7 @@ private Try() { */ @API(status = EXPERIMENTAL, since = "6.0") public final @NonNull V getNonNullOrThrow( - Function exceptionTransformer) throws E { + Function<@Nullable Exception, E> exceptionTransformer) throws E { var value = getOrThrow(exceptionTransformer); if (value == null) { throw exceptionTransformer.apply(null); diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java index ee37d83db1c9..711b42d6c658 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/logging/LoggerFactory.java @@ -145,7 +145,7 @@ public void trace(@Nullable Throwable throwable, Supplier messageSupplie private void log(Level level, @Nullable Throwable throwable, Supplier messageSupplier) { boolean loggable = this.julLogger.isLoggable(level); if (loggable || !listeners.isEmpty()) { - LogRecord logRecord = createLogRecord(level, throwable, nullSafeGet(messageSupplier)); + LogRecord logRecord = createLogRecord(level, throwable, messageSupplier.get()); if (loggable) { this.julLogger.log(logRecord); } @@ -153,7 +153,7 @@ private void log(Level level, @Nullable Throwable throwable, Supplier me } } - private LogRecord createLogRecord(Level level, @Nullable Throwable throwable, @Nullable String message) { + private LogRecord createLogRecord(Level level, @Nullable Throwable throwable, String message) { String sourceClassName = null; String sourceMethodName = null; boolean found = false; @@ -180,10 +180,6 @@ else if (found) { return logRecord; } - private static @Nullable String nullSafeGet(@Nullable Supplier<@Nullable String> messageSupplier) { - return (messageSupplier != null ? messageSupplier.get() : 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 2d7c11e3eace..4fc356365cb2 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 @@ -637,6 +637,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @see #tryToReadFieldValue(Class, String, Object) */ @API(status = INTERNAL, since = "1.4") + @SuppressWarnings("NullAway") public static Try<@Nullable Object> tryToReadFieldValue(Field field, @Nullable Object instance) { Preconditions.notNull(field, "Field must not be null"); Preconditions.condition((instance != null || isStatic(field)), @@ -673,6 +674,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ + @SuppressWarnings("NullAway") public static List<@Nullable Object> readFieldValues(List fields, @Nullable Object instance, Predicate predicate) { Preconditions.notNull(fields, "fields list must not be null"); diff --git a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java index ca1474c2e372..6f63ab1d7432 100644 --- a/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java +++ b/junit-platform-commons/src/testFixtures/java/org/junit/platform/commons/test/ConcurrencyTestingUtils.java @@ -26,13 +26,14 @@ public class ConcurrencyTestingUtils { public static void executeConcurrently(int threads, Runnable action) throws Exception { - executeConcurrently(threads, () -> { + ConcurrencyTestingUtils.<@Nullable Object> executeConcurrently(threads, () -> { action.run(); return null; }); } - public static List executeConcurrently(int threads, Callable<@Nullable T> action) throws Exception { + public static List executeConcurrently(int threads, Callable action) + throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(threads); try { CountDownLatch latch = new CountDownLatch(threads); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java index d721066ce792..63a9b6e16b4d 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java @@ -117,7 +117,7 @@ public interface ConfigurationParameters { * @see #CONFIG_FILE_NAME */ @API(status = STABLE, since = "1.3") - default Optional get(String key, Function transformer) { + default Optional get(String key, Function transformer) { Preconditions.notNull(transformer, "transformer must not be null"); return get(key).map(input -> { try { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java index d78dc800219d..0673d1c003ef 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java @@ -17,6 +17,7 @@ import java.util.function.Function; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.ConfigurationParameters; @@ -57,7 +58,7 @@ public Optional getBoolean(String key) { } @Override - public Optional get(String key, Function transformer) { + public Optional get(String key, Function transformer) { return delegate.get(prefixed(key), transformer); } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java index 3f64d3cd4493..60677dea7bac 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ForkJoinPoolHierarchicalTestExecutorService.java @@ -127,6 +127,7 @@ private static Callable sinceJava7ConstructorInvocation(ParallelEx } @Override + @SuppressWarnings("NullAway") public Future<@Nullable Void> submit(TestTask testTask) { ExclusiveTask exclusiveTask = new ExclusiveTask(testTask); if (!isAlreadyRunningInForkJoinPool()) { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutor.java index 3ce7e541cf43..68549dbf632a 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutor.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/HierarchicalTestExecutor.java @@ -12,6 +12,7 @@ import java.util.concurrent.Future; +import org.jspecify.annotations.Nullable; import org.junit.platform.engine.EngineExecutionListener; import org.junit.platform.engine.ExecutionRequest; import org.junit.platform.engine.TestDescriptor; @@ -46,7 +47,7 @@ class HierarchicalTestExecutor { this.throwableCollectorFactory = throwableCollectorFactory; } - Future execute() { + Future<@Nullable Void> execute() { TestDescriptor rootTestDescriptor = this.request.getRootTestDescriptor(); EngineExecutionListener executionListener = this.request.getEngineExecutionListener(); NodeExecutionAdvisor executionAdvisor = new NodeTreeWalker().walk(rootTestDescriptor); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java index 95af64b24296..2b5082e74ae4 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java @@ -257,7 +257,7 @@ public Future execute(TestDescriptor testDescriptor, EngineExecutionListener testDescriptor, () -> unfinishedTasks.remove(uniqueId)); nodeTestTask.setParentContext(context); unfinishedTasks.put(uniqueId, DynamicTaskState.unscheduled()); - Future future = taskContext.executorService().submit(nodeTestTask); + Future<@Nullable Void> future = taskContext.executorService().submit(nodeTestTask); unfinishedTasks.computeIfPresent(uniqueId, (__, state) -> DynamicTaskState.scheduled(future)); return future; } @@ -289,7 +289,7 @@ static DynamicTaskState unscheduled() { return UNSCHEDULED; } - static DynamicTaskState scheduled(Future future) { + static DynamicTaskState scheduled(Future<@Nullable Void> future) { return future::get; } diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java index 9255e9df16e7..aa05f4330ebb 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/SameThreadHierarchicalTestExecutorService.java @@ -32,6 +32,7 @@ public SameThreadHierarchicalTestExecutorService() { } @Override + @SuppressWarnings("NullAway") public Future<@Nullable Void> submit(TestTask testTask) { testTask.execute(); return completedFuture(null); 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 074d4ecdd329..03e5cb2f0ccf 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 @@ -190,7 +190,8 @@ public void close() { * @throws NamespacedHierarchicalStoreException if this store has already been * closed */ - public @Nullable Object getOrComputeIfAbsent(N namespace, K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(N namespace, K key, + Function defaultCreator) { Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); CompositeKey compositeKey = new CompositeKey<>(namespace, key); StoredValue storedValue = getStoredValue(compositeKey); @@ -218,8 +219,8 @@ public void close() { * @throws NamespacedHierarchicalStoreException if the stored value cannot * be cast to the required type, or if this store has already been closed */ - public @Nullable V getOrComputeIfAbsent(N namespace, K key, Function defaultCreator, - Class requiredType) throws NamespacedHierarchicalStoreException { + public @Nullable V getOrComputeIfAbsent(N namespace, K key, + Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); return castToRequiredType(key, value, requiredType); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java index 413a4521424a..4a128d7ebe20 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TagFilter.java @@ -128,8 +128,8 @@ public static PostDiscoveryFilter excludeTags(List tagExpressions) throw } private static PostDiscoveryFilter includeMatching(List tagExpressions) { - Supplier inclusionReason = () -> inclusionReasonExpressionSatisfy(tagExpressions); - Supplier exclusionReason = () -> exclusionReasonExpressionNotSatisfy(tagExpressions); + Supplier<@Nullable String> inclusionReason = () -> inclusionReasonExpressionSatisfy(tagExpressions); + Supplier<@Nullable String> exclusionReason = () -> exclusionReasonExpressionNotSatisfy(tagExpressions); List parsedTagExpressions = parseAll(tagExpressions); return descriptor -> { Set tags = descriptor.getTags(); @@ -148,8 +148,8 @@ private static String exclusionReasonExpressionNotSatisfy(List tagExpres } private static PostDiscoveryFilter excludeMatching(List tagExpressions) { - Supplier inclusionReason = () -> inclusionReasonExpressionNotSatisfy(tagExpressions); - Supplier exclusionReason = () -> exclusionReasonExpressionSatisfy(tagExpressions); + Supplier<@Nullable String> inclusionReason = () -> inclusionReasonExpressionNotSatisfy(tagExpressions); + Supplier<@Nullable String> exclusionReason = () -> exclusionReasonExpressionSatisfy(tagExpressions); List parsedTagExpressions = parseAll(tagExpressions); return descriptor -> { Set tags = descriptor.getTags(); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java index 063b60a51d22..30178e808414 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/InterceptingLauncher.java @@ -10,6 +10,7 @@ package org.junit.platform.launcher.core; +import org.jspecify.annotations.Nullable; import org.junit.platform.launcher.Launcher; import org.junit.platform.launcher.LauncherDiscoveryRequest; import org.junit.platform.launcher.LauncherInterceptor; @@ -34,18 +35,16 @@ public TestPlan discover(LauncherDiscoveryRequest launcherDiscoveryRequest) { } @Override - @SuppressWarnings("NullAway") public void execute(LauncherDiscoveryRequest launcherDiscoveryRequest, TestExecutionListener... listeners) { - interceptor.intercept(() -> { + interceptor.<@Nullable Object> intercept(() -> { super.execute(launcherDiscoveryRequest, listeners); return null; }); } @Override - @SuppressWarnings("NullAway") public void execute(TestPlan testPlan, TestExecutionListener... listeners) { - interceptor.intercept(() -> { + interceptor.<@Nullable Object> intercept(() -> { super.execute(testPlan, listeners); return null; }); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java index 5536e8c7227d..33d612d7a26e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/LauncherPhase.java @@ -14,7 +14,9 @@ import java.util.Locale; import java.util.Optional; +import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.logging.Logger; import org.junit.platform.commons.logging.LoggerFactory; import org.junit.platform.engine.ConfigurationParameters; @@ -31,7 +33,7 @@ enum LauncherPhase { private static final Logger logger = LoggerFactory.getLogger(LauncherPhase.class); static Optional getDiscoveryIssueFailurePhase(ConfigurationParameters configurationParameters) { - return configurationParameters.get(DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME, value -> { + Function stringLauncherPhaseFunction = value -> { try { return LauncherPhase.valueOf(value.toUpperCase(Locale.ROOT)); } @@ -41,7 +43,8 @@ static Optional getDiscoveryIssueFailurePhase(ConfigurationParame value, DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME)); return null; } - }); + }; + return configurationParameters.get(DISCOVERY_ISSUE_FAILURE_PHASE_PROPERTY_NAME, stringLauncherPhaseFunction); } @Override diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java index a17b48147a40..14ded1f6b141 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/LoggingListener.java @@ -79,14 +79,15 @@ public static LoggingListener forJavaUtilLogging(Level logLevel) { * @see #forJavaUtilLogging() * @see #forJavaUtilLogging(Level) */ - public static LoggingListener forBiConsumer(BiConsumer> logger) { + public static LoggingListener forBiConsumer(BiConsumer<@Nullable Throwable, Supplier> logger) { return new LoggingListener(logger); } private final BiConsumer<@Nullable Throwable, Supplier> logger; - private LoggingListener(BiConsumer> logger) { - this.logger = Preconditions.notNull(logger, "logger must not be null"); + private LoggingListener(BiConsumer<@Nullable Throwable, Supplier> logger) { + Preconditions.notNull(logger, "logger must not be null"); + this.logger = logger; } @Override 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 ad3da44665fa..622e1daf5e87 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 @@ -23,6 +23,8 @@ import org.apiguardian.api.API; import org.assertj.core.api.Assertions; import org.assertj.core.api.Condition; +import org.jspecify.annotations.Nullable; +import org.junit.platform.commons.util.FunctionUtils; import org.junit.platform.commons.util.Preconditions; import org.junit.platform.engine.TestExecutionResult; import org.junit.platform.engine.TestExecutionResult.Status; @@ -138,8 +140,9 @@ public static Condition instanceOf(Class expecte * to the supplied {@link String}. */ public static Condition message(String expectedMessage) { - return new Condition<>(where(Throwable::getMessage, isEqual(expectedMessage)), "message is '%s'", - expectedMessage); + return new Condition<>( + FunctionUtils. where(Throwable::getMessage, isEqual(expectedMessage)), + "message is '%s'", expectedMessage); } /** @@ -148,7 +151,9 @@ public static Condition message(String expectedMessage) { * the supplied {@link Predicate}. */ public static Condition message(Predicate expectedMessagePredicate) { - return new Condition<>(where(Throwable::getMessage, expectedMessagePredicate), "message matches predicate"); + return new Condition<>( + FunctionUtils. where(Throwable::getMessage, expectedMessagePredicate), + "message matches predicate"); } private static Condition throwable(Condition condition) { diff --git a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java index 427bcae80943..14ec702d97fd 100644 --- a/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java +++ b/junit-vintage-engine/src/main/java/org/junit/vintage/engine/discovery/UniqueIdFilter.java @@ -18,7 +18,6 @@ import java.util.Optional; import java.util.Set; -import org.jspecify.annotations.Nullable; import org.junit.platform.engine.TestDescriptor; import org.junit.platform.engine.UniqueId; import org.junit.runner.Description; @@ -34,10 +33,10 @@ class UniqueIdFilter extends Filter { private final RunnerTestDescriptor runnerTestDescriptor; private final UniqueId uniqueId; - @Nullable + @SuppressWarnings({ "NullAway.Init", "NotNullFieldNotInitialized" }) private Deque path; - @Nullable + @SuppressWarnings({ "NullAway.Init", "NotNullFieldNotInitialized" }) private Set descendants; UniqueIdFilter(RunnerTestDescriptor runnerTestDescriptor, UniqueId uniqueId) { @@ -45,6 +44,7 @@ class UniqueIdFilter extends Filter { this.uniqueId = uniqueId; } + @SuppressWarnings("ConstantValue") private void ensureInitialized() { if (descendants == null) { Optional identifiedTestDescriptor = runnerTestDescriptor.findByUniqueId(uniqueId); @@ -78,7 +78,6 @@ private Set determineDescendants(Optional } @Override - @SuppressWarnings({ "NullAway", "DataFlowIssue" }) public boolean shouldRun(Description description) { ensureInitialized(); return path.contains(description) || descendants.contains(description); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java index 1081fd79459c..e9f7dbbaac06 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertAllAssertionsTests.java @@ -61,13 +61,12 @@ void assertAllWithNullInExecutableArray() { assertPrecondition("individual executables must not be null", () -> assertAll((Executable) null)); } - @SuppressWarnings({ "NullAway" }) @Test void assertAllWithNullInExecutableCollection() { assertPrecondition("individual executables must not be null", () -> assertAll(asList((Executable) null))); } - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) + @SuppressWarnings("DataFlowIssue") @Test void assertAllWithNullInExecutableStream() { assertPrecondition("individual executables must not be null", () -> assertAll(Stream.of((Executable) null))); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java index 9cbb09c270ec..4bc5f0c57765 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertLinesMatchAssertionsTests.java @@ -30,6 +30,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.PreconditionViolationException; import org.opentest4j.AssertionFailedError; @@ -273,7 +274,7 @@ void simpleStringMessage() { @Test void stringSupplierWithMultiLineMessage() { var message = "XXX\nYYY"; - Supplier supplier = () -> message; + Supplier<@Nullable String> supplier = () -> message; var expected = List.of("a", "b", "c"); var actual = List.of("a", "d", "c"); var error = assertThrows(AssertionFailedError.class, () -> assertLinesMatch(expected, actual, supplier)); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java index 7ec74ae92ee3..bab28bfee9e4 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/AssertNullAssertionsTests.java @@ -66,7 +66,7 @@ void assertNullWithNonNullObjectWithNullStringReturnedFromToStringAndMessageSupp @SuppressWarnings("unused") private void assertNullWithNonNullObjectWithNullStringReturnedFromToString( - @Nullable Supplier messageSupplier) { + @Nullable Supplier<@Nullable String> messageSupplier) { String actual = "null"; try { if (messageSupplier == null) { @@ -98,7 +98,7 @@ void assertNullWithNonNullObjectWithNullReferenceReturnedFromToStringAndMessageS @SuppressWarnings("unused") private void assertNullWithNonNullObjectWithNullReferenceReturnedFromToString( - @Nullable Supplier messageSupplier) { + @Nullable Supplier<@Nullable String> messageSupplier) { Object actual = new NullToString(); try { if (messageSupplier == null) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java index 252a7974ba95..fff673f1bd56 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/FailAssertionsTests.java @@ -20,6 +20,7 @@ import java.util.function.Supplier; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.opentest4j.AssertionFailedError; /** @@ -77,7 +78,7 @@ void failWithNullString() { @Test void failWithNullMessageSupplier() { try { - fail((Supplier) null); + fail((Supplier<@Nullable String>) null); expectAssertionFailedError(); } catch (AssertionFailedError ex) { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java index 2ababf8d4145..a7552d2787f2 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/Heavyweight.java @@ -10,6 +10,7 @@ package org.junit.jupiter.api.extension; +import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -32,7 +33,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon public Object resolveParameter(ParameterContext parameterContext, ExtensionContext context) { var engineContext = context.getRoot(); var store = engineContext.getStore(ExtensionContext.Namespace.GLOBAL); - var resource = store.getOrComputeIfAbsent(ResourceValue.class); + var resource = requireNonNull(store.getOrComputeIfAbsent(ResourceValue.class)); resource.usages.incrementAndGet(); return resource; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java index ee8d1dba0729..e7b9dbb478d8 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/extension/KitchenSinkExtension.java @@ -15,6 +15,8 @@ import java.util.Optional; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; + /** * Kitchen Sink extension that implements every extension API * supported by JUnit Jupiter. @@ -30,7 +32,6 @@ * @since 5.0 * @see ExtensionComposabilityTests */ -@SuppressWarnings({ "DataFlowIssue", "NullAway" }) // @formatter:off public class KitchenSinkExtension implements @@ -141,7 +142,7 @@ public void preConstructTestInstance(TestInstanceFactoryContext factoryContext, @Override public Object createTestInstance(TestInstanceFactoryContext factoryContext, ExtensionContext extensionContext) { - return null; + throw new UnsupportedOperationException(); } @Override @@ -158,7 +159,7 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon } @Override - public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { + public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { return null; } @@ -166,7 +167,7 @@ public Object resolveParameter(ParameterContext parameterContext, ExtensionConte @Override public ConditionEvaluationResult evaluateExecutionCondition(ExtensionContext context) { - return null; + throw new UnsupportedOperationException(); } // --- @TestTemplate ------------------------------------------------------- @@ -178,7 +179,7 @@ public boolean supportsTestTemplate(ExtensionContext context) { @Override public Stream provideTestTemplateInvocationContexts(ExtensionContext context) { - return null; + throw new UnsupportedOperationException(); } @Override @@ -195,7 +196,7 @@ public boolean supportsClassTemplate(ExtensionContext context) { @Override public Stream provideClassTemplateInvocationContexts(ExtensionContext context) { - return null; + throw new UnsupportedOperationException(); } @Override @@ -214,11 +215,11 @@ public void testSuccessful(ExtensionContext context) { } @Override - public void testAborted(ExtensionContext context, Throwable cause) { + public void testAborted(ExtensionContext context, @Nullable Throwable cause) { } @Override - public void testFailed(ExtensionContext context, Throwable cause) { + public void testFailed(ExtensionContext context, @Nullable Throwable cause) { } // --- InvocationInterceptor ----------------------------------------------- @@ -232,20 +233,20 @@ public T interceptTestClassConstructor(Invocation invocation, } @Override - public void interceptBeforeAllMethod(Invocation invocation, + public void interceptBeforeAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptBeforeAllMethod(invocation, invocationContext, extensionContext); } @Override - public void interceptBeforeEachMethod(Invocation invocation, + public void interceptBeforeEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptBeforeEachMethod(invocation, invocationContext, extensionContext); } @Override - public void interceptTestMethod(Invocation invocation, ReflectiveInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + public void interceptTestMethod(Invocation<@Nullable Void> invocation, + ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptTestMethod(invocation, invocationContext, extensionContext); } @@ -256,25 +257,25 @@ public T interceptTestFactoryMethod(Invocation invocation, } @Override - public void interceptTestTemplateMethod(Invocation invocation, + public void interceptTestTemplateMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptTestTemplateMethod(invocation, invocationContext, extensionContext); } @Override - public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + public void interceptDynamicTest(Invocation<@Nullable Void> invocation, + DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptDynamicTest(invocation, invocationContext, extensionContext); } @Override - public void interceptAfterEachMethod(Invocation invocation, + public void interceptAfterEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptAfterEachMethod(invocation, invocationContext, extensionContext); } @Override - public void interceptAfterAllMethod(Invocation invocation, + public void interceptAfterAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { InvocationInterceptor.super.interceptAfterAllMethod(invocation, invocationContext, extensionContext); } 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 c39bc60b5fb7..de6ddc5c6613 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 @@ -1493,7 +1493,7 @@ static class ClassTemplateInvocationCallbacks implements BeforeClassTemplateInvocationCallback, AfterClassTemplateInvocationCallback { private final String prefix; - private final Function exceptionFactory; + private final Function exceptionFactory; @SuppressWarnings("unused") ClassTemplateInvocationCallbacks() { @@ -1504,7 +1504,7 @@ static class ClassTemplateInvocationCallbacks this(prefix, __ -> null); } - ClassTemplateInvocationCallbacks(String prefix, Function exceptionFactory) { + ClassTemplateInvocationCallbacks(String prefix, Function exceptionFactory) { this.prefix = prefix; this.exceptionFactory = exceptionFactory; } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index 6612530bb977..c5e83c596e66 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -63,6 +63,7 @@ void resolveConstructorArguments() { register(new StringParameterResolver()); Class topLevelClass = ConstructorInjectionTestCase.class; + @Nullable Object[] arguments = resolveConstructorParameters(topLevelClass, null); assertThat(arguments).containsExactly(ENIGMA); @@ -76,6 +77,7 @@ void resolveNestedConstructorArguments() { ConstructorInjectionTestCase outer = ReflectionSupport.newInstance(outerClass, "str"); Class innerClass = ConstructorInjectionTestCase.NestedTestCase.class; + @Nullable Object[] arguments = resolveConstructorParameters(innerClass, outer); assertThat(arguments).containsExactly(outer, 42); @@ -101,6 +103,7 @@ void resolvingArgumentsForMethodsWithoutParameterDoesNotDependOnParameterResolve testMethodWithNoParameters(); throwDuringParameterResolution(new RuntimeException("boom!")); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).isEmpty(); @@ -111,6 +114,7 @@ void resolveArgumentsViaParameterResolver() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("argument"); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("argument"); @@ -127,6 +131,7 @@ void resolveMultipleArguments() { }; })); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("0", 1, 2.0); @@ -138,6 +143,7 @@ void onlyConsiderParameterResolversThatSupportAParticularParameter() { thereIsAParameterResolverThatDoesNotSupportThisParameter(); thereIsAParameterResolverThatResolvesTheParameterTo("something"); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly("something"); @@ -167,6 +173,7 @@ void resolvingArgumentsForMethodsWithPrimitiveTypesIsSupported() { testMethodWithASinglePrimitiveIntParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(42); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).containsExactly(42); @@ -177,6 +184,7 @@ void nullIsAViableArgumentIfAReferenceTypeParameterIsExpected() { testMethodWithASingleStringParameter(); thereIsAParameterResolverThatResolvesTheParameterTo(null); + @Nullable Object[] arguments = resolveMethodParameters(); assertThat(arguments).hasSize(1); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/InvocationInterceptorTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/InvocationInterceptorTests.java index b9b39cecff58..a0138398097e 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/InvocationInterceptorTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/InvocationInterceptorTests.java @@ -30,6 +30,7 @@ import java.util.function.UnaryOperator; import java.util.stream.Stream; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; @@ -71,7 +72,7 @@ static class InvocationIgnoringInterceptorTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override - public void interceptTestMethod(Invocation invocation, + public void interceptTestMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) { // do nothing } @@ -95,7 +96,7 @@ static class InvocationSkippedTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override - public void interceptTestMethod(Invocation invocation, + public void interceptTestMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) { invocation.skip(); } @@ -122,7 +123,7 @@ static class DoubleInvocationInterceptorTestCase { @RegisterExtension Extension interceptor = new InvocationInterceptor() { @Override - public void interceptTestMethod(Invocation invocation, + public void interceptTestMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { invocation.proceed(); @@ -287,7 +288,7 @@ public ExtensionContextScope getTestInstantiationExtensionContextScope(Extension } @Override - public void interceptBeforeAllMethod(Invocation invocation, + public void interceptBeforeAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); @@ -295,7 +296,7 @@ public void interceptBeforeAllMethod(Invocation invocation, assertEquals(testClass.getDeclaredMethod("beforeAll", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_ALL); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_ALL); } @Override @@ -309,7 +310,7 @@ public T interceptTestClassConstructor(Invocation invocation, } @Override - public void interceptBeforeEachMethod(Invocation invocation, + public void interceptBeforeEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); @@ -317,22 +318,22 @@ public void interceptBeforeEachMethod(Invocation invocation, assertEquals(testClass.getDeclaredMethod("beforeEach", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_EACH); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.BEFORE_EACH); } @Override - public void interceptTestMethod(Invocation invocation, + public void interceptTestMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); assertThat(invocationContext.getTarget()).containsInstanceOf(testClass); assertEquals(testClass.getDeclaredMethod("test", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.TEST_METHOD); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.TEST_METHOD); } @Override - public void interceptTestTemplateMethod(Invocation invocation, + public void interceptTestTemplateMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); @@ -340,7 +341,7 @@ public void interceptTestTemplateMethod(Invocation invocation, assertEquals(testClass.getDeclaredMethod("testTemplate", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.TEST_TEMPLATE_METHOD); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.TEST_TEMPLATE_METHOD); } @Override @@ -356,18 +357,18 @@ public T interceptTestFactoryMethod(Invocation invocation, } @Override - public void interceptDynamicTest(Invocation invocation, DynamicTestInvocationContext invocationContext, - ExtensionContext extensionContext) throws Throwable { + public void interceptDynamicTest(Invocation<@Nullable Void> invocation, + DynamicTestInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertThat(invocationContext.getExecutable()).isNotNull(); assertThat(extensionContext.getUniqueId()).isNotBlank(); assertThat(extensionContext.getElement()).isEmpty(); assertThat(extensionContext.getParent().flatMap(ExtensionContext::getTestMethod)) // .contains(testClass.getDeclaredMethod("testFactory", TestReporter.class)); - reportAndProceed(invocation, extensionContext, InvocationType.DYNAMIC_TEST); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.DYNAMIC_TEST); } @Override - public void interceptAfterEachMethod(Invocation invocation, + public void interceptAfterEachMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); @@ -375,11 +376,11 @@ public void interceptAfterEachMethod(Invocation invocation, assertEquals(testClass.getDeclaredMethod("afterEach", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.AFTER_EACH); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.AFTER_EACH); } @Override - public void interceptAfterAllMethod(Invocation invocation, + public void interceptAfterAllMethod(Invocation<@Nullable Void> invocation, ReflectiveInvocationContext invocationContext, ExtensionContext extensionContext) throws Throwable { assertEquals(testClass, invocationContext.getTargetClass()); @@ -387,11 +388,11 @@ public void interceptAfterAllMethod(Invocation invocation, assertEquals(testClass.getDeclaredMethod("afterAll", TestReporter.class), invocationContext.getExecutable()); assertThat(invocationContext.getArguments()).hasSize(1).hasOnlyElementsOfType(TestReporter.class); - reportAndProceed(invocation, extensionContext, InvocationType.AFTER_ALL); + this.<@Nullable Void> reportAndProceed(invocation, extensionContext, InvocationType.AFTER_ALL); } - private T reportAndProceed(Invocation invocation, ExtensionContext extensionContext, InvocationType type) - throws Throwable { + private T reportAndProceed(Invocation invocation, + ExtensionContext extensionContext, InvocationType type) throws Throwable { extensionContext.publishReportEntry(type.name(), "before:" + name); try { return invocation.proceed(); 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 bd1b61c9446b..0d191dfadd99 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 @@ -742,17 +742,17 @@ public void orderMethods(MethodOrdererContext context) { context.getMethodDescriptors().set(1, createMethodDescriptorImpersonator(method2)); } - @SuppressWarnings({ "unchecked", "DataFlowIssue", "NullAway" }) + @SuppressWarnings({ "unchecked", "DataFlowIssue" }) static T createMethodDescriptorImpersonator(MethodDescriptor method) { MethodDescriptor stub = new MethodDescriptor() { @Override public Method getMethod() { - return null; + throw new UnsupportedOperationException(); } @Override public String getDisplayName() { - return null; + throw new UnsupportedOperationException(); } @Override diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java index 61dd3d5bb089..c871279414ed 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/ProgrammaticExtensionRegistrationTests.java @@ -189,7 +189,7 @@ void classLevelWithPrivateField() { void instanceLevelWithNullField() { Class testClass = InstanceLevelExtensionRegistrationWithNullFieldTestCase.class; - executeTestsForClass(testClass).testEvents().assertThatEvents().haveExactly(1, finishedWithFailure( + executeTestsForClass(testClass).testEvents().debug().assertThatEvents().haveExactly(1, finishedWithFailure( instanceOf(PreconditionViolationException.class), message(expectedMessage(testClass, null)))); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java index b74afe95b6ec..7414362b790b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/SeparateThreadTimeoutInvocationTests.java @@ -18,6 +18,7 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicReference; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout.ThreadMode; @@ -36,7 +37,6 @@ class SeparateThreadTimeoutInvocationTests { private static final long PREEMPTIVE_TIMEOUT_MILLIS = WINDOWS.isCurrentOs() ? 1000 : 100; - @SuppressWarnings("NullAway") @Test @DisplayName("throws timeout exception when timeout duration is exceeded") void throwsTimeoutException() { @@ -44,7 +44,7 @@ void throwsTimeoutException() { var invocation = aSeparateThreadInvocation(() -> { threadName.set(Thread.currentThread().getName()); Thread.sleep(PREEMPTIVE_TIMEOUT_MILLIS * 2); - return null; + return "ignored"; }); assertThatThrownBy(invocation::proceed) // @@ -71,7 +71,8 @@ void shouldThrowInvocationException() { .hasMessage("hi!"); } - private static SeparateThreadTimeoutInvocation aSeparateThreadInvocation(Invocation invocation) { + private static SeparateThreadTimeoutInvocation aSeparateThreadInvocation( + Invocation invocation) { var namespace = ExtensionContext.Namespace.create(SeparateThreadTimeoutInvocationTests.class); var store = new NamespaceAwareStore(new NamespacedHierarchicalStore<>(null), Namespace.create(namespace.getParts())); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java index 5e0ef939dd0a..62f5a6f8ceec 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/TimeoutExceptionFactoryTests.java @@ -58,7 +58,7 @@ class ThrowException { @Test @DisplayName("method signature is null") - void methodSignatureIsnull() { + void methodSignatureIsNull() { assertThatThrownBy(() -> create(null, tenMillisDuration, suppressedException)) // .hasMessage("method signature must not be null"); } diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java index e6e49f6488ae..bf0956e41ff0 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java @@ -417,11 +417,10 @@ void method() { class NonStaticArgumentsProvider implements ArgumentsProvider { - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Override public Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context) { - return null; + throw new UnsupportedOperationException(); } } 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 709c6fed82aa..e1701ad6dbd3 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 @@ -1869,7 +1869,6 @@ String specialBaz() { @Nested class ReadFieldTests { - @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test void tryToReadFieldValueOfNonexistentStaticField() { assertThrows(NoSuchFieldException.class, diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorOrderChildrenTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorOrderChildrenTests.java index 55e0d80a20b9..8d0e8e239dc1 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorOrderChildrenTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/descriptor/TestDescriptorOrderChildrenTests.java @@ -116,6 +116,7 @@ default void orderChildrenDuplicatesDescriptor() { assertThat(exception).hasMessage("orderer may not add or remove test descriptors"); } + @SuppressWarnings({ "DataFlowIssue", "NullAway" }) @Test default void orderChildrenOrdererReturnsNull() { var testDescriptor = createTestDescriptorWithChildren(); 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 c15ad7aa543f..3c16dd8a4f40 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 @@ -23,6 +23,7 @@ import io.github.classgraph.ClassGraph; import io.github.classgraph.PackageInfo; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Test; class ClasspathAlignmentCheckerTests { @@ -36,7 +37,7 @@ void classpathIsAligned() { void wrapsLinkageErrorForUnalignedClasspath() { var cause = new LinkageError(); AtomicInteger counter = new AtomicInteger(); - Function packageLookup = name -> { + Function packageLookup = name -> { var pkg = mock(Package.class); when(pkg.getName()).thenReturn(name); when(pkg.getImplementationVersion()).thenReturn(counter.incrementAndGet() + ".0.0"); From cd3042801f1c2ec97b17a4bc7198974f3f37b769 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 10:33:13 +0200 Subject: [PATCH 252/521] Pass `--release=21` to `javac` rather than source/target compatibility --- gradle/base/dsl-extensions/build.gradle.kts | 5 ++--- gradle/plugins/build-parameters/build.gradle.kts | 5 ++--- gradle/plugins/code-generator/build.gradle.kts | 5 ++--- gradle/plugins/common/build.gradle.kts | 5 ++--- gradle/plugins/publishing/build.gradle.kts | 5 ++--- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/gradle/base/dsl-extensions/build.gradle.kts b/gradle/base/dsl-extensions/build.gradle.kts index 8d698e0a8b54..cbfa5598b00d 100644 --- a/gradle/base/dsl-extensions/build.gradle.kts +++ b/gradle/base/dsl-extensions/build.gradle.kts @@ -4,9 +4,8 @@ plugins { `kotlin-dsl` } -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.compileJava { + options.release = 21 } kotlin { diff --git a/gradle/plugins/build-parameters/build.gradle.kts b/gradle/plugins/build-parameters/build.gradle.kts index f2b5a1b564f7..f2db3d75afaa 100644 --- a/gradle/plugins/build-parameters/build.gradle.kts +++ b/gradle/plugins/build-parameters/build.gradle.kts @@ -4,9 +4,8 @@ plugins { group = "junitbuild" -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.compileJava { + options.release = 21 } buildParameters { diff --git a/gradle/plugins/code-generator/build.gradle.kts b/gradle/plugins/code-generator/build.gradle.kts index d63486fafd23..b85fff6b0a5d 100644 --- a/gradle/plugins/code-generator/build.gradle.kts +++ b/gradle/plugins/code-generator/build.gradle.kts @@ -13,9 +13,8 @@ dependencies { implementation(libs.jte) } -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.compileJava { + options.release = 21 } kotlin { diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index 1b8eaa2bdd18..ac0c075a75c1 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -21,9 +21,8 @@ dependencies { implementation(libs.plugins.spotless.markerCoordinates) } -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.compileJava { + options.release = 21 } kotlin { diff --git a/gradle/plugins/publishing/build.gradle.kts b/gradle/plugins/publishing/build.gradle.kts index cefaa5154de6..8df1914a9bc2 100644 --- a/gradle/plugins/publishing/build.gradle.kts +++ b/gradle/plugins/publishing/build.gradle.kts @@ -25,9 +25,8 @@ configurations.configureEach { } } -java { - sourceCompatibility = JavaVersion.VERSION_21 - targetCompatibility = JavaVersion.VERSION_21 +tasks.compileJava { + options.release = 21 } kotlin { From f10dcacf0946b515e562c0dc15e2c2812b3767d4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 10:39:21 +0200 Subject: [PATCH 253/521] Pass `-Xjdk-release` option to Kotlin compiler --- gradle/base/code-generator-model/build.gradle.kts | 7 +++++-- gradle/base/dsl-extensions/build.gradle.kts | 5 ++++- gradle/plugins/code-generator/build.gradle.kts | 5 ++++- gradle/plugins/common/build.gradle.kts | 5 ++++- .../junitbuild.kotlin-library-conventions.gradle.kts | 4 +++- gradle/plugins/publishing/build.gradle.kts | 5 ++++- 6 files changed, 24 insertions(+), 7 deletions(-) diff --git a/gradle/base/code-generator-model/build.gradle.kts b/gradle/base/code-generator-model/build.gradle.kts index 4bf50672a124..ca30027739e8 100644 --- a/gradle/base/code-generator-model/build.gradle.kts +++ b/gradle/base/code-generator-model/build.gradle.kts @@ -1,4 +1,4 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 plugins { `kotlin-dsl` @@ -10,5 +10,8 @@ java { } kotlin { - compilerOptions.jvmTarget = JvmTarget.JVM_17 + compilerOptions { + jvmTarget = JVM_17 + freeCompilerArgs.add("-Xjdk-release=17") + } } diff --git a/gradle/base/dsl-extensions/build.gradle.kts b/gradle/base/dsl-extensions/build.gradle.kts index cbfa5598b00d..a94e377f753e 100644 --- a/gradle/base/dsl-extensions/build.gradle.kts +++ b/gradle/base/dsl-extensions/build.gradle.kts @@ -9,5 +9,8 @@ tasks.compileJava { } kotlin { - compilerOptions.jvmTarget = JVM_21 + compilerOptions { + jvmTarget = JVM_21 + freeCompilerArgs.add("-Xjdk-release=21") + } } diff --git a/gradle/plugins/code-generator/build.gradle.kts b/gradle/plugins/code-generator/build.gradle.kts index b85fff6b0a5d..4b659df799e0 100644 --- a/gradle/plugins/code-generator/build.gradle.kts +++ b/gradle/plugins/code-generator/build.gradle.kts @@ -18,5 +18,8 @@ tasks.compileJava { } kotlin { - compilerOptions.jvmTarget = JVM_21 + compilerOptions { + jvmTarget = JVM_21 + freeCompilerArgs.add("-Xjdk-release=21") + } } diff --git a/gradle/plugins/common/build.gradle.kts b/gradle/plugins/common/build.gradle.kts index ac0c075a75c1..40df3d0c9ce4 100644 --- a/gradle/plugins/common/build.gradle.kts +++ b/gradle/plugins/common/build.gradle.kts @@ -26,5 +26,8 @@ tasks.compileJava { } kotlin { - compilerOptions.jvmTarget = JVM_21 + compilerOptions { + jvmTarget = JVM_21 + freeCompilerArgs.add("-Xjdk-release=21") + } } diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts index 083de1511d7a..907b672a734a 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts @@ -1,3 +1,4 @@ + import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -20,7 +21,8 @@ tasks.withType().configureEach { languageVersion = apiVersion allWarningsAsErrors.convention(true) javaParameters = true - freeCompilerArgs.addAll("-opt-in=kotlin.RequiresOptIn") + freeCompilerArgs.add("-opt-in=kotlin.RequiresOptIn") + freeCompilerArgs.add(jvmTarget.map { "-Xjdk-release=${JavaVersion.toVersion(it.target).majorVersion}" }) } } diff --git a/gradle/plugins/publishing/build.gradle.kts b/gradle/plugins/publishing/build.gradle.kts index 8df1914a9bc2..72d4e4c68236 100644 --- a/gradle/plugins/publishing/build.gradle.kts +++ b/gradle/plugins/publishing/build.gradle.kts @@ -30,5 +30,8 @@ tasks.compileJava { } kotlin { - compilerOptions.jvmTarget = JVM_21 + compilerOptions { + jvmTarget = JVM_21 + freeCompilerArgs.add("-Xjdk-release=21") + } } From 067d976074a8e65a09a40bc794e20a6bfefab3e1 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 12:00:28 +0200 Subject: [PATCH 254/521] WIP --- .../org/junit/jupiter/api/extension/ExtensionContext.java | 5 ++--- .../junit/jupiter/engine/execution/NamespaceAwareStore.java | 4 ++-- .../engine/support/store/NamespacedHierarchicalStore.java | 4 ++-- .../support/store/NamespacedHierarchicalStoreTests.java | 3 ++- 4 files changed, 8 insertions(+), 8 deletions(-) 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 51b0cccdf8cc..71b8d2861007 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 @@ -615,7 +615,6 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see AutoCloseable */ @API(status = STABLE, since = "5.1") - @SuppressWarnings("NullAway") default @Nullable V getOrComputeIfAbsent(Class type) { return getOrComputeIfAbsent(type, ReflectionSupport::newInstance, type); } @@ -650,7 +649,7 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ - @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); + @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); /** * Get the value of the specified required type that is stored under the @@ -681,7 +680,7 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ - @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, + @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType); /** diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java index 60820ac4cea6..7d4b03d91d38 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java @@ -54,7 +54,7 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override - public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Supplier<@Nullable Object> action = () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, @@ -63,7 +63,7 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override - public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, + public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); 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 03e5cb2f0ccf..4f8f00e9a3bd 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 @@ -191,7 +191,7 @@ public void close() { * closed */ public @Nullable Object getOrComputeIfAbsent(N namespace, K key, - Function defaultCreator) { + Function defaultCreator) { Preconditions.notNull(defaultCreator, "defaultCreator must not be null"); CompositeKey compositeKey = new CompositeKey<>(namespace, key); StoredValue storedValue = getStoredValue(compositeKey); @@ -220,7 +220,7 @@ public void close() { * be cast to the required type, or if this store has already been closed */ public @Nullable V getOrComputeIfAbsent(N namespace, K key, - Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { + Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); return castToRequiredType(key, value, requiredType); diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java index cf5b418d2a52..e2212c5f9afc 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java @@ -28,6 +28,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; +import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -319,7 +320,7 @@ void removeNullValueWithTypeSafety() { void simulateRaceConditionInGetOrComputeIfAbsent() throws Exception { int threads = 10; AtomicInteger counter = new AtomicInteger(); - List values; + List<@Nullable Object> values; try (var localStore = new NamespacedHierarchicalStore<>(null)) { values = executeConcurrently(threads, // From c141846326945d8c3abace7780315a606b959fe4 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 15:54:37 +0200 Subject: [PATCH 255/521] Make method signatures for `Function` parameters more flexible --- .../asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 10 ++++++++++ .../junit/jupiter/api/extension/ExtensionContext.java | 9 +++++---- .../engine/config/CachingJupiterConfiguration.java | 2 +- .../engine/config/DefaultJupiterConfiguration.java | 2 +- .../jupiter/engine/config/JupiterConfiguration.java | 2 +- .../engine/descriptor/AbstractExtensionContext.java | 3 ++- .../jupiter/engine/execution/NamespaceAwareStore.java | 7 ++++--- .../junit/platform/engine/ConfigurationParameters.java | 2 +- .../config/PrefixedConfigurationParameters.java | 2 +- .../support/store/NamespacedHierarchicalStore.java | 3 ++- .../params/ParameterizedTestExtensionTests.java | 3 ++- .../store/NamespacedHierarchicalStoreTests.java | 7 ++++--- 12 files changed, 34 insertions(+), 18 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 5b649daa7d71..5cf7d8a9560f 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -76,6 +76,11 @@ repository on GitHub. property has been removed. JUnit now always adheres to standard Java semantics regarding whether a given field or method is visible or overridden according to the rules of the Java language. +* The type bounds of the following methods have been changed to be more flexible and allow + nullable and non-nullable types: + - `ConfigurationParameters.get(String, Function)` + - `NamespacedHierarchicalStore.getOrComputeIfAbsent(N, K, Function)` + - `NamespacedHierarchicalStore.getOrComputeIfAbsent(N, K, Function, Class)` [[release-notes-6.0.0-M1-junit-platform-new-features-and-improvements]] ==== New Features and Improvements @@ -112,6 +117,11 @@ repository on GitHub. `callsInPlace(executable, AT_MOST_ONCE)` which might result in compilation errors. * The `junit-jupiter-migrationsupport` artifact and its contained classes are now deprecated and will be removed in the next major version. +* The type bounds of the following methods have been changed to be more flexible and allow + nullable and non-nullable types: + - `ExtensionContext.getConfigurationParameter(String, Function)` + - `ExtensionContext.getOrComputeIfAbsent(K, Function)` + - `ExtensionContext.getOrComputeIfAbsent(K, Function, Class)` [[release-notes-6.0.0-M1-junit-jupiter-new-features-and-improvements]] ==== New Features and Improvements 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 71b8d2861007..a58cb885e0a6 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 @@ -345,7 +345,7 @@ default Method getRequiredTestMethod() { * @see org.junit.platform.engine.ConfigurationParameters */ @API(status = STABLE, since = "5.10") - Optional getConfigurationParameter(String key, Function transformer); + Optional getConfigurationParameter(String key, Function transformer); /** * Publish a map of key-value pairs to be consumed by an @@ -649,7 +649,8 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ - @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator); + @Nullable Object getOrComputeIfAbsent(K key, + Function defaultCreator); /** * Get the value of the specified required type that is stored under the @@ -680,8 +681,8 @@ default V getOrDefault(Object key, Class requiredType, V defaultValue) { * @see CloseableResource * @see AutoCloseable */ - @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, - Class requiredType); + @Nullable V getOrComputeIfAbsent(K key, + Function defaultCreator, Class requiredType); /** * Store a {@code value} for later retrieval under the supplied {@code key}. diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java index ecab219838f3..33c927038ec3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/CachingJupiterConfiguration.java @@ -59,7 +59,7 @@ public Optional getRawConfigurationParameter(String key) { } @Override - public Optional getRawConfigurationParameter(String key, Function transformer) { + public Optional getRawConfigurationParameter(String key, Function transformer) { return delegate.getRawConfigurationParameter(key, transformer); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java index 9dce4a7397ab..99f08e00ee4a 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/DefaultJupiterConfiguration.java @@ -120,7 +120,7 @@ public Optional getRawConfigurationParameter(String key) { } @Override - public Optional getRawConfigurationParameter(String key, Function transformer) { + public Optional getRawConfigurationParameter(String key, Function transformer) { return configurationParameters.get(key, transformer); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java index ca4f8ff76a7d..92607e4614c3 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/config/JupiterConfiguration.java @@ -57,7 +57,7 @@ public interface JupiterConfiguration { Optional getRawConfigurationParameter(String key); - Optional getRawConfigurationParameter(String key, Function transformer); + Optional getRawConfigurationParameter(String key, Function transformer); boolean isParallelExecutionEnabled(); diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index b3497dfc0c80..a7424f311c73 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -242,7 +242,8 @@ public Optional getConfigurationParameter(String key) { } @Override - public Optional getConfigurationParameter(String key, Function transformer) { + public Optional getConfigurationParameter(String key, + Function transformer) { return this.configuration.getRawConfigurationParameter(key, transformer); } diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java index 7d4b03d91d38..88535ea14931 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/execution/NamespaceAwareStore.java @@ -54,7 +54,8 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override - public @Nullable Object getOrComputeIfAbsent(K key, Function defaultCreator) { + public @Nullable Object getOrComputeIfAbsent(K key, + Function defaultCreator) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Supplier<@Nullable Object> action = () -> this.valuesStore.getOrComputeIfAbsent(this.namespace, key, @@ -63,8 +64,8 @@ public NamespaceAwareStore(NamespacedHierarchicalStore valuesStore, N } @Override - public @Nullable V getOrComputeIfAbsent(K key, Function defaultCreator, - Class requiredType) { + public @Nullable V getOrComputeIfAbsent(K key, + Function defaultCreator, Class requiredType) { Preconditions.notNull(key, "key must not be null"); Preconditions.notNull(defaultCreator, "defaultCreator function must not be null"); Preconditions.notNull(requiredType, "requiredType must not be null"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java index 63a9b6e16b4d..48f2b3d1b0bb 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/ConfigurationParameters.java @@ -117,7 +117,7 @@ public interface ConfigurationParameters { * @see #CONFIG_FILE_NAME */ @API(status = STABLE, since = "1.3") - default Optional get(String key, Function transformer) { + default Optional get(String key, Function transformer) { Preconditions.notNull(transformer, "transformer must not be null"); return get(key).map(input -> { try { diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java index 0673d1c003ef..61a55c72830c 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/config/PrefixedConfigurationParameters.java @@ -58,7 +58,7 @@ public Optional getBoolean(String key) { } @Override - public Optional get(String key, Function transformer) { + public Optional get(String key, Function transformer) { return delegate.get(prefixed(key), transformer); } 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 4f8f00e9a3bd..2abab9ea50cb 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 @@ -220,7 +220,8 @@ public void close() { * be cast to the required type, or if this store has already been closed */ public @Nullable V getOrComputeIfAbsent(N namespace, K key, - Function defaultCreator, Class requiredType) throws NamespacedHierarchicalStoreException { + Function defaultCreator, Class requiredType) + throws NamespacedHierarchicalStoreException { Object value = getOrComputeIfAbsent(namespace, key, defaultCreator); return castToRequiredType(key, value, requiredType); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java index bf0956e41ff0..9f589354ae5c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java @@ -293,7 +293,8 @@ public Optional getConfigurationParameter(String key) { } @Override - public Optional getConfigurationParameter(String key, Function transformer) { + public Optional getConfigurationParameter(String key, + Function transformer) { return configurationSupplier.apply(key).map(transformer); } diff --git a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java index e2212c5f9afc..52f3d5e07d77 100644 --- a/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java +++ b/platform-tests/src/test/java/org/junit/platform/engine/support/store/NamespacedHierarchicalStoreTests.java @@ -10,6 +10,7 @@ package org.junit.platform.engine.support.store; +import static java.util.Objects.requireNonNull; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; @@ -28,7 +29,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -320,11 +320,12 @@ void removeNullValueWithTypeSafety() { void simulateRaceConditionInGetOrComputeIfAbsent() throws Exception { int threads = 10; AtomicInteger counter = new AtomicInteger(); - List<@Nullable Object> values; + List values; try (var localStore = new NamespacedHierarchicalStore<>(null)) { values = executeConcurrently(threads, // - () -> localStore.getOrComputeIfAbsent(namespace, key, it -> counter.incrementAndGet())); + () -> requireNonNull( + localStore.getOrComputeIfAbsent(namespace, key, it -> counter.incrementAndGet()))); } assertEquals(1, counter.get()); From a1f1dd3622904bef123f9172476ced01d6232b2d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 15:57:04 +0200 Subject: [PATCH 256/521] Disable NullAway on OpenJ9 --- .github/workflows/cross-version.yml | 2 +- .../junitbuild.java-nullability-conventions.gradle.kts | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 9cae65c78f66..6368bf02d4a7 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -69,7 +69,7 @@ jobs: strategy: fail-fast: false matrix: - jdk: [ 24 ] + jdk: [ 21 ] name: "OpenJ9 ${{ matrix.jdk }}" runs-on: ubuntu-latest steps: diff --git a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts index e07c8ca8297c..a06ab1becca9 100644 --- a/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts +++ b/gradle/plugins/common/src/main/kotlin/junitbuild.java-nullability-conventions.gradle.kts @@ -21,7 +21,11 @@ tasks.withType().configureEach { options.errorprone { disableAllChecks = true nullaway { - enable() + if (java.toolchain.implementation.orNull == JvmImplementation.J9) { + disable() + } else { + enable() + } isJSpecifyMode = true } } From a1a8b6be5fcf91bb4d4707eda8c5edf8d579f430 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 16:43:11 +0200 Subject: [PATCH 257/521] Adjust ToC colors in Javadoc --- documentation/src/javadoc/junit-stylesheet.css | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/documentation/src/javadoc/junit-stylesheet.css b/documentation/src/javadoc/junit-stylesheet.css index cde05cfb75a6..6d5b1bb6c287 100644 --- a/documentation/src/javadoc/junit-stylesheet.css +++ b/documentation/src/javadoc/junit-stylesheet.css @@ -30,6 +30,9 @@ /* Text colors for links */ --link-color: #dc524a; --link-color-active: #b62b23; + /* Table of contents */ + --toc-background-color: var(--section-background-color); + --toc-link-color: #000; /* Snippet colors */ --snippet-background-color: #ebecee; --snippet-text-color: var(--block-text-color); @@ -39,10 +42,6 @@ --table-border-color: #999; /* Highlight color for active search tag target */ --search-tag-highlight-color: #ffff00; - /* Adjustments for icon and active background colors of copy-to-clipboard buttons */ - --copy-button-background-color-active: rgba(168, 168, 168, 0.3); - /* Colors for invalid tag notifications */ - --invalid-tag-background-color: #ffe6e6; } .title { From b213eb52021a354428b258968546527c6b0d93a8 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 16:52:58 +0200 Subject: [PATCH 258/521] Fix nullability issue in ResolverFacade --- .../jupiter/api/extension/ExtensionConfigurationException.java | 3 ++- .../src/main/java/org/junit/jupiter/params/ResolverFacade.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java index fd915b661156..eedd682c7992 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/extension/ExtensionConfigurationException.java @@ -15,6 +15,7 @@ import java.io.Serial; import org.apiguardian.api.API; +import org.jspecify.annotations.Nullable; import org.junit.platform.commons.JUnitException; /** @@ -33,7 +34,7 @@ public ExtensionConfigurationException(String message) { super(message); } - public ExtensionConfigurationException(String message, Throwable cause) { + public ExtensionConfigurationException(String message, @Nullable Throwable cause) { super(message, cause); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java index 594c3a7bfd49..3aebf1fe27b1 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolverFacade.java @@ -241,7 +241,7 @@ ArgumentSetLifecycleMethod.ParameterResolver createLifecycleMethodParameterResol .call(() -> configurationErrorOrSuccess(errors, () -> new DefaultArgumentSetLifecycleMethodParameterResolver(originalResolverFacade, lifecycleMethodResolverFacade, parameterDeclarationMapping))) // - .getOrThrow(cause -> new ExtensionConfigurationException( + .getNonNullOrThrow(cause -> new ExtensionConfigurationException( "Invalid @%s lifecycle method declaration: %s".formatted( annotation.annotationType().getSimpleName(), method.toGenericString()), cause)); From 5f3ed21e267986344c72a9472f0a4c0c8fbb9ac0 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 16:53:09 +0200 Subject: [PATCH 259/521] Simplify method signature --- .../main/java/org/junit/jupiter/params/ResolutionCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java index 4bd2321faac2..ac013d0ceb70 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ResolutionCache.java @@ -29,14 +29,14 @@ static ResolutionCache enabled() { ResolutionCache DISABLED = (__, resolver) -> resolver.get(); @Nullable - Object resolve(ParameterDeclaration declaration, Supplier<@Nullable Object> resolver); + Object resolve(ParameterDeclaration declaration, Supplier resolver); class Concurrent implements ResolutionCache { private final Map cache = new ConcurrentHashMap<>(); @Override - public @Nullable Object resolve(ParameterDeclaration declaration, Supplier<@Nullable Object> resolver) { + public @Nullable Object resolve(ParameterDeclaration declaration, Supplier resolver) { return cache.computeIfAbsent(declaration, __ -> resolver.get()); } } From d52ddac62126167ff1cae6ccac6640d7664e249c Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 17:03:47 +0200 Subject: [PATCH 260/521] Move `@Nullable` annotation to type declaration --- .../jupiter/api/AssertionFailureBuilder.java | 15 +++++---------- .../java/org/junit/jupiter/api/DynamicNode.java | 3 +-- .../java/org/junit/jupiter/api/condition/OS.java | 3 +-- .../descriptor/AbstractExtensionContext.java | 3 +-- .../descriptor/ClassBasedTestDescriptor.java | 6 ++---- .../engine/descriptor/ClassExtensionContext.java | 3 +-- .../ClassTemplateInvocationTestDescriptor.java | 3 +-- .../descriptor/DynamicTestTestDescriptor.java | 3 +-- .../engine/descriptor/MethodExtensionContext.java | 3 +-- .../descriptor/TestTemplateExtensionContext.java | 3 +-- .../TestTemplateInvocationTestDescriptor.java | 3 +-- .../aggregator/DefaultArgumentsAccessor.java | 3 +-- .../AnnotationBasedArgumentConverter.java | 3 +-- .../FallbackStringToObjectConverter.java | 3 +-- .../commons/util/KotlinReflectionUtils.java | 6 ++---- .../platform/console/options/CommandResult.java | 3 +-- .../console/options/TestConsoleOutputOptions.java | 9 +++------ .../console/options/TestDiscoveryOptions.java | 3 +-- .../console/tasks/StandardStreamsHandler.java | 6 ++---- .../console/tasks/TestFeedPrintingListener.java | 3 +-- .../junit/platform/console/tasks/TreeNode.java | 9 +++------ .../console/tasks/TreePrintingListener.java | 3 +-- .../platform/engine/DefaultDiscoveryIssue.java | 6 ++---- .../junit/platform/engine/ExecutionRequest.java | 6 ++---- .../platform/engine/SelectorResolutionResult.java | 3 +-- .../platform/engine/TestExecutionResult.java | 3 +-- .../java/org/junit/platform/engine/UniqueId.java | 3 +-- .../platform/engine/discovery/ClassSelector.java | 6 ++---- .../discovery/ClasspathResourceSelector.java | 6 ++---- .../platform/engine/discovery/FilePosition.java | 3 +-- .../platform/engine/discovery/FileSelector.java | 3 +-- .../platform/engine/discovery/MethodSelector.java | 9 +++------ .../engine/discovery/NestedClassSelector.java | 3 +-- .../platform/engine/reporting/FileEntry.java | 3 +-- .../descriptor/AbstractTestDescriptor.java | 6 ++---- .../engine/support/descriptor/ClassSource.java | 6 ++---- .../descriptor/ClasspathResourceSource.java | 3 +-- .../engine/support/descriptor/FilePosition.java | 3 +-- .../engine/support/descriptor/FileSource.java | 3 +-- .../engine/support/descriptor/MethodSource.java | 9 +++------ .../engine/support/hierarchical/NodeTestTask.java | 12 ++++-------- .../support/hierarchical/ThrowableCollector.java | 3 +-- .../store/NamespacedHierarchicalStore.java | 6 ++---- .../DemoHierarchicalContainerDescriptor.java | 3 +-- .../DemoHierarchicalEngineDescriptor.java | 3 +-- .../DemoHierarchicalTestDescriptor.java | 6 ++---- .../org/junit/platform/fakes/TestEngineSpy.java | 3 +-- .../platform/launcher/EngineDiscoveryResult.java | 3 +-- .../junit/platform/launcher/TestIdentifier.java | 6 ++---- .../core/HierarchicalOutputDirectoryProvider.java | 3 +-- .../core/LauncherDiscoveryRequestBuilder.java | 6 ++---- .../OutcomeDelayingEngineExecutionListener.java | 9 +++------ .../listeners/SummaryGeneratingListener.java | 6 ++---- .../listeners/UniqueIdTrackingListener.java | 3 +-- .../platform/launcher/tagexpression/Operator.java | 3 +-- .../launcher/tagexpression/ParseStatus.java | 3 +-- .../xml/LegacyXmlReportGeneratingListener.java | 3 +-- .../xml/OpenTestReportGeneratingListener.java | 3 +-- .../SuiteLauncherDiscoveryRequestBuilder.java | 3 +-- .../suite/engine/SuiteTestDescriptor.java | 6 ++---- .../org/junit/platform/testkit/engine/Event.java | 3 +-- .../platform/testkit/engine/TerminationInfo.java | 6 ++---- .../engine/descriptor/RunnerTestDescriptor.java | 3 +-- .../AbstractExecutionConditionTests.java | 3 +-- .../NestedWithSeparateInheritanceTests.java | 3 +-- .../discovery/DiscoverySelectorResolverTests.java | 3 +-- .../execution/AbstractExecutableInvokerTests.java | 3 +-- .../execution/ParameterResolutionUtilsTests.java | 3 +-- .../engine/extension/BeforeAndAfterAllTests.java | 3 +-- .../engine/extension/BeforeAndAfterEachTests.java | 3 +-- .../BeforeAndAfterTestExecutionCallbackTests.java | 3 +-- .../engine/extension/CloseablePathTests.java | 3 +-- .../provider/MethodArgumentsProviderTests.java | 3 +-- .../commons/util/AnnotationUtilsTests.java | 9 +++------ .../console/ConsoleLauncherWrapperResult.java | 3 +-- 75 files changed, 110 insertions(+), 220 deletions(-) diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java index fdb5cdd68d52..a8fd354ce2a4 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/AssertionFailureBuilder.java @@ -32,22 +32,17 @@ @API(status = STABLE, since = "5.9") public class AssertionFailureBuilder { - @Nullable - private Object message; + private @Nullable Object message; - @Nullable - private Throwable cause; + private @Nullable Throwable cause; private boolean mismatch; - @Nullable - private Object expected; + private @Nullable Object expected; - @Nullable - private Object actual; + private @Nullable Object actual; - @Nullable - private String reason; + private @Nullable String reason; private boolean includeValuesInMessage = true; diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java index 59c990ee8b99..0f4d66c5b652 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/DynamicNode.java @@ -34,8 +34,7 @@ public abstract class DynamicNode { private final String displayName; /** Custom test source {@link URI} associated with this node; potentially {@code null}. */ - @Nullable - private final URI testSourceUri; + private final @Nullable URI testSourceUri; DynamicNode(String displayName, @Nullable URI testSourceUri) { this.displayName = Preconditions.notBlank(displayName, "displayName must not be null or blank"); diff --git a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java index 8b6f4a348241..0c7ab8be1bc6 100644 --- a/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java +++ b/junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/OS.java @@ -95,8 +95,7 @@ public enum OS { private static final Logger logger = LoggerFactory.getLogger(OS.class); - @Nullable - private static final OS CURRENT_OS = determineCurrentOs(); + private static final @Nullable OS CURRENT_OS = determineCurrentOs(); /** * {@return the current operating system, if known; otherwise, {@code null}} diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java index a7424f311c73..d19c71845461 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/AbstractExtensionContext.java @@ -55,8 +55,7 @@ abstract class AbstractExtensionContext implements Ext private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExtensionContext.class); - @Nullable - private final ExtensionContext parent; + private final @Nullable ExtensionContext parent; private final EngineExecutionListener engineExecutionListener; private final T testDescriptor; private final Set tags; diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java index 19f89349675a..5aacb02d1af2 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassBasedTestDescriptor.java @@ -93,11 +93,9 @@ public abstract class ClassBasedTestDescriptor extends JupiterTestDescriptor protected final ClassInfo classInfo; - @Nullable - private LifecycleMethods lifecycleMethods; + private @Nullable LifecycleMethods lifecycleMethods; - @Nullable - private TestInstanceFactory testInstanceFactory; + private @Nullable TestInstanceFactory testInstanceFactory; ClassBasedTestDescriptor(UniqueId uniqueId, Class testClass, Supplier displayNameSupplier, JupiterConfiguration configuration) { diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java index 157ae5ccb84c..10e987049260 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/ClassExtensionContext.java @@ -34,8 +34,7 @@ final class ClassExtensionContext extends AbstractExtensionContext { - @Nullable - private final TestInstances testInstances; + private final @Nullable TestInstances testInstances; TestTemplateExtensionContext(ExtensionContext parent, EngineExecutionListener engineExecutionListener, TestTemplateTestDescriptor testDescriptor, JupiterConfiguration configuration, diff --git a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java index 3bd4654732f8..f33a4a035f82 100644 --- a/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java +++ b/junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/descriptor/TestTemplateInvocationTestDescriptor.java @@ -43,8 +43,7 @@ public class TestTemplateInvocationTestDescriptor extends TestMethodTestDescript public static final String SEGMENT_TYPE = "test-template-invocation"; private static final VoidMethodInterceptorCall interceptorCall = InvocationInterceptor::interceptTestTemplateMethod; - @Nullable - private TestTemplateInvocationContext invocationContext; + private @Nullable TestTemplateInvocationContext invocationContext; private final int index; diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java index 67a58840d000..80376859b3da 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/aggregator/DefaultArgumentsAccessor.java @@ -62,8 +62,7 @@ private DefaultArgumentsAccessor(BiFunction<@Nullable Object, Class, @Nullabl } @Override - @Nullable - public Object get(int index) { + public @Nullable Object get(int index) { Preconditions.condition(index >= 0 && index < this.arguments.length, () -> "index must be >= 0 and < %d".formatted(this.arguments.length)); return this.arguments[index]; 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 ca1d68bb6aca..2696d6c5544b 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 @@ -36,8 +36,7 @@ public abstract class AnnotationBasedArgumentConverter implements ArgumentConverter, AnnotationConsumer { - @Nullable - private A annotation; + private @Nullable A annotation; public AnnotationBasedArgumentConverter() { } diff --git a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java index b7f96707a52e..916406e3fbcb 100644 --- a/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java +++ b/junit-platform-commons/src/main/java/org/junit/platform/commons/support/conversion/FallbackStringToObjectConverter.java @@ -76,8 +76,7 @@ public boolean canConvertTo(Class targetType) { } @Override - @Nullable - public Object convert(String source, Class targetType) throws Exception { + public @Nullable Object convert(String source, Class targetType) throws Exception { Function executable = findFactoryExecutable(targetType); Preconditions.condition(executable != NULL_EXECUTABLE, "Illegal state: convert() must not be called if canConvert() returned false"); 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 index 99975cd24a1c..926ae651ee99 100644 --- 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 @@ -30,10 +30,8 @@ @API(status = INTERNAL, since = "6.0") public class KotlinReflectionUtils { - @Nullable - private static final Class kotlinMetadata; - @Nullable - private static final Class kotlinCoroutineContinuation; + private static final @Nullable Class kotlinMetadata; + private static final @Nullable Class kotlinCoroutineContinuation; private static final boolean kotlinReflectPresent; private static final boolean kotlinxCoroutinesPresent; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java index 2044347f8265..ff0031b9e5ec 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/CommandResult.java @@ -47,8 +47,7 @@ public static CommandResult create(int exitCode, @Nullable T value) { private final int exitCode; - @Nullable - private final T value; + private final @Nullable T value; private CommandResult(int exitCode, @Nullable T value) { this.exitCode = exitCode; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java index 235588768f12..396f74fd7cef 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestConsoleOutputOptions.java @@ -30,18 +30,15 @@ public class TestConsoleOutputOptions { private boolean ansiColorOutputDisabled; - @Nullable - private Path colorPalettePath; + private @Nullable Path colorPalettePath; private boolean isSingleColorPalette; private Details details = DEFAULT_DETAILS; private Theme theme = DEFAULT_THEME; - @Nullable - private Path stdoutPath; + private @Nullable Path stdoutPath; - @Nullable - private Path stderrPath; + private @Nullable Path stderrPath; public boolean isAnsiColorOutputDisabled() { return this.ansiColorOutputDisabled; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java index 93e9a77d3366..3e368c90ae94 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/options/TestDiscoveryOptions.java @@ -47,8 +47,7 @@ public class TestDiscoveryOptions { private boolean scanClasspath; private List additionalClasspathEntries = emptyList(); - @Nullable - private List selectedClasspathEntries = emptyList(); + private @Nullable List selectedClasspathEntries = emptyList(); private boolean scanModulepath; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java index 9cb91fce9418..5f7b8bca1307 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/StandardStreamsHandler.java @@ -20,11 +20,9 @@ class StandardStreamsHandler implements AutoCloseable { - @Nullable - private PrintStream stdout; + private @Nullable PrintStream stdout; - @Nullable - private PrintStream stderr; + private @Nullable PrintStream stderr; public StandardStreamsHandler() { } diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java index b549494b0507..cfe4ecb37a60 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TestFeedPrintingListener.java @@ -32,8 +32,7 @@ class TestFeedPrintingListener implements DetailsPrintingListener { private final PrintWriter out; private final ColorPalette colorPalette; - @Nullable - private TestPlan testPlan; + private @Nullable TestPlan testPlan; TestFeedPrintingListener(PrintWriter out, ColorPalette colorPalette) { this.out = out; diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java index 55e05009a24f..03de24ef6bd4 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreeNode.java @@ -32,14 +32,11 @@ class TreeNode { private final long creation; long duration; - @Nullable - private String reason; + private @Nullable String reason; - @Nullable - private TestIdentifier identifier; + private @Nullable TestIdentifier identifier; - @Nullable - private TestExecutionResult result; + private @Nullable TestExecutionResult result; final Queue reports = new ConcurrentLinkedQueue<>(); final Queue files = new ConcurrentLinkedQueue<>(); diff --git a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java index d8d7130e400a..36351d035a0a 100644 --- a/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java +++ b/junit-platform-console/src/main/java/org/junit/platform/console/tasks/TreePrintingListener.java @@ -34,8 +34,7 @@ class TreePrintingListener implements DetailsPrintingListener { private final Map nodesByUniqueId = new ConcurrentHashMap<>(); private final TreePrinter treePrinter; - @Nullable - private TreeNode root; + private @Nullable TreeNode root; TreePrintingListener(PrintWriter out, ColorPalette colorPalette, Theme theme) { this.treePrinter = new TreePrinter(out, theme, colorPalette); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java index c0c2b7647d8d..1f82ef3487b2 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/DefaultDiscoveryIssue.java @@ -24,11 +24,9 @@ final class DefaultDiscoveryIssue implements DiscoveryIssue { private final Severity severity; private final String message; - @Nullable - private final TestSource source; + private final @Nullable TestSource source; - @Nullable - private final Throwable cause; + private final @Nullable Throwable cause; DefaultDiscoveryIssue(Builder builder) { this.severity = builder.severity; 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 7bff6ea78605..0649cec4f867 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 @@ -43,11 +43,9 @@ public class ExecutionRequest { private final EngineExecutionListener engineExecutionListener; private final ConfigurationParameters configurationParameters; - @Nullable - private final OutputDirectoryProvider outputDirectoryProvider; + private final @Nullable OutputDirectoryProvider outputDirectoryProvider; - @Nullable - private final NamespacedHierarchicalStore requestLevelStore; + private final @Nullable NamespacedHierarchicalStore requestLevelStore; @Deprecated @API(status = DEPRECATED, since = "1.11") diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java index 2b2b1a2f0951..8ddad4ab5560 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/SelectorResolutionResult.java @@ -88,8 +88,7 @@ public static SelectorResolutionResult failed(Throwable throwable) { private final Status status; - @Nullable - private final Throwable throwable; + private final @Nullable Throwable throwable; private SelectorResolutionResult(Status status, @Nullable Throwable throwable) { this.status = status; diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java index 2052cf360459..f7e2ddcd889b 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/TestExecutionResult.java @@ -96,8 +96,7 @@ public static TestExecutionResult failed(@Nullable Throwable throwable) { private final Status status; - @Nullable - private final Throwable throwable; + private final @Nullable Throwable throwable; private TestExecutionResult(Status status, @Nullable Throwable throwable) { this.status = Preconditions.notNull(status, "Status must not be null"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java index ab5a002a64c2..c60e716d54ec 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/UniqueId.java @@ -91,8 +91,7 @@ public static UniqueId root(String segmentType, String value) { private transient int hashCode; // lazily computed - @Nullable - private transient SoftReference toString; + private transient @Nullable SoftReference toString; private UniqueId(UniqueIdFormat uniqueIdFormat, Segment segment) { this(uniqueIdFormat, List.of(segment)); 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 06e5d605a249..2c47fd7d3d08 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 @@ -48,13 +48,11 @@ @API(status = STABLE, since = "1.0") public class ClassSelector implements DiscoverySelector { - @Nullable - private final ClassLoader classLoader; + private final @Nullable ClassLoader classLoader; private final String className; - @Nullable - private Class javaClass; + private @Nullable Class javaClass; ClassSelector(@Nullable ClassLoader classLoader, String className) { this.className = className; 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 774b917d2267..4f77553882b2 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 @@ -57,11 +57,9 @@ public class ClasspathResourceSelector implements DiscoverySelector { private final String classpathResourceName; - @Nullable - private final FilePosition position; + private final @Nullable FilePosition position; - @Nullable - private Set classpathResources; + private @Nullable Set classpathResources; ClasspathResourceSelector(String classpathResourceName, @Nullable FilePosition position) { boolean startsWithSlash = classpathResourceName.startsWith("/"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java index eed02fb5ecc7..74973ef3fa90 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FilePosition.java @@ -123,8 +123,7 @@ else if (column == null && "column".equals(key)) { private final int line; - @Nullable - private final Integer column; + private final @Nullable Integer column; private FilePosition(int line) { Preconditions.condition(line > 0, "line number must be greater than zero"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java index 04f9ffb4c23c..ac01e74b5379 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/discovery/FileSelector.java @@ -46,8 +46,7 @@ public class FileSelector implements DiscoverySelector { private final String path; - @Nullable - private final FilePosition position; + private final @Nullable FilePosition position; FileSelector(String path, @Nullable FilePosition position) { this.path = path; 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 41c400874314..5bd67d658470 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 @@ -60,17 +60,14 @@ @API(status = STABLE, since = "1.0") public class MethodSelector implements DiscoverySelector { - @Nullable - private final ClassLoader classLoader; + private final @Nullable ClassLoader classLoader; private final String className; private final String methodName; private final String parameterTypeNames; - @Nullable - private volatile Class javaClass; + private volatile @Nullable Class javaClass; - @Nullable - private volatile Method javaMethod; + private volatile @Nullable Method javaMethod; private volatile Class @Nullable [] parameterTypes; 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 aa3f340df281..a6ed8bd44f2b 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 @@ -53,8 +53,7 @@ @API(status = STABLE, since = "1.6") public class NestedClassSelector implements DiscoverySelector { - @Nullable - private final ClassLoader classLoader; + private final @Nullable ClassLoader classLoader; private final List enclosingClassSelectors; private final ClassSelector nestedClassSelector; 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 2c74c860c7c3..2edd765cb3e6 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 @@ -46,8 +46,7 @@ public static FileEntry from(Path path, @Nullable String mediaType) { private final LocalDateTime timestamp = LocalDateTime.now(); private final Path path; - @Nullable - private final String mediaType; + private final @Nullable String mediaType; private FileEntry(Path path, @Nullable String mediaType) { this.path = Preconditions.notNull(path, "path must not be null"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java index 0454b5c34dad..4292bc7f6028 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/AbstractTestDescriptor.java @@ -45,11 +45,9 @@ public abstract class AbstractTestDescriptor implements TestDescriptor { private final String displayName; - @Nullable - private final TestSource source; + private final @Nullable TestSource source; - @Nullable - private TestDescriptor parent; + private @Nullable TestDescriptor parent; /** * The synchronized set of children associated with this {@code TestDescriptor}. diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java index f31e3d948a14..7852ba45b8a0 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClassSource.java @@ -134,11 +134,9 @@ public static ClassSource from(URI uri) { private final String className; - @Nullable - private final FilePosition filePosition; + private final @Nullable FilePosition filePosition; - @Nullable - private Class javaClass; + private @Nullable Class javaClass; private ClassSource(String className) { this(className, null); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java index 3f547a564606..838b92d9ad8e 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/ClasspathResourceSource.java @@ -114,8 +114,7 @@ public static ClasspathResourceSource from(URI uri) { private final String classpathResourceName; - @Nullable - private final FilePosition filePosition; + private final @Nullable FilePosition filePosition; private ClasspathResourceSource(String classpathResourceName) { this(classpathResourceName, null); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java index de653d5fcacb..7d8d9b5500ff 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FilePosition.java @@ -118,8 +118,7 @@ else if (column == null && "column".equals(key)) { private final int line; - @Nullable - private final Integer column; + private final @Nullable Integer column; private FilePosition(int line) { Preconditions.condition(line > 0, "line number must be greater than zero"); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java index b82e113ff5ee..577f602659db 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/FileSource.java @@ -60,8 +60,7 @@ public static FileSource from(File file, @Nullable FilePosition filePosition) { private final File file; - @Nullable - private final FilePosition filePosition; + private final @Nullable FilePosition filePosition; private FileSource(File file) { this(file, null); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java index b3c95915dd52..1917dd19b168 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/descriptor/MethodSource.java @@ -110,14 +110,11 @@ public static MethodSource from(Class testClass, Method testMethod) { private final String className; private final String methodName; - @Nullable - private final String methodParameterTypes; + private final @Nullable String methodParameterTypes; - @Nullable - private Class javaClass; + private @Nullable Class javaClass; - @Nullable - private transient Method javaMethod; + private transient @Nullable Method javaMethod; private MethodSource(String className, String methodName) { this(className, methodName, null); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java index 2b5082e74ae4..c4868d522a93 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/NodeTestTask.java @@ -54,19 +54,15 @@ class NodeTestTask implements TestTask { private final Node node; private final Runnable finalizer; - @Nullable - private C parentContext; + private @Nullable C parentContext; - @Nullable - private C context; + private @Nullable C context; - @Nullable - private SkipResult skipResult; + private @Nullable SkipResult skipResult; private boolean started; - @Nullable - private ThrowableCollector throwableCollector; + private @Nullable ThrowableCollector throwableCollector; NodeTestTask(NodeTestTaskContext taskContext, TestDescriptor testDescriptor) { this(taskContext, testDescriptor, NOOP); diff --git a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java index f322178a62fa..04282d8b151e 100644 --- a/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java +++ b/junit-platform-engine/src/main/java/org/junit/platform/engine/support/hierarchical/ThrowableCollector.java @@ -43,8 +43,7 @@ public class ThrowableCollector { private final Predicate abortedExecutionPredicate; - @Nullable - private Throwable throwable; + private @Nullable Throwable throwable; /** * Create a new {@code ThrowableCollector} that uses the supplied 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 2abab9ea50cb..d06deba1e679 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 @@ -52,11 +52,9 @@ public final class NamespacedHierarchicalStore implements AutoCloseable { private final ConcurrentMap, StoredValue> storedValues = new ConcurrentHashMap<>(4); - @Nullable - private final NamespacedHierarchicalStore parentStore; + private final @Nullable NamespacedHierarchicalStore parentStore; - @Nullable - private final CloseAction closeAction; + private final @Nullable CloseAction closeAction; private volatile boolean closed = false; diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java index ea0e595862c7..1a5b9c20c7ac 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalContainerDescriptor.java @@ -23,8 +23,7 @@ public class DemoHierarchicalContainerDescriptor extends AbstractTestDescriptor implements Node { - @Nullable - private final Runnable beforeBlock; + private final @Nullable Runnable beforeBlock; public DemoHierarchicalContainerDescriptor(UniqueId uniqueId, String displayName, @Nullable TestSource source, @Nullable Runnable beforeBlock) { diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java index 49aa67dd32f8..519128ce7459 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalEngineDescriptor.java @@ -22,8 +22,7 @@ */ public class DemoHierarchicalEngineDescriptor extends EngineDescriptor implements Node { - @Nullable - private String skippedReason; + private @Nullable String skippedReason; private boolean skipped; private Runnable beforeAllBehavior = () -> { diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java index 26b696be0387..8cb70bd68d0c 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/engine/support/hierarchical/DemoHierarchicalTestDescriptor.java @@ -26,11 +26,9 @@ */ public class DemoHierarchicalTestDescriptor extends AbstractTestDescriptor implements Node { - @Nullable - private final BiConsumer executeBlock; + private final @Nullable BiConsumer executeBlock; - @Nullable - private String skippedReason; + private @Nullable String skippedReason; private boolean skipped; diff --git a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java index 040fe144e446..67a1c34a99d2 100644 --- a/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java +++ b/junit-platform-engine/src/testFixtures/java/org/junit/platform/fakes/TestEngineSpy.java @@ -24,8 +24,7 @@ public class TestEngineSpy implements TestEngine { private final String id; - @Nullable - public ExecutionRequest requestForExecution; + public @Nullable ExecutionRequest requestForExecution; public TestEngineSpy() { this(TestEngineSpy.class.getSimpleName()); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java index c266f3319ab0..5625715ad0dd 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/EngineDiscoveryResult.java @@ -73,8 +73,7 @@ public static EngineDiscoveryResult failed(@Nullable Throwable throwable) { private final Status status; - @Nullable - private final Throwable throwable; + private final @Nullable Throwable throwable; private EngineDiscoveryResult(Status status, @Nullable Throwable throwable) { this.status = status; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java index f2700882724f..6cc56a0dd9af 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/TestIdentifier.java @@ -58,14 +58,12 @@ public final class TestIdentifier implements Serializable { // These are effectively final but not technically due to late initialization when deserializing private /* final */ UniqueId uniqueId; - @Nullable - private /* final */ UniqueId parentId; + private /* final */ @Nullable UniqueId parentId; private /* final */ String displayName; private /* final */ String legacyReportingName; - @Nullable - private /* final */ TestSource source; + private /* final */ @Nullable TestSource source; private /* final */ Set tags; private /* final */ Type type; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java index b836d2ca5b3c..3be48cf03a3e 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/HierarchicalOutputDirectoryProvider.java @@ -36,8 +36,7 @@ class HierarchicalOutputDirectoryProvider implements OutputDirectoryProvider { private final Supplier rootDirSupplier; - @Nullable - private volatile Path rootDir; + private volatile @Nullable Path rootDir; HierarchicalOutputDirectoryProvider(Supplier rootDirSupplier) { this.rootDirSupplier = rootDirSupplier; 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 8f821985f3d6..ed3af5cf796d 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 @@ -111,11 +111,9 @@ public final class LauncherDiscoveryRequestBuilder { private final List discoveryListeners = new ArrayList<>(); private boolean implicitConfigurationParametersEnabled = true; - @Nullable - private ConfigurationParameters parentConfigurationParameters; + private @Nullable ConfigurationParameters parentConfigurationParameters; - @Nullable - private OutputDirectoryProvider outputDirectoryProvider; + private @Nullable OutputDirectoryProvider outputDirectoryProvider; /** * Create a new {@code LauncherDiscoveryRequestBuilder}. diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java index 4ea6111553ce..239044bc95e3 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/core/OutcomeDelayingEngineExecutionListener.java @@ -31,14 +31,11 @@ class OutcomeDelayingEngineExecutionListener extends DelegatingEngineExecutionLi private volatile boolean engineStarted; - @Nullable - private volatile Outcome outcome; + private volatile @Nullable Outcome outcome; - @Nullable - private volatile String skipReason; + private volatile @Nullable String skipReason; - @Nullable - private volatile TestExecutionResult executionResult; + private volatile @Nullable TestExecutionResult executionResult; OutcomeDelayingEngineExecutionListener(EngineExecutionListener delegate, TestDescriptor engineDescriptor) { super(delegate); diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java index c972b968a925..e404a7457c1a 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/SummaryGeneratingListener.java @@ -35,11 +35,9 @@ @API(status = MAINTAINED, since = "1.0") public class SummaryGeneratingListener implements TestExecutionListener { - @Nullable - private TestPlan testPlan; + private @Nullable TestPlan testPlan; - @Nullable - private MutableTestExecutionSummary summary; + private @Nullable MutableTestExecutionSummary summary; public SummaryGeneratingListener() { diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java index 2c05881a5bfb..802168bb5267 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/listeners/UniqueIdTrackingListener.java @@ -137,8 +137,7 @@ public class UniqueIdTrackingListener implements TestExecutionListener { private boolean enabled; - @Nullable - private TestPlan testPlan; + private @Nullable TestPlan testPlan; public UniqueIdTrackingListener() { // to avoid missing-explicit-ctor warning diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java index 55c483abbe93..4f09bb92c59b 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/Operator.java @@ -81,8 +81,7 @@ static Operator binaryOperator(String representation, int precedence, Associativ private final int precedence; private final int arity; - @Nullable - private final Associativity associativity; + private final @Nullable Associativity associativity; private final TagExpressionCreator tagExpressionCreator; diff --git a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java index 9f1b124c6133..de4bbd374d12 100644 --- a/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java +++ b/junit-platform-launcher/src/main/java/org/junit/platform/launcher/tagexpression/ParseStatus.java @@ -62,8 +62,7 @@ private static ParseStatus error(@Nullable String errorMessage) { return new ParseStatus(errorMessage); } - @Nullable - final String errorMessage; + final @Nullable String errorMessage; private ParseStatus(@Nullable String errorMessage) { this.errorMessage = errorMessage; diff --git a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java index 4287192fa408..cf96452b202d 100644 --- a/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java +++ b/junit-platform-reporting/src/main/java/org/junit/platform/reporting/legacy/xml/LegacyXmlReportGeneratingListener.java @@ -50,8 +50,7 @@ public class LegacyXmlReportGeneratingListener implements TestExecutionListener private final PrintWriter out; private final Clock clock; - @Nullable - private XmlReportData reportData; + private @Nullable XmlReportData reportData; public LegacyXmlReportGeneratingListener(Path reportsDir, PrintWriter out) { this(reportsDir, out, Clock.systemDefaultZone()); 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 46f41fa50f64..91c5df3d8f44 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 @@ -117,8 +117,7 @@ public class OpenTestReportGeneratingListener implements TestExecutionListener { private DocumentWriter eventsFileWriter = DocumentWriter.noop(); private final Path workingDir; - @Nullable - private Path outputDir; + private @Nullable Path outputDir; @SuppressWarnings("unused") // Used via ServiceLoader public OpenTestReportGeneratingListener() { diff --git a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java index 52da2210aafb..d0a4464f23ed 100644 --- a/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java +++ b/junit-platform-suite-commons/src/main/java/org/junit/platform/suite/commons/SuiteLauncherDiscoveryRequestBuilder.java @@ -121,8 +121,7 @@ public final class SuiteLauncherDiscoveryRequestBuilder { private boolean includeClassNamePatternsUsed; private boolean filterStandardClassNamePatterns = false; - @Nullable - private ConfigurationParameters parentConfigurationParameters; + private @Nullable ConfigurationParameters parentConfigurationParameters; private boolean enableParentConfigurationParameters = true; diff --git a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java index e9c78c58ff6c..161c5189aa91 100644 --- a/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java +++ b/junit-platform-suite-engine/src/main/java/org/junit/platform/suite/engine/SuiteTestDescriptor.java @@ -73,11 +73,9 @@ final class SuiteTestDescriptor extends AbstractTestDescriptor { private final Class suiteClass; private final LifecycleMethods lifecycleMethods; - @Nullable - private LauncherDiscoveryResult launcherDiscoveryResult; + private @Nullable LauncherDiscoveryResult launcherDiscoveryResult; - @Nullable - private SuiteLauncher launcher; + private @Nullable SuiteLauncher launcher; SuiteTestDescriptor(UniqueId id, Class suiteClass, ConfigurationParameters configurationParameters, OutputDirectoryProvider outputDirectoryProvider, EngineDiscoveryListener discoveryListener, 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 4085b126483f..a18c2052b47e 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 @@ -172,8 +172,7 @@ public static Predicate byTestDescriptor(Predicate filters = new ArrayList<>(); + private @Nullable List filters = new ArrayList<>(); public RunnerTestDescriptor(UniqueId uniqueId, Class testClass, Runner runner, boolean ignored) { super(uniqueId, runner.getDescription(), testClass.getSimpleName(), ClassSource.from(testClass)); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java index 4b213419aad0..9345aec1591d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/AbstractExecutionConditionTests.java @@ -55,8 +55,7 @@ abstract class AbstractExecutionConditionTests { private final ExtensionContext context = mock(); - @Nullable - private ConditionEvaluationResult result; + private @Nullable ConditionEvaluationResult result; @BeforeAll void ensureAllTestMethodsAreCovered() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java index 360bf5ae3f99..c79080613a0c 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/NestedWithSeparateInheritanceTests.java @@ -24,8 +24,7 @@ class NestedWithSeparateInheritanceTests extends SuperClass1 { - @Nullable - static List lifecycleInvokingClassNames; + static @Nullable List lifecycleInvokingClassNames; static String OUTER = NestedWithSeparateInheritanceTests.class.getSimpleName(); static String NESTED = NestedClass.class.getSimpleName(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java index 7f6053f76105..3a58eda73c6b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/discovery/DiscoverySelectorResolverTests.java @@ -100,8 +100,7 @@ class DiscoverySelectorResolverTests extends AbstractJupiterTestEngineTests { private final JupiterConfiguration configuration = mock(); private final LauncherDiscoveryListener discoveryListener = mock(); - @Nullable - private TestDescriptor engineDescriptor; + private @Nullable TestDescriptor engineDescriptor; @BeforeEach void setUp() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java index 683c5c212f9a..bec4c4141d21 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/AbstractExecutableInvokerTests.java @@ -41,8 +41,7 @@ abstract class AbstractExecutableInvokerTests { protected final MethodSource instance = mock(); - @Nullable - protected Method method; + protected @Nullable Method method; protected final ExtensionContext extensionContext = mock(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java index c5e83c596e66..3e2f0e297d6f 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/execution/ParameterResolutionUtilsTests.java @@ -48,8 +48,7 @@ class ParameterResolutionUtilsTests { private final MethodSource instance = mock(); - @Nullable - private Method method; + private @Nullable Method method; private final ExtensionContext extensionContext = mock(); diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java index 0075ace93ab2..04ae42dd6afd 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterAllTests.java @@ -39,8 +39,7 @@ class BeforeAndAfterAllTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); - @Nullable - private static Optional actualExceptionInAfterAllCallback; + private static @Nullable Optional actualExceptionInAfterAllCallback; @Test void beforeAllAndAfterAllCallbacks() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java index 372f8199ff8b..a5e6b501e1ea 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterEachTests.java @@ -43,8 +43,7 @@ class BeforeAndAfterEachTests extends AbstractJupiterTestEngineTests { private static final List callSequence = new ArrayList<>(); private static final List beforeEachMethodCallSequence = new ArrayList<>(); - @Nullable - private static Optional actualExceptionInAfterEachCallback; + private static @Nullable Optional actualExceptionInAfterEachCallback; @SuppressWarnings("OptionalAssignedToNull") @BeforeEach diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java index dd13d741e1ea..18a981e7dc96 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/BeforeAndAfterTestExecutionCallbackTests.java @@ -45,8 +45,7 @@ class BeforeAndAfterTestExecutionCallbackTests extends AbstractJupiterTestEngine private static final List callSequence = new ArrayList<>(); - @Nullable - private static Optional actualExceptionInAfterTestExecution; + private static @Nullable Optional actualExceptionInAfterTestExecution; @SuppressWarnings("OptionalAssignedToNull") @BeforeEach diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java index ad86b2cf460a..6f4a3bfb427b 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/engine/extension/CloseablePathTests.java @@ -89,8 +89,7 @@ class CloseablePathTests extends AbstractJupiterTestEngineTests { private final AnnotatedElementContext elementContext = mock(); private final ExtensionContext extensionContext = mock(); - @Nullable - private CloseablePath closeablePath; + private @Nullable CloseablePath closeablePath; @Target(METHOD) @Retention(RUNTIME) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java index 14e2b6fb9ace..1f64d9dbc047 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/MethodArgumentsProviderTests.java @@ -51,8 +51,7 @@ */ class MethodArgumentsProviderTests { - @Nullable - private MutableExtensionRegistry extensionRegistry; + private @Nullable MutableExtensionRegistry extensionRegistry; @Test void providesArgumentsUsingStream() { 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 724b500f6d05..341739cfc768 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 @@ -996,16 +996,13 @@ static class ClassWithShadowedAnnotatedFields extends ClassWithAnnotatedFields { // ------------------------------------------------------------------------- @Annotation1 - @Nullable - private Boolean privateDirectlyAnnotatedField; + private @Nullable Boolean privateDirectlyAnnotatedField; @Annotation1 - @Nullable - public String directlyAnnotatedField; + public @Nullable String directlyAnnotatedField; @ComposedAnnotation - @Nullable - public Integer metaAnnotatedField; + public @Nullable Integer metaAnnotatedField; interface InterfaceWithAnnotatedFields { diff --git a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java index ca6e410147b7..4f2c6f6a1eff 100644 --- a/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java +++ b/platform-tests/src/test/java/org/junit/platform/console/ConsoleLauncherWrapperResult.java @@ -29,8 +29,7 @@ class ConsoleLauncherWrapperResult implements TestExecutionSummary { final String err; final int code; - @Nullable - private final TestExecutionSummary summary; + private final @Nullable TestExecutionSummary summary; ConsoleLauncherWrapperResult(String[] args, String out, String err, CommandResult result) { this.args = args; From 4bbe57dfbf18efcc3f84111baf2458198ff26c04 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Fri, 6 Jun 2025 18:34:43 +0200 Subject: [PATCH 261/521] Fix support pre-5.13 `AnnotationBasedArgumentsProvider` implementations (#4611) The `provideArguments(ExtensionContext, Annotation)` was deprecated in 5.13 and no longer taken into account when determining the consumed annotation. Now, it is checked for again if the new method overload couldn't be found. Fixes #4610. --- .../release-notes/release-notes-5.13.1.adoc | 2 + .../AnnotationConsumerInitializer.java | 1 + .../AnnotationConsumerInitializerTests.java | 41 +++++++++++++++---- 3 files changed, 37 insertions(+), 7 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc index 505bdb10b39b..388e5a1dde1c 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc @@ -42,6 +42,8 @@ on GitHub. in their enclosing class. This undesired change in behavior has now been reverted so that tests in `@Nested` test classes are always executed _after_ tests in enclosing test classes again. +* Fix support for `AnnotationBasedArgumentsProvider` implementations that override the + deprecated `provideArguments(ExtensionContext, Annotation)` method. [[release-notes-5.13.1-junit-jupiter-deprecations-and-breaking-changes]] ==== Deprecations and Breaking Changes diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java index b6bdfd90f2a1..e48a5995a4ea 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/support/AnnotationConsumerInitializer.java @@ -41,6 +41,7 @@ public final class AnnotationConsumerInitializer { private static final List annotationConsumingMethodSignatures = asList( // new AnnotationConsumingMethodSignature("accept", 1, 0), // new AnnotationConsumingMethodSignature("provideArguments", 3, 2), // + new AnnotationConsumingMethodSignature("provideArguments", 2, 1), // new AnnotationConsumingMethodSignature("convert", 3, 2)); private AnnotationConsumerInitializer() { diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java index 4d4ea67ecf24..0cbcceb950b5 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/support/AnnotationConsumerInitializerTests.java @@ -23,18 +23,22 @@ import java.time.LocalDate; import java.util.ArrayList; import java.util.List; +import java.util.function.Supplier; import java.util.stream.Stream; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Named; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.converter.AnnotationBasedArgumentConverter; import org.junit.jupiter.params.converter.JavaTimeConversionPattern; import org.junit.jupiter.params.provider.AnnotationBasedArgumentsProvider; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.CsvSource; +import org.junit.jupiter.params.provider.FieldSource; import org.junit.platform.commons.JUnitException; @DisplayName("AnnotationConsumerInitializer") @@ -52,10 +56,11 @@ void shouldInitializeAnnotationConsumer() throws NoSuchMethodException { source -> assertThat(source.value()).containsExactly("a", "b")); } - @Test + @ParameterizedTest + @FieldSource("argumentsProviders") @DisplayName("should initialize annotation-based ArgumentsProvider") - void shouldInitializeAnnotationBasedArgumentsProvider() throws NoSuchMethodException { - var instance = new SomeAnnotationBasedArgumentsProvider(); + void shouldInitializeAnnotationBasedArgumentsProvider(AbstractAnnotationBasedArgumentsProvider instance) + throws NoSuchMethodException { var method = SubjectClass.class.getDeclaredMethod("foo"); var initialisedAnnotationConsumer = initialize(method, instance); @@ -102,9 +107,11 @@ void shouldThrowExceptionWhenParameterIsNotAnnotated() throws NoSuchMethodExcept assertThatThrownBy(() -> initialize(parameter, instance)).isInstanceOf(JUnitException.class); } - @Test - void shouldInitializeForEachAnnotations() throws NoSuchMethodException { - var instance = spy(new SomeAnnotationBasedArgumentsProvider()); + @ParameterizedTest + @FieldSource("argumentsProviders") + void shouldInitializeForEachAnnotations(AbstractAnnotationBasedArgumentsProvider provider) + throws NoSuchMethodException { + var instance = spy(provider); var method = SubjectClass.class.getDeclaredMethod("repeatableAnnotation", String.class); initialize(method, instance); @@ -112,10 +119,20 @@ void shouldInitializeForEachAnnotations() throws NoSuchMethodException { verify(instance, times(2)).accept(any(CsvSource.class)); } - private static class SomeAnnotationBasedArgumentsProvider extends AnnotationBasedArgumentsProvider { + static Supplier>> argumentsProviders = () -> List.of( // + Named.of("current", new SomeAnnotationBasedArgumentsProvider()), // + Named.of("deprecated", new DeprecatedAnnotationBasedArgumentsProvider()) // + ); + + private static abstract class AbstractAnnotationBasedArgumentsProvider + extends AnnotationBasedArgumentsProvider { List annotations = new ArrayList<>(); + } + + private static class SomeAnnotationBasedArgumentsProvider extends AbstractAnnotationBasedArgumentsProvider { + @Override protected Stream provideArguments(ParameterDeclarations parameters, ExtensionContext context, CsvSource annotation) { @@ -124,6 +141,16 @@ protected Stream provideArguments(ParameterDeclarations par } } + private static class DeprecatedAnnotationBasedArgumentsProvider extends AbstractAnnotationBasedArgumentsProvider { + + @Override + @SuppressWarnings("deprecation") + protected Stream provideArguments(ExtensionContext context, CsvSource annotation) { + annotations.add(annotation); + return Stream.empty(); + } + } + private static class SomeAnnotationBasedArgumentConverter extends AnnotationBasedArgumentConverter { From bd496b0ef24f196b69d85fcbacc7a36205341995 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 7 Jun 2025 09:29:55 +0200 Subject: [PATCH 262/521] Finalize 5.13.1 release notes --- .../release-notes/release-notes-5.13.1.adoc | 44 ++----------------- 1 file changed, 4 insertions(+), 40 deletions(-) diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc index 388e5a1dde1c..cfd56ea3e397 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc @@ -1,9 +1,9 @@ [[release-notes-5.13.1]] == 5.13.1 -*Date of Release:* ❓ +*Date of Release:* June 7, 2025 -*Scope:* ❓ +*Scope:* Bug fixes and enhancements since 5.13.0 For a complete list of all _closed_ issues and pull requests for this release, consult the link:{junit5-repo}+/milestone/97?closed=1+[5.13.1] milestone page in the JUnit repository @@ -13,20 +13,7 @@ on GitHub. [[release-notes-5.13.1-junit-platform]] === JUnit Platform -[[release-notes-5.13.1-junit-platform-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-5.13.1-junit-platform-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-5.13.1-junit-platform-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ +No changes. [[release-notes-5.13.1-junit-jupiter]] @@ -45,31 +32,8 @@ on GitHub. * Fix support for `AnnotationBasedArgumentsProvider` implementations that override the deprecated `provideArguments(ExtensionContext, Annotation)` method. -[[release-notes-5.13.1-junit-jupiter-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-5.13.1-junit-jupiter-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ - [[release-notes-5.13.1-junit-vintage]] === JUnit Vintage -[[release-notes-5.13.1-junit-vintage-bug-fixes]] -==== Bug Fixes - -* ❓ - -[[release-notes-5.13.1-junit-vintage-deprecations-and-breaking-changes]] -==== Deprecations and Breaking Changes - -* ❓ - -[[release-notes-5.13.1-junit-vintage-new-features-and-improvements]] -==== New Features and Improvements - -* ❓ +No changes From 77bfc1384533c9b862b26909d78bdb813928cedc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 07:31:59 +0000 Subject: [PATCH 263/521] Update plugin openrewrite to v7.8.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index c48781d6ce53..ec90aad11748 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -107,7 +107,7 @@ jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC2" } nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } -openrewrite = { id = "org.openrewrite.rewrite", version = "7.7.0" } +openrewrite = { id = "org.openrewrite.rewrite", version = "7.8.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } shadow = { id = "com.gradleup.shadow", version = "8.3.6" } spotless = { id = "com.diffplug.spotless", version = "7.0.4" } From c3764f9b7f320d3ab32e321f36415c829c3917e6 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 7 Jun 2025 09:48:42 +0200 Subject: [PATCH 264/521] Release 5.13.1 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f5de32911e7e..323494355d04 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository is the home of JUnit Platform, Jupiter, and Vintage. ## Latest Releases -- General Availability (GA): [JUnit 5.13.0](https://github.com/junit-team/junit5/releases/tag/r5.13.0) (May 30, 2025) +- General Availability (GA): [JUnit 5.13.1](https://github.com/junit-team/junit5/releases/tag/r5.13.1) (June 7, 2025) - Preview (Milestone/Release Candidate): [JUnit 5.13.0-RC1](https://github.com/junit-team/junit5/releases/tag/r5.13.0-RC1) (May 16, 2025) ## Documentation From df24efbe7759018c2fa69a1c0b418299ab4eed25 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 7 Jun 2025 12:35:34 +0200 Subject: [PATCH 265/521] Update nullability section Since module descriptors are no longer annotated but packages must be --- CONTRIBUTING.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e4184c29e388..f22bf77dd267 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -125,11 +125,8 @@ See [`ExtensionContext`](junit-jupiter-api/src/main/java/org/junit/jupiter/api/e This project uses JSpecify's annotation to indicate nullability. In general, the approach is as follows: -- The Gradle build is set up to treat all code as being `@NullMarked` -- The descriptor of each module is annotated with `@NullMarked` for IDEs such as IntelliJ - IDEA to treat code correctly. -- Fields, parameters, return types etc. may be annotated with `@Nullable` -- A package can be excluded (temporarily) using `@NullUnmarked` +- All packages are annotated with `@NullMarked` +- Types of fields, parameters, return types etc. may be annotated with `@Nullable` ### Tests From 2089504fad389ffb686dbeaab6330aadefa9a705 Mon Sep 17 00:00:00 2001 From: Vladimir Sitnikov Date: Sat, 7 Jun 2025 16:54:38 +0300 Subject: [PATCH 266/521] Replace `List<@Nullable Object>` with `List` for internal APIs The latter is easier to read and forbids `list.add(...)` at compile time. See jspecify.dev/docs/user-guide#wildcard-bounds --- .../commons/support/AnnotationSupport.java | 8 +++++-- .../commons/util/ReflectionUtils.java | 6 ++--- .../commons/util/ReflectionUtilsTests.java | 24 ++++++++++--------- 3 files changed, 21 insertions(+), 17 deletions(-) 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 a29801a7c333..f098ba5c34bf 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 @@ -450,7 +450,9 @@ public static List findAnnotatedFields(Class clazz, Class fields = findAnnotatedFields(instance.getClass(), annotationType, ModifierSupport::isNotStatic, HierarchyTraversalMode.TOP_DOWN); - return ReflectionUtils.readFieldValues(fields, instance); + @SuppressWarnings("unchecked") + List<@Nullable Object> result = (List<@Nullable Object>) ReflectionUtils.readFieldValues(fields, instance); + return result; } /** @@ -482,7 +484,9 @@ public static List findAnnotatedFields(Class clazz, Class fields = findAnnotatedFields(clazz, annotationType, ModifierSupport::isStatic, HierarchyTraversalMode.TOP_DOWN); - return ReflectionUtils.readFieldValues(fields, null); + @SuppressWarnings("unchecked") + List<@Nullable Object> result = (List<@Nullable Object>) ReflectionUtils.readFieldValues(fields, null); + return result; } /** 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 4fc356365cb2..3836d2369977 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 @@ -657,7 +657,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - public static List<@Nullable Object> readFieldValues(List fields, @Nullable Object instance) { + public static List readFieldValues(List fields, @Nullable Object instance) { return readFieldValues(fields, instance, field -> true); } @@ -674,9 +674,7 @@ public static Try tryToReadFieldValue(Class clazz, String fieldNa * @return an immutable list of the values of the specified fields; never * {@code null} but may be empty or contain {@code null} entries */ - @SuppressWarnings("NullAway") - public static List<@Nullable Object> readFieldValues(List fields, @Nullable Object instance, - Predicate predicate) { + public static List readFieldValues(List fields, @Nullable Object instance, Predicate predicate) { Preconditions.notNull(fields, "fields list must not be null"); Preconditions.notNull(predicate, "Predicate must not be null"); 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 e1701ad6dbd3..87872afbb645 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 @@ -60,6 +60,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import org.assertj.core.api.Assertions; import org.jspecify.annotations.Nullable; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; @@ -1952,7 +1953,8 @@ void readFieldValuesFromInstance() { var values = readFieldValues(fields, new ClassWithFields()); - assertThat(values).containsExactly("enigma", 3.14, "text", 2.5, null, 42, "constant", 99); + Assertions. assertThat(values).containsExactly("enigma", 3.14, "text", 2.5, null, 42, "constant", + 99); } @Test @@ -1961,7 +1963,7 @@ void readFieldValuesFromClass() { var values = readFieldValues(fields, null); - assertThat(values).containsExactly(2.5, "constant", 99); + Assertions. assertThat(values).containsExactly(2.5, "constant", 99); } /** @@ -1972,15 +1974,15 @@ void readFieldValuesFromClass() { void readFieldValuesFromInterfacesAndClassesInTypeHierarchy() { var fields = findFields(InterfaceWithField.class, ReflectionUtils::isStatic, TOP_DOWN); var values = readFieldValues(fields, null); - assertThat(values).containsOnly("ifc"); + Assertions. assertThat(values).containsOnly("ifc"); fields = findFields(SuperclassWithFieldAndFieldFromInterface.class, ReflectionUtils::isStatic, TOP_DOWN); values = readFieldValues(fields, null); - assertThat(values).containsExactly("ifc", "super"); + Assertions. assertThat(values).containsExactly("ifc", "super"); fields = findFields(SubclassWithFieldAndFieldFromInterface.class, ReflectionUtils::isStatic, TOP_DOWN); values = readFieldValues(fields, null); - assertThat(values).containsExactly("ifc", "super", "sub"); + Assertions. assertThat(values).containsExactly("ifc", "super", "sub"); } @Test @@ -1989,7 +1991,7 @@ void readFieldValuesFromInstanceWithTypeFilterForString() { var values = readFieldValues(fields, new ClassWithFields(), isA(String.class)); - assertThat(values).containsExactly("enigma", "text", null, "constant"); + Assertions. assertThat(values).containsExactly("enigma", "text", null, "constant"); } @Test @@ -1998,7 +2000,7 @@ void readFieldValuesFromClassWithTypeFilterForString() { var values = readFieldValues(fields, null, isA(String.class)); - assertThat(values).containsExactly("constant"); + Assertions. assertThat(values).containsExactly("constant"); } @Test @@ -2007,7 +2009,7 @@ void readFieldValuesFromInstanceWithTypeFilterForInteger() { var values = readFieldValues(fields, new ClassWithFields(), isA(int.class)); - assertThat(values).containsExactly(42); + Assertions. assertThat(values).containsExactly(42); } @Test @@ -2016,7 +2018,7 @@ void readFieldValuesFromClassWithTypeFilterForInteger() { var values = readFieldValues(fields, null, isA(Integer.class)); - assertThat(values).containsExactly(99); + Assertions. assertThat(values).containsExactly(99); } @Test @@ -2025,7 +2027,7 @@ void readFieldValuesFromInstanceWithTypeFilterForDouble() { var values = readFieldValues(fields, new ClassWithFields(), isA(double.class)); - assertThat(values).containsExactly(3.14); + Assertions. assertThat(values).containsExactly(3.14); } @Test @@ -2034,7 +2036,7 @@ void readFieldValuesFromClassWithTypeFilterForDouble() { var values = readFieldValues(fields, null, isA(Double.class)); - assertThat(values).containsExactly(2.5); + Assertions. assertThat(values).containsExactly(2.5); } private static Predicate isA(Class type) { From 501f4429e2c597b16f7f631b2cb2a91c98507416 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Sat, 7 Jun 2025 22:18:54 +0200 Subject: [PATCH 267/521] Install GraalVM JDK 21 on CI Because that's what's used by the integration test --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 631844011063..aadc10b78069 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -29,7 +29,7 @@ jobs: with: distribution: graalvm-community version: 'latest' - java-version: '24' + java-version: '21' github-token: ${{ secrets.GITHUB_TOKEN }} - name: Build uses: ./.github/actions/main-build From 91a5f71076fdb1d7b772566048660507620c3cf3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 8 Jun 2025 00:43:18 +0000 Subject: [PATCH 268/521] Update sbt/setup-sbt action to v1.1.9 --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 91c8ac3903ba..fc5b1dfd99b1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -89,7 +89,7 @@ jobs: with: java-version: 24 distribution: temurin - - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 + - uses: sbt/setup-sbt@6c68d2fe8dfbc0a0534d70101baa2e0420e1a506 # v1.1.9 - name: Update JUnit dependencies in samples run: java src/Updater.java ${{ inputs.releaseVersion }} working-directory: junit5-samples @@ -247,7 +247,7 @@ jobs: with: java-version: 24 distribution: temurin - - uses: sbt/setup-sbt@69a46ab4acd4316aa16e68d91a9249a98d7e78d5 # v1.1.8 + - uses: sbt/setup-sbt@6c68d2fe8dfbc0a0534d70101baa2e0420e1a506 # v1.1.9 - name: Update JUnit dependencies in samples run: java src/Updater.java ${{ inputs.releaseVersion }} - name: Build samples From 9448de5a56f7f1ebfec10b375087d29e37329107 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 11 Jun 2025 23:52:06 +0000 Subject: [PATCH 269/521] Update actions/attest-build-provenance action to v2.4.0 (#4644) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/main.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aadc10b78069..0f343adcd606 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -93,7 +93,7 @@ jobs: publish -x check \ prepareGitHubAttestation - name: Generate build provenance attestations - uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 with: subject-path: documentation/build/attestation/*.jar diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fc5b1dfd99b1..43d3825c0b3c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -63,7 +63,7 @@ jobs: --remote-repo-url=${{ env.STAGING_REPO_URL }} - name: Generate build provenance attestations if: ${{ inputs.dryRun == false }} - uses: actions/attest-build-provenance@db473fddc028af60658334401dc6fa3ffd8669fd # v2.3.0 + uses: actions/attest-build-provenance@e8998f949152b193b063cb0ec769d69d929409be # v2.4.0 with: subject-path: build/repo/**/*.jar From 551d6b97de8993efd0739e7863cf93e846625a67 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 02:11:26 +0000 Subject: [PATCH 270/521] Update github/codeql-action action to v3.29.0 (#4645) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codeql-analysis.yml | 4 ++-- .github/workflows/ossf-scorecard.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index a951c049cd72..99f293f4d6a5 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -34,7 +34,7 @@ jobs: - name: Check out repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Initialize CodeQL - uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 + uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 with: languages: ${{ matrix.language }} tools: linked @@ -47,4 +47,4 @@ jobs: -Dscan.tag.CodeQL \ classes - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 + uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 diff --git a/.github/workflows/ossf-scorecard.yml b/.github/workflows/ossf-scorecard.yml index dab9a2cff69b..cec69109af88 100644 --- a/.github/workflows/ossf-scorecard.yml +++ b/.github/workflows/ossf-scorecard.yml @@ -57,6 +57,6 @@ jobs: # Upload the results to GitHub's code scanning dashboard (optional). # Commenting out will disable upload of results to your repo's Code Scanning dashboard - name: "Upload to code-scanning" - uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19 + uses: github/codeql-action/upload-sarif@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 with: sarif_file: results.sarif From 39931b7acad6c0a56b0dd0c1f21f918c2daad382 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 12 Jun 2025 02:12:26 +0000 Subject: [PATCH 271/521] Update gradle/actions action to v4.4.1 --- .github/actions/run-gradle/action.yml | 2 +- .github/workflows/gradle-dependency-submission.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/actions/run-gradle/action.yml b/.github/actions/run-gradle/action.yml index 00e36b096d47..06b1affcf7ff 100644 --- a/.github/actions/run-gradle/action.yml +++ b/.github/actions/run-gradle/action.yml @@ -17,7 +17,7 @@ runs: distribution: temurin java-version: 24 check-latest: true - - uses: gradle/actions/setup-gradle@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 + - uses: gradle/actions/setup-gradle@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 with: cache-encryption-key: ${{ inputs.encryptionKey }} - shell: bash diff --git a/.github/workflows/gradle-dependency-submission.yml b/.github/workflows/gradle-dependency-submission.yml index d71f044b604c..fbcb550a10e1 100644 --- a/.github/workflows/gradle-dependency-submission.yml +++ b/.github/workflows/gradle-dependency-submission.yml @@ -25,4 +25,4 @@ jobs: java-version: 24 check-latest: true - name: Generate and submit dependency graph - uses: gradle/actions/dependency-submission@8379f6a1328ee0e06e2bb424dadb7b159856a326 # v4.4.0 + uses: gradle/actions/dependency-submission@ac638b010cf58a27ee6c972d7336334ccaf61c96 # v4.4.1 From 5571b6a2454e75203b6fdb3bc620d9af4b85e532 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:07:53 +0000 Subject: [PATCH 272/521] Update jackson monorepo to v2.19.1 (#4648) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec90aad11748..b23f8145b499 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ assertj = "3.27.3" bnd = "7.1.0" checkstyle = "10.25.0" eclipse = "4.35.0" -jackson = "2.19.0" +jackson = "2.19.1" jacoco = "0.8.13" jmh = "1.37" junit4 = "4.13.2" From d99505acd79e72497bd254687ea2163558d21ef1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 19:09:14 +0000 Subject: [PATCH 273/521] Update dependency org.eclipse.platform:org.eclipse.platform to v4.36.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b23f8145b499..a1c462d145c8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,7 +6,7 @@ asciidoctor-plugins = "4.0.4" # Check if workaround in documentation.gradle.kts assertj = "3.27.3" bnd = "7.1.0" checkstyle = "10.25.0" -eclipse = "4.35.0" +eclipse = "4.36.0" jackson = "2.19.1" jacoco = "0.8.13" jmh = "1.37" From 51f5c7c6acb858c80f7de74f13246036db21bc81 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 16 Jun 2025 20:10:29 +0000 Subject: [PATCH 274/521] Update plugin kotlin to v2.2.0-RC3 --- gradle/libs.versions.toml | 2 +- .../projects/gradle-kotlin-extensions/build.gradle.kts | 2 +- .../projects/kotlin-coroutines/build.gradle.kts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a1c462d145c8..3dcc0e69ad07 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -105,7 +105,7 @@ gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" } jmh = { id = "me.champeau.jmh", version = "0.7.3" } jreleaser = { id = "org.jreleaser", version = "1.18.0" } # check if workaround in gradle.properties can be removed when updating -kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC2" } +kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC3" } nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" } openrewrite = { id = "org.openrewrite.rewrite", version = "7.8.0" } plantuml = { id = "io.freefair.plantuml", version = "8.13.1" } diff --git a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts index facdb0179c8d..b0bc8af8281f 100644 --- a/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts +++ b/platform-tooling-support-tests/projects/gradle-kotlin-extensions/build.gradle.kts @@ -3,7 +3,7 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 import org.jetbrains.kotlin.gradle.dsl.KotlinVersion.KOTLIN_2_1 plugins { - kotlin("jvm") version "2.2.0-RC2" + kotlin("jvm") version "2.2.0-RC3" } repositories { diff --git a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts index 783bae5fddbb..a5512598e3f9 100644 --- a/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts +++ b/platform-tooling-support-tests/projects/kotlin-coroutines/build.gradle.kts @@ -1,5 +1,5 @@ plugins { - kotlin("jvm") version "2.2.0-RC2" + kotlin("jvm") version "2.2.0-RC3" } val junitVersion: String by project From e6ab3e35ff8df6f433c1eea0b13010ceebfffe03 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 09:49:41 +0200 Subject: [PATCH 275/521] Create initial 5.13.2 release notes from template --- .../docs/asciidoc/release-notes/index.adoc | 2 + .../release-notes/release-notes-5.13.2.adoc | 67 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc diff --git a/documentation/src/docs/asciidoc/release-notes/index.adoc b/documentation/src/docs/asciidoc/release-notes/index.adoc index a4f401543146..48edb09c11f4 100644 --- a/documentation/src/docs/asciidoc/release-notes/index.adoc +++ b/documentation/src/docs/asciidoc/release-notes/index.adoc @@ -19,6 +19,8 @@ include::{includedir}/link-attributes.adoc[] include::{basedir}/release-notes-6.0.0-M1.adoc[ +include::{basedir}/release-notes-5.13.2.adoc[] + include::{basedir}/release-notes-5.13.1.adoc[] include::{basedir}/release-notes-5.13.0.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 new file mode 100644 index 000000000000..633f4b185eac --- /dev/null +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-5.13.2.adoc @@ -0,0 +1,67 @@ +[[release-notes-5.13.2]] +== 5.13.2 + +*Date of Release:* ❓ + +*Scope:* ❓ + +For a complete list of all _closed_ issues and pull requests for this release, consult the +link:{junit5-repo}+/milestone/98?closed=1+[5.13.2] milestone page in the JUnit repository +on GitHub. + + +[[release-notes-5.13.2-junit-platform]] +=== JUnit Platform + +[[release-notes-5.13.2-junit-platform-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.2-junit-platform-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.2-junit-platform-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.13.2-junit-jupiter]] +=== JUnit Jupiter + +[[release-notes-5.13.2-junit-jupiter-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.2-junit-jupiter-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.2-junit-jupiter-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ + + +[[release-notes-5.13.2-junit-vintage]] +=== JUnit Vintage + +[[release-notes-5.13.2-junit-vintage-bug-fixes]] +==== Bug Fixes + +* ❓ + +[[release-notes-5.13.2-junit-vintage-deprecations-and-breaking-changes]] +==== Deprecations and Breaking Changes + +* ❓ + +[[release-notes-5.13.2-junit-vintage-new-features-and-improvements]] +==== New Features and Improvements + +* ❓ From 00d380bfce0902e5231afaed2dcf84e8dd861c20 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 17 Jun 2025 11:58:26 +0200 Subject: [PATCH 276/521] Add `JAVA_26` to `JRE` enum Add `JRE.JAVA_26` constant and introduce JDK 26-ea CI build Closes #4642 --- .github/workflows/cross-version.yml | 2 ++ .../docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc | 1 + .../base/code-generator-model/src/main/resources/jre.yaml | 2 ++ .../api/condition/EnabledForJreRangeConditionTests.java | 6 ++++-- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cross-version.yml b/.github/workflows/cross-version.yml index 6368bf02d4a7..dd768a9c745e 100644 --- a/.github/workflows/cross-version.yml +++ b/.github/workflows/cross-version.yml @@ -24,6 +24,8 @@ jobs: jdk: - version: 25 type: ea + - version: 26 + type: ea name: "OpenJDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || matrix.jdk.type }})" runs-on: ubuntu-latest steps: diff --git a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc index 5cf7d8a9560f..940d555585fa 100644 --- a/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc +++ b/documentation/src/docs/asciidoc/release-notes/release-notes-6.0.0-M1.adoc @@ -129,6 +129,7 @@ repository on GitHub. * Kotlin's `suspend` modifier may now be applied to test and lifecycle methods. * The `Arguments` interface for parameterized tests is now officially a `@FunctionalInterface`. +* `JAVA_26` has been added to the `JRE` enum for use with JRE-based execution conditions. [[release-notes-6.0.0-M1-junit-vintage]] diff --git a/gradle/base/code-generator-model/src/main/resources/jre.yaml b/gradle/base/code-generator-model/src/main/resources/jre.yaml index 1747ffa12dd6..90654b64919d 100644 --- a/gradle/base/code-generator-model/src/main/resources/jre.yaml +++ b/gradle/base/code-generator-model/src/main/resources/jre.yaml @@ -30,3 +30,5 @@ since: '5.11' - version: 25 since: '5.11.4' +- version: 26 + since: '6.0' diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java index 3b7afb076d8a..c05af5d4d71d 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava23; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava24; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava25; +import static org.junit.jupiter.api.condition.JavaVersionPredicates.onJava26; import static org.junit.jupiter.api.condition.JavaVersionPredicates.onKnownVersion; import org.junit.jupiter.api.Test; @@ -201,7 +202,8 @@ void minVersionGreaterThanMax() { @Test void min20() { evaluateCondition(); - assertEnabledOnCurrentJreIf(onJava20() || onJava21() || onJava22() || onJava23() || onJava24() || onJava25()); + assertEnabledOnCurrentJreIf( + onJava20() || onJava21() || onJava22() || onJava23() || onJava24() || onJava25() || onJava26()); } /** @@ -310,7 +312,7 @@ void minVersion20MaxVersion21() { void minVersion21MaxVersionMaxInteger() { evaluateCondition(); assertEnabledOnCurrentJreIf(onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22() - || onJava23() || onJava24() || onJava25()); + || onJava23() || onJava24() || onJava25() || onJava26()); } /** From faf8dfc5bc6d965de29b77858356bed734fab0dc Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 12:47:53 +0200 Subject: [PATCH 277/521] Update to open-test-reporting 0.2.4 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3dcc0e69ad07..54428dc613ab 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -16,7 +16,7 @@ ktlint = "1.6.0" log4j = "2.24.3" logback = "1.5.18" opentest4j = "1.3.0" -openTestReporting = "0.3.0-SNAPSHOT" +openTestReporting = "0.2.4" snapshotTests = "1.11.0" surefire = "3.5.3" xmlunit = "2.10.2" From 0174c23e2e0cb27cb664bf1420d32fc59b1b1ea6 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 12:48:18 +0200 Subject: [PATCH 278/521] Remove maven-central snapshot repo config --- .../projects/graalvm-starter/settings.gradle.kts | 6 ------ .../projects/jupiter-starter/build.gradle.kts | 6 ------ settings.gradle.kts | 6 ------ 3 files changed, 18 deletions(-) diff --git a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts index f0890183d0f2..6a59f78e05fd 100644 --- a/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts +++ b/platform-tooling-support-tests/projects/graalvm-starter/settings.gradle.kts @@ -28,12 +28,6 @@ dependencyResolutionManagement { snapshotsOnly() } } - maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { - mavenContent { - snapshotsOnly() - includeGroup("org.opentest4j.reporting") - } - } } } } diff --git a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts index 3a43729855f2..2714c5c41b51 100644 --- a/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts +++ b/platform-tooling-support-tests/projects/jupiter-starter/build.gradle.kts @@ -7,12 +7,6 @@ val junitVersion: String by project repositories { maven { url = uri(file(System.getProperty("maven.repo"))) } mavenCentral() - maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { - mavenContent { - snapshotsOnly() - includeGroup("org.opentest4j.reporting") - } - } } dependencies { diff --git a/settings.gradle.kts b/settings.gradle.kts index 3d3cd294178d..3cb5c303cc6f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -15,12 +15,6 @@ plugins { dependencyResolutionManagement { repositories { mavenCentral() - maven(url = "https://central.sonatype.com/repository/maven-snapshots") { - mavenContent { - snapshotsOnly() - includeGroup("org.opentest4j.reporting") - } - } } } From b8ee743ceca9bc1e98d2003de0680f7f7bca1929 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 12:55:08 +0200 Subject: [PATCH 279/521] Restore strictness of test after JDK 17 baseline change --- .../api/condition/EnabledForJreRangeConditionTests.java | 3 +-- .../api/condition/EnabledForJreRangeIntegrationTests.java | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java index c05af5d4d71d..d142586050ef 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeConditionTests.java @@ -311,8 +311,7 @@ void minVersion20MaxVersion21() { @Test void minVersion21MaxVersionMaxInteger() { evaluateCondition(); - assertEnabledOnCurrentJreIf(onJava17() || onJava18() || onJava19() || onJava20() || onJava21() || onJava22() - || onJava23() || onJava24() || onJava25() || onJava26()); + assertEnabledOnCurrentJreIf(onJava21() || onJava22() || onJava23() || onJava24() || onJava25() || onJava26()); } /** diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java index d1c26b36507f..f075bd2cd886 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/api/condition/EnabledForJreRangeIntegrationTests.java @@ -242,7 +242,7 @@ void minVersion20MaxVersion21() { @EnabledForJreRange(minVersion = 21, maxVersion = Integer.MAX_VALUE) void minVersion21MaxVersionMaxInteger() { assertTrue(onKnownVersion()); - assertTrue(JRE.currentVersionNumber() >= 17); + assertTrue(JRE.currentVersionNumber() >= 21); } @Test From 05121bf4f1a7fc4f7ed7ee181640cb39e86e4922 Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 13:04:00 +0200 Subject: [PATCH 280/521] Add GitHub private vulnerability reporting option (#4652) Since this is now enabled on the repo, add it as an option. --- SECURITY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/SECURITY.md b/SECURITY.md index 90102e191264..1f54183d68eb 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -16,4 +16,7 @@ You'll find more information about the key here: [KEYS](./KEYS) ## Reporting a Vulnerability -To report a security vulnerability, please send an email to security@junit.org. You can use the [published OpenPGP key](https://keys.openpgp.org/search?q=security%40junit.org) with fingerprint `0152DA30EABC7ABADCB09D10D9A6B1329D191D25` to encrypt the message body. +To report a security vulnerability, you have two options: + +- [Privately report a vulnerability](https://github.com/junit-team/junit5/security/advisories/new) on GitHub (see [docs](https://docs.github.com/en/code-security/security-advisories/guidance-on-reporting-and-writing-information-about-vulnerabilities/privately-reporting-a-security-vulnerability) for details) +- Send an email to security@junit.org. You can use the [published OpenPGP key](https://keys.openpgp.org/search?q=security%40junit.org) with fingerprint `0152DA30EABC7ABADCB09D10D9A6B1329D191D25` to encrypt the message body. From 21a2ea0d9e747532f4cc5e0f2e662c54ef31dc05 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 11:05:01 +0000 Subject: [PATCH 281/521] Update log4j2 monorepo to v2.25.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 54428dc613ab..07aa3ccf0535 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,7 +13,7 @@ jmh = "1.37" junit4 = "4.13.2" junit4Min = "4.12" ktlint = "1.6.0" -log4j = "2.24.3" +log4j = "2.25.0" logback = "1.5.18" opentest4j = "1.3.0" openTestReporting = "0.2.4" From 767ae695d7de6a5d2949758810126848a8ee5e2d Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Tue, 17 Jun 2025 19:41:37 +0200 Subject: [PATCH 282/521] Enable CodeQL checks for GitHub Actions workflows (#4656) see https://github.blog/security/application-security/how-to-secure-your-github-actions-workflows-with-codeql --- .github/workflows/codeql-analysis.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index 99f293f4d6a5..c0ab89fab5e1 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -27,9 +27,13 @@ jobs: strategy: fail-fast: false matrix: - language: - - java - - javascript + include: + - language: actions + build-mode: none + - language: java + build-mode: manual + - language: javascript + build-mode: none steps: - name: Check out repository uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 @@ -37,8 +41,10 @@ jobs: uses: github/codeql-action/init@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 with: languages: ${{ matrix.language }} + build-mode: ${{ matrix.build-mode }} tools: linked - name: Build + if: matrix.build-mode == 'manual' uses: ./.github/actions/run-gradle with: encryptionKey: ${{ secrets.GRADLE_ENCRYPTION_KEY }} @@ -48,3 +54,5 @@ jobs: classes - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@ce28f5bb42b7a9f2c824e633a3f6ee835bab6858 # v3.29.0 + with: + category: "/language:${{matrix.language}}" From b39ea8c9051aad0c21d72b437b5daf6fef9e31db Mon Sep 17 00:00:00 2001 From: Marc Philipp Date: Wed, 18 Jun 2025 07:29:22 +0200 Subject: [PATCH 283/521] Update IntelliJ settings for 2025.1.2 --- .idea/codeStyles/Project.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml index 9f10a217b5b9..da9a350c8e4c 100644 --- a/.idea/codeStyles/Project.xml +++ b/.idea/codeStyles/Project.xml @@ -7,6 +7,7 @@