< prev index next >

test/jdk/tools/jpackage/share/IconTest.java

Print this page

        

@@ -20,74 +20,416 @@
  * or visit www.oracle.com if you need additional information or have any
  * questions.
  */
 
 import java.io.IOException;
+import java.util.*;
+import java.util.stream.Stream;
+import java.util.stream.Collectors;
+import java.util.function.Consumer;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.StandardCopyOption;
-import jdk.incubator.jpackage.internal.IOUtils;
-import jdk.jpackage.test.TKit;
-import jdk.jpackage.test.Functional;
+import jdk.jpackage.test.*;
+import jdk.jpackage.test.Functional.ThrowingConsumer;
+import jdk.jpackage.test.Functional.ThrowingBiConsumer;
 import jdk.jpackage.test.Annotations.*;
-import jdk.jpackage.test.JPackageCommand;
 
 /*
  * @test
- * @summary jpackage create image with custom icon
+ * @summary jpackage create image and package with custom icons for the main and additional launcher
  * @library ../helpers
  * @build jdk.jpackage.test.*
  * @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
  * @compile IconTest.java
- * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
+ * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
  *  --jpt-run=IconTest
  */
 
 public class IconTest {
-    @Test
-    public static void testResourceDir() throws IOException {
-        TKit.withTempDirectory("resources", tempDir -> {
-            JPackageCommand cmd = JPackageCommand.helloAppImage()
-                    .addArguments("--resource-dir", tempDir);
 
-            Files.copy(GOLDEN_ICON, tempDir.resolve(appIconFileName(cmd)),
-                    StandardCopyOption.REPLACE_EXISTING);
+    enum IconType {
+        /**
+         * Icon not specified.
+         */
+        DefaultIcon,
 
-            testIt(cmd);
-        });
+        /**
+         * Explicit no icon.
+         */
+        NoIcon,
+
+        /**
+         * Custom icon on command line.
+         */
+        CustomIcon,
+
+        /**
+         * Custom icon in resource dir.
+         */
+        ResourceDirIcon,
+
+        /**
+         * Custom icon on command line and in resource dir.
+         */
+        CustomWithResourceDirIcon
+    }
+
+    enum BundleType { AppImage, Package }
+
+    public IconTest(BundleType bundleType, IconType mainLauncherIconType,
+            IconType additionalLauncherIconType, String[] extraJPackageArgs) {
+        this.appImage = (bundleType == BundleType.AppImage);
+        this.extraJPackageArgs = extraJPackageArgs;
+        config = Map.of(
+                Launcher.Main, mainLauncherIconType,
+                Launcher.Additional, additionalLauncherIconType);
+    }
+
+    public IconTest(BundleType bundleType, IconType mainLauncherIconType,
+            IconType additionalLauncherIconType) {
+        this.appImage = (bundleType == BundleType.AppImage);
+        this.extraJPackageArgs = new String[0];
+        config = Map.of(
+                Launcher.Main, mainLauncherIconType,
+                Launcher.Additional, additionalLauncherIconType);
+    }
+
+    public IconTest(BundleType bundleType, IconType mainLauncherIconType) {
+        this.appImage = (bundleType == BundleType.AppImage);
+        this.extraJPackageArgs = new String[0];
+        config = Map.of(Launcher.Main, mainLauncherIconType);
+    }
+
+    @Parameters
+    public static Collection data() {
+        List<Object[]> data = new ArrayList<>();
+
+        var withLinuxShortcut = Set.of(IconType.DefaultIcon, IconType.NoIcon);
+
+        for (var bundleType : BundleType.values()) {
+            if (TKit.isWindows() && bundleType == BundleType.Package) {
+                // On Windows icons are embedded in launcher executables in
+                // application image. Nothing is changed when app image is
+                // packed in msi/exe package bundle, so skip testing of package
+                // bundle.
+                continue;
+            }
+            for (var mainLauncherIconType : IconType.values()) {
+                if (mainLauncherIconType == IconType.NoIcon) {
+                    // `No icon` setting is not applicable for the main launcher.
+                    continue;
+                }
+
+                if (TKit.isOSX()) {
+                    // Custom icons not supported for additional launchers on Mac.
+                    data.add(new Object[]{bundleType, mainLauncherIconType});
+                    continue;
+                }
+
+                for (var additionalLauncherIconType : IconType.values()) {
+                    data.add(new Object[]{bundleType, mainLauncherIconType,
+                        additionalLauncherIconType});
+
+                    if (TKit.isLinux() && bundleType == BundleType.Package
+                            && withLinuxShortcut.contains(mainLauncherIconType)
+                            && withLinuxShortcut.contains(
+                                    additionalLauncherIconType)) {
+                        data.add(new Object[]{bundleType, mainLauncherIconType,
+                            additionalLauncherIconType, new String[]{
+                            "--linux-shortcut"}});
+                    }
+                }
+            }
+        }
+        return data;
     }
 
     @Test
-    @Parameter("true")
-    @Parameter("false")
-    public static void testParameter(boolean relativePath) throws IOException {
-        final Path iconPath;
-        if (relativePath) {
-            iconPath = TKit.createRelativePathCopy(GOLDEN_ICON);
+    public void test() throws IOException {
+        if (appImage) {
+            JPackageCommand cmd = initAppImageTest();
+            var result = cmd.executeAndAssertImageCreated();
+            ThrowingConsumer.toConsumer(createInstallVerifier()).accept(cmd);
+            ThrowingBiConsumer.toBiConsumer(createBundleVerifier()).accept(cmd, result);
+        } else {
+            PackageTest test = initPackageTest();
+            test.addInstallVerifier(createInstallVerifier());
+            test.addBundleVerifier(createBundleVerifier());
+
+            test.addBundleDesktopIntegrationVerifier(config.values().stream()
+                    .anyMatch(this::isWithDesktopIntegration));
+
+            test.run(PackageTest.Action.CREATE_AND_UNPACK);
+        }
+    }
+
+    boolean isWithDesktopIntegration(IconType iconType) {
+        if (appImage) {
+            return false;
+        }
+        boolean withDesktopFile = !Set.of(
+                IconType.NoIcon,
+                IconType.DefaultIcon).contains(iconType);
+        withDesktopFile |= List.of(extraJPackageArgs).contains("--linux-shortcut");
+        return withDesktopFile;
+    }
+
+    private ThrowingBiConsumer<JPackageCommand, Executor.Result> createBundleVerifier() {
+        return (cmd, result) -> {
+            var verifier = createConsoleOutputVerifier(cmd.name(), config.get(
+                    Launcher.Main), null);
+            if (verifier != null) {
+                verifier.apply(result.getOutput().stream());
+            }
+
+            if (config.containsKey(Launcher.Additional)) {
+                verifier = createConsoleOutputVerifier(
+                        Launcher.Additional.launcherName, config.get(
+                                Launcher.Additional), config.get(Launcher.Main));
+                if (verifier != null) {
+                    verifier.apply(result.getOutput().stream());
+                }
+            }
+        };
+    }
+
+    private TKit.TextStreamVerifier createConsoleOutputVerifier(
+            String launcherName, IconType iconType, IconType mainIconType) {
+        if (iconType == IconType.DefaultIcon && mainIconType != null) {
+            iconType = mainIconType;
+        }
+        return createConsoleOutputVerifier(launcherName, iconType);
+    }
+
+    private static TKit.TextStreamVerifier createConsoleOutputVerifier(
+            String launcherName, IconType iconType) {
+        String lookupString = null;
+        switch (iconType) {
+            case DefaultIcon:
+                lookupString = String.format(
+                        "Using default package resource %s [icon] (add %s%s to the resource-dir to customize)",
+                        LauncherIconVerifier.getDefaultIcon().getFileName(),
+                        launcherName, TKit.ICON_SUFFIX);
+                break;
+
+            case ResourceDirIcon:
+                lookupString = String.format(
+                        "Using custom package resource [icon] (loaded from %s%s)",
+                        launcherName, TKit.ICON_SUFFIX);
+                break;
+
+            case CustomIcon:
+            case CustomWithResourceDirIcon:
+                lookupString = "Using custom package resource [icon] (loaded from file";
+                break;
+
+            default:
+                return null;
+        }
+
+        return TKit.assertTextStream(lookupString);
+    }
+
+    private ThrowingConsumer<JPackageCommand> createInstallVerifier() {
+        LauncherIconVerifier verifier = new LauncherIconVerifier();
+        switch (config.get(Launcher.Main)) {
+            case NoIcon:
+                verifier.setExpectedIcon(null);
+                break;
+
+            case DefaultIcon:
+                verifier.setExpectedDefaultIcon();
+                break;
+
+            case CustomIcon:
+                verifier.setExpectedIcon(Launcher.Main.cmdlineIcon);
+                break;
+
+            case ResourceDirIcon:
+                verifier.setExpectedIcon(Launcher.Main.resourceDirIcon);
+                break;
+
+            case CustomWithResourceDirIcon:
+                verifier.setExpectedIcon(Launcher.Main2.cmdlineIcon);
+                break;
+        }
+
+        return cmd -> {
+            verifier.applyTo(cmd);
+            if (TKit.isLinux() && !cmd.isImagePackageType()) {
+                Path desktopFile = LinuxHelper.getDesktopFile(cmd);
+                if (isWithDesktopIntegration(config.get(Launcher.Main))) {
+                    TKit.assertFileExists(desktopFile);
         } else {
-            iconPath = GOLDEN_ICON;
+                    TKit.assertPathExists(desktopFile, false);
+                }
+            }
+        };
         }
 
-        testIt(JPackageCommand.helloAppImage().addArguments("--icon", iconPath));
+    private void initTest(JPackageCommand cmd, PackageTest test) {
+        config.entrySet().forEach(ThrowingConsumer.toConsumer(entry -> {
+            initTest(entry.getKey(), entry.getValue(), cmd, test);
+        }));
+
+        ThrowingConsumer<JPackageCommand> initializer = testCmd -> {
+            testCmd.saveConsoleOutput(true);
+            testCmd.setFakeRuntime();
+            testCmd.addArguments(extraJPackageArgs);
+        };
+
+        if (test != null) {
+            test.addInitializer(initializer);
+        } else {
+            ThrowingConsumer.toConsumer(initializer).accept(cmd);
+        }
     }
 
-    private static String appIconFileName(JPackageCommand cmd) {
-        return IOUtils.replaceSuffix(cmd.appLauncherPath().getFileName(),
-                TKit.ICON_SUFFIX).toString();
+    private static void initTest(Launcher cfg, IconType iconType,
+            JPackageCommand cmd, PackageTest test) throws IOException {
+        Consumer<AdditionalLauncher> addLauncher = v -> {
+            if (test != null) {
+                v.applyTo(test);
+            } else {
+                v.applyTo(cmd);
     }
+        };
 
-    private static void testIt(JPackageCommand cmd) throws IOException {
-        cmd.executeAndAssertHelloAppImageCreated();
+        switch (iconType) {
+            case DefaultIcon:
+                if (cfg.launcherName != null) {
+                    addLauncher.accept(new AdditionalLauncher(cfg.launcherName));
+                }
+                break;
 
-        Path iconPath = cmd.appLayout().destktopIntegrationDirectory().resolve(
-                appIconFileName(cmd));
+            case NoIcon:
+                if (cfg.launcherName != null) {
+                    addLauncher.accept(
+                            new AdditionalLauncher(cfg.launcherName).setNoIcon());
+                }
+                break;
+
+            case CustomIcon:
+                if (test != null) {
+                    addCustomIcon(null, test, cfg.launcherName, cfg.cmdlineIcon);
+                } else {
+                    addCustomIcon(cmd, null, cfg.launcherName, cfg.cmdlineIcon);
+                }
+                break;
+
+            case ResourceDirIcon:
+                if (Launcher.PRIMARY.contains(cfg) && cfg.launcherName != null) {
+                    addLauncher.accept(new AdditionalLauncher(cfg.launcherName));
+                }
+                if (test != null) {
+                    test.addInitializer(testCmd -> {
+                        addResourceDirIcon(testCmd, cfg.launcherName,
+                                cfg.resourceDirIcon);
+                    });
+                } else {
+                    addResourceDirIcon(cmd, cfg.launcherName, cfg.resourceDirIcon);
+                }
+                break;
+
+            case CustomWithResourceDirIcon:
+                switch (cfg) {
+                    case Main:
+                        initTest(Launcher.Main2, IconType.CustomIcon, cmd, test);
+                        initTest(Launcher.Main2, IconType.ResourceDirIcon, cmd, test);
+                        break;
+
+                    case Additional:
+                        initTest(Launcher.Additional2, IconType.CustomIcon, cmd, test);
+                        initTest(Launcher.Additional2, IconType.ResourceDirIcon, cmd, test);
+                        break;
+
+                    default:
+                        throw new IllegalArgumentException();
+                }
+                break;
+        }
+    }
+
+    private JPackageCommand initAppImageTest() {
+        JPackageCommand cmd = JPackageCommand.helloAppImage();
+        initTest(cmd, null);
+        return cmd;
+    }
+
+    private PackageTest initPackageTest() {
+        PackageTest test = new PackageTest().configureHelloApp();
+        initTest(null, test);
+        return test;
+    }
+
+    private static void addResourceDirIcon(JPackageCommand cmd,
+            String launcherName, Path iconPath) throws IOException {
+        Path resourceDir = cmd.getArgumentValue("--resource-dir", () -> null,
+                Path::of);
+        if (resourceDir == null) {
+            resourceDir = TKit.createTempDirectory("resources");
+            cmd.addArguments("--resource-dir", resourceDir);
+        }
+
+        String dstIconFileName = Optional.ofNullable(launcherName).orElseGet(
+                () -> cmd.name()) + TKit.ICON_SUFFIX;
+
+        TKit.trace(String.format("Resource file: [%s] <- [%s]",
+                resourceDir.resolve(dstIconFileName), iconPath));
+        Files.copy(iconPath, resourceDir.resolve(dstIconFileName),
+                StandardCopyOption.REPLACE_EXISTING);
+    }
+
+    private static void addCustomIcon(JPackageCommand cmd, PackageTest test,
+            String launcherName, Path iconPath) throws IOException {
+
+        if (launcherName != null) {
+            AdditionalLauncher al = new AdditionalLauncher(launcherName).setIcon(
+                    iconPath);
+            if (test != null) {
+                al.applyTo(test);
+            } else {
+                al.applyTo(cmd);
+            }
+        } else if (test != null) {
+            test.addInitializer(testCmd -> {
+                testCmd.addArguments("--icon", iconPath);
+            });
+        } else {
+            cmd.addArguments("--icon", iconPath);
+        }
+    }
+
+    private enum Launcher {
+        Main(null, ICONS[0], ICONS[1]),
+        Main2(null, ICONS[1], ICONS[0]),
+        Additional("x", ICONS[2], ICONS[3]),
+        Additional2("x", ICONS[3], ICONS[2]);
+
+        Launcher(String name, Path cmdlineIcon, Path resourceDirIcon) {
+            this.launcherName = name;
+            this.cmdlineIcon = cmdlineIcon;
+            this.resourceDirIcon = resourceDirIcon;
+        }
+
+        private final String launcherName;
+        private final Path cmdlineIcon;
+        private final Path resourceDirIcon;
+
+        private final static Set<Launcher> PRIMARY = Set.of(Main, Additional);
+    }
 
-        TKit.assertFileExists(iconPath);
-        TKit.assertTrue(-1 == Files.mismatch(GOLDEN_ICON, iconPath),
-                String.format(
-                        "Check application icon file [%s] is a copy of source icon file [%s]",
-                        iconPath, GOLDEN_ICON));
+    private final boolean appImage;
+    private final Map<Launcher, IconType> config;
+    private final String[] extraJPackageArgs;
+
+    private static Path iconPath(String name) {
+        return TKit.TEST_SRC_ROOT.resolve(Path.of("resources", name
+                + TKit.ICON_SUFFIX));
     }
 
-    private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
-            "resources", "icon" + TKit.ICON_SUFFIX));
+    private final static Path[] ICONS = Stream.of("icon", "icon2", "icon3",
+            "icon4")
+            .map(IconTest::iconPath)
+            .collect(Collectors.toList()).toArray(Path[]::new);
 }
< prev index next >