/* * Copyright (c) 2019, 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 output = getJPackageToolProvider().executeAndGetOutput(); TKit.assertStringListEquals(List.of("Usage: jpackage ", "Use jpackage --help (or -h) for a list of possible options"), output, "Check jpackage output"); } @Test public void testVersion() { List output = getJPackageToolProvider() .addArgument("--version") .executeAndGetOutput(); TKit.assertStringListEquals(List.of(System.getProperty("java.version")), output, "Check jpackage output"); } @Test public void testHelp() { List hOutput = getJPackageToolProvider() .addArgument("-h").executeAndGetOutput(); List 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 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> createPattern = (prefix) -> { return Pattern.compile("^ " + prefix).asPredicate(); }; Function, 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 expectedVerboseOutputStrings = new ArrayList<>(); expectedVerboseOutputStrings.add("Creating app package:"); if (TKit.isWindows()) { expectedVerboseOutputStrings.add("Result application bundle:"); 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 nonVerboseOutput = cmd.execute().getOutput(); List[] verboseOutput = (List[])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"); 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 getTempDir = cmd -> { return tempRoot.resolve(cmd.outputBundle().getFileName()); }; Supplier 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() .addInitializer(cmd -> { // Clean output from the previus jpackage run. Files.delete(cmd.outputBundle()); }) // 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"); 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); } }