[pure-refactor] Make everything incremental, fix custom version bugs (#17)

This commit is contained in:
iamdanfox 2018-10-02 22:44:14 +01:00 committed by GitHub
parent 6e94f257c2
commit 7d2d672697
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 384 additions and 199 deletions

View file

@ -4,7 +4,7 @@ A simple wrapper around GraalVM tooling that will download and locally cache a G
available select parts of the GraalVM compiler for use in Gradle builds. available select parts of the GraalVM compiler for use in Gradle builds.
To use this plugin, apply `com.palantir.graal`. See a full example in the To use this plugin, apply `com.palantir.graal`. See a full example in the
[integration tests](src/test/groovy/com/palantir/gradle/graal/GradleGraalPluginIntegrationSpec.groovy). [ETE tests](src/test/groovy/com/palantir/gradle/graal/GradleGraalEndToEndSpec.groovy).
Gradle Tasks Gradle Tasks
------------ ------------

View file

@ -65,6 +65,7 @@ dependencies {
testCompile gradleTestKit() testCompile gradleTestKit()
testCompile 'com.netflix.nebula:nebula-test' testCompile 'com.netflix.nebula:nebula-test'
testCompile 'com.squareup.okhttp3:mockwebserver'
baseline 'com.palantir.baseline:gradle-baseline-java-config:0.26.1@zip' baseline 'com.palantir.baseline:gradle-baseline-java-config:0.26.1@zip'
} }

View file

@ -23,63 +23,65 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.internal.TaskInternal; import org.gradle.api.file.RegularFile;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
/** Downloads GraalVM binaries to {@link GradleGraalPlugin#CACHE_DIR}. */ /** Downloads GraalVM binaries. */
public class DownloadGraalTask extends DefaultTask { public class DownloadGraalTask extends DefaultTask {
private static final String ARTIFACT_PATTERN = "[url]/vm-[version]/graalvm-ce-[version]-[os]-[arch].tar.gz"; private static final String ARTIFACT_PATTERN = "[url]/vm-[version]/graalvm-ce-[version]-[os]-[arch].tar.gz";
private static final String FILENAME_PATTERN = "graalvm-ce-[version]-[arch].tar.gz"; private static final String FILENAME_PATTERN = "graalvm-ce-[version]-[arch].tar.gz";
@Input private Provider<String> graalVersion; private final Property<String> graalVersion = getProject().getObjects().property(String.class);
@Input private Provider<String> downloadBaseUrl; private final Property<String> downloadBaseUrl = getProject().getObjects().property(String.class);
private final Property<Path> cacheDir = getProject().getObjects().property(Path.class);
public DownloadGraalTask() {
setGroup(GradleGraalPlugin.TASK_GROUP);
setDescription("Downloads and caches GraalVM binaries.");
onlyIf(task -> !getTgz().get().getAsFile().exists());
}
@TaskAction @TaskAction
public final void downloadGraal() throws IOException { public final void downloadGraal() throws IOException {
Path cache = getCache(); Path cache = getCacheSubdirectory().get();
if (!(cache.toFile().mkdirs() || cache.toFile().exists())) { Files.createDirectories(cache);
throw new IllegalStateException( try (InputStream in = new URL(render(ARTIFACT_PATTERN)).openStream()) {
"Unable to make cache directory, and the cache directory does not already exist: " + cache); Files.copy(in, getTgz().get().getAsFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
} }
InputStream in = new URL(render(ARTIFACT_PATTERN)).openStream();
Files.copy(in, getOutput(), StandardCopyOption.REPLACE_EXISTING);
}
@Override
public final String getGroup() {
return GradleGraalPlugin.TASK_GROUP;
}
@Override
public final String getDescription() {
return "Downloads and caches GraalVM binaries.";
} }
@OutputFile @OutputFile
public final Path getOutput() { public final Provider<RegularFile> getTgz() {
return getCache().resolve(render(FILENAME_PATTERN)); return getProject().getLayout()
.file(getCacheSubdirectory().map(dir -> dir.resolve(render(FILENAME_PATTERN)).toFile()));
} }
/** Returns a lambda that prevents this task from running if the download target already exists in the cache. */ @Input
@Override public final Provider<String> getGraalVersion() {
public final Spec<? super TaskInternal> getOnlyIf() { return graalVersion;
return spec -> !getOutput().toFile().exists();
} }
@SuppressWarnings("checkstyle:hiddenfield") public final void setGraalVersion(Provider<String> provider) {
public final void configure(Provider<String> graalVersion, Provider<String> downloadBaseUrl) { graalVersion.set(provider);
this.graalVersion = graalVersion;
this.downloadBaseUrl = downloadBaseUrl;
} }
private Path getCache() { @Input
return GradleGraalPlugin.CACHE_DIR.resolve(graalVersion.get()); public final Provider<String> getDownloadBaseUrl() {
return downloadBaseUrl;
}
public final void setDownloadBaseUrl(Provider<String> provider) {
downloadBaseUrl.set(provider);
}
private Provider<Path> getCacheSubdirectory() {
return cacheDir.map(dir -> dir.resolve(graalVersion.get()));
} }
private String render(String pattern) { private String render(String pattern) {
@ -109,4 +111,8 @@ public class DownloadGraalTask extends DefaultTask {
throw new IllegalStateException("No GraalVM support for " + Platform.architecture()); throw new IllegalStateException("No GraalVM support for " + Platform.architecture());
} }
} }
final void setCacheDir(Path value) {
cacheDir.set(value);
}
} }

