Path: blob/master/test/jdk/tools/jpackage/share/IconTest.java
41152 views
/*1* Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223import java.io.IOException;24import java.util.stream.Stream;25import java.util.stream.Collectors;26import java.util.function.Consumer;27import java.nio.file.Files;28import java.nio.file.Path;29import java.nio.file.StandardCopyOption;30import java.util.ArrayList;31import java.util.Collection;32import java.util.List;33import java.util.Map;34import java.util.Optional;35import java.util.Set;36import jdk.jpackage.test.TKit;37import jdk.jpackage.test.JPackageCommand;38import jdk.jpackage.test.LauncherIconVerifier;39import jdk.jpackage.test.PackageTest;40import jdk.jpackage.test.Executor;41import jdk.jpackage.test.LinuxHelper;42import jdk.jpackage.test.AdditionalLauncher;43import jdk.jpackage.test.Functional.ThrowingConsumer;44import jdk.jpackage.test.Functional.ThrowingBiConsumer;45import jdk.jpackage.test.Annotations.Parameters;46import jdk.jpackage.test.Annotations.Test;4748/*49* @test50* @summary jpackage create image and package with custom icons for the main and additional launcher51* @library ../helpers52* @build jdk.jpackage.test.*53* @modules jdk.jpackage/jdk.jpackage.internal54* @compile IconTest.java55* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main56* --jpt-run=IconTest57*/5859public class IconTest {6061enum IconType {62/**63* Icon not specified.64*/65DefaultIcon,6667/**68* Explicit no icon.69*/70NoIcon,7172/**73* Custom icon on command line.74*/75CustomIcon,7677/**78* Custom icon in resource dir.79*/80ResourceDirIcon,8182/**83* Custom icon on command line and in resource dir.84*/85CustomWithResourceDirIcon86}8788enum BundleType { AppImage, Package }8990public IconTest(BundleType bundleType, IconType mainLauncherIconType,91IconType additionalLauncherIconType, String[] extraJPackageArgs) {92this.appImage = (bundleType == BundleType.AppImage);93this.extraJPackageArgs = extraJPackageArgs;94config = Map.of(95Launcher.Main, mainLauncherIconType,96Launcher.Additional, additionalLauncherIconType);97}9899public IconTest(BundleType bundleType, IconType mainLauncherIconType,100IconType additionalLauncherIconType) {101this.appImage = (bundleType == BundleType.AppImage);102this.extraJPackageArgs = new String[0];103config = Map.of(104Launcher.Main, mainLauncherIconType,105Launcher.Additional, additionalLauncherIconType);106}107108public IconTest(BundleType bundleType, IconType mainLauncherIconType) {109this.appImage = (bundleType == BundleType.AppImage);110this.extraJPackageArgs = new String[0];111config = Map.of(Launcher.Main, mainLauncherIconType);112}113114@Parameters115public static Collection data() {116List<Object[]> data = new ArrayList<>();117118var withLinuxShortcut = Set.of(IconType.DefaultIcon, IconType.NoIcon);119120for (var bundleType : BundleType.values()) {121if (TKit.isWindows() && bundleType == BundleType.Package) {122// On Windows icons are embedded in launcher executables in123// application image. Nothing is changed when app image is124// packed in msi/exe package bundle, so skip testing of package125// bundle.126continue;127}128for (var mainLauncherIconType : IconType.values()) {129if (mainLauncherIconType == IconType.NoIcon) {130// `No icon` setting is not applicable for the main launcher.131continue;132}133134if (TKit.isOSX()) {135// Custom icons not supported for additional launchers on Mac.136data.add(new Object[]{bundleType, mainLauncherIconType});137continue;138}139140for (var additionalLauncherIconType : IconType.values()) {141data.add(new Object[]{bundleType, mainLauncherIconType,142additionalLauncherIconType});143144if (TKit.isLinux() && bundleType == BundleType.Package145&& withLinuxShortcut.contains(mainLauncherIconType)146&& withLinuxShortcut.contains(147additionalLauncherIconType)) {148data.add(new Object[]{bundleType, mainLauncherIconType,149additionalLauncherIconType, new String[]{150"--linux-shortcut"}});151}152}153}154}155return data;156}157158@Test159public void test() throws IOException {160if (appImage) {161JPackageCommand cmd = initAppImageTest();162var result = cmd.executeAndAssertImageCreated();163ThrowingConsumer.toConsumer(createInstallVerifier()).accept(cmd);164ThrowingBiConsumer.toBiConsumer(createBundleVerifier()).accept(cmd, result);165} else {166PackageTest test = initPackageTest();167test.addInstallVerifier(createInstallVerifier());168test.addBundleVerifier(createBundleVerifier());169170test.addBundleDesktopIntegrationVerifier(config.values().stream()171.anyMatch(this::isWithDesktopIntegration));172173test.run(PackageTest.Action.CREATE_AND_UNPACK);174}175}176177boolean isWithDesktopIntegration(IconType iconType) {178if (appImage) {179return false;180}181boolean withDesktopFile = !Set.of(182IconType.NoIcon,183IconType.DefaultIcon).contains(iconType);184withDesktopFile |= List.of(extraJPackageArgs).contains("--linux-shortcut");185return withDesktopFile;186}187188private ThrowingBiConsumer<JPackageCommand, Executor.Result> createBundleVerifier() {189return (cmd, result) -> {190var verifier = createConsoleOutputVerifier(cmd.name(), config.get(191Launcher.Main), null);192if (verifier != null) {193verifier.apply(result.getOutput().stream());194}195196if (config.containsKey(Launcher.Additional)) {197verifier = createConsoleOutputVerifier(198Launcher.Additional.launcherName, config.get(199Launcher.Additional), config.get(Launcher.Main));200if (verifier != null) {201verifier.apply(result.getOutput().stream());202}203}204};205}206207private TKit.TextStreamVerifier createConsoleOutputVerifier(208String launcherName, IconType iconType, IconType mainIconType) {209if (iconType == IconType.DefaultIcon && mainIconType != null) {210iconType = mainIconType;211}212return createConsoleOutputVerifier(launcherName, iconType);213}214215private static TKit.TextStreamVerifier createConsoleOutputVerifier(216String launcherName, IconType iconType) {217String lookupString = null;218switch (iconType) {219case DefaultIcon:220lookupString = String.format(221"Using default package resource %s [icon] (add %s%s to the resource-dir to customize)",222"JavaApp" + TKit.ICON_SUFFIX,223launcherName, TKit.ICON_SUFFIX);224break;225226case ResourceDirIcon:227lookupString = String.format(228"Using custom package resource [icon] (loaded from %s%s)",229launcherName, TKit.ICON_SUFFIX);230break;231232case CustomIcon:233case CustomWithResourceDirIcon:234lookupString = "Using custom package resource [icon] (loaded from file";235break;236237default:238return null;239}240241return TKit.assertTextStream(lookupString);242}243244private ThrowingConsumer<JPackageCommand> createInstallVerifier() {245LauncherIconVerifier verifier = new LauncherIconVerifier();246switch (config.get(Launcher.Main)) {247case NoIcon:248verifier.setExpectedIcon(null);249break;250251case DefaultIcon:252verifier.setExpectedDefaultIcon();253break;254255case CustomIcon:256verifier.setExpectedIcon(Launcher.Main.cmdlineIcon);257break;258259case ResourceDirIcon:260verifier.setExpectedIcon(Launcher.Main.resourceDirIcon);261break;262263case CustomWithResourceDirIcon:264verifier.setExpectedIcon(Launcher.Main2.cmdlineIcon);265break;266}267268return cmd -> {269verifier.applyTo(cmd);270if (TKit.isLinux() && !cmd.isImagePackageType()) {271Path desktopFile = LinuxHelper.getDesktopFile(cmd);272if (isWithDesktopIntegration(config.get(Launcher.Main))) {273TKit.assertFileExists(desktopFile);274} else {275TKit.assertPathExists(desktopFile, false);276}277}278};279}280281private void initTest(JPackageCommand cmd, PackageTest test) {282config.entrySet().forEach(ThrowingConsumer.toConsumer(entry -> {283initTest(entry.getKey(), entry.getValue(), cmd, test);284}));285286ThrowingConsumer<JPackageCommand> initializer = testCmd -> {287testCmd.saveConsoleOutput(true);288testCmd.setFakeRuntime();289testCmd.addArguments(extraJPackageArgs);290};291292if (test != null) {293test.addInitializer(initializer);294} else {295ThrowingConsumer.toConsumer(initializer).accept(cmd);296}297}298299private static void initTest(Launcher cfg, IconType iconType,300JPackageCommand cmd, PackageTest test) throws IOException {301Consumer<AdditionalLauncher> addLauncher = v -> {302if (test != null) {303v.applyTo(test);304} else {305v.applyTo(cmd);306}307};308309switch (iconType) {310case DefaultIcon:311if (cfg.launcherName != null) {312addLauncher.accept(new AdditionalLauncher(cfg.launcherName));313}314break;315316case NoIcon:317if (cfg.launcherName != null) {318addLauncher.accept(319new AdditionalLauncher(cfg.launcherName).setNoIcon());320}321break;322323case CustomIcon:324if (test != null) {325addCustomIcon(null, test, cfg.launcherName, cfg.cmdlineIcon);326} else {327addCustomIcon(cmd, null, cfg.launcherName, cfg.cmdlineIcon);328}329break;330331case ResourceDirIcon:332if (Launcher.PRIMARY.contains(cfg) && cfg.launcherName != null) {333addLauncher.accept(new AdditionalLauncher(cfg.launcherName));334}335if (test != null) {336test.addInitializer(testCmd -> {337addResourceDirIcon(testCmd, cfg.launcherName,338cfg.resourceDirIcon);339});340} else {341addResourceDirIcon(cmd, cfg.launcherName, cfg.resourceDirIcon);342}343break;344345case CustomWithResourceDirIcon:346switch (cfg) {347case Main:348initTest(Launcher.Main2, IconType.CustomIcon, cmd, test);349initTest(Launcher.Main2, IconType.ResourceDirIcon, cmd, test);350break;351352case Additional:353initTest(Launcher.Additional2, IconType.CustomIcon, cmd, test);354initTest(Launcher.Additional2, IconType.ResourceDirIcon, cmd, test);355break;356357default:358throw new IllegalArgumentException();359}360break;361}362}363364private JPackageCommand initAppImageTest() {365JPackageCommand cmd = JPackageCommand.helloAppImage();366initTest(cmd, null);367return cmd;368}369370private PackageTest initPackageTest() {371PackageTest test = new PackageTest().configureHelloApp();372initTest(null, test);373return test;374}375376private static void addResourceDirIcon(JPackageCommand cmd,377String launcherName, Path iconPath) throws IOException {378Path resourceDir = cmd.getArgumentValue("--resource-dir", () -> null,379Path::of);380if (resourceDir == null) {381resourceDir = TKit.createTempDirectory("resources");382cmd.addArguments("--resource-dir", resourceDir);383}384385String dstIconFileName = Optional.ofNullable(launcherName).orElseGet(386() -> cmd.name()) + TKit.ICON_SUFFIX;387388TKit.trace(String.format("Resource file: [%s] <- [%s]",389resourceDir.resolve(dstIconFileName), iconPath));390Files.copy(iconPath, resourceDir.resolve(dstIconFileName),391StandardCopyOption.REPLACE_EXISTING);392}393394private static void addCustomIcon(JPackageCommand cmd, PackageTest test,395String launcherName, Path iconPath) throws IOException {396397if (launcherName != null) {398AdditionalLauncher al = new AdditionalLauncher(launcherName).setIcon(399iconPath);400if (test != null) {401al.applyTo(test);402} else {403al.applyTo(cmd);404}405} else if (test != null) {406test.addInitializer(testCmd -> {407testCmd.addArguments("--icon", iconPath);408});409} else {410cmd.addArguments("--icon", iconPath);411}412}413414private enum Launcher {415Main(null, ICONS[0], ICONS[1]),416Main2(null, ICONS[1], ICONS[0]),417Additional("x", ICONS[2], ICONS[3]),418Additional2("x", ICONS[3], ICONS[2]);419420Launcher(String name, Path cmdlineIcon, Path resourceDirIcon) {421this.launcherName = name;422this.cmdlineIcon = cmdlineIcon;423this.resourceDirIcon = resourceDirIcon;424}425426private final String launcherName;427private final Path cmdlineIcon;428private final Path resourceDirIcon;429430private final static Set<Launcher> PRIMARY = Set.of(Main, Additional);431}432433private final boolean appImage;434private final Map<Launcher, IconType> config;435private final String[] extraJPackageArgs;436437private static Path iconPath(String name) {438return TKit.TEST_SRC_ROOT.resolve(Path.of("resources", name439+ TKit.ICON_SUFFIX));440}441442private final static Path[] ICONS = Stream.of("icon", "icon2", "icon3",443"icon4")444.map(IconTest::iconPath)445.collect(Collectors.toList()).toArray(Path[]::new);446}447448449