Skip to content

Commit c449238

Browse files
authored
Merge branch 'main' into marc/4610-fix-annotation-arguments-provider-regression
2 parents 6e44292 + 934d05e commit c449238

File tree

13 files changed

+95
-32
lines changed

13 files changed

+95
-32
lines changed

.editorconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
trim_trailing_whitespace = true
6+
insert_final_newline = true
7+
8+
[*.bat]
9+
end_of_line = crlf
10+
11+
[*.md]
12+
# Trailing whitespace is important in Markdown (they distinguish a new line from a new paragraph)
13+
trim_trailing_whitespace = false
14+
115
[*.{kt,kts}]
216
ij_kotlin_allow_trailing_comma = false
317
ij_kotlin_allow_trailing_comma_on_call_site = false

.github/workflows/codeql-analysis.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ jobs:
3434
- name: Check out repository
3535
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3636
- name: Initialize CodeQL
37-
uses: github/codeql-action/init@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
37+
uses: github/codeql-action/init@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
3838
with:
3939
languages: ${{ matrix.language }}
4040
tools: linked
@@ -47,4 +47,4 @@ jobs:
4747
-Dscan.tag.CodeQL \
4848
classes
4949
- name: Perform CodeQL Analysis
50-
uses: github/codeql-action/analyze@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
50+
uses: github/codeql-action/analyze@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19

.github/workflows/ossf-scorecard.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@ jobs:
5757
# Upload the results to GitHub's code scanning dashboard (optional).
5858
# Commenting out will disable upload of results to your repo's Code Scanning dashboard
5959
- name: "Upload to code-scanning"
60-
uses: github/codeql-action/upload-sarif@ff0a06e83cb2de871e5a09832bc6a81e7276941f # v3.28.18
60+
uses: github/codeql-action/upload-sarif@fca7ace96b7d713c7035871441bd52efbe39e27e # v3.28.19
6161
with:
6262
sarif_file: results.sarif

