test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java
branchJDK-8200758-branch
changeset 58113 885b0543f6e4
parent 58036 f7f10023f7c0
child 58114 42df7de58e39
--- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	Fri Sep 06 17:42:06 2019 -0400
+++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java	Tue Sep 10 09:18:19 2019 -0400
@@ -22,17 +22,17 @@
  */
 package jdk.jpackage.test;
 
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
 import java.util.function.Function;
 import java.util.function.Supplier;
+import java.util.stream.Stream;
 
 /**
  * jpackage command line with prerequisite actions. Prerequisite actions can be
@@ -53,6 +53,8 @@
     }
 
     public void setArgumentValue(String argName, String newValue) {
+        verifyMutable();
+
         String prevArg = null;
         ListIterator<String> it = args.listIterator();
         while (it.hasNext()) {
@@ -75,8 +77,12 @@
         }
     }
 
+    public boolean hasArgument(String argName) {
+        return args.contains(argName);
+    }
+
     public <T> T getArgumentValue(String argName,
-            Supplier<T> defaultValueSupplier,
+            Function<JPackageCommand, T> defaultValueSupplier,
             Function<String, T> stringConverter) {
         String prevArg = null;
         for (String arg : args) {
@@ -86,15 +92,42 @@
             prevArg = arg;
         }
         if (defaultValueSupplier != null) {
-            return defaultValueSupplier.get();
+            return defaultValueSupplier.apply(this);
         }
         return null;
     }
 
     public String getArgumentValue(String argName,
+            Function<JPackageCommand, String> defaultValueSupplier) {
+        return getArgumentValue(argName, defaultValueSupplier, v -> v);
+    }
+
+    public <T> T getArgumentValue(String argName,
+            Supplier<T> defaultValueSupplier,
+            Function<String, T> stringConverter) {
+        return getArgumentValue(argName, (unused) -> defaultValueSupplier.get(),
+                stringConverter);
+    }
+
+    public String getArgumentValue(String argName,
             Supplier<String> defaultValueSupplier) {
-        return getArgumentValue(argName, defaultValueSupplier,
-                (v) -> v);
+        return getArgumentValue(argName, defaultValueSupplier, v -> v);
+    }
+
+    public String getArgumentValue(String argName) {
+        return getArgumentValue(argName, (Supplier<String>)null);
+    }
+
+    public String[] getAllArgumentValues(String argName) {
+        List<String> values = new ArrayList<>();
+        String prevArg = null;
+        for (String arg : args) {
+            if (prevArg != null && prevArg.equals(argName)) {
+                values.add(arg);
+            }
+            prevArg = arg;
+        }
+        return values.toArray(String[]::new);
     }
 
     public PackageType packageType() {
@@ -104,24 +137,23 @@
     }
 
     public Path outputDir() {
-        return getArgumentValue("--output",
-                () -> Test.defaultOutputDir(),
-                (v) -> Path.of(v));
+        return getArgumentValue("--output", () -> Test.defaultOutputDir(), Path::of);
     }
 
     public Path inputDir() {
-        return getArgumentValue("--input",
-                () -> Test.defaultInputDir(),
-                (v) -> Path.of(v));
+        return getArgumentValue("--input", () -> Test.defaultInputDir(),Path::of);
     }
 
     public String version() {
-        return getArgumentValue("--version", () -> "1.0");
+        return getArgumentValue("--app-version", () -> "1.0");
     }
 
     public String name() {
-        return getArgumentValue("--name",
-                () -> getArgumentValue("--main-class", null));
+        return getArgumentValue("--name", () -> getArgumentValue("--main-class"));
+    }
+
+    public boolean isRuntime() {
+        return getArgumentValue("--runtime-image", () -> false, v -> true);
     }
 
     public JPackageCommand setDefaultInputOutput() {
@@ -131,48 +163,157 @@
         return this;
     }
 
-    public JPackageCommand setHelloApp() {
+    JPackageCommand addAction(Runnable action) {
         verifyMutable();
-        actions.add(new Runnable() {
-            @Override
-            public void run() {
-                String mainClass = "Hello";
-                Path jar = inputDir().resolve("hello.jar");
-                new JarBuilder()
-                        .setOutputJar(jar.toFile())
-                        .setMainClass(mainClass)
-                        .addSourceFile(Test.TEST_SRC_ROOT.resolve(
-                                Path.of("apps", "image", mainClass + ".java")))
-                        .create();
-                addArguments("--main-jar", jar.getFileName().toString());
-                addArguments("--main-class", mainClass);
-            }
-        });
+        actions.add(action);
         return this;
     }
 
+    public static JPackageCommand helloAppImage() {
+        JPackageCommand cmd = new JPackageCommand();
+        cmd.setDefaultInputOutput().setDefaultAppName();
+        HelloApp.addTo(cmd);
+        return cmd;
+    }
+
     public JPackageCommand setPackageType(PackageType type) {
         verifyMutable();
         type.applyTo(this);
         return this;
     }
 
+    JPackageCommand setDefaultAppName() {
+        StackTraceElement st[] = Thread.currentThread().getStackTrace();
+        for (StackTraceElement ste : st) {
+            if ("main".equals(ste.getMethodName())) {
+                String name = ste.getClassName();
+                name = Stream.of(name.split("[.$]")).reduce((f, l) -> l).get();
+                addArguments("--name", name);
+                break;
+            }
+        }
+        return this;
+    }
+
     public Path outputBundle() {
-        switch (packageType()) {
-            case LINUX_RPM:
-            case LINUX_DEB:
-                return outputDir().resolve(LinuxHelper.getBundleName(this));
+        final PackageType type = packageType();
+        if (PackageType.IMAGE == type) {
+            return null;
+        }
+
+        String bundleName = null;
+        if (PackageType.LINUX.contains(type)) {
+            bundleName = LinuxHelper.getBundleName(this);
+        } else if (PackageType.WINDOWS.contains(type)) {
+            bundleName = WindowsHelper.getBundleName(this);
+        } else if (PackageType.MAC.contains(type)) {
+            bundleName = MacHelper.getBundleName(this);
         }
-        return null;
+
+        return outputDir().resolve(bundleName);
+    }
+
+    /**
+     * Returns path to directory where application will be installed.
+     *
+     * E.g. on Linux for app named Foo default the function will return
+     * `/opt/foo`
+     */
+    public Path appInstallationDirectory() {
+        final PackageType type = packageType();
+        if (PackageType.IMAGE == type) {
+            return null;
+        }
+
+        if (PackageType.LINUX.contains(type)) {
+            // Launcher is in "bin" subfolder of the installation directory.
+            return launcherInstallationPath().getParent().getParent();
+        }
+
+        if (PackageType.WINDOWS.contains(type)) {
+            return WindowsHelper.getInstallationDirectory(this);
+        }
+
+        if (PackageType.MAC.contains(type)) {
+            return MacHelper.getInstallationDirectory(this);
+        }
+
+        throw new IllegalArgumentException("Unexpected package type");
     }
 
