From 633d976c1ced05676ead58824dcfa7980c3a1c03 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Sun, 1 Dec 2019 13:14:17 +0530 Subject: [PATCH] issue-5880 java.library.path should be configurable when launching the application's native image --- .../steps/NativeImageConfigBuildStep.java | 3 +- .../io/quarkus/maven/it/NativeImageIT.java | 83 +++++++++++++++++++ .../projects/native-image-app/pom.xml | 75 +++++++++++++++++ .../src/main/java/org/acme/HelloResource.java | 24 ++++++ 4 files changed, 184 insertions(+), 1 deletion(-) create mode 100644 integration-tests/maven/src/test/java/io/quarkus/maven/it/NativeImageIT.java create mode 100644 integration-tests/maven/src/test/resources/projects/native-image-app/pom.xml create mode 100644 integration-tests/maven/src/test/resources/projects/native-image-app/src/main/java/org/acme/HelloResource.java diff --git a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageConfigBuildStep.java b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageConfigBuildStep.java index 05413732fca39..be812764a266a 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageConfigBuildStep.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/steps/NativeImageConfigBuildStep.java @@ -102,7 +102,8 @@ void build(SslContextConfigurationRecorder sslContextConfigurationRecorder, } else { // On MacOS, the SunEC library is directly in jre/lib/ // This is useful for testing or if you have a similar environment in production - systemProperty.produce(new SystemPropertyBuildItem("java.library.path", graalVmLibDirectory.toString())); + javaLibraryPathAdditionalPath + .produce(new JavaLibraryPathAdditionalPathBuildItem(graalVmLibDirectory.toString())); } // This is useful for testing but the user will have to override it. diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/NativeImageIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/NativeImageIT.java new file mode 100644 index 0000000000000..424482e4970d7 --- /dev/null +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/NativeImageIT.java @@ -0,0 +1,83 @@ +package io.quarkus.maven.it; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.awaitility.Awaitility.await; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.Test; + +import io.quarkus.maven.it.verifier.MavenProcessInvocationResult; +import io.quarkus.maven.it.verifier.RunningInvoker; + +/** + * + */ +public class NativeImageIT extends MojoTestBase { + + /** + * Tests that the {@code java.library.path} can be overridden/configurable by passing the system property + * when launching the generated application's native image. + * + * @throws Exception + */ + @Test + public void testJavaLibraryPathAtRuntime() throws Exception { + final File testDir = initProject("projects/native-image-app", "projects/native-image-app-output"); + final RunningInvoker running = new RunningInvoker(testDir, false); + + // trigger mvn package -Pnative -Dquarkus.ssl.native=true + final String[] mvnArgs = new String[] { "package", "-DskipTests", "-Pnative", "-Dquarkus.ssl.native=true" }; + final MavenProcessInvocationResult result = running.execute(Arrays.asList(mvnArgs), Collections.emptyMap()); + await().atMost(5, TimeUnit.MINUTES).until(() -> result.getProcess() != null && !result.getProcess().isAlive()); + final String processLog = running.log(); + try { + assertThat(processLog).containsIgnoringCase("BUILD SUCCESS"); + } catch (AssertionError ae) { + // skip this test (instead of failing), if the native-image command wasn't available. + // Bit brittle to rely on the log message, but it's OK in the context of this test + Assumptions.assumeFalse(processLog.contains("Cannot find the `native-image"), + "Skipping test since native-image tool isn't available"); + // native-image command was available but the build failed for some reason, throw the original error + throw ae; + } finally { + running.stop(); + } + + // now that the native image is built, run it + final Path nativeImageRunner = testDir.toPath().toAbsolutePath().resolve(Paths.get("target/acme-1.0-SNAPSHOT-runner")); + final Path tmpDir = Files.createTempDirectory("native-image-test"); + tmpDir.toFile().deleteOnExit(); + final Process nativeImageRunWithAdditionalLibPath = runNativeImage(nativeImageRunner, + new String[] { "-Djava.library.path=" + tmpDir.toString() }); + try { + final String response = getHttpResponse("/hello/javaLibraryPath"); + Assertions.assertTrue(response.contains(tmpDir.toString()), + "Response " + response + " for java.library.path was expected to contain the " + tmpDir + ", but didn't"); + } finally { + nativeImageRunWithAdditionalLibPath.destroy(); + } + + } + + private static Process runNativeImage(final Path nativeImageRunnerFile, final String[] params) throws Exception { + final List commands = new ArrayList<>(); + commands.add(nativeImageRunnerFile.toString()); + if (params != null) { + commands.addAll(Arrays.asList(params)); + } + final ProcessBuilder processBuilder = new ProcessBuilder(commands.toArray(new String[0])); + processBuilder.inheritIO(); + return processBuilder.start(); + } +} diff --git a/integration-tests/maven/src/test/resources/projects/native-image-app/pom.xml b/integration-tests/maven/src/test/resources/projects/native-image-app/pom.xml new file mode 100644 index 0000000000000..b2a13b7541827 --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/native-image-app/pom.xml @@ -0,0 +1,75 @@ + + + 4.0.0 + org.acme + acme + 1.0-SNAPSHOT + + io.quarkus + quarkus-bom + @project.version@ + @project.version@ + 1.8 + UTF-8 + 1.8 + + + + + ${quarkus.platform.group-id} + ${quarkus.platform.artifact-id} + ${quarkus.platform.version} + pom + import + + + + + + + io.quarkus + quarkus-resteasy + + + + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + build + + + + + + + + + native + + + + io.quarkus + quarkus-maven-plugin + ${quarkus-plugin.version} + + + + native-image + + + true + + + + + + + + + diff --git a/integration-tests/maven/src/test/resources/projects/native-image-app/src/main/java/org/acme/HelloResource.java b/integration-tests/maven/src/test/resources/projects/native-image-app/src/main/java/org/acme/HelloResource.java new file mode 100644 index 0000000000000..30a1efa26ccfd --- /dev/null +++ b/integration-tests/maven/src/test/resources/projects/native-image-app/src/main/java/org/acme/HelloResource.java @@ -0,0 +1,24 @@ +package org.acme; + +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; + +@Path("/hello") +public class HelloResource { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } + + @GET + @Path("/javaLibraryPath") + @Produces(MediaType.TEXT_PLAIN) + public String javaLibraryPath() { + return System.getProperty("java.library.path"); + } + +}