Skip to content

Commit

Permalink
Merge branch 'junit-team:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
XJ114514 authored Sep 23, 2024
2 parents 3d73d1e + e8c92f8 commit c8a7b95
Show file tree
Hide file tree
Showing 37 changed files with 1,270 additions and 130 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/codeql-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
- name: Check out repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: Initialize CodeQL
uses: github/codeql-action/init@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3
uses: github/codeql-action/init@294a9d92911152fe08befb9ec03e240add280cb3 # v3
with:
languages: ${{ matrix.language }}
tools: latest
Expand All @@ -44,4 +44,4 @@ jobs:
-Dscan.tag.CodeQL \
allMainClasses
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@4dd16135b69a43b6c8efb853346f8437d92d3c93 # v3
uses: github/codeql-action/analyze@294a9d92911152fe08befb9ec03e240add280cb3 # v3
16 changes: 14 additions & 2 deletions .github/workflows/cross-version.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,15 @@ jobs:
matrix:
jdk:
- version: 22
type: ga
- version: 23
type: ga
- version: 24
type: ea
- version: 24
type: ea
release: leyden
name: "OpenJDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || 'ea' }})"
name: "OpenJDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || matrix.jdk.type }})"
runs-on: ubuntu-latest
steps:
- name: Check out repository
Expand All @@ -35,11 +39,19 @@ jobs:
- name: Set up Test JDK
uses: ./.github/actions/setup-test-jdk
- name: "Set up JDK ${{ matrix.jdk.version }} (${{ matrix.jdk.release || 'ea' }})"
uses: oracle-actions/setup-java@v1
if: matrix.jdk.type == 'ea'
uses: oracle-actions/setup-java@2e744f723b003fdd759727d0ff654c8717024845 # v1.4.0
with:
website: jdk.java.net
release: ${{ matrix.jdk.release || matrix.jdk.version }}
version: latest
- name: "Set up JDK ${{ matrix.jdk.version }} (${{ matrix.jdk.distribution || 'temurin' }})"
if: matrix.jdk.type == 'ga'
uses: actions/setup-java@2dfa2011c5b2a0f1489bf9e433881c92c1631f88 # v4
with:
distribution: ${{ matrix.jdk.distribution || 'temurin' }}
java-version: ${{ matrix.jdk.version }}
check-latest: true
- name: 'Prepare JDK${{ matrix.jdk.version }} env var'
shell: bash
run: echo "JDK${{ matrix.jdk.version }}=$JAVA_HOME" >> $GITHUB_ENV
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ on GitHub.

* Fixed potential locking issue with `ExclusiveResource` in the
`HierarchicalTestExecutorService`, which could lead to deadlocks in certain scenarios.
* `NamespacedHierarchicalStore` no longer throws an exception after it has been closed if
the store is queried via one of the `get(...)` or `getOrComputeIfAbsent(...)` methods;
however, if a `getOrComputeIfAbsent(...)` invocation results in the computation of a new
value, an exception will still be thrown.

[[release-notes-5.11.1-junit-platform-deprecations-and-breaking-changes]]
==== Deprecations and Breaking Changes
Expand All @@ -27,8 +31,9 @@ on GitHub.
[[release-notes-5.11.1-junit-platform-new-features-and-improvements]]
==== New Features and Improvements

* Introduce `ReflectionSupport.makeAccessible(Field)` for third-party use rather than
calling the internal `ReflectionUtils.makeAccessible(Field)` method directly.
* Improve parallelism and reduce number of blocked threads used by
`HierarchicalTestEngine` implementations when parallel execution is enabled and the
global read-write lock is used.


[[release-notes-5.11.1-junit-jupiter]]
Expand All @@ -37,7 +42,8 @@ on GitHub.
[[release-notes-5.11.1-junit-jupiter-bug-fixes]]
==== Bug Fixes

* ❓
* `TestWatcher` callback methods can once again access data in the
`ExtensionContext.Store`.

[[release-notes-5.11.1-junit-jupiter-deprecations-and-breaking-changes]]
==== Deprecations and Breaking Changes
Expand All @@ -47,7 +53,8 @@ on GitHub.
[[release-notes-5.11.1-junit-jupiter-new-features-and-improvements]]
==== New Features and Improvements

* ❓
* Improve parallelism and reduce number of blocked threads in the presence of `@Isolated`
tests when parallel execution is enabled