+    /**
+     * Returns path where application launcher will be installed.
+     * If the command will package Java run-time only, still returns path to
+     * application launcher.
+     *
+     * E.g. on Linux for app named Foo default the function will return
+     * `/opt/foo/bin/Foo`
+     */
     public Path launcherInstallationPath() {
-        switch (packageType()) {
-            case LINUX_RPM:
-            case LINUX_DEB:
-                return LinuxHelper.getLauncherPath(this);
+        final PackageType type = packageType();
+        if (PackageType.IMAGE == type) {
+            return null;
+        }
+
+        if (PackageType.LINUX.contains(type)) {
+            return outputDir().resolve(LinuxHelper.getLauncherPath(this));
+        }
+
+        if (PackageType.WINDOWS.contains(type)) {
+            return appInstallationDirectory().resolve(name() + ".exe");
+        }
+
+        if (PackageType.MAC.contains(type)) {
+            return appInstallationDirectory().resolve(Path.of("Contents", "MacOS", name()));
         }
-        return null;
+
+        throw new IllegalArgumentException("Unexpected package type");
+    }
+
+    /**
+     * Returns path to application image directory.
+     *
+     * E.g. if --output is set to `foo` and --name is set to `bar` the function
+     * will return `foo/bar` path.
+     *
+     * @throws IllegalArgumentException is command is doing platform packaging
+     */
+    public Path appImage() {
+        final PackageType type = packageType();
+        if (PackageType.IMAGE != type) {
+            throw new IllegalArgumentException("Unexpected package type");
+        }
+
+        return outputDir().resolve(name());
+    }
+
+    /**
+     * Returns path to application launcher relative to image directory.
+     *
+     * E.g. if --name is set to `Foo` the function will return `bin/Foo` path on
+     * Linux, and `Foo.exe` on Windows.
+     *
+     * @throws IllegalArgumentException is command is doing platform packaging
+     */
+    public Path launcherPathInAppImage() {
+        final PackageType type = packageType();
+        if (PackageType.IMAGE != type) {
+            throw new IllegalArgumentException("Unexpected package type");
+        }
+
+        if (Test.isLinux()) {
+            return Path.of("bin", name());
+        }
+
+        if (Test.isOSX()) {
+            return Path.of("Contents", "MacOS", name());
+        }
+
+        if (Test.isWindows()) {
+            return Path.of(name() + ".exe");
+        }
+
+        throw new IllegalArgumentException("Unexpected package type");
     }
 
     public Executor.Result execute() {
@@ -186,34 +327,21 @@
                 .execute();
     }
 
-    static void verifyHelloApp(Path helloAppLauncher) {
-        File outputFile = Test.workDir().resolve("appOutput.txt").toFile();
-        new Executor()
-                .setDirectory(outputFile.getParentFile().toPath())
-                .setExecutable(helloAppLauncher.toString())
-                .execute()
-                .assertExitCodeIsZero();
-
-        Test.assertTrue(outputFile.exists(), String.format(
-                "Check file [%s] exists", outputFile));
+    String getPrintableCommandLine() {
+        return new Executor()
+                .setExecutable(JavaTool.JPACKAGE)
+                .addArguments(args)
+                .getPrintableCommandLine();
+    }
 
-        List<String> output = null;
-        try {
-            output = Files.readAllLines(outputFile.toPath());
-        } catch (IOException ex) {
-            throw new RuntimeException(ex);
-        }
-        Test.assertEquals(2, output.size(), String.format(
-                "Check file [%s] contains %d text lines", outputFile, 2));
+    void verifyIsOfType(Collection<PackageType> types) {
+        verifyIsOfType(types.toArray(PackageType[]::new));
+    }
 
-        Test.assertEquals("jpackage test application", output.get(0),
-                String.format(
-                        "Check contents of the first text line in [%s] file",
-                        outputFile));
-
-        Test.assertEquals("args.length: 0", output.get(1), String.format(
-                "Check contents of the second text line in [%s] file",
-                outputFile));
+    void verifyIsOfType(PackageType ... types) {
+        if (!Arrays.asList(types).contains(packageType())) {
+            throw new IllegalArgumentException("Unexpected package type");
+        }
     }
 
     @Override
@@ -229,7 +357,7 @@
                 @Override
                 public Map<String, PackageType> get() {
                     Map<String, PackageType> reply = new HashMap<>();
-                    for (PackageType type : PackageType.values()) {
+                    for (PackageType type : PackageType.NATIVE) {
                         reply.put(type.getName(), type);
                     }
                     return reply;