View file

@ -16,21 +16,38 @@
package com.palantir.gradle.graal; package com.palantir.gradle.graal;
import java.io.File;
import java.nio.file.Path; import java.nio.file.Path;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.internal.TaskInternal; import org.gradle.api.file.Directory;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.OutputDirectory; import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
/** Extracts GraalVM tooling from downloaded tgz archive using the system's tar command. */ /** Extracts GraalVM tooling from downloaded tgz archive using the system's tar command. */
public class ExtractGraalTask extends DefaultTask { public class ExtractGraalTask extends DefaultTask {
@Input private Provider<File> inputTgz; private final RegularFileProperty inputTgz = newInputFile();
@Input private Provider<String> graalVersion; private final Property<String> graalVersion = getProject().getObjects().property(String.class);
private final DirectoryProperty outputDirectory = newOutputDirectory();
private final Property<Path> cacheDir = getProject().getObjects().property(Path.class);
public ExtractGraalTask() {
setGroup(GradleGraalPlugin.TASK_GROUP);
setDescription("Extracts GraalVM tooling from downloaded tgz archive using the system's tar command.");
onlyIf(task -> !getOutputDirectory().get().getAsFile().exists());
outputDirectory.set(graalVersion.map(v ->
getProject().getLayout().getProjectDirectory()
.dir(cacheDir.get().toFile().getAbsolutePath())
.dir(v)
.dir("graalvm-ce-" + v)));
}
@TaskAction @TaskAction
public final void extractGraal() { public final void extractGraal() {
@ -41,34 +58,35 @@ public class ExtractGraalTask extends DefaultTask {
// ideally this would be a CopyTask, but through Gradle 4.9 CopyTask fails to correctly extract symlinks // ideally this would be a CopyTask, but through Gradle 4.9 CopyTask fails to correctly extract symlinks
getProject().exec(spec -> { getProject().exec(spec -> {
spec.executable("tar"); spec.executable("tar");
spec.args("-xzf", inputTgz.get().getAbsolutePath()); spec.args("-xzf", inputTgz.get().getAsFile().getAbsolutePath());
spec.workingDir(GradleGraalPlugin.CACHE_DIR.resolve(graalVersion.get())); spec.workingDir(cacheDir.get().resolve(graalVersion.get()));
}); });
} }
@InputFile
public final Provider<RegularFile> getInputTgz() {
return inputTgz;
}
public final void setInputTgz(Provider<RegularFile> value) {
this.inputTgz.set(value);
}
@Input
public final Provider<String> getGraalVersion() {
return graalVersion;
}
public final void setGraalVersion(Provider<String> provider) {
graalVersion.set(provider);
}
@OutputDirectory @OutputDirectory
public final Path getOutputDirectory() { public final Provider<Directory> getOutputDirectory() {
return GradleGraalPlugin.CACHE_DIR.resolve(graalVersion.get()).resolve("graalvm-ce-" + graalVersion.get()); return outputDirectory;
} }
@Override final void setCacheDir(Path value) {
public final Spec<? super TaskInternal> getOnlyIf() { cacheDir.set(value);
return spec -> !getOutputDirectory().toFile().exists();
}
@Override
public final String getGroup() {
return GradleGraalPlugin.TASK_GROUP;
}
@Override
public final String getDescription() {
return "Extracts GraalVM tooling from downloaded tgz archive using the system's tar command.";
}
@SuppressWarnings("checkstyle:hiddenfield")
public final void configure(Provider<File> inputTgz, Provider<String> graalVersion) {
this.inputTgz = inputTgz;
this.graalVersion = graalVersion;
} }
} }

View file

@ -26,10 +26,10 @@ public class GraalExtension {
private static final String DEFAULT_DOWNLOAD_BASE_URL = "https://github.com/oracle/graal/releases/download/"; private static final String DEFAULT_DOWNLOAD_BASE_URL = "https://github.com/oracle/graal/releases/download/";
private static final String DEFAULT_GRAAL_VERSION = "1.0.0-rc6"; private static final String DEFAULT_GRAAL_VERSION = "1.0.0-rc6";
private Property<String> downloadBaseUrl; private final Property<String> downloadBaseUrl;
private Property<String> graalVersion; private final Property<String> graalVersion;
private Property<String> mainClass; private final Property<String> mainClass;
private Property<String> outputName; private final Property<String> outputName;
public GraalExtension(Project project) { public GraalExtension(Project project) {
downloadBaseUrl = project.getObjects().property(String.class); downloadBaseUrl = project.getObjects().property(String.class);
@ -86,7 +86,7 @@ public class GraalExtension {
* *
* <p>Defaults to {@link #DEFAULT_GRAAL_VERSION}</p> * <p>Defaults to {@link #DEFAULT_GRAAL_VERSION}</p>
*/ */
public final Property<String> getGraalVersion() { public final Provider<String> getGraalVersion() {
return graalVersion; return graalVersion;
} }

View file

@ -18,12 +18,12 @@ package com.palantir.gradle.graal;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.function.Supplier; import java.util.Optional;
import javax.annotation.Nullable;
import org.gradle.api.Plugin; import org.gradle.api.Plugin;
import org.gradle.api.Project; import org.gradle.api.Project;
import org.gradle.api.Transformer; import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.provider.Provider; import org.gradle.api.tasks.TaskProvider;
import org.gradle.jvm.tasks.Jar;
/** /**
* Adds tasks to download, extract and interact with GraalVM tooling. * Adds tasks to download, extract and interact with GraalVM tooling.
@ -44,61 +44,51 @@ import org.gradle.api.provider.Provider;
*/ */
public class GradleGraalPlugin implements Plugin<Project> { public class GradleGraalPlugin implements Plugin<Project> {
/** Location to cache downloaded and extracted GraalVM tooling. */ static final String TASK_GROUP = "Graal";
public static final Path CACHE_DIR =
Paths.get(System.getProperty("user.home"), ".gradle", "caches", "com.palantir.graal");
public static final String TASK_GROUP = "Graal";
@Override @Override
public final void apply(Project project) { public final void apply(Project project) {
project.getPluginManager().apply(JavaPlugin.class);
GraalExtension extension = project.getExtensions().create("graal", GraalExtension.class, project); GraalExtension extension = project.getExtensions().create("graal", GraalExtension.class, project);
DownloadGraalTask downloadGraal = project.getTasks().create( Path cacheDir = Optional.ofNullable((String) project.getProperties().get("com.palantir.graal.cache.dir"))
"downloadGraalTooling", DownloadGraalTask.class, task -> { .map(Paths::get)
task.configure(extension.getGraalVersion(), extension.getDownloadBaseUrl()); .orElse(project.getGradle().getGradleUserHomeDir().toPath()
.resolve("caches")
.resolve("com.palantir.graal"));
TaskProvider<DownloadGraalTask> downloadGraal = project.getTasks().register(
"downloadGraalTooling",
DownloadGraalTask.class,
task -> {
task.setGraalVersion(extension.getGraalVersion());
task.setDownloadBaseUrl(extension.getDownloadBaseUrl());
task.setCacheDir(cacheDir);
}); });
ExtractGraalTask extractGraal = project.getTasks().create( TaskProvider<ExtractGraalTask> extractGraal = project.getTasks().register(
"extractGraalTooling", ExtractGraalTask.class, task -> { "extractGraalTooling",
ExtractGraalTask.class,
task -> {
task.setGraalVersion(extension.getGraalVersion());
task.setInputTgz(downloadGraal.get().getTgz());
task.setCacheDir(cacheDir);
task.dependsOn(downloadGraal); task.dependsOn(downloadGraal);
task.configure(asProvider(() -> downloadGraal.getOutput().toFile()), extension.getGraalVersion());
}); });
project.getTasks().create("nativeImage", NativeImageTask.class, task -> { TaskProvider<Jar> jar = project.getTasks().withType(Jar.class).named("jar");
project.getTasks().register(
"nativeImage",
NativeImageTask.class,
task -> {
task.setMainClass(extension.getMainClass());
task.setOutputName(extension.getOutputName());
task.setGraalVersion(extension.getGraalVersion());
task.setJarFile(jar.map(j -> j.getOutputs().getFiles().getSingleFile()));
task.setClasspath(project.getConfigurations().named("runtimeClasspath"));
task.setCacheDir(cacheDir);
task.dependsOn(extractGraal); task.dependsOn(extractGraal);
task.dependsOn("jar"); task.dependsOn(jar);
task.configure(extension.getMainClass(), extension.getOutputName(), extension.getGraalVersion());
}); });
} }
private static <T> Provider<T> asProvider(Supplier<T> supplier) {
return new Provider<T>() {
@Override
public T get() {
return supplier.get();
}
@Nullable
@Override
public T getOrNull() {
return supplier.get();
}
@Override
public T getOrElse(T other) {
return supplier.get();
}
@Override
public <S> Provider<S> map(Transformer<? extends S, ? super T> transformer) {
return asProvider(() -> transformer.transform(get()));
}
@Override
public boolean isPresent() {
return true;
}
};
}
} }

View file

@ -17,6 +17,8 @@
package com.palantir.gradle.graal; package com.palantir.gradle.graal;
import java.io.File; import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.ArrayList; import java.util.ArrayList;
@ -25,90 +27,82 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider; import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFile;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
/** Runs GraalVM's native-image command with configured options and parameters. */ /** Runs GraalVM's native-image command with configured options and parameters. */
public class NativeImageTask extends DefaultTask { public class NativeImageTask extends DefaultTask {
@Input private Provider<String> mainClass; private final Property<String> mainClass = getProject().getObjects().property(String.class);
@Input private Provider<String> outputName; private final Property<String> outputName = getProject().getObjects().property(String.class);
@Input private Provider<String> graalVersion; private final Property<String> graalVersion = getProject().getObjects().property(String.class);
private final Property<Configuration> classpath = getProject().getObjects().property(Configuration.class);
private final RegularFileProperty jarFile = newInputFile();
private final RegularFileProperty outputFile = newOutputFile();
private final Property<Path> cacheDir = getProject().getObjects().property(Path.class);
public NativeImageTask() {
setGroup(GradleGraalPlugin.TASK_GROUP);
setDescription("Runs GraalVM's native-image command with configured options and parameters.");
this.outputFile.set(getProject().getLayout().getBuildDirectory()
.dir("graal")
.map(d -> d.file(outputName.get())));
doLast(t -> {
getLogger().warn("native-image available at {} ({}MB)",
getProject().relativePath(outputFile.get().getAsFile()),
fileSizeMegabytes(outputFile.get()));
});
}
@TaskAction @TaskAction
public final void nativeImage() { public final void nativeImage() throws IOException {
// TODO(rfink): declare classpath list as @Input in order to unlock incremental builds
getProject().exec(spec -> {
if (!mainClass.isPresent()) {
throw new IllegalArgumentException("nativeImage requires graal.mainClass to be defined.");
}
if (!graalVersion.isPresent()) {
throw new IllegalStateException("nativeImage requires graal.version to be defined.");
}
List<String> args = new ArrayList<>(); List<String> args = new ArrayList<>();
args.add("-cp"); args.add("-cp");
args.add(generateClasspathArgument()); args.add(generateClasspathArgument());
args.add("-H:Path=" + maybeCreateOutputDirectory().getAbsolutePath());
args.add("-H:Path=" + getOutputDirectory());
if (outputName.isPresent()) { if (outputName.isPresent()) {
args.add("-H:Name=" + outputName.get()); args.add("-H:Name=" + outputName.get());
} }
args.add(mainClass.get()); args.add(mainClass.get());
spec.executable(getExecutable(graalVersion.get())); getProject().exec(spec -> {
spec.executable(getExecutable());
spec.args(args); spec.args(args);
}); });
} }
@Override private File maybeCreateOutputDirectory() throws IOException {
public final String getGroup() { File directory = getOutputFile().get().getAsFile().getParentFile();
return GradleGraalPlugin.TASK_GROUP; Files.createDirectories(directory.toPath());
return directory;
} }
@Override private String getExecutable() {
public final String getDescription() { return cacheDir.get()
return "Runs GraalVM's native-image command with configured options and parameters."; .resolve(Paths.get(graalVersion.get(), "graalvm-ce-" + graalVersion.get()))
}
private String getOutputDirectory() {
File outputDirectory = getProject().getProjectDir().toPath().resolve(Paths.get("build", "graal")).toFile();
if (!(outputDirectory.mkdirs() || outputDirectory.exists())) {
throw new IllegalStateException(
"Output directory does not exist and cannot be created: " + outputDirectory);
}
return outputDirectory.getAbsolutePath();
}
private String getExecutable(String version) {
return GradleGraalPlugin.CACHE_DIR
.resolve(Paths.get(version, "graalvm-ce-" + version))
.resolve(getArchitectureSpecifiedBinaryPath()) .resolve(getArchitectureSpecifiedBinaryPath())
.toFile() .toFile()
.getAbsolutePath(); .getAbsolutePath();
} }
private String generateClasspathArgument() { private String generateClasspathArgument() {
Set<File> classpath = new LinkedHashSet<>(); Set<File> classpathArgument = new LinkedHashSet<>();
classpath.addAll(getProject().getConfigurations().getByName("runtimeClasspath").getFiles());
classpath.addAll(getProject().getTasks().getByName("jar").getOutputs().getFiles().getFiles());
return classpath.stream() classpathArgument.addAll(classpath.get().getFiles());
.map(File::getAbsolutePath) classpathArgument.add(jarFile.getAsFile().get());
.collect(Collectors.joining(":"));
}
@SuppressWarnings("checkstyle:hiddenfield") return classpathArgument.stream().map(File::getAbsolutePath).collect(Collectors.joining(":"));
public final void configure(Provider<String> mainClass, Provider<String> outputName,
Provider<String> graalVersion) {
this.mainClass = mainClass;
this.outputName = outputName;
this.graalVersion = graalVersion;
} }
private Path getArchitectureSpecifiedBinaryPath() { private Path getArchitectureSpecifiedBinaryPath() {
@ -120,4 +114,66 @@ public class NativeImageTask extends DefaultTask {
} }
} }
private long fileSizeMegabytes(RegularFile regularFile) {
try {
return Files.size(regularFile.getAsFile().toPath()) / (1000 * 1000);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Input
public final Provider<String> getMainClass() {
return mainClass;
}
public final void setMainClass(Provider<String> provider) {
mainClass.set(provider);
}
@Input
public final Provider<String> getOutputName() {
return outputName;
}
@Input
public final Provider<String> getGraalVersion() {
return graalVersion;
}
public final void setGraalVersion(Provider<String> provider) {
graalVersion.set(provider);
}
@InputFiles
@Classpath
public final Provider<Configuration> getClasspath() {
return classpath;
}
public final void setClasspath(Provider<Configuration> provider) {
classpath.set(provider);
}
@InputFile
public final Provider<RegularFile> getJarFiles() {
return jarFile;
}
public final void setJarFile(Provider<File> provider) {
jarFile.set(getProject().getLayout().file(provider));
}
@OutputFile
public final Provider<RegularFile> getOutputFile() {
return outputFile;
}
public final void setOutputName(Provider<String> provider) {
outputName.set(provider);
}
final void setCacheDir(Path value) {
cacheDir.set(value);
}
} }

View file

@ -0,0 +1 @@
implementation-class=com.palantir.gradle.graal.GradleGraalPlugin

View file

@ -0,0 +1,80 @@
/*
* (c) Copyright 2018 Palantir Technologies Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.palantir.gradle.graal
import nebula.test.IntegrationSpec
import nebula.test.functional.ExecutionResult
class GradleGraalEndToEndSpec extends IntegrationSpec {
def 'test default version nativeImage'() {
setup:
directory("src/main/java/com/palantir/test")
file("src/main/java/com/palantir/test/Main.java") << '''
package com.palantir.test;
public final class Main {
public static final void main(String[] args) {
System.out.println("hello, world!");
}
}
'''
buildFile << '''
apply plugin: 'com.palantir.graal'
graal {
mainClass 'com.palantir.test.Main'
outputName 'hello-world'
graalVersion '1.0.0-rc5'
}
'''
when:
ExecutionResult result = runTasksSuccessfully('nativeImage') // note, this accesses your real ~/.gradle cache
println "Gradle Standard Out:\n" + result.standardOutput
println "Gradle Standard Error:\n" + result.standardError
File output = new File(getProjectDir(), "build/graal/hello-world");
then:
output.exists()
output.getAbsolutePath().execute().text.equals("hello, world!\n")
when:
ExecutionResult result2 = runTasksSuccessfully('nativeImage')
then:
result2.wasUpToDate(':nativeImage')
when:
new File(getProjectDir(), "src/main/java/com/palantir/test/Main.java").text = '''
package com.palantir.test;
public final class Main {
public static final void main(String[] args) {
System.out.println("hello, world (modified)!");
}
}
'''
ExecutionResult result3 = runTasksSuccessfully('nativeImage')
then:
println result3.standardOutput
!result3.wasUpToDate(':nativeImage')
output.getAbsolutePath().execute().text.equals("hello, world (modified)!\n")
}
}

View file

@ -18,12 +18,20 @@ package com.palantir.gradle.graal
import nebula.test.IntegrationSpec import nebula.test.IntegrationSpec
import nebula.test.functional.ExecutionResult import nebula.test.functional.ExecutionResult
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.Rule
class GradleGraalPluginIntegrationSpec extends IntegrationSpec { class GradleGraalPluginIntegrationSpec extends IntegrationSpec {
def 'test default version nativeImage'() {
setup: @Rule MockWebServer server = new MockWebServer()
new File(getProjectDir(), "src/main/java/com/palantir/test").mkdirs() String fakeBaseUrl
new File(getProjectDir(), "src/main/java/com/palantir/test/Main.java") << '''
def setup() {
fakeBaseUrl = String.format("http://localhost:%s/oracle/graal/releases/download/", server.getPort())
directory("src/main/java/com/palantir/test")
file("src/main/java/com/palantir/test/Main.java") << '''
package com.palantir.test; package com.palantir.test;
public final class Main { public final class Main {
@ -33,26 +41,53 @@ class GradleGraalPluginIntegrationSpec extends IntegrationSpec {
} }
''' '''
buildFile << ''' file('gradle.properties') << "com.palantir.graal.cache.dir=${getProjectDir().toPath().resolve("cacheDir").toAbsolutePath()}"
apply plugin: 'java' }
def 'allows specifying different graal version'() {
setup:
buildFile << """
apply plugin: 'com.palantir.graal' apply plugin: 'com.palantir.graal'
graal { graal {
mainClass 'com.palantir.test.Main' graalVersion '1.0.0-rc3'
outputName 'hello-world' downloadBaseUrl '${fakeBaseUrl}'
} }
''' """
server.enqueue(new MockResponse().setBody('<<tgz>>'));
when: when:
ExecutionResult result = runTasks('nativeImage') ExecutionResult result = runTasksSuccessfully('downloadGraalTooling')
// capture output from Gradle runs
println "Gradle Standard Out:\n" + result.standardOutput
println "Gradle Standard Error:\n" + result.standardError
File output = new File(getProjectDir(), "build/graal/hello-world");
then: then:
result.success println result.getStandardOutput()
output.exists() result.wasExecuted(':downloadGraalTooling')
output.getAbsolutePath().execute().text.equals("hello, world!\n") !result.wasUpToDate(':downloadGraalTooling')
!result.wasSkipped(':downloadGraalTooling')
server.takeRequest().requestUrl.toString() =~ "http://localhost:${server.port}" +
"/oracle/graal/releases/download//vm-1.0.0-rc3/graalvm-ce-1.0.0-rc3-(macos|linux)-amd64.tar.gz"
file("cacheDir/1.0.0-rc3/graalvm-ce-1.0.0-rc3-amd64.tar.gz").text == '<<tgz>>'
}
def 'downloadGraalTooling behaves incrementally'() {
setup:
buildFile << """
apply plugin: 'com.palantir.graal'
graal {
downloadBaseUrl '${fakeBaseUrl}'
}
"""
server.enqueue(new MockResponse().setBody('<<tgz>>'));
when:
ExecutionResult result1 = runTasksSuccessfully('downloadGraalTooling')
ExecutionResult result2 = runTasksSuccessfully('downloadGraalTooling')
then:
result1.wasSkipped(':downloadGraalTooling') == false
result2.wasSkipped(':downloadGraalTooling') == true
} }
} }

View file

@ -18,9 +18,6 @@ package com.palantir.gradle.graal
import nebula.test.PluginProjectSpec import nebula.test.PluginProjectSpec
/**
* Tests for {@link GradleGraalPlugin}.
*/
class GradleGraalPluginProjectSpec extends PluginProjectSpec { class GradleGraalPluginProjectSpec extends PluginProjectSpec {
@Override @Override

View file

@ -1 +1,2 @@
com.netflix.nebula:nebula-test = 6.7.1 com.netflix.nebula:nebula-test = 6.7.1
com.squareup.okhttp3:* = 3.11.0