| /* |
| * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package jdk.jpackage.tests; |
| |
| import java.io.IOException; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.util.List; |
| import java.util.ArrayList; |
| import java.util.function.Function; |
| import java.util.function.Predicate; |
| import java.util.function.Supplier; |
| import java.util.regex.Pattern; |
| import java.util.stream.Collectors; |
| import java.util.stream.Stream; |
| import jdk.jpackage.test.*; |
| import jdk.jpackage.test.Functional.ThrowingConsumer; |
| import jdk.jpackage.test.Annotations.*; |
| |
| /* |
| * @test |
| * @summary jpackage basic testing |
| * @library ../../../../helpers |
| * @build jdk.jpackage.test.* |
| * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal |
| * @compile BasicTest.java |
| * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main |
| * --jpt-run=jdk.jpackage.tests.BasicTest |
| */ |
| |
| public final class BasicTest { |
| @Test |
| public void testNoArgs() { |
| List<String> output = |
| getJPackageToolProvider().executeAndGetOutput(); |
| TKit.assertStringListEquals(List.of("Usage: jpackage <options>", |
| "Use jpackage --help (or -h) for a list of possible options"), |
| output, "Check jpackage output"); |
| } |
| |
| @Test |
| public void testVersion() { |
| List<String> output = |
| getJPackageToolProvider() |
| .addArgument("--version") |
| .executeAndGetOutput(); |
| TKit.assertStringListEquals(List.of(System.getProperty("java.version")), |
| output, "Check jpackage output"); |
| } |
| |
| @Test |
| public void testHelp() { |
| List<String> hOutput = getJPackageToolProvider() |
| .addArgument("-h").executeAndGetOutput(); |
| List<String> helpOutput = getJPackageToolProvider() |
| .addArgument("--help").executeAndGetOutput(); |
| |
| TKit.assertStringListEquals(hOutput, helpOutput, |
| "Check -h and --help parameters produce the same output"); |
| |
| final String windowsPrefix = "--win-"; |
| final String linuxPrefix = "--linux-"; |
| final String osxPrefix = "--mac-"; |
| |
| final String expectedPrefix; |
| final List<String> unexpectedPrefixes; |
| |
| if (TKit.isWindows()) { |
| expectedPrefix = windowsPrefix; |
| unexpectedPrefixes = List.of(osxPrefix, linuxPrefix); |
| } else if (TKit.isLinux()) { |
| expectedPrefix = linuxPrefix; |
| unexpectedPrefixes = List.of(windowsPrefix, osxPrefix); |
| } else if (TKit.isOSX()) { |
| expectedPrefix = osxPrefix; |
| unexpectedPrefixes = List.of(linuxPrefix, windowsPrefix); |
| } else { |
| throw TKit.throwUnknownPlatformError(); |
| } |
| |
| Function<String, Predicate<String>> createPattern = (prefix) -> { |
| return Pattern.compile("^ " + prefix).asPredicate(); |
| }; |
| |
| Function<List<String>, Long> countStrings = (prefixes) -> { |
| return hOutput.stream().filter( |
| prefixes.stream().map(createPattern).reduce(x -> false, |
| Predicate::or)).peek(TKit::trace).count(); |
| }; |
| |
| TKit.trace("Check parameters in help text"); |
| TKit.assertNotEquals(0, countStrings.apply(List.of(expectedPrefix)), |
| "Check help text contains plaform specific parameters"); |
| TKit.assertEquals(0, countStrings.apply(unexpectedPrefixes), |
| "Check help text doesn't contain unexpected parameters"); |
| } |
| |
| @Test |
| @SuppressWarnings("unchecked") |
| public void testVerbose() { |
| JPackageCommand cmd = JPackageCommand.helloAppImage() |
| // Disable default logic adding `--verbose` option |
| // to jpackage command line. |
| .ignoreDefaultVerbose(true) |
| .saveConsoleOutput(true) |
| .setFakeRuntime().executePrerequisiteActions(); |
| |
| List<String> expectedVerboseOutputStrings = new ArrayList<>(); |
| expectedVerboseOutputStrings.add("Creating app package:"); |
| if (TKit.isWindows()) { |
| expectedVerboseOutputStrings.add( |
| "Succeeded in building Windows Application Image package"); |
| } else if (TKit.isLinux()) { |
| expectedVerboseOutputStrings.add( |
| "Succeeded in building Linux Application Image package"); |
| } else if (TKit.isOSX()) { |
| expectedVerboseOutputStrings.add("Preparing Info.plist:"); |
| expectedVerboseOutputStrings.add( |
| "Succeeded in building Mac Application Image package"); |
| } else { |
| TKit.throwUnknownPlatformError(); |
| } |
| |
| TKit.deleteDirectoryContentsRecursive(cmd.outputDir()); |
| List<String> nonVerboseOutput = cmd.execute().getOutput(); |
| List<String>[] verboseOutput = (List<String>[])new List<?>[1]; |
| |
| // Directory clean up is not 100% reliable on Windows because of |
| // antivirus software that can lock .exe files. Setup |
| // different output directory instead of cleaning the default one for |
| // verbose jpackage run. |
| TKit.withTempDirectory("verbose-output", tempDir -> { |
| cmd.setArgumentValue("--dest", tempDir); |
| cmd.addArgument("--verbose"); |
| verboseOutput[0] = cmd.execute().getOutput(); |
| }); |
| |
| TKit.assertTrue(nonVerboseOutput.size() < verboseOutput[0].size(), |
| "Check verbose output is longer than regular"); |
| |
| expectedVerboseOutputStrings.forEach(str -> { |
| TKit.assertTextStream(str).label("regular output") |
| .predicate(String::contains).negate() |
| .apply(nonVerboseOutput.stream()); |
| }); |
| |
| expectedVerboseOutputStrings.forEach(str -> { |
| TKit.assertTextStream(str).label("verbose output") |
| .apply(verboseOutput[0].stream()); |
| }); |
| } |
| |
| @Test |
| public void testNoName() { |
| final String mainClassName = "Greetings"; |
| |
| JPackageCommand cmd = JPackageCommand.helloAppImage(mainClassName) |
| .removeArgumentWithValue("--name"); |
| |
| Path expectedImageDir = cmd.outputDir().resolve(mainClassName); |
| if (TKit.isOSX()) { |
| expectedImageDir = expectedImageDir.getParent().resolve( |
| expectedImageDir.getFileName().toString() + ".app"); |
| } |
| |
| cmd.executeAndAssertHelloAppImageCreated(); |
| TKit.assertEquals(expectedImageDir.toAbsolutePath().normalize().toString(), |
| cmd.outputBundle().toAbsolutePath().normalize().toString(), |
| String.format( |
| "Check [%s] directory is filled with application image data", |
| expectedImageDir)); |
| } |
| |
| @Test |
| // Regular app |
| @Parameter("Hello") |
| // Modular app in .jar file |
| @Parameter("com.other/com.other.Hello") |
| // Modular app in .jmod file |
| @Parameter("hello.jmod:com.other/com.other.Hello") |
| public void testApp(String javaAppDesc) { |
| JavaAppDesc appDesc = JavaAppDesc.parse(javaAppDesc); |
| JPackageCommand cmd = JPackageCommand.helloAppImage(appDesc); |
| if (appDesc.jmodFileName() != null) { |
| // .jmod files are not supported at run-time. They should be |
| // bundled in Java run-time with jlink command, so disable |
| // use of external Java run-time if any configured. |
| cmd.ignoreDefaultRuntime(true); |
| } |
| cmd.executeAndAssertHelloAppImageCreated(); |
| } |
| |
| @Test |
| public void testWhitespaceInPaths() { |
| JPackageCommand.helloAppImage("a/b c.jar:Hello") |
| .setArgumentValue("--input", TKit.workDir().resolve("The quick brown fox")) |
| .setArgumentValue("--dest", TKit.workDir().resolve("jumps over the lazy dog")) |
| .executeAndAssertHelloAppImageCreated(); |
| } |
| |
| @Test |
| @Parameter("ALL-MODULE-PATH") |
| @Parameter("ALL-DEFAULT") |
| @Parameter("java.desktop") |
| @Parameter("java.desktop,jdk.jartool") |
| @Parameter({ "java.desktop", "jdk.jartool" }) |
| public void testAddModules(String... addModulesArg) { |
| JPackageCommand cmd = JPackageCommand |
| .helloAppImage("goodbye.jar:com.other/com.other.Hello") |
| .ignoreDefaultRuntime(true); // because of --add-modules |
| Stream.of(addModulesArg).map(v -> Stream.of("--add-modules", v)).flatMap( |
| s -> s).forEachOrdered(cmd::addArgument); |
| cmd.executeAndAssertHelloAppImageCreated(); |
| } |
| |
| /** |
| * Test --temp option. Doesn't make much sense for app image as temporary |
| * directory is used only on Windows. Test it in packaging mode. |
| * @throws IOException |
| */ |
| @Test |
| public void testTemp() throws IOException { |
| final Path tempRoot = TKit.createTempDirectory("temp-root"); |
| |
| Function<JPackageCommand, Path> getTempDir = cmd -> { |
| return tempRoot.resolve(cmd.outputBundle().getFileName()); |
| }; |
| |
| Supplier<PackageTest> createTest = () -> { |
| return new PackageTest() |
| .configureHelloApp() |
| // Force save of package bundle in test work directory. |
| .addInitializer(JPackageCommand::setDefaultInputOutput) |
| .addInitializer(cmd -> { |
| Path tempDir = getTempDir.apply(cmd); |
| Files.createDirectories(tempDir); |
| cmd.addArguments("--temp", tempDir); |
| }); |
| }; |
| |
| createTest.get() |
| .addBundleVerifier(cmd -> { |
| // Check jpackage actually used the supplied directory. |
| Path tempDir = getTempDir.apply(cmd); |
| TKit.assertNotEquals(0, tempDir.toFile().list().length, |
| String.format( |
| "Check jpackage wrote some data in the supplied temporary directory [%s]", |
| tempDir)); |
| }) |
| .run(PackageTest.Action.CREATE); |
| |
| createTest.get() |
| // Temporary directory should not be empty, |
| // jpackage should exit with error. |
| .setExpectedExitCode(1) |
| .run(PackageTest.Action.CREATE); |
| } |
| |
| @Test |
| public void testAtFile() throws IOException { |
| JPackageCommand cmd = JPackageCommand |
| .helloAppImage() |
| .setArgumentValue("--dest", TKit.createTempDirectory("output")); |
| |
| // Init options file with the list of options configured |
| // for JPackageCommand instance. |
| final Path optionsFile = TKit.createTempFile(Path.of("options")); |
| Files.write(optionsFile, |
| List.of(String.join(" ", cmd.getAllArguments()))); |
| |
| // Build app jar file. |
| cmd.executePrerequisiteActions(); |
| |
| // Instead of running jpackage command through configured |
| // JPackageCommand instance, run vanilla jpackage command with @ file. |
| getJPackageToolProvider() |
| .addArgument(String.format("@%s", optionsFile)) |
| .execute(); |
| |
| // Verify output of jpackage command. |
| cmd.assertImageCreated(); |
| HelloApp.executeLauncherAndVerifyOutput(cmd); |
| } |
| |
| @Parameter("Hello") |
| @Parameter("com.foo/com.foo.main.Aloha") |
| @Test |
| public void testJLinkRuntime(String javaAppDesc) throws IOException { |
| JavaAppDesc appDesc = JavaAppDesc.parse(javaAppDesc); |
| |
| JPackageCommand cmd = JPackageCommand.helloAppImage(appDesc); |
| |
| final String moduleName = appDesc.moduleName(); |
| |
| if (moduleName != null) { |
| // Build module jar. |
| cmd.executePrerequisiteActions(); |
| } |
| |
| final Path runtimeDir = TKit.createTempDirectory("runtime").resolve("data"); |
| |
| // List of modules required for test app. |
| final var modules = new String[] { |
| "java.base", |
| "java.desktop" |
| }; |
| |
| Executor jlink = getToolProvider(JavaTool.JLINK) |
| .saveOutput(false) |
| .addArguments( |
| "--add-modules", String.join(",", modules), |
| "--output", runtimeDir.toString(), |
| "--strip-debug", |
| "--no-header-files", |
| "--no-man-pages"); |
| |
| TKit.trace("jlink output BEGIN"); |
| try (Stream<Path> paths = Files.walk(runtimeDir)) { |
| paths.filter(Files::isRegularFile) |
| .map(runtimeDir::relativize) |
| .map(Path::toString) |
| .forEach(TKit::trace); |
| } |
| TKit.trace("jlink output END"); |
| |
| if (moduleName != null) { |
| jlink.addArguments("--add-modules", moduleName, "--module-path", |
| Path.of(cmd.getArgumentValue("--module-path")).resolve( |
| "hello.jar").toString()); |
| } |
| |
| jlink.execute(); |
| |
| cmd.addArguments("--runtime-image", runtimeDir); |
| cmd.executeAndAssertHelloAppImageCreated(); |
| } |
| |
| private static Executor getJPackageToolProvider() { |
| return getToolProvider(JavaTool.JPACKAGE); |
| } |
| |
| private static Executor getToolProvider(JavaTool tool) { |
| return new Executor().dumpOutput().saveOutput().setToolProvider(tool); |
| } |
| } |