documentation/documentation.gradle.kts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ tasks {
165165
args.addAll("--config=junit.platform.reporting.open.xml.enabled=true")
166166
args.addAll("--config=junit.platform.output.capture.stdout=true")
167167
args.addAll("--config=junit.platform.output.capture.stderr=true")
168-
args.addAll("--config=junit.platform.discovery.issue.severity.critical=warn")
168+
args.addAll("--config=junit.platform.discovery.issue.severity.critical=warning")
169169
outputs.dir(consoleLauncherTestReportsDir)
170170
argumentProviders.add(CommandLineArgumentProvider {
171171
listOf(
@@ -202,7 +202,7 @@ tasks {
202202
(options as JUnitPlatformOptions).apply {
203203
includeEngines("junit-vintage")
204204
includeTags("timeout")
205-
systemProperty("junit.platform.discovery.issue.severity.critical", "warn")
205+
systemProperty("junit.platform.discovery.issue.severity.critical", "warning")
206206
}
207207
}
208208

documentation/src/docs/asciidoc/release-notes/release-notes-5.13.1.adoc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,13 @@ on GitHub.
3535
[[release-notes-5.13.1-junit-jupiter-bug-fixes]]
3636
==== Bug Fixes
3737

38+
* The 5.13.0 release introduced a regression regarding the execution order in test classes
39+
containing both test methods and `@Nested` test classes. When classpath scanning was
40+
used during test discovery -- for example, when resolving a package selector for a
41+
`@Suite` class -- test methods in `@Nested` classes were executed _before_ test methods
42+
in their enclosing class. This undesired change in behavior has now been reverted so
43+
that tests in `@Nested` test classes are always executed _after_ tests in enclosing test
44+
classes again.
3845
* Fix support for `AnnotationBasedArgumentsProvider` implementations that override the
3946
deprecated `provideArguments(ExtensionContext, Annotation)` method.
4047

gradle/libs.versions.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ junit4 = { module = "junit:junit", version = { require = "[4.12,)", prefer = "4.
5353
kotlinx-coroutines = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version = "1.10.2" }
5454
log4j-core = { module = "org.apache.logging.log4j:log4j-core", version.ref = "log4j" }
5555
log4j-jul = { module = "org.apache.logging.log4j:log4j-jul", version.ref = "log4j" }
56-
maven = { module = "org.apache.maven:apache-maven", version = "3.9.9" }
56+
maven = { module = "org.apache.maven:apache-maven", version = "3.9.10" }
5757
mavenSurefirePlugin = { module = "org.apache.maven.plugins:maven-surefire-plugin", version.ref = "surefire" }
5858
memoryfilesystem = { module = "com.github.marschall:memoryfilesystem", version = "2.8.1" }
5959
mockito-bom = { module = "org.mockito:mockito-bom", version = "5.18.0" }
@@ -96,7 +96,7 @@ asciidoctorConvert = { id = "org.asciidoctor.jvm.convert", version.ref = "asciid
9696
asciidoctorPdf = { id = "org.asciidoctor.jvm.pdf", version.ref = "asciidoctor-plugins" }
9797
bnd = { id = "biz.aQute.bnd", version.ref = "bnd" }
9898
buildParameters = { id = "org.gradlex.build-parameters", version = "1.4.4" }
99-
commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.2.1" }
99+
commonCustomUserData = { id = "com.gradle.common-custom-user-data-gradle-plugin", version = "2.3" }
100100
develocity = { id = "com.gradle.develocity", version = "4.0.2" }
101101
errorProne = { id = "net.ltgt.errorprone", version = "4.2.0" }
102102
extraJavaModuleInfo = { id = "org.gradlex.extra-java-module-info", version = "1.12" }
@@ -105,7 +105,7 @@ gitPublish = { id = "org.ajoberstar.git-publish", version = "5.1.1" }
105105
jmh = { id = "me.champeau.jmh", version = "0.7.3" }
106106
jreleaser = { id = "org.jreleaser", version = "1.18.0" }
107107
# check if workaround in gradle.properties can be removed when updating
108-
kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC" }
108+
kotlin = { id = "org.jetbrains.kotlin.jvm", version = "2.2.0-RC2" }
109109
nullaway = { id = "net.ltgt.nullaway", version = "2.2.0" }
110110
openrewrite = { id = "org.openrewrite.rewrite", version = "7.7.0" }
111111
plantuml = { id = "io.freefair.plantuml", version = "8.13.1" }

gradle/wrapper/gradle-wrapper.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
3-
distributionSha256Sum=845952a9d6afa783db70bb3b0effaae45ae5542ca2bb7929619e8af49cb634cf
4-
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
3+
distributionSha256Sum=7197a12f450794931532469d4ff21a59ea2c1cd59a3ec3f89c035c3c420a6999
4+
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
55
networkTimeout=10000
66
validateDistributionUrl=true
77
zipStoreBase=GRADLE_USER_HOME

junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreCondition.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,21 +33,20 @@ abstract class AbstractJreCondition<A extends Annotation> extends BooleanExecuti
3333
static final String DISABLED_ON_CURRENT_JRE = //
3434
"Disabled on JRE version: " + System.getProperty("java.version");
3535

36-
private final String annotationName;
37-
3836
AbstractJreCondition(Class<A> annotationType, Function<A, String> customDisabledReason) {
3937
super(annotationType, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, customDisabledReason);
40-
this.annotationName = annotationType.getSimpleName();
4138
}
4239

4340
protected final IntStream validatedVersions(JRE[] jres, int[] versions) {
41+
String annotationName = super.annotationType.getSimpleName();
42+
4443
Preconditions.condition(jres.length > 0 || versions.length > 0,
45-
() -> "You must declare at least one JRE or version in @" + this.annotationName);
44+
() -> "You must declare at least one JRE or version in @" + annotationName);
4645

4746
Preconditions.condition(Arrays.stream(jres).noneMatch(isEqual(JRE.UNDEFINED)),
48-
() -> "JRE.UNDEFINED is not supported in @" + this.annotationName);
47+
() -> "JRE.UNDEFINED is not supported in @" + annotationName);
4948
Arrays.stream(versions).min().ifPresent(version -> Preconditions.condition(version >= JRE.MINIMUM_VERSION,
50-
() -> "Version [%d] in @%s must be greater than or equal to %d".formatted(version, this.annotationName,
49+
() -> "Version [%d] in @%s must be greater than or equal to %d".formatted(version, annotationName,
5150
JRE.MINIMUM_VERSION)));
5251

5352
return IntStream.concat(//

junit-jupiter-api/src/main/java/org/junit/jupiter/api/condition/AbstractJreRangeCondition.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,13 @@ abstract class AbstractJreRangeCondition<A extends Annotation> extends BooleanEx
2929
private static final JRE DEFAULT_MINIMUM_JRE = JRE.JAVA_17;
3030
private static final JRE DEFAULT_MAXIMUM_JRE = JRE.OTHER;
3131

32-
private final String annotationName;
33-
3432
AbstractJreRangeCondition(Class<A> annotationType, Function<A, String> customDisabledReason) {
3533
super(annotationType, ENABLED_ON_CURRENT_JRE, DISABLED_ON_CURRENT_JRE, customDisabledReason);
36-
this.annotationName = annotationType.getSimpleName();
3734
}
3835

3936
protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int minVersion, int maxVersion) {
37+
String annotationName = super.annotationType.getSimpleName();
38+
4039
boolean minJreSet = minJre != JRE.UNDEFINED;
4140
boolean maxJreSet = maxJre != JRE.UNDEFINED;
4241
boolean minVersionSet = minVersion != JRE.UNDEFINED_VERSION;
@@ -45,17 +44,17 @@ protected final boolean isCurrentVersionWithinRange(JRE minJre, JRE maxJre, int
4544
// Users must choose between JRE enum constants and version numbers.
4645
Preconditions.condition(!minJreSet || !minVersionSet,
4746
() -> "@%s's minimum value must be configured with either a JRE enum constant or numeric version, but not both".formatted(
48-
this.annotationName));
47+
annotationName));
4948
Preconditions.condition(!maxJreSet || !maxVersionSet,
5049
() -> "@%s's maximum value must be configured with either a JRE enum constant or numeric version, but not both".formatted(
51-
this.annotationName));
50+
annotationName));
5251

5352
// Users must supply valid values for minVersion and maxVersion.
5453
Preconditions.condition(!minVersionSet || (minVersion >= JRE.MINIMUM_VERSION),
55-
() -> "@%s's minVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, minVersion,
54+
() -> "@%s's minVersion [%d] must be greater than or equal to %d".formatted(annotationName, minVersion,
5655
JRE.MINIMUM_VERSION));
5756
Preconditions.condition(!maxVersionSet || (maxVersion >= JRE.MINIMUM_VERSION),
58-
() -> "@%s's maxVersion [%d] must be greater than or equal to %d".formatted(this.annotationName, maxVersion,
57+
() -> "@%s's maxVersion [%d] must be greater than or equal to %d".formatted(annotationName, maxVersion,
5958
JRE.MINIMUM_VERSION));
6059

6160
// 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
7271

7372
// Finally, we need to validate the effective minimum and maximum values.
7473
Preconditions.condition((min != DEFAULT_MINIMUM_JRE.version() || max != DEFAULT_MAXIMUM_JRE.version()),
75-
() -> "You must declare a non-default value for the minimum or maximum value in @" + this.annotationName);
74+
() -> "You must declare a non-default value for the minimum or maximum value in @" + annotationName);
7675
Preconditions.condition(min <= max,
7776
() -> "@%s's minimum value [%d] must be less than or equal to its maximum value [%d]".formatted(
78-
this.annotationName, min, max));
77+
annotationName, min, max));
7978

8079
return JRE.isCurrentVersionWithinRange(min, max);
8180
}

junit-jupiter-engine/src/main/java/org/junit/jupiter/engine/discovery/MethodOrderingVisitor.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,14 @@
1010

1111
package org.junit.jupiter.engine.discovery;
1212

13+
import static java.util.Comparator.comparing;
1314
import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation;
1415
import static org.junit.platform.commons.support.AnnotationSupport.isAnnotated;
1516

1617
import java.util.List;
1718
import java.util.Optional;
1819
import java.util.function.Consumer;
20+
import java.util.function.UnaryOperator;
1921

2022
import org.junit.jupiter.api.MethodOrderer;
2123
import org.junit.jupiter.api.Order;
@@ -40,6 +42,9 @@ class MethodOrderingVisitor extends AbstractOrderingVisitor {
4042
private final JupiterConfiguration configuration;
4143
private final Condition<MethodBasedTestDescriptor> noOrderAnnotation;
4244

45+
// Not a static field to avoid initialization at build time for GraalVM
46+
private final UnaryOperator<List<TestDescriptor>> methodsBeforeNestedClassesOrderer;
47+
4348
MethodOrderingVisitor(JupiterConfiguration configuration, DiscoveryIssueReporter issueReporter) {
4449
super(issueReporter);
4550
this.configuration = configuration;
@@ -51,6 +56,7 @@ class MethodOrderingVisitor extends AbstractOrderingVisitor {
5156
.source(MethodSource.from(testDescriptor.getTestMethod())) //
5257
.build();
5358
});
59+
this.methodsBeforeNestedClassesOrderer = createMethodsBeforeNestedClassesOrderer();
5460
}
5561

5662
@Override
@@ -80,6 +86,7 @@ private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescri
8086

8187
private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescriptor, Class<?> testClass,
8288
Optional<MethodOrderer> methodOrderer) {
89+
8390
DescriptorWrapperOrderer<?, DefaultMethodDescriptor> descriptorWrapperOrderer = createDescriptorWrapperOrderer(
8491
testClass, methodOrderer);
8592

@@ -89,6 +96,11 @@ private void orderContainedMethods(ClassBasedTestDescriptor classBasedTestDescri
8996
DefaultMethodDescriptor::new, //
9097
descriptorWrapperOrderer);
9198

99+
if (methodOrderer.isEmpty()) {
100+
// If there is an orderer, this is ensured by the call above
101+
classBasedTestDescriptor.orderChildren(methodsBeforeNestedClassesOrderer);
102+
}
103+
92104
// Note: MethodOrderer#getDefaultExecutionMode() is guaranteed
93105
// to be invoked after MethodOrderer#orderMethods().
94106
methodOrderer //
@@ -126,4 +138,12 @@ private Optional<Consumer<MethodBasedTestDescriptor>> toValidationAction(Optiona
126138
return Optional.of(noOrderAnnotation::check);
127139
}
128140

141+
private static UnaryOperator<List<TestDescriptor>> createMethodsBeforeNestedClassesOrderer() {
142+
var methodsFirst = comparing(MethodBasedTestDescriptor.class::isInstance).reversed();
143+
return children -> {
144+
children.sort(methodsFirst);
145+
return children;
146+
};
147+
}
148+
129149
}

0 commit comments

Comments
 (0)