Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Daemon toolchain auto-provisioning updateDaemonJvm generates download URLs #29022

Draft
wants to merge 2 commits into
base: release
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -371,4 +371,13 @@ public boolean isIbmJvm() {
return false;
}

@Nullable
public String getVendor() {
for (String vendorProperty : VENDOR_PROPERTIES) {
if (System.getProperties().containsKey(vendorProperty) && !System.getProperty(vendorProperty).isEmpty()) {
return System.getProperty(vendorProperty);
}
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ dependencies {
api(project(":base-services"))
api(project(":core"))
api(project(":core-api"))
api(project(":jvm-services"))
api(project(":toolchains-jvm-shared"))
api(project(":base-annotations"))
api(project(":platform-jvm"))
implementation(project(":logging"))
implementation(project(":jvm-services"))

testImplementation(testFixtures(project(":core")))
testImplementation(testFixtures(project(":toolchains-jvm-shared")))

testFixturesImplementation(project(":core-api"))
testFixturesImplementation(project(":internal-integ-testing"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,17 @@ import org.gradle.api.JavaVersion
import org.gradle.buildconfiguration.tasks.UpdateDaemonJvm
import org.gradle.integtests.fixtures.AbstractIntegrationSpec
import org.gradle.integtests.fixtures.AvailableJavaHomes
import org.gradle.integtests.fixtures.jvm.JavaToolchainFixture
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesDefaults
import org.gradle.internal.buildconfiguration.fixture.DaemonJvmPropertiesFixture
import org.gradle.internal.jvm.Jvm
import org.gradle.test.precondition.Requires
import org.gradle.test.preconditions.IntegTestPreconditions

class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements DaemonJvmPropertiesFixture {
import static org.gradle.jvm.toolchain.JavaToolchainDownloadUtil.applyToolchainResolverPlugin
import static org.gradle.jvm.toolchain.JavaToolchainDownloadUtil.noUrlResolverCode

class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements DaemonJvmPropertiesFixture, JavaToolchainFixture {

def "root project has an updateDaemonJvm task only"() {
buildFile << """
Expand All @@ -46,7 +50,19 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
fails(":sub:updateDaemonJvm") // should not exist
}

def "When execute updateDaemonJvm without options Then build properties are populated with default values"() {
def "When execute updateDaemonJvm without toolchain download repositories configured Then fails with expected exception message"() {
when:
fails "updateDaemonJvm"

then:
failureDescriptionContains("Execution failed for task ':updateDaemonJvm'.")
failureHasCause("Toolchain download repositories have not been configured.")
}

def "When execute updateDaemonJvm without options Then daemon jvm properties are populated with default values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm"

Expand All @@ -55,7 +71,10 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
outputContains("Daemon JVM criteria is an incubating feature.")
}

def "When execute updateDaemonJvm for valid version Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm for valid version Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--jvm-version=${version.majorVersion}"

Expand All @@ -66,7 +85,10 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
version << [JavaVersion.VERSION_11, JavaVersion.VERSION_15, JavaVersion.VERSION_HIGHER]
}

def "When execute updateDaemonJvm for valid Java 8 versions Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm for valid Java 8 versions Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--jvm-version=${version}"

Expand All @@ -78,6 +100,9 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
}

def "When execute updateDaemonJvm with invalid argument --jvm-version option Then fails with expected exception message"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
fails "updateDaemonJvm", "--jvm-version=$invalidVersion"

Expand All @@ -90,6 +115,9 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
}

def "When execute updateDaemonJvm with unsupported Java version Then fails with expected exception message"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
fails "updateDaemonJvm", "--jvm-version=7"

Expand All @@ -99,15 +127,20 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
}

def "When execute updateDaemonJvm with unsupported future Java version"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

// Captures current, but maybe not desired behavior
expect:
succeeds( "updateDaemonJvm", "--jvm-version=10000")
}

@NotYetImplemented
def "When execute updateDaemonJvm for valid vendor option Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm for valid vendor option Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--toolchain-vendor=$vendor"
run "updateDaemonJvm", "--jvm-vendor=$vendor"

then:
assertJvmCriteria(DaemonJvmPropertiesDefaults.TOOLCHAIN_VERSION, vendor)
Expand All @@ -117,7 +150,10 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
}

@NotYetImplemented
def "When execute updateDaemonJvm for valid implementation option Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm for valid implementation option Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--toolchain-implementation=$implementation"

Expand All @@ -128,37 +164,45 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
implementation << ["VENDOR_SPECIFIC", "J9"]
}

@NotYetImplemented
def "When execute updateDaemonJvm specifying different options Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm specifying different options Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--jvm-version=17", "--toolchain-vendor=IBM", "--toolchain-implementation=J9"
run "updateDaemonJvm", "--jvm-version=17", "--jvm-vendor=IBM"

then:
assertJvmCriteria(JavaVersion.VERSION_17, "IBM", "J9")
assertJvmCriteria(JavaVersion.VERSION_17, "IBM")
}

@NotYetImplemented
def "When execute updateDaemonJvm specifying different options in lower case Then build properties are populated with expected values"() {
def "When execute updateDaemonJvm specifying different options in lower case Then daemon jvm properties are populated with expected values"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
run "updateDaemonJvm", "--jvm-version=17", "--toolchain-vendor=ibm", "--toolchain-implementation=j9"
run "updateDaemonJvm", "--jvm-version=17", "--jvm-vendor=ibm"

then:
assertJvmCriteria(JavaVersion.VERSION_17, "IBM", "J9")
assertJvmCriteria(JavaVersion.VERSION_17, "IBM")
}

@NotYetImplemented
def "When execute updateDaemonJvm with unexpected --toolchain-vendor option Then fails with expected exception message"() {
def "When execute updateDaemonJvm with unexpected --jvm-vendor option Then fails with expected exception message"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
fails "updateDaemonJvm", "--toolchain-vendor=unknown-vendor"
fails "updateDaemonJvm", "--jvm-vendor=unknown-vendor"

then:
failureDescriptionContains("Problem configuring option 'toolchain-vendor' on task ':updateDaemonJvm' from command line.")
failureHasCause("Cannot convert string value 'unknown-vendor' to an enum value of type 'org.gradle.internal.jvm.inspection.JvmVendor\$KnownJvmVendor' " +
"(valid case insensitive values: ADOPTIUM, ADOPTOPENJDK, AMAZON, APPLE, AZUL, BELLSOFT, GRAAL_VM, HEWLETT_PACKARD, IBM, JETBRAINS, MICROSOFT, ORACLE, SAP, TENCENT, UNKNOWN)")
failureDescriptionContains("Value 'unknown-vendor' given for toolchainVendor is an invalid Java vendor. " +
"Possible values are [ADOPTIUM, ADOPTOPENJDK, AMAZON, APPLE, AZUL, BELLSOFT, GRAAL_VM, HEWLETT_PACKARD, IBM, JETBRAINS, MICROSOFT, ORACLE, SAP, TENCENT, UNKNOWN]")
}

@NotYetImplemented
def "When execute updateDaemonJvm with unexpected --toolchain-implementation option Then fails with expected exception message"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

when:
fails "updateDaemonJvm", "--toolchain-implementation=unknown-implementation"

Expand All @@ -168,8 +212,9 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
"(valid case insensitive values: VENDOR_SPECIFIC, J9)")
}

def "Given already existing build properties When execute updateDaemonJvm with different criteria Then criteria get modified"() {
def "Given already existing daemon jvm properties When execute updateDaemonJvm with different criteria Then criteria get modified"() {
given:
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())
def otherJvm = AvailableJavaHomes.differentVersion
writeJvmCriteria(Jvm.current())

Expand All @@ -180,29 +225,67 @@ class UpdateDaemonJvmIntegrationTest extends AbstractIntegrationSpec implements
assertJvmCriteria(otherJvm.javaVersion)
}

@NotYetImplemented
def "Given defined invalid criteria When execute updateDaemonJvm with different criteria Then criteria get modified using java home"() {
def currentJvm = JavaVersion.current()

given:
def currentJvm = JavaVersion.current()
writeJvmCriteria(currentJvm, "invalidVendor")
captureJavaHome()
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

expect:
succeeds("updateDaemonJvm", "--jvm-version=20", "--toolchain-vendor=AZUL")
succeeds("updateDaemonJvm", "--jvm-version=20", "--jvm-vendor=AZUL")
assertJvmCriteria(JavaVersion.VERSION_20, "AZUL")
assertDaemonUsedJvm(Jvm.current())
}

@NotYetImplemented
@Requires(IntegTestPreconditions.JavaHomeWithDifferentVersionAvailable)
def "Given defined valid criteria matching with local toolchain When execute updateDaemonJvm with different criteria Then criteria get modified using the expected local toolchain"() {
given:
def otherJvm = AvailableJavaHomes.differentVersion
def otherMetadata = AvailableJavaHomes.getJvmInstallationMetadata(otherJvm)

given:
writeJvmCriteria(otherJvm.javaVersion, otherMetadata.vendor.knownVendor.name())
captureJavaHome()
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", noUrlResolverCode())

expect:
succeeds("updateDaemonJvm", "--jvm-version=20", "--toolchain-vendor=AZUL")
withInstallations(otherJvm).succeeds("updateDaemonJvm", "--jvm-version=20", "--jvm-vendor=AZUL")
assertJvmCriteria(JavaVersion.VERSION_20, "AZUL")
assertDaemonUsedJvm(otherJvm)
}

def "Given custom applied toolchain resolver When execute updateDaemonJvm Then daemon jvm properties are populated with download toolchain urls"() {
given:
writeJvmCriteria(Jvm.current())
settingsFile << applyToolchainResolverPlugin("CustomToolchainResolver", """
@Override
public Optional<JavaToolchainDownload> resolve(JavaToolchainRequest request) {
def version = request.getJavaToolchainSpec().getLanguageVersion().get().asInt();
def vendor = request.getJavaToolchainSpec().getVendor().get();
def operatingSystem = request.getBuildPlatform().operatingSystem;
def architecture = request.getBuildPlatform().architecture;
URI uri = URI.create("https://server?platform=\$operatingSystem.\$architecture&toolchain=\$version.\$vendor");
return Optional.of(JavaToolchainDownload.fromUri(uri));
}
""")

when:
run "updateDaemonJvm", "--jvm-version=20", "--jvm-vendor=AZUL"

then:
assertJvmCriteria(JavaVersion.VERSION_20, "AZUL")
assertToolchainDownloadUrlsProperties([
["FreeBsd", "X8664"]: "https://server?platform=FREE_BSD.X86_64&toolchain=20.AZUL",
["FreeBsd", "Aarch64"]: "https://server?platform=FREE_BSD.AARCH64&toolchain=20.AZUL",
["Linux", "X8664"]: "https://server?platform=LINUX.X86_64&toolchain=20.AZUL",
["Linux", "Aarch64"]: "https://server?platform=LINUX.AARCH64&toolchain=20.AZUL",
["MacOs", "X8664"]: "https://server?platform=MAC_OS.X86_64&toolchain=20.AZUL",
["MacOs", "Aarch64"]: "https://server?platform=MAC_OS.AARCH64&toolchain=20.AZUL",
["Solaris", "X8664"]: "https://server?platform=SOLARIS.X86_64&toolchain=20.AZUL",
["Solaris", "Aarch64"]: "https://server?platform=SOLARIS.AARCH64&toolchain=20.AZUL",
["Unix", "X8664"]: "https://server?platform=UNIX.X86_64&toolchain=20.AZUL",
["Unix", "Aarch64"]: "https://server?platform=UNIX.AARCH64&toolchain=20.AZUL",
["Windows", "X8664"]: "https://server?platform=WINDOWS.X86_64&toolchain=20.AZUL",
["Windows", "Aarch64"]: "https://server?platform=WINDOWS.AARCH64&toolchain=20.AZUL"
])
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,15 @@
import org.gradle.api.tasks.options.Option;
import org.gradle.internal.buildconfiguration.DaemonJvmPropertiesDefaults;
import org.gradle.internal.buildconfiguration.tasks.UpdateDaemonJvmModifier;
import org.gradle.internal.jvm.inspection.JvmVendor;
import org.gradle.jvm.toolchain.JvmVendorSpec;
import org.gradle.jvm.toolchain.internal.DefaultJvmVendorSpec;
import org.gradle.util.internal.GUtil;
import org.gradle.util.internal.IncubationLogger;
import org.gradle.work.DisableCachingByDefault;

import javax.inject.Inject;
import java.util.Arrays;

/**
* Generates or updates the Gradle Daemon JVM criteria.
Expand All @@ -43,23 +48,28 @@
@DisableCachingByDefault(because = "Not worth caching")
@Incubating
public abstract class UpdateDaemonJvm extends DefaultTask {

private final Property<JvmVendorSpec> jvmVendorSpec = getProject().getObjects().property(JvmVendorSpec.class);
private final UpdateDaemonJvmModifier updateDaemonJvmModifier;

/**
* Constructor.
*
* @since 8.8
*/
@Inject
public UpdateDaemonJvm() {

public UpdateDaemonJvm(UpdateDaemonJvmModifier updateDaemonJvmModifier) {
this.updateDaemonJvmModifier = updateDaemonJvmModifier;
}

@TaskAction
void generate() {
IncubationLogger.incubatingFeatureUsed("Daemon JVM criteria");
UpdateDaemonJvmModifier.updateJvmCriteria(

updateDaemonJvmModifier.updateJvmCriteria(
getPropertiesFile().get().getAsFile(),
getJvmVersion().get(),
null,
jvmVendorSpec.getOrNull(),
null
);
}
Expand All @@ -85,4 +95,32 @@ void generate() {
@Option(option = "jvm-version", description = "The version of the JVM required to run the Gradle Daemon.")
@Incubating
public abstract Property<JavaVersion> getJvmVersion();

/**
* The vendor of Java required to run the Gradle Daemon.
*
* @since 8.9
*/
@Input
@Optional
@Incubating
public Property<JvmVendorSpec> getJvmVendor() {
return jvmVendorSpec;
}

/**
* The vendor of Java required to run the Gradle Daemon.
*
* @since 8.9
*/
@Option(option = "jvm-vendor", description = "The vendor of Java required to run the Gradle Daemon.")
@Incubating
public void setJvmVendor(String vendor) {
try {
JvmVendor.KnownJvmVendor jvmVendor = GUtil.toEnum(JvmVendor.KnownJvmVendor.class, vendor);
jvmVendorSpec.set(DefaultJvmVendorSpec.of(jvmVendor));
} catch (Exception e) {
throw new IllegalArgumentException(String.format("Value '%s' given for %s is an invalid Java vendor. Possible values are %s", vendor, DaemonJvmPropertiesDefaults.TOOLCHAIN_VENDOR_PROPERTY, Arrays.toString(JvmVendor.KnownJvmVendor.values())));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class DaemonJvmPropertiesDefaults {
public static final String TOOLCHAIN_VERSION_PROPERTY = "toolchainVersion";
public static final String TOOLCHAIN_VENDOR_PROPERTY = "toolchainVendor";
public static final String TOOLCHAIN_IMPLEMENTATION_PROPERTY = "toolchainImplementation";
public static final String TOOLCHAIN_URL_PROPERTY_FORMAT = "toolchain%s%sUrl";

public static final JavaVersion TOOLCHAIN_VERSION = JavaVersion.current();
}