44 */
55package net .minecraftforge .testing .aggregate ;
66
7+ import org .codehaus .groovy .runtime .InvokerHelper ;
78import org .codehaus .groovy .runtime .StringGroovyMethods ;
89import org .gradle .api .Project ;
910import org .gradle .api .file .Directory ;
1011import org .gradle .api .file .ProjectLayout ;
12+ import org .gradle .api .internal .tasks .testing .TestFramework ;
1113import org .gradle .api .model .ObjectFactory ;
1214import org .gradle .api .plugins .jvm .JvmTestSuite ;
15+ import org .gradle .api .provider .Property ;
1316import org .gradle .api .provider .Provider ;
1417import org .gradle .api .tasks .TaskProvider ;
1518import org .gradle .api .tasks .testing .Test ;
19+ import org .gradle .api .testing .toolchains .internal .JvmTestToolchain ;
1620import org .gradle .jvm .toolchain .JavaLanguageVersion ;
1721import org .gradle .jvm .toolchain .JavaToolchainService ;
1822import org .gradle .jvm .toolchain .JvmImplementation ;
1923import org .gradle .jvm .toolchain .JvmVendorSpec ;
24+ import org .gradle .language .base .plugins .LifecycleBasePlugin ;
2025import org .gradle .testing .base .TestingExtension ;
26+ import org .jetbrains .annotations .Nullable ;
2127import org .jetbrains .annotations .UnmodifiableView ;
2228
2329import javax .inject .Inject ;
2632import java .util .List ;
2733import java .util .Map ;
2834import java .util .TreeMap ;
35+ import java .util .function .Function ;
2936
3037abstract class AggregateTestExtensionImpl implements AggregateTestExtensionInternal {
3138 private final Map <String , List <Integer >> jvms = new TreeMap <>(Comparator .naturalOrder ());
@@ -67,18 +74,33 @@ private void finish(Project project) {
6774 var suites = testing .getSuites ().withType (JvmTestSuite .class );
6875
6976 for (var suite : suites ) {
77+ @ Nullable var testToolchain = this .getTestToolchain (suite );
7078 for (var target : suite .getTargets ()) {
71- this .configure (project , target .getTestTask ().get ());
79+ this .configure (project , target .getTestTask ().get (), testToolchain );
7280 }
7381 }
7482 } else {
83+ this .problems .reportNotUsingJvmTestSuite ();
7584 for (var test : project .getTasks ().withType (Test .class )) {
76- this .configure (project , test );
85+ this .configure (project , test , null );
7786 }
7887 }
7988 }
8089
81- private void configure (Project project , Test test ) {
90+ // NOTE: Avoiding leaking the JvmTestToolchain type since it is part of an incubating plugin's internal implementation and could be removed.
91+ // While TestFramework is also internal, it has since been stabilized and is not expected to be removed.
92+ @ SuppressWarnings ("unchecked" )
93+ private @ Nullable Function <Test , Provider <TestFramework >> getTestToolchain (JvmTestSuite suite ) {
94+ try {
95+ var testToolchain = (Property <JvmTestToolchain <?>>) InvokerHelper .getProperty (suite , "testToolchain" );
96+ return test -> testToolchain .map (t -> t .createTestFramework (test ));
97+ } catch (Exception e ) {
98+ this .problems .reportTestToolchainInaccessible (e , suite .getName ());
99+ return null ;
100+ }
101+ }
102+
103+ private void configure (Project project , Test test , @ Nullable Function <Test , Provider <TestFramework >> testToolchain ) {
82104 if (this .jvms .isEmpty ()) return ;
83105
84106 TaskProvider <? extends AggregateTest > testAll = project .getTasks ().register ("jvmAggregate" + StringGroovyMethods .capitalize (test .getName ()), AggregateTestImpl .class , task -> {
@@ -91,7 +113,7 @@ private void configure(Project project, Test test) {
91113
92114 for (int version : versions ) {
93115 var output = this .getLayout ().getBuildDirectory ().dir (AggregateTest .TEST_RESULTS_DIRECTORY + "/%s-%d" .formatted (vendor , version )).map (this .problems .ensureFileLocation ());
94- var task = this .register (project , test , vendor , version , output );
116+ var task = this .register (project , testToolchain , test , vendor , version , output );
95117
96118 testAll .configure (testAllTask -> {
97119 testAllTask .getInputs ().dir (output );
@@ -101,19 +123,23 @@ private void configure(Project project, Test test) {
101123 }
102124 }
103125
104- private TaskProvider <Test > register (Project project , Test test , String vendor , int version , Provider <Directory > output ) {
126+ private TaskProvider <Test > register (Project project , @ Nullable Function < Test , Provider < TestFramework >> testToolchain , Test test , String vendor , int version , Provider <Directory > output ) {
105127 var vendorSpec = JvmVendorSpec .of (vendor );
106128
107129 return project .getTasks ().register ("testUsing" + StringGroovyMethods .capitalize (vendor ) + version , Test .class , task -> {
108130 var description = test .getDescription ();
109131 task .setDescription (description != null
110132 ? "%s (using %s %s)" .formatted (description , vendorSpec , version )
111133 : "Runs '%s' using %s %s" .formatted (test .getName (), vendorSpec , version ));
112- task .notCompatibleWithConfigurationCache (
113- "JVM-specific tests need the test framework from the parent test task, which cannot be serialized."
114- );
134+ if (testToolchain != null ) {
135+ task .getTestFrameworkProperty ().set (testToolchain .apply (task ));
136+ } else {
137+ task .getTestFrameworkProperty ().set (test .getTestFrameworkProperty ());
138+ task .notCompatibleWithConfigurationCache (
139+ "JVM-specific tests need the test framework from the parent test task, which cannot be serialized."
140+ );
141+ }
115142
116- task .getTestFrameworkProperty ().set (test .getTestFrameworkProperty ());
117143 task .setClasspath (test .getClasspath ());
118144 task .setTestClassesDirs (test .getTestClassesDirs ());
119145 task .getJavaLauncher ().set (this .getJavaToolchains ().launcherFor (spec -> {
0 commit comments