[[release-notes-5.11.1-junit-vintage]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ JUnit repository on GitHub.
[[release-notes-5.12.0-M1-junit-platform-new-features-and-improvements]]
==== New Features and Improvements

* ❓
* Introduce `ReflectionSupport.makeAccessible(Field)` for third-party use rather than
calling the internal `ReflectionUtils.makeAccessible(Field)` method directly.


[[release-notes-5.12.0-M1-junit-jupiter]]
Expand All @@ -47,7 +48,9 @@ JUnit repository on GitHub.
[[release-notes-5.12.0-M1-junit-jupiter-new-features-and-improvements]]
==== New Features and Improvements

* ❓
* In a `@ParameterizedTest` method, a `null` value can now be supplied for Java Date/Time
types such as `LocalDate` if the new `nullable` attribute in
`@JavaTimeConversionPattern` is set to `true`.


[[release-notes-5.12.0-M1-junit-vintage]]
Expand Down
7 changes: 7 additions & 0 deletions documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,13 @@ JUnit Jupiter comes with many of the assertion methods that JUnit 4 has and adds
that lend themselves well to being used with Java 8 lambdas. All JUnit Jupiter assertions
are `static` methods in the `{Assertions}` class.

Assertion methods optionally accept the assertion message as their third parameter, which
can be either a `String` or a `Supplier<String>`.

When using a `Supplier<String>` (e.g., a lambda expression), the message is evaluated
lazily. This can provide a performance benefit, especially if message construction is
complex or time-consuming, as it is only evaluated when the assertion fails.

[source,java,indent=0]
----
include::{testDir}/example/AssertionsDemo.java[tags=user_guide]
Expand Down
9 changes: 7 additions & 2 deletions documentation/src/test/java/example/AssertionsDemo.java
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,9 @@ void standardAssertions() {
assertEquals(2, calculator.add(1, 1));
assertEquals(4, calculator.multiply(2, 2),
"The optional failure message is now the last parameter");
assertTrue('a' < 'b', () -> "Assertion messages can be lazily evaluated -- "
+ "to avoid constructing complex messages unnecessarily.");

// Lazily evaluates generateFailureMessage('a','b').
assertTrue('a' < 'b', () -> generateFailureMessage('a','b'));
}

@Test
Expand Down Expand Up @@ -160,6 +161,10 @@ private static String greeting() {
return "Hello, World!";
}

private static String generateFailureMessage(char a, char b) {
return "Assertion messages can be lazily evaluated -- "
+ "to avoid constructing complex messages unnecessarily." + (a < b);
}
}
// end::user_guide[]
// @formatter:on
14 changes: 7 additions & 7 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ assertj = { module = "org.assertj:assertj-core", version.ref = "assertj" }
bartholdy = { module = "de.sormuras:bartholdy", version = "0.2.3" }
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.175" }
commons-io = { module = "commons-io:commons-io", version = "2.16.1" }
groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.22" }
classgraph = { module = "io.github.classgraph:classgraph", version = "4.8.176" }
commons-io = { module = "commons-io:commons-io", version = "2.17.0" }
groovy4 = { module = "org.apache.groovy:groovy", version = "4.0.23" }
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" }
Expand All @@ -49,12 +49,12 @@ java-diff-utils = { module = "io.github.java-diff-utils:java-diff-utils", versio
joox = { module = "org.jooq:joox", version = "2.0.1" }
jte = { module = "gg.jte:jte", version = "3.1.12" }
junit4 = { module = "junit:junit", version = { require = "[4.12,)", prefer = "4.13.2" } }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.8.1" }
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.9.0" }
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" }
mavenSurefirePlugin = { module = "org.apache.maven.plugins:maven-surefire-plugin", version.ref = "surefire" }
memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.8.0" }
memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.8.1" }
mockito = { module = "org.mockito:mockito-junit-jupiter", version = "5.13.0" }
nohttp-checkstyle = { module = "io.spring.nohttp:nohttp-checkstyle", version = "0.0.11" }
opentest4j = { module = "org.opentest4j:opentest4j", version.ref = "opentest4j" }
Expand Down Expand Up @@ -92,7 +92,7 @@ foojayResolver = { id = "org.gradle.toolchains.foojay-resolver", version = "0.8.
gitPublish = { id = "org.ajoberstar.git-publish", version = "4.2.2" }
jmh = { id = "me.champeau.jmh", version = "0.7.2" }
nexusPublish = { id = "io.github.gradle-nexus.publish-plugin", version = "2.0.0" }
plantuml = { id = "io.freefair.plantuml", version = "8.6" }
shadow = { id = "com.gradleup.shadow", version = "8.3.1" }
plantuml = { id = "io.freefair.plantuml", version = "8.10" }
shadow = { id = "com.gradleup.shadow", version = "8.3.2" }
spotless = { id = "com.diffplug.spotless", version = "7.0.0.BETA2" }
versions = { id = "com.github.ben-manes.versions", version = "0.51.0" }
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ abstract class GenerateJreRelatedSourceCode : DefaultTask() {
val codeResolver = DirectoryCodeResolver(templateDir.toPath())
val templateEngine =
TemplateEngine.create(codeResolver, temporaryDir.toPath(), ContentType.Plain, javaClass.classLoader)
templateEngine.setCompileArgs("-proc:none")

val templates = templateDir.walkTopDown()
.filter { it.extension == "jte" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ tasks.withType<Test>().configureEach {
}
}
systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
// https://github.com/gradle/gradle/issues/30554
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")
// Required until ASM officially supports the JDK 14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,11 @@ class JavaTimeArgumentConverter extends AnnotationBasedArgumentConverter<JavaTim
@Override
protected Object convert(Object input, Class<?> targetClass, JavaTimeConversionPattern annotation) {
if (input == null) {
throw new ArgumentConversionException("Cannot convert null to " + targetClass.getName());
if (annotation.nullable()) {
return null;
}
throw new ArgumentConversionException(
"Cannot convert null to " + targetClass.getName() + "; consider setting 'nullable = true'");
}
TemporalQuery<?> temporalQuery = TEMPORAL_QUERIES.get(targetClass);
if (temporalQuery == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

package org.junit.jupiter.params.converter;

import static org.apiguardian.api.API.Status.EXPERIMENTAL;
import static org.apiguardian.api.API.Status.STABLE;

import java.lang.annotation.Documented;
Expand Down Expand Up @@ -45,4 +46,15 @@
*/
String value();

/**
* Whether {@code null} argument values are allowed.
*
* <p>Defaults to {@code false}, in which case a {@code null} value will result in
* an exception.
*
* @since 5.12
*/
@API(status = EXPERIMENTAL, since = "5.12")
boolean nullable() default false;

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,12 @@ public boolean equals(Object o) {
public int hashCode() {
return Objects.hash(name, uri);
}

@Override
public String toString() {
return new ToStringBuilder(this) //
.append("name", name) //
.append("uri", uri) //
.toString();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,36 @@

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;
import java.util.concurrent.locks.Lock;

import org.junit.platform.commons.util.Preconditions;
import org.junit.platform.commons.util.ToStringBuilder;

/**
* @since 1.3
*/
class CompositeLock implements ResourceLock {

private final List<ExclusiveResource> resources;
private final List<Lock> locks;
private final boolean exclusive;

CompositeLock(List<ExclusiveResource> resources, List<Lock> locks) {
Preconditions.condition(resources.size() == locks.size(), "Resources and locks must have the same size");
this.resources = unmodifiableList(resources);
this.locks = Preconditions.notEmpty(locks, "Locks must not be empty");
this.exclusive = resources.stream().anyMatch(
resource -> resource.getLockMode() == ExclusiveResource.LockMode.READ_WRITE);
}

CompositeLock(List<Lock> locks) {
this.locks = locks;
@Override
public List<ExclusiveResource> getResources() {
return resources;
}

// for tests only
Expand Down Expand Up @@ -62,6 +78,18 @@ private void release(List<Lock> acquiredLocks) {
}
}

@Override
public boolean isExclusive() {
return exclusive;
}

@Override
public String toString() {
return new ToStringBuilder(this) //
.append("resources", resources) //
.toString();
}

private class CompositeLockManagedBlocker implements ForkJoinPool.ManagedBlocker {

private volatile boolean acquired;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,11 @@

package org.junit.platform.engine.support.hierarchical;

import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static org.apiguardian.api.API.Status.STABLE;

import java.util.Comparator;
import java.util.Objects;
import java.util.concurrent.locks.ReadWriteLock;

Expand Down Expand Up @@ -50,6 +53,14 @@ public class ExclusiveResource {
static final ExclusiveResource GLOBAL_READ = new ExclusiveResource(GLOBAL_KEY, LockMode.READ);
static final ExclusiveResource GLOBAL_READ_WRITE = new ExclusiveResource(GLOBAL_KEY, LockMode.READ_WRITE);

static final Comparator<ExclusiveResource> COMPARATOR //
= comparing(ExclusiveResource::getKey, globalKeyFirst().thenComparing(naturalOrder())) //
.thenComparing(ExclusiveResource::getLockMode);

private static Comparator<String> globalKeyFirst() {
return comparing(key -> !GLOBAL_KEY.equals(key));
}

private final String key;
private final LockMode lockMode;
private int hash;
Expand Down
Loading

0 comments on commit c8a7b95

Please sign in to comment.