8233270: Add support to jtreg helpers to unpack packages
8230933: Default icon is not set for additional launchers Reviewed-by: herrick, prr, almatvee
This commit is contained in:
parent
0743555685
commit
14459b2ad2
@ -48,8 +48,9 @@ final class DesktopIntegration {
|
|||||||
static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
static final String DESKTOP_COMMANDS_UNINSTALL = "DESKTOP_COMMANDS_UNINSTALL";
|
||||||
static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
|
static final String UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
|
||||||
|
|
||||||
DesktopIntegration(PlatformPackage thePackage,
|
private DesktopIntegration(PlatformPackage thePackage,
|
||||||
Map<String, ? super Object> params) {
|
Map<String, ? super Object> params,
|
||||||
|
Map<String, ? super Object> mainParams) throws IOException {
|
||||||
|
|
||||||
associations = FileAssociation.fetchFrom(params).stream()
|
associations = FileAssociation.fetchFrom(params).stream()
|
||||||
.filter(fa -> !fa.mimeTypes.isEmpty())
|
.filter(fa -> !fa.mimeTypes.isEmpty())
|
||||||
@ -60,11 +61,25 @@ final class DesktopIntegration {
|
|||||||
|
|
||||||
this.thePackage = thePackage;
|
this.thePackage = thePackage;
|
||||||
|
|
||||||
final File customIconFile = ICON_PNG.fetchFrom(params);
|
// Need desktop and icon files if one of conditions is met:
|
||||||
|
// - there are file associations configured
|
||||||
|
// - user explicitely requested to create a shortcut
|
||||||
|
boolean withDesktopFile = !associations.isEmpty() || SHORTCUT_HINT.fetchFrom(params);
|
||||||
|
|
||||||
|
var curIconResource = LinuxAppImageBuilder.createIconResource(DEFAULT_ICON,
|
||||||
|
ICON_PNG, params, mainParams);
|
||||||
|
if (curIconResource == null) {
|
||||||
|
// This is additional launcher with explicit `no icon` configuration.
|
||||||
|
withDesktopFile = false;
|
||||||
|
} else {
|
||||||
|
final Path nullPath = null;
|
||||||
|
if (curIconResource.saveToFile(nullPath)
|
||||||
|
!= OverridableResource.Source.DefaultResource) {
|
||||||
|
// This launcher has custom icon configured.
|
||||||
|
withDesktopFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
iconResource = createResource(DEFAULT_ICON, params)
|
|
||||||
.setCategory(I18N.getString("resource.menu-icon"))
|
|
||||||
.setExternal(customIconFile);
|
|
||||||
desktopFileResource = createResource("template.desktop", params)
|
desktopFileResource = createResource("template.desktop", params)
|
||||||
.setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
|
.setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
|
||||||
.setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
|
.setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
|
||||||
@ -79,27 +94,42 @@ final class DesktopIntegration {
|
|||||||
|
|
||||||
mimeInfoFile = new DesktopFile(mimeInfoFileName);
|
mimeInfoFile = new DesktopFile(mimeInfoFileName);
|
||||||
|
|
||||||
if (!associations.isEmpty() || SHORTCUT_HINT.fetchFrom(params) || customIconFile != null) {
|
if (withDesktopFile) {
|
||||||
//
|
|
||||||
// Create primary .desktop file if one of conditions is met:
|
|
||||||
// - there are file associations configured
|
|
||||||
// - user explicitely requested to create a shortcut
|
|
||||||
// - custom icon specified
|
|
||||||
//
|
|
||||||
desktopFile = new DesktopFile(desktopFileName);
|
desktopFile = new DesktopFile(desktopFileName);
|
||||||
iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
|
iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
|
||||||
+ IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
|
+ IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
|
||||||
|
|
||||||
|
if (curIconResource == null) {
|
||||||
|
// Create default icon.
|
||||||
|
curIconResource = LinuxAppImageBuilder.createIconResource(
|
||||||
|
DEFAULT_ICON, ICON_PNG, mainParams, null);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
desktopFile = null;
|
desktopFile = null;
|
||||||
iconFile = null;
|
iconFile = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iconResource = curIconResource;
|
||||||
|
|
||||||
desktopFileData = Collections.unmodifiableMap(
|
desktopFileData = Collections.unmodifiableMap(
|
||||||
createDataForDesktopFile(params));
|
createDataForDesktopFile(params));
|
||||||
|
|
||||||
nestedIntegrations = launchers.stream().map(
|
nestedIntegrations = new ArrayList<>();
|
||||||
launcherParams -> new DesktopIntegration(thePackage,
|
for (var launcherParams : launchers) {
|
||||||
launcherParams)).collect(Collectors.toList());
|
launcherParams = AddLauncherArguments.merge(params, launcherParams,
|
||||||
|
ICON.getID(), ICON_PNG.getID(), ADD_LAUNCHERS.getID(),
|
||||||
|
FILE_ASSOCIATIONS.getID());
|
||||||
|
nestedIntegrations.add(new DesktopIntegration(thePackage,
|
||||||
|
launcherParams, params));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static DesktopIntegration create(PlatformPackage thePackage,
|
||||||
|
Map<String, ? super Object> params) throws IOException {
|
||||||
|
if (StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return new DesktopIntegration(thePackage, params, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<String> requiredPackages() {
|
List<String> requiredPackages() {
|
||||||
|
@ -30,10 +30,10 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.text.MessageFormat;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import static jdk.incubator.jpackage.internal.LinuxAppBundler.ICON_PNG;
|
||||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||||
|
|
||||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||||
@ -45,21 +45,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
|
|
||||||
private final ApplicationLayout appLayout;
|
private final ApplicationLayout appLayout;
|
||||||
|
|
||||||
public static final BundlerParamInfo<File> ICON_PNG =
|
|
||||||
new StandardBundlerParam<>(
|
|
||||||
"icon.png",
|
|
||||||
File.class,
|
|
||||||
params -> {
|
|
||||||
File f = ICON.fetchFrom(params);
|
|
||||||
if (f != null && !f.getName().toLowerCase().endsWith(".png")) {
|
|
||||||
Log.error(MessageFormat.format(I18N.getString(
|
|
||||||
"message.icon-not-png"), f));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
},
|
|
||||||
(s, p) -> new File(s));
|
|
||||||
|
|
||||||
private static ApplicationLayout createAppLayout(Map<String, Object> params,
|
private static ApplicationLayout createAppLayout(Map<String, Object> params,
|
||||||
Path imageOutDir) {
|
Path imageOutDir) {
|
||||||
return ApplicationLayout.linuxAppImage().resolveAt(
|
return ApplicationLayout.linuxAppImage().resolveAt(
|
||||||
@ -113,8 +98,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
@Override
|
@Override
|
||||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Map<String, ? super Object> originalParams = new HashMap<>(params);
|
|
||||||
|
|
||||||
appLayout.roots().stream().forEach(dir -> {
|
appLayout.roots().stream().forEach(dir -> {
|
||||||
try {
|
try {
|
||||||
IOUtils.writableOutputDir(dir);
|
IOUtils.writableOutputDir(dir);
|
||||||
@ -124,7 +107,7 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// create the primary launcher
|
// create the primary launcher
|
||||||
createLauncherForEntryPoint(params);
|
createLauncherForEntryPoint(params, null);
|
||||||
|
|
||||||
// Copy library to the launcher folder
|
// Copy library to the launcher folder
|
||||||
try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
|
try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
|
||||||
@ -135,23 +118,20 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
List<Map<String, ? super Object>> entryPoints
|
List<Map<String, ? super Object>> entryPoints
|
||||||
= StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
= StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
||||||
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
||||||
createLauncherForEntryPoint(
|
createLauncherForEntryPoint(AddLauncherArguments.merge(params,
|
||||||
AddLauncherArguments.merge(originalParams, entryPoint));
|
entryPoint, ICON.getID(), ICON_PNG.getID()), params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy class path entries to Java folder
|
// Copy class path entries to Java folder
|
||||||
copyApplication(params);
|
copyApplication(params);
|
||||||
|
|
||||||
// Copy icon to Resources folder
|
|
||||||
copyIcon(params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void prepareJreFiles(Map<String, ? super Object> params)
|
public void prepareJreFiles(Map<String, ? super Object> params)
|
||||||
throws IOException {}
|
throws IOException {}
|
||||||
|
|
||||||
private void createLauncherForEntryPoint(
|
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||||
Map<String, ? super Object> params) throws IOException {
|
Map<String, ? super Object> mainParams) throws IOException {
|
||||||
// Copy executable to launchers folder
|
// Copy executable to launchers folder
|
||||||
Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params));
|
Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params));
|
||||||
try (InputStream is_launcher =
|
try (InputStream is_launcher =
|
||||||
@ -163,19 +143,15 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
executableFile.toFile().setWritable(true, true);
|
executableFile.toFile().setWritable(true, true);
|
||||||
|
|
||||||
writeCfgFile(params, getLauncherCfgPath(params).toFile());
|
writeCfgFile(params, getLauncherCfgPath(params).toFile());
|
||||||
}
|
|
||||||
|
|
||||||
private void copyIcon(Map<String, ? super Object> params)
|
var iconResource = createIconResource(DEFAULT_ICON, ICON_PNG, params,
|
||||||
throws IOException {
|
mainParams);
|
||||||
|
if (iconResource != null) {
|
||||||
Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
|
Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
|
||||||
APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
|
APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
|
||||||
DEFAULT_ICON)));
|
DEFAULT_ICON)));
|
||||||
|
iconResource.saveToFile(iconTarget);
|
||||||
createResource(DEFAULT_ICON, params)
|
}
|
||||||
.setCategory("icon")
|
|
||||||
.setExternal(ICON_PNG.fetchFrom(params))
|
|
||||||
.saveToFile(iconTarget);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyApplication(Map<String, ? super Object> params)
|
private void copyApplication(Map<String, ? super Object> params)
|
||||||
|
@ -135,11 +135,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!StandardBundlerParam.isRuntimeInstaller(params)) {
|
desktopIntegration = DesktopIntegration.create(thePackage, params);
|
||||||
desktopIntegration = new DesktopIntegration(thePackage, params);
|
|
||||||
} else {
|
|
||||||
desktopIntegration = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, String> data = createDefaultReplacementData(params);
|
Map<String, String> data = createDefaultReplacementData(params);
|
||||||
if (desktopIntegration != null) {
|
if (desktopIntegration != null) {
|
||||||
|
@ -102,21 +102,6 @@ public class MacAppBundler extends AbstractImageBundler {
|
|||||||
params -> IDENTIFIER.fetchFrom(params) + ".",
|
params -> IDENTIFIER.fetchFrom(params) + ".",
|
||||||
(s, p) -> s);
|
(s, p) -> s);
|
||||||
|
|
||||||
public static final BundlerParamInfo<File> ICON_ICNS =
|
|
||||||
new StandardBundlerParam<>(
|
|
||||||
"icon.icns",
|
|
||||||
File.class,
|
|
||||||
params -> {
|
|
||||||
File f = ICON.fetchFrom(params);
|
|
||||||
if (f != null && !f.getName().toLowerCase().endsWith(".icns")) {
|
|
||||||
Log.error(MessageFormat.format(
|
|
||||||
I18N.getString("message.icon-not-icns"), f));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
},
|
|
||||||
(s, p) -> new File(s));
|
|
||||||
|
|
||||||
public static boolean validCFBundleVersion(String v) {
|
public static boolean validCFBundleVersion(String v) {
|
||||||
// CFBundleVersion (String - iOS, OS X) specifies the build version
|
// CFBundleVersion (String - iOS, OS X) specifies the build version
|
||||||
// number of the bundle, which identifies an iteration (released or
|
// number of the bundle, which identifies an iteration (released or
|
||||||
|
@ -29,6 +29,7 @@ import java.io.*;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import static jdk.incubator.jpackage.internal.MacAppImageBuilder.ICON_ICNS;
|
||||||
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||||
|
|
||||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||||
@ -160,7 +161,7 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
|
|||||||
|
|
||||||
createResource(TEMPLATE_BUNDLE_ICON, params)
|
createResource(TEMPLATE_BUNDLE_ICON, params)
|
||||||
.setCategory(I18N.getString("resource.volume-icon"))
|
.setCategory(I18N.getString("resource.volume-icon"))
|
||||||
.setExternal(MacAppBundler.ICON_ICNS.fetchFrom(params))
|
.setExternal(ICON_ICNS.fetchFrom(params))
|
||||||
.saveToFile(getConfig_VolumeIcon(params));
|
.saveToFile(getConfig_VolumeIcon(params));
|
||||||
|
|
||||||
createResource(null, params)
|
createResource(null, params)
|
||||||
|
@ -25,23 +25,21 @@
|
|||||||
|
|
||||||
package jdk.incubator.jpackage.internal;
|
package jdk.incubator.jpackage.internal;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.text.MessageFormat;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
import java.util.ArrayList;
|
import static jdk.incubator.jpackage.internal.OverridableResource.createResource;
|
||||||
|
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||||
|
|
||||||
import jdk.incubator.jpackage.internal.resources.ResourceLocator;
|
import jdk.incubator.jpackage.internal.resources.ResourceLocator;
|
||||||
|
|
||||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* AbstractAppImageBuilder
|
* AbstractAppImageBuilder
|
||||||
@ -188,4 +186,57 @@ public abstract class AbstractAppImageBuilder {
|
|||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static OverridableResource createIconResource(String defaultIconName,
|
||||||
|
BundlerParamInfo<File> iconParam, Map<String, ? super Object> params,
|
||||||
|
Map<String, ? super Object> mainParams) throws IOException {
|
||||||
|
|
||||||
|
if (mainParams != null) {
|
||||||
|
params = AddLauncherArguments.merge(mainParams, params, ICON.getID(),
|
||||||
|
iconParam.getID());
|
||||||
|
}
|
||||||
|
|
||||||
|
final String resourcePublicName = APP_NAME.fetchFrom(params)
|
||||||
|
+ IOUtils.getSuffix(Path.of(defaultIconName));
|
||||||
|
|
||||||
|
IconType iconType = getLauncherIconType(params);
|
||||||
|
if (iconType == IconType.NoIcon) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverridableResource resource = createResource(defaultIconName, params)
|
||||||
|
.setCategory("icon")
|
||||||
|
.setExternal(iconParam.fetchFrom(params))
|
||||||
|
.setPublicName(resourcePublicName);
|
||||||
|
|
||||||
|
if (iconType == IconType.DefaultOrResourceDirIcon && mainParams != null) {
|
||||||
|
// No icon explicitly configured for this launcher.
|
||||||
|
// Dry-run resource creation to figure out its source.
|
||||||
|
final Path nullPath = null;
|
||||||
|
if (resource.saveToFile(nullPath)
|
||||||
|
!= OverridableResource.Source.ResourceDir) {
|
||||||
|
// No icon in resource dir for this launcher, inherit icon
|
||||||
|
// configured for the main launcher.
|
||||||
|
resource = createIconResource(defaultIconName, iconParam,
|
||||||
|
mainParams, null).setLogPublicName(resourcePublicName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum IconType { DefaultOrResourceDirIcon, CustomIcon, NoIcon };
|
||||||
|
|
||||||
|
private static IconType getLauncherIconType(Map<String, ? super Object> params) {
|
||||||
|
File launcherIcon = ICON.fetchFrom(params);
|
||||||
|
if (launcherIcon == null) {
|
||||||
|
return IconType.DefaultOrResourceDirIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (launcherIcon.getName().isEmpty()) {
|
||||||
|
return IconType.NoIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return IconType.CustomIcon;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,6 +29,7 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.List;
|
||||||
import jdk.incubator.jpackage.internal.Arguments.CLIOptions;
|
import jdk.incubator.jpackage.internal.Arguments.CLIOptions;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -160,8 +161,10 @@ class AddLauncherArguments {
|
|||||||
|
|
||||||
static Map<String, ? super Object> merge(
|
static Map<String, ? super Object> merge(
|
||||||
Map<String, ? super Object> original,
|
Map<String, ? super Object> original,
|
||||||
Map<String, ? super Object> additional) {
|
Map<String, ? super Object> additional, String... exclude) {
|
||||||
Map<String, ? super Object> tmp = new HashMap<>(original);
|
Map<String, ? super Object> tmp = new HashMap<>(original);
|
||||||
|
List.of(exclude).forEach(tmp::remove);
|
||||||
|
|
||||||
if (additional.containsKey(CLIOptions.MODULE.getId())) {
|
if (additional.containsKey(CLIOptions.MODULE.getId())) {
|
||||||
tmp.remove(CLIOptions.MAIN_JAR.getId());
|
tmp.remove(CLIOptions.MAIN_JAR.getId());
|
||||||
tmp.remove(CLIOptions.APPCLASS.getId());
|
tmp.remove(CLIOptions.APPCLASS.getId());
|
||||||
|
@ -30,10 +30,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.HashMap;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
|
import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
|
||||||
@ -64,6 +61,7 @@ final class OverridableResource {
|
|||||||
|
|
||||||
OverridableResource(String defaultName) {
|
OverridableResource(String defaultName) {
|
||||||
this.defaultName = defaultName;
|
this.defaultName = defaultName;
|
||||||
|
setSourceOrder(Source.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
OverridableResource setSubstitutionData(Map<String, String> v) {
|
OverridableResource setSubstitutionData(Map<String, String> v) {
|
||||||
@ -90,6 +88,15 @@ final class OverridableResource {
|
|||||||
return setResourceDir(toPath(v));
|
return setResourceDir(toPath(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Source { External, ResourceDir, DefaultResource };
|
||||||
|
|
||||||
|
OverridableResource setSourceOrder(Source... v) {
|
||||||
|
sources = Stream.of(v)
|
||||||
|
.map(source -> Map.entry(source, getHandler(source)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set name of file to look for in resource dir.
|
* Set name of file to look for in resource dir.
|
||||||
*
|
*
|
||||||
@ -104,6 +111,20 @@ final class OverridableResource {
|
|||||||
return setPublicName(Path.of(v));
|
return setPublicName(Path.of(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set name of file to look for in resource dir to put in verbose log.
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
OverridableResource setLogPublicName(Path v) {
|
||||||
|
logPublicName = v;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
OverridableResource setLogPublicName(String v) {
|
||||||
|
return setLogPublicName(Path.of(v));
|
||||||
|
}
|
||||||
|
|
||||||
OverridableResource setExternal(Path v) {
|
OverridableResource setExternal(Path v) {
|
||||||
externalPath = v;
|
externalPath = v;
|
||||||
return this;
|
return this;
|
||||||
@ -113,57 +134,17 @@ final class OverridableResource {
|
|||||||
return setExternal(toPath(v));
|
return setExternal(toPath(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveToFile(Path dest) throws IOException {
|
Source saveToFile(Path dest) throws IOException {
|
||||||
final String printableCategory;
|
for (var source: sources) {
|
||||||
if (category != null) {
|
if (source.getValue().apply(dest)) {
|
||||||
printableCategory = String.format("[%s]", category);
|
return source.getKey();
|
||||||
} else {
|
|
||||||
printableCategory = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (externalPath != null && externalPath.toFile().exists()) {
|
|
||||||
Log.verbose(MessageFormat.format(I18N.getString(
|
|
||||||
"message.using-custom-resource-from-file"),
|
|
||||||
printableCategory,
|
|
||||||
externalPath.toAbsolutePath().normalize()));
|
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(externalPath)) {
|
|
||||||
processResourceStream(in, dest);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Path resourceName = Optional.ofNullable(publicName).orElse(
|
|
||||||
dest.getFileName());
|
|
||||||
|
|
||||||
if (resourceDir != null) {
|
|
||||||
final Path customResource = resourceDir.resolve(resourceName);
|
|
||||||
if (customResource.toFile().exists()) {
|
|
||||||
Log.verbose(MessageFormat.format(I18N.getString(
|
|
||||||
"message.using-custom-resource"), printableCategory,
|
|
||||||
resourceDir.normalize().toAbsolutePath().relativize(
|
|
||||||
customResource.normalize().toAbsolutePath())));
|
|
||||||
|
|
||||||
try (InputStream in = Files.newInputStream(customResource)) {
|
|
||||||
processResourceStream(in, dest);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (defaultName != null) {
|
|
||||||
Log.verbose(MessageFormat.format(
|
|
||||||
I18N.getString("message.using-default-resource"),
|
|
||||||
defaultName, printableCategory, resourceName));
|
|
||||||
|
|
||||||
try (InputStream in = readDefault(defaultName)) {
|
|
||||||
processResourceStream(in, dest);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveToFile(File dest) throws IOException {
|
Source saveToFile(File dest) throws IOException {
|
||||||
saveToFile(dest.toPath());
|
return saveToFile(toPath(dest));
|
||||||
}
|
}
|
||||||
|
|
||||||
static InputStream readDefault(String resourceName) {
|
static InputStream readDefault(String resourceName) {
|
||||||
@ -176,6 +157,81 @@ final class OverridableResource {
|
|||||||
RESOURCE_DIR.fetchFrom(params));
|
RESOURCE_DIR.fetchFrom(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getPrintableCategory() {
|
||||||
|
if (category != null) {
|
||||||
|
return String.format("[%s]", category);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useExternal(Path dest) throws IOException {
|
||||||
|
boolean used = externalPath != null && Files.exists(externalPath);
|
||||||
|
if (used && dest != null) {
|
||||||
|
Log.verbose(MessageFormat.format(I18N.getString(
|
||||||
|
"message.using-custom-resource-from-file"),
|
||||||
|
getPrintableCategory(),
|
||||||
|
externalPath.toAbsolutePath().normalize()));
|
||||||
|
|
||||||
|
try (InputStream in = Files.newInputStream(externalPath)) {
|
||||||
|
processResourceStream(in, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useResourceDir(Path dest) throws IOException {
|
||||||
|
boolean used = false;
|
||||||
|
|
||||||
|
if (dest == null && publicName == null) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
|
||||||
|
final Path resourceName = Optional.ofNullable(publicName).orElseGet(
|
||||||
|
() -> dest.getFileName());
|
||||||
|
|
||||||
|
if (resourceDir != null) {
|
||||||
|
final Path customResource = resourceDir.resolve(resourceName);
|
||||||
|
used = Files.exists(customResource);
|
||||||
|
if (used && dest != null) {
|
||||||
|
final Path logResourceName;
|
||||||
|
if (logPublicName != null) {
|
||||||
|
logResourceName = logPublicName.normalize();
|
||||||
|
} else {
|
||||||
|
logResourceName = resourceName.normalize();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.verbose(MessageFormat.format(I18N.getString(
|
||||||
|
"message.using-custom-resource"), getPrintableCategory(),
|
||||||
|
logResourceName));
|
||||||
|
|
||||||
|
try (InputStream in = Files.newInputStream(customResource)) {
|
||||||
|
processResourceStream(in, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean useDefault(Path dest) throws IOException {
|
||||||
|
boolean used = defaultName != null;
|
||||||
|
if (used && dest != null) {
|
||||||
|
final Path resourceName = Optional
|
||||||
|
.ofNullable(logPublicName)
|
||||||
|
.orElse(Optional
|
||||||
|
.ofNullable(publicName)
|
||||||
|
.orElseGet(() -> dest.getFileName()));
|
||||||
|
Log.verbose(MessageFormat.format(
|
||||||
|
I18N.getString("message.using-default-resource"),
|
||||||
|
defaultName, getPrintableCategory(), resourceName));
|
||||||
|
|
||||||
|
try (InputStream in = readDefault(defaultName)) {
|
||||||
|
processResourceStream(in, dest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return used;
|
||||||
|
}
|
||||||
|
|
||||||
private static List<String> substitute(Stream<String> lines,
|
private static List<String> substitute(Stream<String> lines,
|
||||||
Map<String, String> substitutionData) {
|
Map<String, String> substitutionData) {
|
||||||
return lines.map(line -> {
|
return lines.map(line -> {
|
||||||
@ -210,10 +266,33 @@ final class OverridableResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SourceHandler getHandler(Source sourceType) {
|
||||||
|
switch (sourceType) {
|
||||||
|
case DefaultResource:
|
||||||
|
return this::useDefault;
|
||||||
|
|
||||||
|
case External:
|
||||||
|
return this::useExternal;
|
||||||
|
|
||||||
|
case ResourceDir:
|
||||||
|
return this::useResourceDir;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private Map<String, String> substitutionData;
|
private Map<String, String> substitutionData;
|
||||||
private String category;
|
private String category;
|
||||||
private Path resourceDir;
|
private Path resourceDir;
|
||||||
private Path publicName;
|
private Path publicName;
|
||||||
|
private Path logPublicName;
|
||||||
private Path externalPath;
|
private Path externalPath;
|
||||||
private final String defaultName;
|
private final String defaultName;
|
||||||
|
private List<Map.Entry<Source, SourceHandler>> sources;
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
static interface SourceHandler {
|
||||||
|
public boolean apply(Path dest) throws IOException;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -37,21 +37,6 @@ public class WinAppBundler extends AbstractImageBundler {
|
|||||||
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
private static final ResourceBundle I18N = ResourceBundle.getBundle(
|
||||||
"jdk.incubator.jpackage.internal.resources.WinResources");
|
"jdk.incubator.jpackage.internal.resources.WinResources");
|
||||||
|
|
||||||
static final BundlerParamInfo<File> ICON_ICO =
|
|
||||||
new StandardBundlerParam<>(
|
|
||||||
"icon.ico",
|
|
||||||
File.class,
|
|
||||||
params -> {
|
|
||||||
File f = ICON.fetchFrom(params);
|
|
||||||
if (f != null && !f.getName().toLowerCase().endsWith(".ico")) {
|
|
||||||
Log.error(MessageFormat.format(
|
|
||||||
I18N.getString("message.icon-not-ico"), f));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return f;
|
|
||||||
},
|
|
||||||
(s, p) -> new File(s));
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validate(Map<String, ? super Object> params)
|
public boolean validate(Map<String, ? super Object> params)
|
||||||
throws ConfigException {
|
throws ConfigException {
|
||||||
|
@ -152,11 +152,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
return "app/" + APP_NAME.fetchFrom(params) +".cfg";
|
return "app/" + APP_NAME.fetchFrom(params) +".cfg";
|
||||||
}
|
}
|
||||||
|
|
||||||
private File getConfig_AppIcon(Map<String, ? super Object> params) {
|
|
||||||
return new File(getConfigRoot(params),
|
|
||||||
APP_NAME.fetchFrom(params) + ".ico");
|
|
||||||
}
|
|
||||||
|
|
||||||
private File getConfig_ExecutableProperties(
|
private File getConfig_ExecutableProperties(
|
||||||
Map<String, ? super Object> params) {
|
Map<String, ? super Object> params) {
|
||||||
return new File(getConfigRoot(params),
|
return new File(getConfigRoot(params),
|
||||||
@ -180,8 +175,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
@Override
|
@Override
|
||||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
Map<String, ? super Object> originalParams = new HashMap<>(params);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
IOUtils.writableOutputDir(root);
|
IOUtils.writableOutputDir(root);
|
||||||
IOUtils.writableOutputDir(binDir);
|
IOUtils.writableOutputDir(binDir);
|
||||||
@ -191,7 +184,7 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
AppImageFile.save(root, params);
|
AppImageFile.save(root, params);
|
||||||
|
|
||||||
// create the .exe launchers
|
// create the .exe launchers
|
||||||
createLauncherForEntryPoint(params);
|
createLauncherForEntryPoint(params, null);
|
||||||
|
|
||||||
// copy the jars
|
// copy the jars
|
||||||
copyApplication(params);
|
copyApplication(params);
|
||||||
@ -207,8 +200,8 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
List<Map<String, ? super Object>> entryPoints =
|
List<Map<String, ? super Object>> entryPoints =
|
||||||
StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
||||||
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
||||||
createLauncherForEntryPoint(
|
createLauncherForEntryPoint(AddLauncherArguments.merge(params,
|
||||||
AddLauncherArguments.merge(originalParams, entryPoint));
|
entryPoint, ICON.getID(), ICON_ICO.getID()), params);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,15 +265,18 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
.saveToFile(getConfig_ExecutableProperties(params));
|
.saveToFile(getConfig_ExecutableProperties(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLauncherForEntryPoint(
|
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||||
Map<String, ? super Object> params) throws IOException {
|
Map<String, ? super Object> mainParams) throws IOException {
|
||||||
|
|
||||||
File iconTarget = getConfig_AppIcon(params);
|
var iconResource = createIconResource(TEMPLATE_APP_ICON, ICON_ICO, params,
|
||||||
|
mainParams);
|
||||||
createResource(TEMPLATE_APP_ICON, params)
|
Path iconTarget = null;
|
||||||
.setCategory("icon")
|
if (iconResource != null) {
|
||||||
.setExternal(ICON_ICO.fetchFrom(params))
|
iconTarget = binDir.resolve(APP_NAME.fetchFrom(params) + ".ico");
|
||||||
.saveToFile(iconTarget);
|
if (null == iconResource.saveToFile(iconTarget)) {
|
||||||
|
iconTarget = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writeCfgFile(params, root.resolve(
|
writeCfgFile(params, root.resolve(
|
||||||
getLauncherCfgName(params)).toFile());
|
getLauncherCfgName(params)).toFile());
|
||||||
@ -315,8 +311,8 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
|
|
||||||
launcher.setWritable(true);
|
launcher.setWritable(true);
|
||||||
|
|
||||||
if (iconTarget.exists()) {
|
if (iconTarget != null) {
|
||||||
iconSwap(iconTarget.getAbsolutePath(),
|
iconSwap(iconTarget.toAbsolutePath().toString(),
|
||||||
launcher.getAbsolutePath());
|
launcher.getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,9 +332,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
|||||||
executableFile.toFile().setReadOnly();
|
executableFile.toFile().setReadOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Files.copy(iconTarget.toPath(),
|
|
||||||
binDir.resolve(APP_NAME.fetchFrom(params) + ".ico"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void copyApplication(Map<String, ? super Object> params)
|
private void copyApplication(Map<String, ? super Object> params)
|
||||||
|
@ -398,10 +398,6 @@ public class JPackageHelper {
|
|||||||
createModule("Hello.java", "input", "hello", moduleArgs, true);
|
createModule("Hello.java", "input", "hello", moduleArgs, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void createOtherModule() throws Exception {
|
|
||||||
createModule("Other.java", "input-other", "other", null, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void createModule(String javaFile, String inputDir, String aName,
|
private static void createModule(String javaFile, String inputDir, String aName,
|
||||||
ModuleArgs moduleArgs, boolean createModularJar) throws Exception {
|
ModuleArgs moduleArgs, boolean createModularJar) throws Exception {
|
||||||
int retVal;
|
int retVal;
|
||||||
|
@ -39,6 +39,11 @@ import jdk.jpackage.test.Functional.ThrowingSupplier;
|
|||||||
|
|
||||||
public final class Executor extends CommandArguments<Executor> {
|
public final class Executor extends CommandArguments<Executor> {
|
||||||
|
|
||||||
|
public static Executor of(String... cmdline) {
|
||||||
|
return new Executor().setExecutable(cmdline[0]).addArguments(
|
||||||
|
Arrays.copyOfRange(cmdline, 1, cmdline.length));
|
||||||
|
}
|
||||||
|
|
||||||
public Executor() {
|
public Executor() {
|
||||||
saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE));
|
saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE));
|
||||||
}
|
}
|
||||||
@ -170,7 +175,7 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
private List<String> output;
|
private List<String> output;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Result execute() {
|
public Result executeWithoutExitCodeCheck() {
|
||||||
if (toolProvider != null && directory != null) {
|
if (toolProvider != null && directory != null) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"Can't change directory when using tool provider");
|
"Can't change directory when using tool provider");
|
||||||
@ -189,12 +194,20 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
}).get();
|
}).get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Result execute(int expectedCode) {
|
||||||
|
return executeWithoutExitCodeCheck().assertExitCodeIs(expectedCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result execute() {
|
||||||
|
return execute(0);
|
||||||
|
}
|
||||||
|
|
||||||
public String executeAndGetFirstLineOfOutput() {
|
public String executeAndGetFirstLineOfOutput() {
|
||||||
return saveFirstLineOfOutput().execute().assertExitCodeIsZero().getFirstLineOfOutput();
|
return saveFirstLineOfOutput().execute().getFirstLineOfOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> executeAndGetOutput() {
|
public List<String> executeAndGetOutput() {
|
||||||
return saveOutput().execute().assertExitCodeIsZero().getOutput();
|
return saveOutput().execute().getOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean withSavedOutput() {
|
private boolean withSavedOutput() {
|
||||||
@ -203,7 +216,9 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Path executablePath() {
|
private Path executablePath() {
|
||||||
if (directory == null || executable.isAbsolute()) {
|
if (directory == null
|
||||||
|
|| executable.isAbsolute()
|
||||||
|
|| !Set.of(".", "..").contains(executable.getName(0).toString())) {
|
||||||
return executable;
|
return executable;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,7 +252,7 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
sb.append(String.format("; in directory [%s]", directory));
|
sb.append(String.format("; in directory [%s]", directory));
|
||||||
}
|
}
|
||||||
|
|
||||||
TKit.trace("Execute " + sb.toString() + "...");
|
trace("Execute " + sb.toString() + "...");
|
||||||
Process process = builder.start();
|
Process process = builder.start();
|
||||||
|
|
||||||
List<String> outputLines = null;
|
List<String> outputLines = null;
|
||||||
@ -266,7 +281,7 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result reply = new Result(process.waitFor());
|
Result reply = new Result(process.waitFor());
|
||||||
TKit.trace("Done. Exit code: " + reply.exitCode);
|
trace("Done. Exit code: " + reply.exitCode);
|
||||||
|
|
||||||
if (outputLines != null) {
|
if (outputLines != null) {
|
||||||
reply.output = Collections.unmodifiableList(outputLines);
|
reply.output = Collections.unmodifiableList(outputLines);
|
||||||
@ -275,10 +290,10 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Result runToolProvider(PrintStream out, PrintStream err) {
|
private Result runToolProvider(PrintStream out, PrintStream err) {
|
||||||
TKit.trace("Execute " + getPrintableCommandLine() + "...");
|
trace("Execute " + getPrintableCommandLine() + "...");
|
||||||
Result reply = new Result(toolProvider.run(out, err, args.toArray(
|
Result reply = new Result(toolProvider.run(out, err, args.toArray(
|
||||||
String[]::new)));
|
String[]::new)));
|
||||||
TKit.trace("Done. Exit code: " + reply.exitCode);
|
trace("Done. Exit code: " + reply.exitCode);
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -353,6 +368,10 @@ public final class Executor extends CommandArguments<Executor> {
|
|||||||
Collectors.joining(" "));
|
Collectors.joining(" "));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void trace(String msg) {
|
||||||
|
TKit.trace(String.format("exec: %s", msg));
|
||||||
|
}
|
||||||
|
|
||||||
private ToolProvider toolProvider;
|
private ToolProvider toolProvider;
|
||||||
private Path executable;
|
private Path executable;
|
||||||
private Set<SaveOutputType> saveOutputType;
|
private Set<SaveOutputType> saveOutputType;
|
||||||
|
@ -23,10 +23,7 @@
|
|||||||
package jdk.jpackage.test;
|
package jdk.jpackage.test;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.*;
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
|
|
||||||
public class Functional {
|
public class Functional {
|
||||||
@ -45,6 +42,21 @@ public class Functional {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface ThrowingBiConsumer<T, U> {
|
||||||
|
void accept(T t, U u) throws Throwable;
|
||||||
|
|
||||||
|
public static <T, U> BiConsumer<T, U> toBiConsumer(ThrowingBiConsumer<T, U> v) {
|
||||||
|
return (t, u) -> {
|
||||||
|
try {
|
||||||
|
v.accept(t, u);
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
rethrowUnchecked(ex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@FunctionalInterface
|
@FunctionalInterface
|
||||||
public interface ThrowingSupplier<T> {
|
public interface ThrowingSupplier<T> {
|
||||||
T get() throws Throwable;
|
T get() throws Throwable;
|
||||||
@ -102,6 +114,10 @@ public class Functional {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T, U> BiConsumer<T, U> identity(BiConsumer<T, U> v) {
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
public static Runnable identity(Runnable v) {
|
public static Runnable identity(Runnable v) {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
@ -26,16 +26,16 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import jdk.jpackage.test.Functional.ThrowingFunction;
|
import jdk.jpackage.test.Functional.ThrowingFunction;
|
||||||
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||||
|
|
||||||
public class HelloApp {
|
public final class HelloApp {
|
||||||
|
|
||||||
HelloApp(JavaAppDesc appDesc) {
|
HelloApp(JavaAppDesc appDesc) {
|
||||||
if (appDesc == null) {
|
if (appDesc == null) {
|
||||||
@ -131,13 +131,13 @@ public class HelloApp {
|
|||||||
|
|
||||||
if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) {
|
if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) {
|
||||||
// Use Hello.java as is.
|
// Use Hello.java as is.
|
||||||
cmd.addAction((self) -> {
|
cmd.addPrerequisiteAction((self) -> {
|
||||||
Path jarFile = self.inputDir().resolve(jarFileName);
|
Path jarFile = self.inputDir().resolve(jarFileName);
|
||||||
createJarBuilder().setOutputJar(jarFile).addSourceFile(
|
createJarBuilder().setOutputJar(jarFile).addSourceFile(
|
||||||
HELLO_JAVA).create();
|
HELLO_JAVA).create();
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cmd.addAction((self) -> {
|
cmd.addPrerequisiteAction((self) -> {
|
||||||
final Path jarFile;
|
final Path jarFile;
|
||||||
if (moduleName == null) {
|
if (moduleName == null) {
|
||||||
jarFile = self.inputDir().resolve(jarFileName);
|
jarFile = self.inputDir().resolve(jarFileName);
|
||||||
@ -177,9 +177,11 @@ public class HelloApp {
|
|||||||
"hello.jar");
|
"hello.jar");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void verifyOutputFile(Path outputFile, List<String> args) {
|
static void verifyOutputFile(Path outputFile, List<String> args,
|
||||||
|
Map<String, String> params) {
|
||||||
if (!outputFile.isAbsolute()) {
|
if (!outputFile.isAbsolute()) {
|
||||||
verifyOutputFile(outputFile.toAbsolutePath().normalize(), args);
|
verifyOutputFile(outputFile.toAbsolutePath().normalize(), args,
|
||||||
|
params);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,38 +195,121 @@ public class HelloApp {
|
|||||||
String.format("args.length: %d", args.size())
|
String.format("args.length: %d", args.size())
|
||||||
));
|
));
|
||||||
expected.addAll(args);
|
expected.addAll(args);
|
||||||
|
expected.addAll(params.entrySet().stream()
|
||||||
|
.sorted(Comparator.comparing(Map.Entry::getKey))
|
||||||
|
.map(entry -> String.format("-D%s=%s", entry.getKey(),
|
||||||
|
entry.getValue()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
TKit.assertStringListEquals(expected, contents, String.format(
|
TKit.assertStringListEquals(expected, contents, String.format(
|
||||||
"Check contents of [%s] file", outputFile));
|
"Check contents of [%s] file", outputFile));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeLauncherAndVerifyOutput(JPackageCommand cmd) {
|
public static void executeLauncherAndVerifyOutput(JPackageCommand cmd,
|
||||||
|
String... args) {
|
||||||
final Path launcherPath = cmd.appLauncherPath();
|
final Path launcherPath = cmd.appLauncherPath();
|
||||||
if (!cmd.isFakeRuntime(String.format("Not running [%s] launcher",
|
if (cmd.isFakeRuntime(String.format("Not running [%s] launcher",
|
||||||
launcherPath))) {
|
launcherPath))) {
|
||||||
executeAndVerifyOutput(launcherPath, cmd.getAllArgumentValues(
|
return;
|
||||||
"--arguments"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assertApp(launcherPath)
|
||||||
|
.addDefaultArguments(Optional
|
||||||
|
.ofNullable(cmd.getAllArgumentValues("--arguments"))
|
||||||
|
.orElseGet(() -> new String[0]))
|
||||||
|
.addJavaOptions(Optional
|
||||||
|
.ofNullable(cmd.getAllArgumentValues("--java-options"))
|
||||||
|
.orElseGet(() -> new String[0]))
|
||||||
|
.executeAndVerifyOutput(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeAndVerifyOutput(Path helloAppLauncher,
|
public final static class AppOutputVerifier {
|
||||||
String... defaultLauncherArgs) {
|
AppOutputVerifier(Path helloAppLauncher) {
|
||||||
executeAndVerifyOutput(helloAppLauncher, List.of(defaultLauncherArgs));
|
this.launcherPath = helloAppLauncher;
|
||||||
|
this.params = new HashMap<>();
|
||||||
|
this.defaultLauncherArgs = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addDefaultArguments(String... v) {
|
||||||
|
return addDefaultArguments(List.of(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addDefaultArguments(Collection<String> v) {
|
||||||
|
defaultLauncherArgs.addAll(v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addParam(String name, String value) {
|
||||||
|
if (name.startsWith("param")) {
|
||||||
|
params.put(name, value);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addParams(Collection<Map.Entry<String, String>> v) {
|
||||||
|
v.forEach(entry -> addParam(entry.getKey(), entry.getValue()));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public AppOutputVerifier addParams(Map<String, String> v) {
|
||||||
|
return addParams(v.entrySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addParams(Map.Entry<String, String>... v) {
|
||||||
|
return addParams(List.of(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addJavaOptions(String... v) {
|
||||||
|
return addJavaOptions(List.of(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
public AppOutputVerifier addJavaOptions(Collection<String> v) {
|
||||||
|
return addParams(v.stream()
|
||||||
|
.filter(javaOpt -> javaOpt.startsWith("-D"))
|
||||||
|
.map(javaOpt -> {
|
||||||
|
var components = javaOpt.split("=", 2);
|
||||||
|
return Map.entry(components[0].substring(2), components[1]);
|
||||||
|
})
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void executeAndVerifyOutput(String... args) {
|
||||||
|
// Output file will be created in the current directory.
|
||||||
|
Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME);
|
||||||
|
ThrowingFunction.toFunction(Files::deleteIfExists).apply(outputFile);
|
||||||
|
|
||||||
|
final Path executablePath;
|
||||||
|
if (launcherPath.isAbsolute()) {
|
||||||
|
executablePath = launcherPath;
|
||||||
|
} else {
|
||||||
|
// Make sure path to executable is relative to the current directory.
|
||||||
|
executablePath = Path.of(".").resolve(launcherPath.normalize());
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<String> launcherArgs = List.of(args);
|
||||||
|
new Executor()
|
||||||
|
.setDirectory(outputFile.getParent())
|
||||||
|
.setExecutable(executablePath)
|
||||||
|
.addArguments(launcherArgs)
|
||||||
|
.dumpOutput()
|
||||||
|
.execute();
|
||||||
|
|
||||||
|
final List<String> appArgs;
|
||||||
|
if (launcherArgs.isEmpty()) {
|
||||||
|
appArgs = defaultLauncherArgs;
|
||||||
|
} else {
|
||||||
|
appArgs = launcherArgs;
|
||||||
|
}
|
||||||
|
|
||||||
|
verifyOutputFile(outputFile, appArgs, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Path launcherPath;
|
||||||
|
private final List<String> defaultLauncherArgs;
|
||||||
|
private final Map<String, String> params;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void executeAndVerifyOutput(Path helloAppLauncher,
|
public static AppOutputVerifier assertApp(Path helloAppLauncher) {
|
||||||
List<String> defaultLauncherArgs) {
|
return new AppOutputVerifier(helloAppLauncher);
|
||||||
// Output file will be created in the current directory.
|
|
||||||
Path outputFile = TKit.workDir().resolve(OUTPUT_FILENAME);
|
|
||||||
ThrowingFunction.toFunction(Files::deleteIfExists).apply(outputFile);
|
|
||||||
new Executor()
|
|
||||||
.setDirectory(outputFile.getParent())
|
|
||||||
.setExecutable(helloAppLauncher)
|
|
||||||
.dumpOutput()
|
|
||||||
.execute()
|
|
||||||
.assertExitCodeIsZero();
|
|
||||||
|
|
||||||
verifyOutputFile(outputFile, defaultLauncherArgs);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final static String OUTPUT_FILENAME = "appOutput.txt";
|
final static String OUTPUT_FILENAME = "appOutput.txt";
|
||||||
|
@ -30,14 +30,15 @@ import java.security.SecureRandom;
|
|||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import jdk.incubator.jpackage.internal.ApplicationLayout;
|
import jdk.incubator.jpackage.internal.ApplicationLayout;
|
||||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||||
import jdk.jpackage.test.Functional.ThrowingFunction;
|
import jdk.jpackage.test.Functional.ThrowingFunction;
|
||||||
|
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* jpackage command line with prerequisite actions. Prerequisite actions can be
|
* jpackage command line with prerequisite actions. Prerequisite actions can be
|
||||||
@ -47,18 +48,20 @@ import jdk.jpackage.test.Functional.ThrowingFunction;
|
|||||||
public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||||
|
|
||||||
public JPackageCommand() {
|
public JPackageCommand() {
|
||||||
actions = new ArrayList<>();
|
prerequisiteActions = new Actions();
|
||||||
|
verifyActions = new Actions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand(JPackageCommand cmd) {
|
public JPackageCommand(JPackageCommand cmd) {
|
||||||
this();
|
|
||||||
args.addAll(cmd.args);
|
args.addAll(cmd.args);
|
||||||
withToolProvider = cmd.withToolProvider;
|
withToolProvider = cmd.withToolProvider;
|
||||||
saveConsoleOutput = cmd.saveConsoleOutput;
|
saveConsoleOutput = cmd.saveConsoleOutput;
|
||||||
suppressOutput = cmd.suppressOutput;
|
suppressOutput = cmd.suppressOutput;
|
||||||
ignoreDefaultRuntime = cmd.ignoreDefaultRuntime;
|
ignoreDefaultRuntime = cmd.ignoreDefaultRuntime;
|
||||||
|
ignoreDefaultVerbose = cmd.ignoreDefaultVerbose;
|
||||||
immutable = cmd.immutable;
|
immutable = cmd.immutable;
|
||||||
actionsExecuted = cmd.actionsExecuted;
|
prerequisiteActions = new Actions(cmd.prerequisiteActions);
|
||||||
|
verifyActions = new Actions(cmd.verifyActions);
|
||||||
}
|
}
|
||||||
|
|
||||||
JPackageCommand createImmutableCopy() {
|
JPackageCommand createImmutableCopy() {
|
||||||
@ -204,8 +207,8 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand setDefaultInputOutput() {
|
public JPackageCommand setDefaultInputOutput() {
|
||||||
addArguments("--input", TKit.defaultInputDir());
|
setArgumentValue("--input", TKit.workDir().resolve("input"));
|
||||||
addArguments("--dest", TKit.defaultOutputDir());
|
setArgumentValue("--dest", TKit.workDir().resolve("output"));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +224,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addAction(cmd -> {
|
addPrerequisiteAction(cmd -> {
|
||||||
Path fakeRuntimeDir = TKit.workDir().resolve("fake_runtime");
|
Path fakeRuntimeDir = TKit.workDir().resolve("fake_runtime");
|
||||||
|
|
||||||
TKit.trace(String.format("Init fake runtime in [%s] directory",
|
TKit.trace(String.format("Init fake runtime in [%s] directory",
|
||||||
@ -254,9 +257,15 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
JPackageCommand addAction(ThrowingConsumer<JPackageCommand> action) {
|
JPackageCommand addPrerequisiteAction(ThrowingConsumer<JPackageCommand> action) {
|
||||||
verifyMutable();
|
verifyMutable();
|
||||||
actions.add(ThrowingConsumer.toConsumer(action));
|
prerequisiteActions.add(action);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
JPackageCommand addVerifyAction(ThrowingConsumer<JPackageCommand> action) {
|
||||||
|
verifyMutable();
|
||||||
|
verifyActions.add(action);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,6 +372,12 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
* `/opt/foo`
|
* `/opt/foo`
|
||||||
*/
|
*/
|
||||||
public Path appInstallationDirectory() {
|
public Path appInstallationDirectory() {
|
||||||
|
Path unpackedDir = getArgumentValue(UNPACKED_PATH_ARGNAME, () -> null,
|
||||||
|
Path::of);
|
||||||
|
if (unpackedDir != null) {
|
||||||
|
return unpackedDir;
|
||||||
|
}
|
||||||
|
|
||||||
if (isImagePackageType()) {
|
if (isImagePackageType()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -426,7 +441,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
launcherName = launcherName + ".exe";
|
launcherName = launcherName + ".exe";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isImagePackageType()) {
|
if (isImagePackageType() || isPackageUnpacked()) {
|
||||||
return appLayout().launchersDirectory().resolve(launcherName);
|
return appLayout().launchersDirectory().resolve(launcherName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -496,6 +511,19 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isPackageUnpacked(String msg) {
|
||||||
|
if (isPackageUnpacked()) {
|
||||||
|
TKit.trace(String.format(
|
||||||
|
"%s because package was unpacked, not installed", msg));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isPackageUnpacked() {
|
||||||
|
return hasArgument(UNPACKED_PATH_ARGNAME);
|
||||||
|
}
|
||||||
|
|
||||||
public static void useToolProviderByDefault() {
|
public static void useToolProviderByDefault() {
|
||||||
defaultWithToolProvider = true;
|
defaultWithToolProvider = true;
|
||||||
}
|
}
|
||||||
@ -528,24 +556,28 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JPackageCommand ignoreDefaultVerbose(boolean v) {
|
||||||
|
verifyMutable();
|
||||||
|
ignoreDefaultVerbose = v;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isWithToolProvider() {
|
public boolean isWithToolProvider() {
|
||||||
return Optional.ofNullable(withToolProvider).orElse(
|
return Optional.ofNullable(withToolProvider).orElse(
|
||||||
defaultWithToolProvider);
|
defaultWithToolProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand executePrerequisiteActions() {
|
public JPackageCommand executePrerequisiteActions() {
|
||||||
verifyMutable();
|
prerequisiteActions.run();
|
||||||
if (!actionsExecuted) {
|
|
||||||
actionsExecuted = true;
|
|
||||||
if (actions != null) {
|
|
||||||
actions.stream().forEach(r -> r.accept(this));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Executor createExecutor() {
|
public JPackageCommand executeVerifyActions() {
|
||||||
verifyMutable();
|
verifyActions.run();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Executor createExecutor() {
|
||||||
Executor exec = new Executor()
|
Executor exec = new Executor()
|
||||||
.saveOutput(saveConsoleOutput).dumpOutput(!suppressOutput)
|
.saveOutput(saveConsoleOutput).dumpOutput(!suppressOutput)
|
||||||
.addArguments(args);
|
.addArguments(args);
|
||||||
@ -560,27 +592,60 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Executor.Result execute() {
|
public Executor.Result execute() {
|
||||||
|
return execute(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Executor.Result execute(int expectedExitCode) {
|
||||||
executePrerequisiteActions();
|
executePrerequisiteActions();
|
||||||
|
|
||||||
if (isImagePackageType()) {
|
if (isImagePackageType()) {
|
||||||
TKit.deleteDirectoryContentsRecursive(outputDir());
|
TKit.deleteDirectoryContentsRecursive(outputDir());
|
||||||
|
} else if (ThrowingSupplier.toSupplier(() -> Files.deleteIfExists(
|
||||||
|
outputBundle())).get()) {
|
||||||
|
TKit.trace(
|
||||||
|
String.format("Deleted [%s] file before running jpackage",
|
||||||
|
outputBundle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new JPackageCommand(this)
|
Path resourceDir = getArgumentValue("--resource-dir", () -> null, Path::of);
|
||||||
|
if (resourceDir != null && Files.isDirectory(resourceDir)) {
|
||||||
|
TKit.trace(String.format("Files in [%s] resource dir:",
|
||||||
|
resourceDir));
|
||||||
|
try (var files = Files.walk(resourceDir, 1)) {
|
||||||
|
files.sequential()
|
||||||
|
.filter(Predicate.not(resourceDir::equals))
|
||||||
|
.map(path -> String.format("[%s]", path.getFileName()))
|
||||||
|
.forEachOrdered(TKit::trace);
|
||||||
|
TKit.trace("Done");
|
||||||
|
} catch (IOException ex) {
|
||||||
|
TKit.trace(String.format(
|
||||||
|
"Failed to list files in [%s] resource directory: %s",
|
||||||
|
resourceDir, ex));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Executor.Result result = new JPackageCommand(this)
|
||||||
.adjustArgumentsBeforeExecution()
|
.adjustArgumentsBeforeExecution()
|
||||||
.createExecutor()
|
.createExecutor()
|
||||||
.execute();
|
.execute(expectedExitCode);
|
||||||
|
|
||||||
|
if (result.exitCode == 0) {
|
||||||
|
executeVerifyActions();
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand executeAndAssertHelloAppImageCreated() {
|
public Executor.Result executeAndAssertHelloAppImageCreated() {
|
||||||
executeAndAssertImageCreated();
|
Executor.Result result = executeAndAssertImageCreated();
|
||||||
HelloApp.executeLauncherAndVerifyOutput(this);
|
HelloApp.executeLauncherAndVerifyOutput(this);
|
||||||
return this;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand executeAndAssertImageCreated() {
|
public Executor.Result executeAndAssertImageCreated() {
|
||||||
execute().assertExitCodeIsZero();
|
Executor.Result result = execute();
|
||||||
return assertImageCreated();
|
assertImageCreated();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public JPackageCommand assertImageCreated() {
|
public JPackageCommand assertImageCreated() {
|
||||||
@ -595,23 +660,26 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JPackageCommand setUnpackedPackageLocation(Path path) {
|
||||||
|
verifyIsOfType(PackageType.NATIVE);
|
||||||
|
setArgumentValue(UNPACKED_PATH_ARGNAME, path);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
private JPackageCommand adjustArgumentsBeforeExecution() {
|
private JPackageCommand adjustArgumentsBeforeExecution() {
|
||||||
if (!hasArgument("--runtime-image") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) {
|
if (!hasArgument("--runtime-image") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) {
|
||||||
addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE);
|
addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasArgument("--verbose") && TKit.VERBOSE_JPACKAGE) {
|
if (!hasArgument("--verbose") && TKit.VERBOSE_JPACKAGE && !ignoreDefaultVerbose) {
|
||||||
addArgument("--verbose");
|
addArgument("--verbose");
|
||||||
}
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
String getPrintableCommandLine() {
|
public String getPrintableCommandLine() {
|
||||||
return new Executor()
|
return createExecutor().getPrintableCommandLine();
|
||||||
.setExecutable(JavaTool.JPACKAGE)
|
|
||||||
.addArguments(args)
|
|
||||||
.getPrintableCommandLine();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void verifyIsOfType(Collection<PackageType> types) {
|
public void verifyIsOfType(Collection<PackageType> types) {
|
||||||
@ -699,13 +767,48 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return !immutable;
|
return !immutable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private final class Actions implements Runnable {
|
||||||
|
Actions() {
|
||||||
|
actions = new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
Actions(Actions other) {
|
||||||
|
this();
|
||||||
|
actions.addAll(other.actions);
|
||||||
|
}
|
||||||
|
|
||||||
|
void add(ThrowingConsumer<JPackageCommand> action) {
|
||||||
|
Objects.requireNonNull(action);
|
||||||
|
verifyMutable();
|
||||||
|
actions.add(new Consumer<JPackageCommand>() {
|
||||||
|
@Override
|
||||||
|
public void accept(JPackageCommand t) {
|
||||||
|
if (!executed) {
|
||||||
|
executed = true;
|
||||||
|
ThrowingConsumer.toConsumer(action).accept(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private boolean executed;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
verifyMutable();
|
||||||
|
actions.forEach(action -> action.accept(JPackageCommand.this));
|
||||||
|
}
|
||||||
|
|
||||||
|
private final List<Consumer<JPackageCommand>> actions;
|
||||||
|
}
|
||||||
|
|
||||||
private Boolean withToolProvider;
|
private Boolean withToolProvider;
|
||||||
private boolean saveConsoleOutput;
|
private boolean saveConsoleOutput;
|
||||||
private boolean suppressOutput;
|
private boolean suppressOutput;
|
||||||
private boolean ignoreDefaultRuntime;
|
private boolean ignoreDefaultRuntime;
|
||||||
|
private boolean ignoreDefaultVerbose;
|
||||||
private boolean immutable;
|
private boolean immutable;
|
||||||
private boolean actionsExecuted;
|
private final Actions prerequisiteActions;
|
||||||
private final List<Consumer<JPackageCommand>> actions;
|
private final Actions verifyActions;
|
||||||
private static boolean defaultWithToolProvider;
|
private static boolean defaultWithToolProvider;
|
||||||
|
|
||||||
private final static Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
private final static Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
||||||
@ -729,4 +832,6 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}).get();
|
}).get();
|
||||||
|
|
||||||
|
private final static String UNPACKED_PATH_ARGNAME = "jpt-unpacked-folder";
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ public final class JarBuilder {
|
|||||||
.setToolProvider(JavaTool.JAVAC)
|
.setToolProvider(JavaTool.JAVAC)
|
||||||
.addArguments("-d", workDir.toString())
|
.addArguments("-d", workDir.toString())
|
||||||
.addPathArguments(sourceFiles)
|
.addPathArguments(sourceFiles)
|
||||||
.execute().assertExitCodeIsZero();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
Files.createDirectories(outputJar.getParent());
|
Files.createDirectories(outputJar.getParent());
|
||||||
@ -87,7 +87,7 @@ public final class JarBuilder {
|
|||||||
jarExe.addArguments("-e", mainClass);
|
jarExe.addArguments("-e", mainClass);
|
||||||
}
|
}
|
||||||
jarExe.addArguments("-C", workDir.toString(), ".");
|
jarExe.addArguments("-C", workDir.toString(), ".");
|
||||||
jarExe.execute().assertExitCodeIsZero();
|
jarExe.execute();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
private List<Path> sourceFiles;
|
private List<Path> sourceFiles;
|
||||||
|
@ -25,14 +25,11 @@ package jdk.jpackage.test;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Arrays;
|
import java.util.*;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||||
|
|
||||||
public class LinuxHelper {
|
public class LinuxHelper {
|
||||||
private static String getRelease(JPackageCommand cmd) {
|
private static String getRelease(JPackageCommand cmd) {
|
||||||
@ -45,6 +42,19 @@ public class LinuxHelper {
|
|||||||
() -> cmd.name().toLowerCase());
|
() -> cmd.name().toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Path getDesktopFile(JPackageCommand cmd) {
|
||||||
|
return getDesktopFile(cmd, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Path getDesktopFile(JPackageCommand cmd, String launcherName) {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX);
|
||||||
|
String desktopFileName = String.format("%s-%s.desktop", getPackageName(
|
||||||
|
cmd), Optional.ofNullable(launcherName).orElseGet(
|
||||||
|
() -> cmd.name()));
|
||||||
|
return cmd.appLayout().destktopIntegrationDirectory().resolve(
|
||||||
|
desktopFileName);
|
||||||
|
}
|
||||||
|
|
||||||
static String getBundleName(JPackageCommand cmd) {
|
static String getBundleName(JPackageCommand cmd) {
|
||||||
cmd.verifyIsOfType(PackageType.LINUX);
|
cmd.verifyIsOfType(PackageType.LINUX);
|
||||||
|
|
||||||
@ -73,18 +83,14 @@ public class LinuxHelper {
|
|||||||
final PackageType packageType = cmd.packageType();
|
final PackageType packageType = cmd.packageType();
|
||||||
final Path packageFile = cmd.outputBundle();
|
final Path packageFile = cmd.outputBundle();
|
||||||
|
|
||||||
Executor exec = new Executor();
|
Executor exec = null;
|
||||||
switch (packageType) {
|
switch (packageType) {
|
||||||
case LINUX_DEB:
|
case LINUX_DEB:
|
||||||
exec.setExecutable("dpkg")
|
exec = Executor.of("dpkg", "--contents").addArgument(packageFile);
|
||||||
.addArgument("--contents")
|
|
||||||
.addArgument(packageFile);
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LINUX_RPM:
|
case LINUX_RPM:
|
||||||
exec.setExecutable("rpm")
|
exec = Executor.of("rpm", "-qpl").addArgument(packageFile);
|
||||||
.addArgument("-qpl")
|
|
||||||
.addArgument(packageFile);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -109,8 +115,8 @@ public class LinuxHelper {
|
|||||||
Collectors.toList());
|
Collectors.toList());
|
||||||
|
|
||||||
case LINUX_RPM:
|
case LINUX_RPM:
|
||||||
return new Executor().setExecutable("rpm")
|
return Executor.of("rpm", "-qp", "-R")
|
||||||
.addArguments("-qp", "-R", cmd.outputBundle().toString())
|
.addArgument(cmd.outputBundle())
|
||||||
.executeAndGetOutput();
|
.executeAndGetOutput();
|
||||||
}
|
}
|
||||||
// Unreachable
|
// Unreachable
|
||||||
@ -141,6 +147,57 @@ public class LinuxHelper {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createDebPackageHandlers() {
|
||||||
|
PackageHandlers deb = new PackageHandlers();
|
||||||
|
deb.installHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_DEB);
|
||||||
|
Executor.of("sudo", "dpkg", "-i")
|
||||||
|
.addArgument(cmd.outputBundle())
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
|
deb.uninstallHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_DEB);
|
||||||
|
Executor.of("sudo", "dpkg", "-r", getPackageName(cmd)).execute();
|
||||||
|
};
|
||||||
|
deb.unpackHandler = (cmd, destinationDir) -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_DEB);
|
||||||
|
Executor.of("dpkg", "-x")
|
||||||
|
.addArgument(cmd.outputBundle())
|
||||||
|
.addArgument(destinationDir)
|
||||||
|
.execute();
|
||||||
|
return destinationDir.resolve(String.format(".%s",
|
||||||
|
cmd.appInstallationDirectory())).normalize();
|
||||||
|
};
|
||||||
|
return deb;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createRpmPackageHandlers() {
|
||||||
|
PackageHandlers rpm = new PackageHandlers();
|
||||||
|
rpm.installHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_RPM);
|
||||||
|
Executor.of("sudo", "rpm", "-i")
|
||||||
|
.addArgument(cmd.outputBundle())
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
|
rpm.uninstallHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_RPM);
|
||||||
|
Executor.of("sudo", "rpm", "-e", getPackageName(cmd)).execute();
|
||||||
|
};
|
||||||
|
rpm.unpackHandler = (cmd, destinationDir) -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.LINUX_RPM);
|
||||||
|
Executor.of("sh", "-c", String.format(
|
||||||
|
"rpm2cpio '%s' | cpio -idm --quiet",
|
||||||
|
JPackageCommand.escapeAndJoin(
|
||||||
|
cmd.outputBundle().toAbsolutePath().toString())))
|
||||||
|
.setDirectory(destinationDir)
|
||||||
|
.execute();
|
||||||
|
return destinationDir.resolve(String.format(".%s",
|
||||||
|
cmd.appInstallationDirectory())).normalize();
|
||||||
|
};
|
||||||
|
|
||||||
|
return rpm;
|
||||||
|
}
|
||||||
|
|
||||||
static Path getLauncherPath(JPackageCommand cmd) {
|
static Path getLauncherPath(JPackageCommand cmd) {
|
||||||
cmd.verifyIsOfType(PackageType.LINUX);
|
cmd.verifyIsOfType(PackageType.LINUX);
|
||||||
|
|
||||||
@ -173,20 +230,15 @@ public class LinuxHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static String getDebBundleProperty(Path bundle, String fieldName) {
|
static String getDebBundleProperty(Path bundle, String fieldName) {
|
||||||
return new Executor()
|
return Executor.of("dpkg-deb", "-f")
|
||||||
.setExecutable("dpkg-deb")
|
.addArgument(bundle)
|
||||||
.addArguments("-f", bundle.toString(), fieldName)
|
.addArgument(fieldName)
|
||||||
.executeAndGetFirstLineOfOutput();
|
.executeAndGetFirstLineOfOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getRpmBundleProperty(Path bundle, String fieldName) {
|
static String getRpmBundleProperty(Path bundle, String fieldName) {
|
||||||
return new Executor()
|
return Executor.of("rpm", "-qp", "--queryformat", String.format("%%{%s}", fieldName))
|
||||||
.setExecutable("rpm")
|
.addArgument(bundle)
|
||||||
.addArguments(
|
|
||||||
"-qp",
|
|
||||||
"--queryformat",
|
|
||||||
String.format("%%{%s}", fieldName),
|
|
||||||
bundle.toString())
|
|
||||||
.executeAndGetFirstLineOfOutput();
|
.executeAndGetFirstLineOfOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,13 +316,10 @@ public class LinuxHelper {
|
|||||||
test.addBundleVerifier(cmd -> {
|
test.addBundleVerifier(cmd -> {
|
||||||
TKit.withTempDirectory("dpkg-control-files", tempDir -> {
|
TKit.withTempDirectory("dpkg-control-files", tempDir -> {
|
||||||
// Extract control Debian package files into temporary directory
|
// Extract control Debian package files into temporary directory
|
||||||
new Executor()
|
Executor.of("dpkg", "-e")
|
||||||
.setExecutable("dpkg")
|
.addArgument(cmd.outputBundle())
|
||||||
.addArguments(
|
.addArgument(tempDir)
|
||||||
"-e",
|
.execute();
|
||||||
cmd.outputBundle().toString(),
|
|
||||||
tempDir.toString()
|
|
||||||
).execute().assertExitCodeIsZero();
|
|
||||||
|
|
||||||
Path controlFile = Path.of("postinst");
|
Path controlFile = Path.of("postinst");
|
||||||
|
|
||||||
@ -318,6 +367,10 @@ public class LinuxHelper {
|
|||||||
|
|
||||||
static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) {
|
static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) {
|
||||||
test.addInstallVerifier(cmd -> {
|
test.addInstallVerifier(cmd -> {
|
||||||
|
if (cmd.isPackageUnpacked("Not running file associations checks")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PackageTest.withTestFileAssociationsFile(fa, testFile -> {
|
PackageTest.withTestFileAssociationsFile(fa, testFile -> {
|
||||||
String mimeType = queryFileMimeType(testFile);
|
String mimeType = queryFileMimeType(testFile);
|
||||||
|
|
||||||
@ -363,16 +416,12 @@ public class LinuxHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String queryFileMimeType(Path file) {
|
private static String queryFileMimeType(Path file) {
|
||||||
return new Executor()
|
return Executor.of("xdg-mime", "query", "filetype").addArgument(file)
|
||||||
.setExecutable("xdg-mime")
|
|
||||||
.addArguments("query", "filetype", file.toString())
|
|
||||||
.executeAndGetFirstLineOfOutput();
|
.executeAndGetFirstLineOfOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String queryMimeTypeDefaultHandler(String mimeType) {
|
private static String queryMimeTypeDefaultHandler(String mimeType) {
|
||||||
return new Executor()
|
return Executor.of("xdg-mime", "query", "default", mimeType)
|
||||||
.setExecutable("xdg-mime")
|
|
||||||
.addArguments("query", "default", mimeType)
|
|
||||||
.executeAndGetFirstLineOfOutput();
|
.executeAndGetFirstLineOfOutput();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -383,16 +432,14 @@ public class LinuxHelper {
|
|||||||
|
|
||||||
String arch = archs.get(type);
|
String arch = archs.get(type);
|
||||||
if (arch == null) {
|
if (arch == null) {
|
||||||
Executor exec = new Executor();
|
Executor exec = null;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LINUX_DEB:
|
case LINUX_DEB:
|
||||||
exec.setExecutable("dpkg").addArgument(
|
exec = Executor.of("dpkg", "--print-architecture");
|
||||||
"--print-architecture");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case LINUX_RPM:
|
case LINUX_RPM:
|
||||||
exec.setExecutable("rpmbuild").addArgument(
|
exec = Executor.of("rpmbuild", "--eval=%{_target_cpu}");
|
||||||
"--eval=%{_target_cpu}");
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
arch = exec.executeAndGetFirstLineOfOutput();
|
arch = exec.executeAndGetFirstLineOfOutput();
|
||||||
|
@ -29,6 +29,7 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
@ -39,6 +40,7 @@ import javax.xml.xpath.XPathConstants;
|
|||||||
import javax.xml.xpath.XPathFactory;
|
import javax.xml.xpath.XPathFactory;
|
||||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||||
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||||
|
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
|
|
||||||
public class MacHelper {
|
public class MacHelper {
|
||||||
@ -47,10 +49,12 @@ public class MacHelper {
|
|||||||
ThrowingConsumer<Path> consumer) {
|
ThrowingConsumer<Path> consumer) {
|
||||||
cmd.verifyIsOfType(PackageType.MAC_DMG);
|
cmd.verifyIsOfType(PackageType.MAC_DMG);
|
||||||
|
|
||||||
var plist = readPList(new Executor()
|
// Explode DMG assuming this can require interaction, thus use `yes`.
|
||||||
.setExecutable("/usr/bin/hdiutil")
|
var plist = readPList(Executor.of("sh", "-c",
|
||||||
|
String.join(" ", "yes", "|", "/usr/bin/hdiutil", "attach",
|
||||||
|
JPackageCommand.escapeAndJoin(
|
||||||
|
cmd.outputBundle().toString()), "-plist"))
|
||||||
.dumpOutput()
|
.dumpOutput()
|
||||||
.addArguments("attach", cmd.outputBundle().toString(), "-plist")
|
|
||||||
.executeAndGetOutput());
|
.executeAndGetOutput());
|
||||||
|
|
||||||
final Path mountPoint = Path.of(plist.queryValue("mount-point"));
|
final Path mountPoint = Path.of(plist.queryValue("mount-point"));
|
||||||
@ -60,10 +64,7 @@ public class MacHelper {
|
|||||||
cmd.outputBundle(), dmgImage));
|
cmd.outputBundle(), dmgImage));
|
||||||
ThrowingConsumer.toConsumer(consumer).accept(dmgImage);
|
ThrowingConsumer.toConsumer(consumer).accept(dmgImage);
|
||||||
} finally {
|
} finally {
|
||||||
new Executor()
|
Executor.of("/usr/bin/hdiutil", "detach").addArgument(mountPoint).execute();
|
||||||
.setExecutable("/usr/bin/hdiutil")
|
|
||||||
.addArgument("detach").addArgument(mountPoint)
|
|
||||||
.execute().assertExitCodeIsZero();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,8 +83,62 @@ public class MacHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static PListWrapper readPList(Stream<String> lines) {
|
public static PListWrapper readPList(Stream<String> lines) {
|
||||||
return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines.collect(
|
return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines
|
||||||
Collectors.joining()))).get();
|
// Skip leading lines before xml declaration
|
||||||
|
.dropWhile(Pattern.compile("\\s?<\\?xml\\b.+\\?>").asPredicate().negate())
|
||||||
|
.collect(Collectors.joining()))).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createDmgPackageHandlers() {
|
||||||
|
PackageHandlers dmg = new PackageHandlers();
|
||||||
|
|
||||||
|
dmg.installHandler = cmd -> {
|
||||||
|
withExplodedDmg(cmd, dmgImage -> {
|
||||||
|
Executor.of("sudo", "cp", "-r")
|
||||||
|
.addArgument(dmgImage)
|
||||||
|
.addArgument("/Applications")
|
||||||
|
.execute();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
dmg.unpackHandler = (cmd, destinationDir) -> {
|
||||||
|
Path[] unpackedFolder = new Path[1];
|
||||||
|
withExplodedDmg(cmd, dmgImage -> {
|
||||||
|
Executor.of("cp", "-r")
|
||||||
|
.addArgument(dmgImage)
|
||||||
|
.addArgument(destinationDir)
|
||||||
|
.execute();
|
||||||
|
unpackedFolder[0] = destinationDir.resolve(dmgImage.getFileName());
|
||||||
|
});
|
||||||
|
return unpackedFolder[0];
|
||||||
|
};
|
||||||
|
dmg.uninstallHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.MAC_DMG);
|
||||||
|
Executor.of("sudo", "rm", "-rf")
|
||||||
|
.addArgument(cmd.appInstallationDirectory())
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
return dmg;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createPkgPackageHandlers() {
|
||||||
|
PackageHandlers pkg = new PackageHandlers();
|
||||||
|
|
||||||
|
pkg.installHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||||
|
Executor.of("sudo", "/usr/sbin/installer", "-allowUntrusted", "-pkg")
|
||||||
|
.addArgument(cmd.outputBundle())
|
||||||
|
.addArguments("-target", "/")
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
|
pkg.uninstallHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.MAC_PKG);
|
||||||
|
Executor.of("sudo", "rm", "-rf")
|
||||||
|
.addArgument(cmd.appInstallationDirectory())
|
||||||
|
.execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
return pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getBundleName(JPackageCommand cmd) {
|
static String getBundleName(JPackageCommand cmd) {
|
||||||
|
@ -28,14 +28,13 @@ import java.io.File;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.*;
|
||||||
import java.util.function.Consumer;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||||
import jdk.incubator.jpackage.internal.AppImageFile;
|
import jdk.incubator.jpackage.internal.AppImageFile;
|
||||||
|
import jdk.jpackage.test.Functional.ThrowingBiConsumer;
|
||||||
|
import jdk.jpackage.test.Functional.ThrowingRunnable;
|
||||||
import static jdk.jpackage.test.PackageType.*;
|
import static jdk.jpackage.test.PackageType.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,25 +44,16 @@ import static jdk.jpackage.test.PackageType.*;
|
|||||||
* Provides methods to hook up custom configuration of jpackage command and
|
* Provides methods to hook up custom configuration of jpackage command and
|
||||||
* verification of the output bundle.
|
* verification of the output bundle.
|
||||||
*/
|
*/
|
||||||
public final class PackageTest {
|
public final class PackageTest extends RunnablePackageTest {
|
||||||
|
|
||||||
/**
|
|
||||||
* Default test configuration for jpackage command. Default jpackage command
|
|
||||||
* initialization includes:
|
|
||||||
* <li>Set --input and --dest parameters.
|
|
||||||
* <li>Set --name parameter. Value of the parameter is the name of the first
|
|
||||||
* class with main function found in the callers stack. Defaults can be
|
|
||||||
* overridden with custom initializers set with subsequent addInitializer()
|
|
||||||
* function calls.
|
|
||||||
*/
|
|
||||||
public PackageTest() {
|
public PackageTest() {
|
||||||
action = DEFAULT_ACTION;
|
|
||||||
excludeTypes = new HashSet<>();
|
excludeTypes = new HashSet<>();
|
||||||
forTypes();
|
forTypes();
|
||||||
setExpectedExitCode(0);
|
setExpectedExitCode(0);
|
||||||
handlers = new HashMap<>();
|
|
||||||
namedInitializers = new HashSet<>();
|
namedInitializers = new HashSet<>();
|
||||||
currentTypes.forEach(v -> handlers.put(v, new Handler(v)));
|
handlers = currentTypes.stream()
|
||||||
|
.collect(Collectors.toMap(v -> v, v -> new Handler()));
|
||||||
|
packageHandlers = createDefaultPackageHandlers();
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest excludeTypes(PackageType... types) {
|
public PackageTest excludeTypes(PackageType... types) {
|
||||||
@ -117,19 +107,37 @@ public final class PackageTest {
|
|||||||
|
|
||||||
namedInitializers.add(id);
|
namedInitializers.add(id);
|
||||||
}
|
}
|
||||||
currentTypes.stream().forEach(type -> handlers.get(type).addInitializer(
|
currentTypes.forEach(type -> handlers.get(type).addInitializer(
|
||||||
ThrowingConsumer.toConsumer(v)));
|
ThrowingConsumer.toConsumer(v)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private PackageTest addRunOnceInitializer(ThrowingRunnable v, String id) {
|
||||||
|
return addInitializer(new ThrowingConsumer<JPackageCommand>() {
|
||||||
|
@Override
|
||||||
|
public void accept(JPackageCommand unused) throws Throwable {
|
||||||
|
if (!executed) {
|
||||||
|
executed = true;
|
||||||
|
v.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean executed;
|
||||||
|
}, id);
|
||||||
|
}
|
||||||
|
|
||||||
public PackageTest addInitializer(ThrowingConsumer<JPackageCommand> v) {
|
public PackageTest addInitializer(ThrowingConsumer<JPackageCommand> v) {
|
||||||
return addInitializer(v, null);
|
return addInitializer(v, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public PackageTest addRunOnceInitializer(ThrowingRunnable v) {
|
||||||
|
return addRunOnceInitializer(v, null);
|
||||||
|
}
|
||||||
|
|
||||||
public PackageTest addBundleVerifier(
|
public PackageTest addBundleVerifier(
|
||||||
BiConsumer<JPackageCommand, Executor.Result> v) {
|
ThrowingBiConsumer<JPackageCommand, Executor.Result> v) {
|
||||||
currentTypes.stream().forEach(
|
currentTypes.forEach(type -> handlers.get(type).addBundleVerifier(
|
||||||
type -> handlers.get(type).addBundleVerifier(v));
|
ThrowingBiConsumer.toBiConsumer(v)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,19 +147,26 @@ public final class PackageTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest addBundlePropertyVerifier(String propertyName,
|
public PackageTest addBundlePropertyVerifier(String propertyName,
|
||||||
BiConsumer<String, String> pred) {
|
Predicate<String> pred, String predLabel) {
|
||||||
return addBundleVerifier(cmd -> {
|
return addBundleVerifier(cmd -> {
|
||||||
pred.accept(propertyName,
|
final String value;
|
||||||
LinuxHelper.getBundleProperty(cmd, propertyName));
|
if (TKit.isLinux()) {
|
||||||
|
value = LinuxHelper.getBundleProperty(cmd, propertyName);
|
||||||
|
} else if (TKit.isWindows()) {
|
||||||
|
value = WindowsHelper.getMsiProperty(cmd, propertyName);
|
||||||
|
} else {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
TKit.assertTrue(pred.test(value), String.format(
|
||||||
|
"Check value of %s property %s [%s]", propertyName,
|
||||||
|
predLabel, value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest addBundlePropertyVerifier(String propertyName,
|
public PackageTest addBundlePropertyVerifier(String propertyName,
|
||||||
String expectedPropertyValue) {
|
String expectedPropertyValue) {
|
||||||
return addBundlePropertyVerifier(propertyName, (unused, v) -> {
|
return addBundlePropertyVerifier(propertyName,
|
||||||
TKit.assertEquals(expectedPropertyValue, v, String.format(
|
expectedPropertyValue::equals, "is");
|
||||||
"Check value of %s property is [%s]", propertyName, v));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest addBundleDesktopIntegrationVerifier(boolean integrated) {
|
public PackageTest addBundleDesktopIntegrationVerifier(boolean integrated) {
|
||||||
@ -162,24 +177,39 @@ public final class PackageTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest addInstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
public PackageTest addInstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
||||||
currentTypes.stream().forEach(
|
currentTypes.forEach(type -> handlers.get(type).addInstallVerifier(
|
||||||
type -> handlers.get(type).addInstallVerifier(
|
ThrowingConsumer.toConsumer(v)));
|
||||||
ThrowingConsumer.toConsumer(v)));
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest addUninstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
public PackageTest addUninstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
||||||
currentTypes.stream().forEach(
|
currentTypes.forEach(type -> handlers.get(type).addUninstallVerifier(
|
||||||
type -> handlers.get(type).addUninstallVerifier(
|
ThrowingConsumer.toConsumer(v)));
|
||||||
ThrowingConsumer.toConsumer(v)));
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackageTest setPackageInstaller(Consumer<JPackageCommand> v) {
|
||||||
|
currentTypes.forEach(
|
||||||
|
type -> packageHandlers.get(type).installHandler = v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackageTest setPackageUnpacker(
|
||||||
|
BiFunction<JPackageCommand, Path, Path> v) {
|
||||||
|
currentTypes.forEach(type -> packageHandlers.get(type).unpackHandler = v);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackageTest setPackageUninstaller(Consumer<JPackageCommand> v) {
|
||||||
|
currentTypes.forEach(
|
||||||
|
type -> packageHandlers.get(type).uninstallHandler = v);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void withTestFileAssociationsFile(FileAssociations fa,
|
static void withTestFileAssociationsFile(FileAssociations fa,
|
||||||
ThrowingConsumer<Path> consumer) {
|
ThrowingConsumer<Path> consumer) {
|
||||||
final String testFileDefaultName = String.join(".", "test",
|
final Path testFileDefaultName = Path.of("test" + fa.getSuffix());
|
||||||
fa.getSuffix());
|
TKit.withTempFile(testFileDefaultName, testFile -> {
|
||||||
TKit.withTempFile(testFileDefaultName, fa.getSuffix(), testFile -> {
|
|
||||||
if (TKit.isLinux()) {
|
if (TKit.isLinux()) {
|
||||||
LinuxHelper.initFileAssociationsTestFile(testFile);
|
LinuxHelper.initFileAssociationsTestFile(testFile);
|
||||||
}
|
}
|
||||||
@ -192,7 +222,7 @@ public final class PackageTest {
|
|||||||
|
|
||||||
// Setup test app to have valid jpackage command line before
|
// Setup test app to have valid jpackage command line before
|
||||||
// running check of type of environment.
|
// running check of type of environment.
|
||||||
addInitializer(cmd -> new HelloApp(null).addTo(cmd), "HelloApp");
|
addHelloAppInitializer(null);
|
||||||
|
|
||||||
String noActionMsg = "Not running file associations test";
|
String noActionMsg = "Not running file associations test";
|
||||||
if (GraphicsEnvironment.isHeadless()) {
|
if (GraphicsEnvironment.isHeadless()) {
|
||||||
@ -202,7 +232,7 @@ public final class PackageTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
addInstallVerifier(cmd -> {
|
addInstallVerifier(cmd -> {
|
||||||
if (cmd.isFakeRuntime(noActionMsg)) {
|
if (cmd.isFakeRuntime(noActionMsg) || cmd.isPackageUnpacked(noActionMsg)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +255,8 @@ public final class PackageTest {
|
|||||||
// Wait a little bit after file has been created to
|
// Wait a little bit after file has been created to
|
||||||
// make sure there are no pending writes into it.
|
// make sure there are no pending writes into it.
|
||||||
Thread.sleep(3000);
|
Thread.sleep(3000);
|
||||||
HelloApp.verifyOutputFile(appOutput, expectedArgs);
|
HelloApp.verifyOutputFile(appOutput, expectedArgs,
|
||||||
|
Collections.emptyMap());
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -236,7 +267,7 @@ public final class PackageTest {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageTest forTypes(Collection<PackageType> types, Runnable action) {
|
public PackageTest forTypes(Collection<PackageType> types, Runnable action) {
|
||||||
Set<PackageType> oldTypes = Set.of(currentTypes.toArray(
|
Set<PackageType> oldTypes = Set.of(currentTypes.toArray(
|
||||||
PackageType[]::new));
|
PackageType[]::new));
|
||||||
try {
|
try {
|
||||||
@ -248,17 +279,17 @@ public final class PackageTest {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageTest forTypes(PackageType type, Runnable action) {
|
public PackageTest forTypes(PackageType type, Runnable action) {
|
||||||
return forTypes(List.of(type), action);
|
return forTypes(List.of(type), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageTest notForTypes(Collection<PackageType> types, Runnable action) {
|
public PackageTest notForTypes(Collection<PackageType> types, Runnable action) {
|
||||||
Set<PackageType> workset = new HashSet<>(currentTypes);
|
Set<PackageType> workset = new HashSet<>(currentTypes);
|
||||||
workset.removeAll(types);
|
workset.removeAll(types);
|
||||||
return forTypes(workset, action);
|
return forTypes(workset, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
PackageTest notForTypes(PackageType type, Runnable action) {
|
public PackageTest notForTypes(PackageType type, Runnable action) {
|
||||||
return notForTypes(List.of(type), action);
|
return notForTypes(List.of(type), action);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,55 +297,167 @@ public final class PackageTest {
|
|||||||
return configureHelloApp(null);
|
return configureHelloApp(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest configureHelloApp(String encodedName) {
|
public PackageTest configureHelloApp(String javaAppDesc) {
|
||||||
addInitializer(
|
addHelloAppInitializer(javaAppDesc);
|
||||||
cmd -> new HelloApp(JavaAppDesc.parse(encodedName)).addTo(cmd));
|
|
||||||
addInstallVerifier(HelloApp::executeLauncherAndVerifyOutput);
|
addInstallVerifier(HelloApp::executeLauncherAndVerifyOutput);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public final static class Group extends RunnablePackageTest {
|
||||||
List<Handler> supportedHandlers = handlers.values().stream()
|
public Group(PackageTest... tests) {
|
||||||
.filter(entry -> !entry.isVoid())
|
handlers = Stream.of(tests)
|
||||||
.collect(Collectors.toList());
|
.map(PackageTest::createPackageTypeHandlers)
|
||||||
|
.flatMap(List<Consumer<Action>>::stream)
|
||||||
if (supportedHandlers.isEmpty()) {
|
.collect(Collectors.toUnmodifiableList());
|
||||||
// No handlers with initializers found. Nothing to do.
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Supplier<JPackageCommand> initializer = new Supplier<>() {
|
@Override
|
||||||
@Override
|
protected void runAction(Action... action) {
|
||||||
public JPackageCommand get() {
|
if (Set.of(action).contains(Action.UNINSTALL)) {
|
||||||
JPackageCommand cmd = new JPackageCommand().setDefaultInputOutput();
|
ListIterator<Consumer<Action>> listIterator = handlers.listIterator(
|
||||||
if (bundleOutputDir != null) {
|
handlers.size());
|
||||||
cmd.setArgumentValue("--dest", bundleOutputDir.toString());
|
while (listIterator.hasPrevious()) {
|
||||||
|
var handler = listIterator.previous();
|
||||||
|
List.of(action).forEach(handler::accept);
|
||||||
}
|
}
|
||||||
cmd.setDefaultAppName();
|
} else {
|
||||||
return cmd;
|
handlers.forEach(handler -> List.of(action).forEach(handler::accept));
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
supportedHandlers.forEach(handler -> handler.accept(initializer.get()));
|
private final List<Consumer<Action>> handlers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PackageTest setAction(Action value) {
|
final static class PackageHandlers {
|
||||||
action = value;
|
Consumer<JPackageCommand> installHandler;
|
||||||
return this;
|
Consumer<JPackageCommand> uninstallHandler;
|
||||||
|
BiFunction<JPackageCommand, Path, Path> unpackHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Action getAction() {
|
@Override
|
||||||
return action;
|
protected void runActions(List<Action[]> actions) {
|
||||||
|
createPackageTypeHandlers().forEach(
|
||||||
|
handler -> actions.forEach(
|
||||||
|
action -> List.of(action).forEach(handler::accept)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Handler implements Consumer<JPackageCommand> {
|
@Override
|
||||||
|
protected void runAction(Action... action) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
Handler(PackageType type) {
|
private void addHelloAppInitializer(String javaAppDesc) {
|
||||||
if (!PackageType.NATIVE.contains(type)) {
|
addInitializer(
|
||||||
throw new IllegalArgumentException(
|
cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd),
|
||||||
"Attempt to configure a test for image packaging");
|
"HelloApp");
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Consumer<Action>> createPackageTypeHandlers() {
|
||||||
|
return PackageType.NATIVE.stream()
|
||||||
|
.map(type -> {
|
||||||
|
Handler handler = handlers.entrySet().stream()
|
||||||
|
.filter(entry -> !entry.getValue().isVoid())
|
||||||
|
.filter(entry -> entry.getKey() == type)
|
||||||
|
.map(entry -> entry.getValue())
|
||||||
|
.findAny().orElse(null);
|
||||||
|
Map.Entry<PackageType, Handler> result = null;
|
||||||
|
if (handler != null) {
|
||||||
|
result = Map.entry(type, handler);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.map(entry -> createPackageTypeHandler(
|
||||||
|
entry.getKey(), entry.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Consumer<Action> createPackageTypeHandler(
|
||||||
|
PackageType type, Handler handler) {
|
||||||
|
return ThrowingConsumer.toConsumer(new ThrowingConsumer<Action>() {
|
||||||
|
@Override
|
||||||
|
public void accept(Action action) throws Throwable {
|
||||||
|
if (action == Action.FINALIZE) {
|
||||||
|
if (unpackDir != null && Files.isDirectory(unpackDir)
|
||||||
|
&& !unpackDir.startsWith(TKit.workDir())) {
|
||||||
|
TKit.deleteDirectoryRecursive(unpackDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aborted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final JPackageCommand curCmd;
|
||||||
|
if (Set.of(Action.INITIALIZE, Action.CREATE).contains(action)) {
|
||||||
|
curCmd = cmd;
|
||||||
|
} else {
|
||||||
|
curCmd = cmd.createImmutableCopy();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (action) {
|
||||||
|
case UNPACK: {
|
||||||
|
var handler = packageHandlers.get(type).unpackHandler;
|
||||||
|
if (!(aborted = (handler == null))) {
|
||||||
|
unpackDir = TKit.createTempDirectory(
|
||||||
|
String.format("unpacked-%s",
|
||||||
|
type.getName()));
|
||||||
|
unpackDir = handler.apply(cmd, unpackDir);
|
||||||
|
cmd.setUnpackedPackageLocation(unpackDir);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case INSTALL: {
|
||||||
|
var handler = packageHandlers.get(type).installHandler;
|
||||||
|
if (!(aborted = (handler == null))) {
|
||||||
|
handler.accept(curCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case UNINSTALL: {
|
||||||
|
var handler = packageHandlers.get(type).uninstallHandler;
|
||||||
|
if (!(aborted = (handler == null))) {
|
||||||
|
handler.accept(curCmd);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case CREATE:
|
||||||
|
handler.accept(action, curCmd);
|
||||||
|
aborted = (expectedJPackageExitCode != 0);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
handler.accept(action, curCmd);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aborted) {
|
||||||
|
TKit.trace(
|
||||||
|
String.format("Aborted [%s] action of %s command",
|
||||||
|
action, cmd.getPrintableCommandLine()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.type = type;
|
|
||||||
|
private Path unpackDir;
|
||||||
|
private boolean aborted;
|
||||||
|
private final JPackageCommand cmd = Functional.identity(() -> {
|
||||||
|
JPackageCommand result = new JPackageCommand();
|
||||||
|
result.setDefaultInputOutput().setDefaultAppName();
|
||||||
|
if (BUNDLE_OUTPUT_DIR != null) {
|
||||||
|
result.setArgumentValue("--dest", BUNDLE_OUTPUT_DIR.toString());
|
||||||
|
}
|
||||||
|
type.applyTo(result);
|
||||||
|
return result;
|
||||||
|
}).get();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Handler implements BiConsumer<Action, JPackageCommand> {
|
||||||
|
|
||||||
|
Handler() {
|
||||||
initializers = new ArrayList<>();
|
initializers = new ArrayList<>();
|
||||||
bundleVerifiers = new ArrayList<>();
|
bundleVerifiers = new ArrayList<>();
|
||||||
installVerifiers = new ArrayList<>();
|
installVerifiers = new ArrayList<>();
|
||||||
@ -342,33 +485,35 @@ public final class PackageTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void accept(JPackageCommand cmd) {
|
public void accept(Action action, JPackageCommand cmd) {
|
||||||
type.applyTo(cmd);
|
|
||||||
|
|
||||||
initializers.stream().forEach(v -> v.accept(cmd));
|
|
||||||
cmd.executePrerequisiteActions();
|
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
|
case INITIALIZE:
|
||||||
|
initializers.forEach(v -> v.accept(cmd));
|
||||||
|
if (cmd.isImagePackageType()) {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
cmd.executePrerequisiteActions();
|
||||||
|
break;
|
||||||
|
|
||||||
case CREATE:
|
case CREATE:
|
||||||
Executor.Result result = cmd.execute();
|
Executor.Result result = cmd.execute(expectedJPackageExitCode);
|
||||||
result.assertExitCodeIs(expectedJPackageExitCode);
|
|
||||||
if (expectedJPackageExitCode == 0) {
|
if (expectedJPackageExitCode == 0) {
|
||||||
TKit.assertFileExists(cmd.outputBundle());
|
TKit.assertFileExists(cmd.outputBundle());
|
||||||
} else {
|
} else {
|
||||||
TKit.assertPathExists(cmd.outputBundle(), false);
|
TKit.assertPathExists(cmd.outputBundle(), false);
|
||||||
}
|
}
|
||||||
verifyPackageBundle(cmd.createImmutableCopy(), result);
|
verifyPackageBundle(cmd, result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VERIFY_INSTALL:
|
case VERIFY_INSTALL:
|
||||||
if (expectedJPackageExitCode == 0) {
|
if (expectedJPackageExitCode == 0) {
|
||||||
verifyPackageInstalled(cmd.createImmutableCopy());
|
verifyPackageInstalled(cmd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case VERIFY_UNINSTALL:
|
case VERIFY_UNINSTALL:
|
||||||
if (expectedJPackageExitCode == 0) {
|
if (expectedJPackageExitCode == 0) {
|
||||||
verifyPackageUninstalled(cmd.createImmutableCopy());
|
verifyPackageUninstalled(cmd);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -381,25 +526,33 @@ public final class PackageTest {
|
|||||||
LinuxHelper.verifyPackageBundleEssential(cmd);
|
LinuxHelper.verifyPackageBundleEssential(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bundleVerifiers.stream().forEach(v -> v.accept(cmd, result));
|
bundleVerifiers.forEach(v -> v.accept(cmd, result));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyPackageInstalled(JPackageCommand cmd) {
|
private void verifyPackageInstalled(JPackageCommand cmd) {
|
||||||
TKit.trace(String.format("Verify installed: %s",
|
final String formatString;
|
||||||
cmd.getPrintableCommandLine()));
|
if (cmd.isPackageUnpacked()) {
|
||||||
|
formatString = "Verify unpacked: %s";
|
||||||
|
} else {
|
||||||
|
formatString = "Verify installed: %s";
|
||||||
|
}
|
||||||
|
TKit.trace(String.format(formatString, cmd.getPrintableCommandLine()));
|
||||||
|
|
||||||
TKit.assertDirectoryExists(cmd.appRuntimeDirectory());
|
TKit.assertDirectoryExists(cmd.appRuntimeDirectory());
|
||||||
if (!cmd.isRuntime()) {
|
if (!cmd.isRuntime()) {
|
||||||
TKit.assertExecutableFileExists(cmd.appLauncherPath());
|
TKit.assertExecutableFileExists(cmd.appLauncherPath());
|
||||||
|
|
||||||
if (PackageType.WINDOWS.contains(cmd.packageType())) {
|
if (PackageType.WINDOWS.contains(cmd.packageType())
|
||||||
new WindowsHelper.AppVerifier(cmd);
|
&& !cmd.isPackageUnpacked(
|
||||||
|
"Not verifying desktop integration")) {
|
||||||
|
new WindowsHelper.DesktopIntegrationVerifier(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TKit.assertPathExists(AppImageFile.getPathInAppImage(
|
TKit.assertPathExists(AppImageFile.getPathInAppImage(
|
||||||
cmd.appInstallationDirectory()), false);
|
cmd.appInstallationDirectory()), false);
|
||||||
|
|
||||||
installVerifiers.stream().forEach(v -> v.accept(cmd));
|
installVerifiers.forEach(v -> v.accept(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyPackageUninstalled(JPackageCommand cmd) {
|
private void verifyPackageUninstalled(JPackageCommand cmd) {
|
||||||
@ -409,79 +562,63 @@ public final class PackageTest {
|
|||||||
TKit.assertPathExists(cmd.appLauncherPath(), false);
|
TKit.assertPathExists(cmd.appLauncherPath(), false);
|
||||||
|
|
||||||
if (PackageType.WINDOWS.contains(cmd.packageType())) {
|
if (PackageType.WINDOWS.contains(cmd.packageType())) {
|
||||||
new WindowsHelper.AppVerifier(cmd);
|
new WindowsHelper.DesktopIntegrationVerifier(cmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TKit.assertPathExists(cmd.appInstallationDirectory(), false);
|
TKit.assertPathExists(cmd.appInstallationDirectory(), false);
|
||||||
|
|
||||||
uninstallVerifiers.stream().forEach(v -> v.accept(cmd));
|
uninstallVerifiers.forEach(v -> v.accept(cmd));
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PackageType type;
|
|
||||||
private final List<Consumer<JPackageCommand>> initializers;
|
private final List<Consumer<JPackageCommand>> initializers;
|
||||||
private final List<BiConsumer<JPackageCommand, Executor.Result>> bundleVerifiers;
|
private final List<BiConsumer<JPackageCommand, Executor.Result>> bundleVerifiers;
|
||||||
private final List<Consumer<JPackageCommand>> installVerifiers;
|
private final List<Consumer<JPackageCommand>> installVerifiers;
|
||||||
private final List<Consumer<JPackageCommand>> uninstallVerifiers;
|
private final List<Consumer<JPackageCommand>> uninstallVerifiers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Map<PackageType, PackageHandlers> createDefaultPackageHandlers() {
|
||||||
|
HashMap<PackageType, PackageHandlers> handlers = new HashMap<>();
|
||||||
|
if (TKit.isLinux()) {
|
||||||
|
handlers.put(PackageType.LINUX_DEB, LinuxHelper.createDebPackageHandlers());
|
||||||
|
handlers.put(PackageType.LINUX_RPM, LinuxHelper.createRpmPackageHandlers());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TKit.isWindows()) {
|
||||||
|
handlers.put(PackageType.WIN_MSI, WindowsHelper.createMsiPackageHandlers());
|
||||||
|
handlers.put(PackageType.WIN_EXE, WindowsHelper.createExePackageHandlers());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TKit.isOSX()) {
|
||||||
|
handlers.put(PackageType.MAC_DMG, MacHelper.createDmgPackageHandlers());
|
||||||
|
handlers.put(PackageType.MAC_PKG, MacHelper.createPkgPackageHandlers());
|
||||||
|
}
|
||||||
|
|
||||||
|
return handlers;
|
||||||
|
}
|
||||||
|
|
||||||
private Collection<PackageType> currentTypes;
|
private Collection<PackageType> currentTypes;
|
||||||
private Set<PackageType> excludeTypes;
|
private Set<PackageType> excludeTypes;
|
||||||
private int expectedJPackageExitCode;
|
private int expectedJPackageExitCode;
|
||||||
private Map<PackageType, Handler> handlers;
|
private Map<PackageType, Handler> handlers;
|
||||||
private Set<String> namedInitializers;
|
private Set<String> namedInitializers;
|
||||||
private Action action;
|
private Map<PackageType, PackageHandlers> packageHandlers;
|
||||||
|
|
||||||
/**
|
private final static File BUNDLE_OUTPUT_DIR;
|
||||||
* Test action.
|
|
||||||
*/
|
|
||||||
static public enum Action {
|
|
||||||
/**
|
|
||||||
* Create bundle.
|
|
||||||
*/
|
|
||||||
CREATE,
|
|
||||||
/**
|
|
||||||
* Verify bundle installed.
|
|
||||||
*/
|
|
||||||
VERIFY_INSTALL,
|
|
||||||
/**
|
|
||||||
* Verify bundle uninstalled.
|
|
||||||
*/
|
|
||||||
VERIFY_UNINSTALL;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return name().toLowerCase().replace('_', '-');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
private final static Action DEFAULT_ACTION;
|
|
||||||
private final static File bundleOutputDir;
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
final String propertyName = "output";
|
final String propertyName = "output";
|
||||||
String val = TKit.getConfigProperty(propertyName);
|
String val = TKit.getConfigProperty(propertyName);
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
bundleOutputDir = null;
|
BUNDLE_OUTPUT_DIR = null;
|
||||||
} else {
|
} else {
|
||||||
bundleOutputDir = new File(val).getAbsoluteFile();
|
BUNDLE_OUTPUT_DIR = new File(val).getAbsoluteFile();
|
||||||
|
|
||||||
if (!bundleOutputDir.isDirectory()) {
|
if (!BUNDLE_OUTPUT_DIR.isDirectory()) {
|
||||||
throw new IllegalArgumentException(String.format(
|
throw new IllegalArgumentException(String.format("Invalid value of %s sytem property: [%s]. Should be existing directory",
|
||||||
"Invalid value of %s sytem property: [%s]. Should be existing directory",
|
|
||||||
TKit.getConfigPropertyName(propertyName),
|
TKit.getConfigPropertyName(propertyName),
|
||||||
bundleOutputDir));
|
BUNDLE_OUTPUT_DIR));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
|
||||||
final String propertyName = "action";
|
|
||||||
String action = Optional.ofNullable(TKit.getConfigProperty(propertyName)).orElse(
|
|
||||||
Action.CREATE.toString()).toLowerCase();
|
|
||||||
DEFAULT_ACTION = Stream.of(Action.values()).filter(
|
|
||||||
a -> a.toString().equals(action)).findFirst().orElseThrow(
|
|
||||||
() -> new IllegalArgumentException(String.format(
|
|
||||||
"Unrecognized value of %s property: [%s]",
|
|
||||||
TKit.getConfigPropertyName(propertyName), action)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ public enum PackageType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void applyTo(JPackageCommand cmd) {
|
void applyTo(JPackageCommand cmd) {
|
||||||
cmd.addArguments("--type", getName());
|
cmd.setArgumentValue("--type", getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
String getSuffix() {
|
String getSuffix() {
|
||||||
|
@ -52,7 +52,7 @@ final public class TKit {
|
|||||||
|
|
||||||
for (int i = 0; i != 10; ++i) {
|
for (int i = 0; i != 10; ++i) {
|
||||||
if (root.resolve("apps").toFile().isDirectory()) {
|
if (root.resolve("apps").toFile().isDirectory()) {
|
||||||
return root.toAbsolutePath();
|
return root.normalize().toAbsolutePath();
|
||||||
}
|
}
|
||||||
root = root.resolve("..");
|
root = root.resolve("..");
|
||||||
}
|
}
|
||||||
@ -60,6 +60,10 @@ final public class TKit {
|
|||||||
throw new RuntimeException("Failed to locate apps directory");
|
throw new RuntimeException("Failed to locate apps directory");
|
||||||
}).get();
|
}).get();
|
||||||
|
|
||||||
|
public static final Path SRC_ROOT = Functional.identity(() -> {
|
||||||
|
return TEST_SRC_ROOT.resolve("../../../../src/jdk.incubator.jpackage").normalize().toAbsolutePath();
|
||||||
|
}).get();
|
||||||
|
|
||||||
public final static String ICON_SUFFIX = Functional.identity(() -> {
|
public final static String ICON_SUFFIX = Functional.identity(() -> {
|
||||||
if (isOSX()) {
|
if (isOSX()) {
|
||||||
return ".icns";
|
return ".icns";
|
||||||
@ -150,14 +154,6 @@ final public class TKit {
|
|||||||
return currentTest.workDir();
|
return currentTest.workDir();
|
||||||
}
|
}
|
||||||
|
|
||||||
static Path defaultInputDir() {
|
|
||||||
return workDir().resolve("input");
|
|
||||||
}
|
|
||||||
|
|
||||||
static Path defaultOutputDir() {
|
|
||||||
return workDir().resolve("output");
|
|
||||||
}
|
|
||||||
|
|
||||||
static String getCurrentDefaultAppName() {
|
static String getCurrentDefaultAppName() {
|
||||||
// Construct app name from swapping and joining test base name
|
// Construct app name from swapping and joining test base name
|
||||||
// and test function name.
|
// and test function name.
|
||||||
@ -275,18 +271,16 @@ final public class TKit {
|
|||||||
return Files.createDirectory(createUniqueFileName(role));
|
return Files.createDirectory(createUniqueFileName(role));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path createTempFile(String role, String suffix) throws
|
public static Path createTempFile(Path templateFile) throws
|
||||||
IOException {
|
IOException {
|
||||||
if (role == null) {
|
return Files.createFile(createUniqueFileName(
|
||||||
return Files.createTempFile(workDir(), TEMP_FILE_PREFIX, suffix);
|
templateFile.getFileName().toString()));
|
||||||
}
|
|
||||||
return Files.createFile(createUniqueFileName(role));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Path withTempFile(String role, String suffix,
|
public static Path withTempFile(Path templateFile,
|
||||||
ThrowingConsumer<Path> action) {
|
ThrowingConsumer<Path> action) {
|
||||||
final Path tempFile = ThrowingSupplier.toSupplier(() -> createTempFile(
|
final Path tempFile = ThrowingSupplier.toSupplier(() -> createTempFile(
|
||||||
role, suffix)).get();
|
templateFile)).get();
|
||||||
boolean keepIt = true;
|
boolean keepIt = true;
|
||||||
try {
|
try {
|
||||||
ThrowingConsumer.toConsumer(action).accept(tempFile);
|
ThrowingConsumer.toConsumer(action).accept(tempFile);
|
||||||
@ -449,10 +443,11 @@ final public class TKit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Path createRelativePathCopy(final Path file) {
|
public static Path createRelativePathCopy(final Path file) {
|
||||||
Path fileCopy = workDir().resolve(file.getFileName()).toAbsolutePath().normalize();
|
Path fileCopy = ThrowingSupplier.toSupplier(() -> {
|
||||||
|
Path localPath = createTempFile(file);
|
||||||
ThrowingRunnable.toRunnable(() -> Files.copy(file, fileCopy,
|
Files.copy(file, localPath, StandardCopyOption.REPLACE_EXISTING);
|
||||||
StandardCopyOption.REPLACE_EXISTING)).run();
|
return localPath;
|
||||||
|
}).get().toAbsolutePath().normalize();
|
||||||
|
|
||||||
final Path basePath = Path.of(".").toAbsolutePath().normalize();
|
final Path basePath = Path.of(".").toAbsolutePath().normalize();
|
||||||
try {
|
try {
|
||||||
@ -713,32 +708,32 @@ final public class TKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public final static class TextStreamAsserter {
|
public final static class TextStreamVerifier {
|
||||||
TextStreamAsserter(String value) {
|
TextStreamVerifier(String value) {
|
||||||
this.value = value;
|
this.value = value;
|
||||||
predicate(String::contains);
|
predicate(String::contains);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextStreamAsserter label(String v) {
|
public TextStreamVerifier label(String v) {
|
||||||
label = v;
|
label = v;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextStreamAsserter predicate(BiPredicate<String, String> v) {
|
public TextStreamVerifier predicate(BiPredicate<String, String> v) {
|
||||||
predicate = v;
|
predicate = v;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextStreamAsserter negate() {
|
public TextStreamVerifier negate() {
|
||||||
negate = true;
|
negate = true;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextStreamAsserter orElseThrow(RuntimeException v) {
|
public TextStreamVerifier orElseThrow(RuntimeException v) {
|
||||||
return orElseThrow(() -> v);
|
return orElseThrow(() -> v);
|
||||||
}
|
}
|
||||||
|
|
||||||
public TextStreamAsserter orElseThrow(Supplier<RuntimeException> v) {
|
public TextStreamVerifier orElseThrow(Supplier<RuntimeException> v) {
|
||||||
createException = v;
|
createException = v;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -779,8 +774,8 @@ final public class TKit {
|
|||||||
final private String value;
|
final private String value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TextStreamAsserter assertTextStream(String what) {
|
public static TextStreamVerifier assertTextStream(String what) {
|
||||||
return new TextStreamAsserter(what);
|
return new TextStreamVerifier(what);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PrintStream openLogStream() {
|
private static PrintStream openLogStream() {
|
||||||
@ -809,13 +804,23 @@ final public class TKit {
|
|||||||
return "jpackage.test." + propertyName;
|
return "jpackage.test." + propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Set<String> tokenizeConfigProperty(String propertyName) {
|
static List<String> tokenizeConfigPropertyAsList(String propertyName) {
|
||||||
final String val = TKit.getConfigProperty(propertyName);
|
final String val = TKit.getConfigProperty(propertyName);
|
||||||
if (val == null) {
|
if (val == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return Stream.of(val.toLowerCase().split(",")).map(String::strip).filter(
|
return Stream.of(val.toLowerCase().split(","))
|
||||||
Predicate.not(String::isEmpty)).collect(Collectors.toSet());
|
.map(String::strip)
|
||||||
|
.filter(Predicate.not(String::isEmpty))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
static Set<String> tokenizeConfigProperty(String propertyName) {
|
||||||
|
List<String> tokens = tokenizeConfigPropertyAsList(propertyName);
|
||||||
|
if (tokens == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return tokens.stream().collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
static final Path LOG_FILE = Functional.identity(() -> {
|
static final Path LOG_FILE = Functional.identity(() -> {
|
||||||
|
@ -68,11 +68,11 @@ final class TestBuilder implements AutoCloseable {
|
|||||||
|
|
||||||
CMDLINE_ARG_PREFIX + "exclude",
|
CMDLINE_ARG_PREFIX + "exclude",
|
||||||
arg -> (excludedTests = Optional.ofNullable(
|
arg -> (excludedTests = Optional.ofNullable(
|
||||||
excludedTests).orElse(new HashSet<String>())).add(arg),
|
excludedTests).orElseGet(() -> new HashSet<String>())).add(arg),
|
||||||
|
|
||||||
CMDLINE_ARG_PREFIX + "include",
|
CMDLINE_ARG_PREFIX + "include",
|
||||||
arg -> (includedTests = Optional.ofNullable(
|
arg -> (includedTests = Optional.ofNullable(
|
||||||
includedTests).orElse(new HashSet<String>())).add(arg),
|
includedTests).orElseGet(() -> new HashSet<String>())).add(arg),
|
||||||
|
|
||||||
CMDLINE_ARG_PREFIX + "space-subst",
|
CMDLINE_ARG_PREFIX + "space-subst",
|
||||||
arg -> spaceSubstitute = arg,
|
arg -> spaceSubstitute = arg,
|
||||||
@ -127,8 +127,7 @@ final class TestBuilder implements AutoCloseable {
|
|||||||
// Log all matches before returning from the function
|
// Log all matches before returning from the function
|
||||||
return tests.filter(test -> {
|
return tests.filter(test -> {
|
||||||
String testDescription = test.createDescription().testFullName();
|
String testDescription = test.createDescription().testFullName();
|
||||||
boolean match = filters.stream().anyMatch(
|
boolean match = filters.stream().anyMatch(testDescription::contains);
|
||||||
v -> testDescription.contains(v));
|
|
||||||
if (match) {
|
if (match) {
|
||||||
trace(String.format(logMsg + ": %s", testDescription));
|
trace(String.format(logMsg + ": %s", testDescription));
|
||||||
}
|
}
|
||||||
@ -159,7 +158,7 @@ final class TestBuilder implements AutoCloseable {
|
|||||||
|
|
||||||
private void flushTestGroup() {
|
private void flushTestGroup() {
|
||||||
if (testGroup != null) {
|
if (testGroup != null) {
|
||||||
filterTestGroup().forEach(testBody -> createTestInstance(testBody));
|
filterTestGroup().forEach(this::createTestInstance);
|
||||||
clear();
|
clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -170,7 +169,7 @@ final class TestBuilder implements AutoCloseable {
|
|||||||
|
|
||||||
Method testMethod = testBody.getMethod();
|
Method testMethod = testBody.getMethod();
|
||||||
if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch(
|
if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch(
|
||||||
type -> testMethod.isAnnotationPresent(type))) {
|
testMethod::isAnnotationPresent)) {
|
||||||
curBeforeActions = beforeActions;
|
curBeforeActions = beforeActions;
|
||||||
curAfterActions = afterActions;
|
curAfterActions = afterActions;
|
||||||
} else {
|
} else {
|
||||||
@ -286,7 +285,7 @@ final class TestBuilder implements AutoCloseable {
|
|||||||
List<Method> methods = Stream.of(methodClass.getMethods()).filter(
|
List<Method> methods = Stream.of(methodClass.getMethods()).filter(
|
||||||
(m) -> filterMethod(methodName, m)).collect(Collectors.toList());
|
(m) -> filterMethod(methodName, m)).collect(Collectors.toList());
|
||||||
if (methods.isEmpty()) {
|
if (methods.isEmpty()) {
|
||||||
new ParseException(String.format(
|
throw new ParseException(String.format(
|
||||||
"Method [%s] not found in [%s] class;",
|
"Method [%s] not found in [%s] class;",
|
||||||
methodName, className));
|
methodName, className));
|
||||||
}
|
}
|
||||||
|
@ -236,7 +236,13 @@ final class TestInstance implements ThrowingRunnable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!KEEP_WORK_DIR.contains(status)) {
|
if (!KEEP_WORK_DIR.contains(status)) {
|
||||||
TKit.deleteDirectoryRecursive(workDir);
|
if (Files.isSameFile(workDir, Path.of("."))) {
|
||||||
|
// 1. If the work directory is the current directory, don't
|
||||||
|
// delete it, just clean as deleting it would be confusing.
|
||||||
|
TKit.deleteDirectoryContentsRecursive(workDir);
|
||||||
|
} else {
|
||||||
|
TKit.deleteDirectoryRecursive(workDir);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TKit.log(String.format("%s %s; checks=%d", status, fullName,
|
TKit.log(String.format("%s %s; checks=%d", status, fullName,
|
||||||
|
@ -26,8 +26,11 @@ import java.io.IOException;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import jdk.jpackage.test.Functional.ThrowingRunnable;
|
||||||
|
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||||
|
|
||||||
public class WindowsHelper {
|
public class WindowsHelper {
|
||||||
|
|
||||||
@ -38,22 +41,82 @@ public class WindowsHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Path getInstallationDirectory(JPackageCommand cmd) {
|
static Path getInstallationDirectory(JPackageCommand cmd) {
|
||||||
cmd.verifyIsOfType(PackageType.WINDOWS);
|
Path installSubDir = getInstallationSubDirectory(cmd);
|
||||||
Path installDir = Path.of(
|
|
||||||
cmd.getArgumentValue("--install-dir", () -> cmd.name()));
|
|
||||||
if (isUserLocalInstall(cmd)) {
|
if (isUserLocalInstall(cmd)) {
|
||||||
return USER_LOCAL.resolve(installDir);
|
return USER_LOCAL.resolve(installSubDir);
|
||||||
}
|
}
|
||||||
return PROGRAM_FILES.resolve(installDir);
|
return PROGRAM_FILES.resolve(installSubDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Path getInstallationSubDirectory(JPackageCommand cmd) {
|
||||||
|
cmd.verifyIsOfType(PackageType.WINDOWS);
|
||||||
|
return Path.of(cmd.getArgumentValue("--install-dir", () -> cmd.name()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void runMsiexecWithRetries(Executor misexec) {
|
||||||
|
Executor.Result result = null;
|
||||||
|
for (int attempt = 0; attempt != 3; ++attempt) {
|
||||||
|
result = misexec.executeWithoutExitCodeCheck();
|
||||||
|
if (result.exitCode == 1618) {
|
||||||
|
// Another installation is already in progress.
|
||||||
|
// Wait a little and try again.
|
||||||
|
ThrowingRunnable.toRunnable(() -> Thread.sleep(3000)).run();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.assertExitCodeIsZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createMsiPackageHandlers() {
|
||||||
|
BiConsumer<JPackageCommand, Boolean> installMsi = (cmd, install) -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.WIN_MSI);
|
||||||
|
runMsiexecWithRetries(Executor.of("msiexec", "/qn", "/norestart",
|
||||||
|
install ? "/i" : "/x").addArgument(cmd.outputBundle()));
|
||||||
|
};
|
||||||
|
|
||||||
|
PackageHandlers msi = new PackageHandlers();
|
||||||
|
msi.installHandler = cmd -> installMsi.accept(cmd, true);
|
||||||
|
msi.uninstallHandler = cmd -> installMsi.accept(cmd, false);
|
||||||
|
msi.unpackHandler = (cmd, destinationDir) -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.WIN_MSI);
|
||||||
|
runMsiexecWithRetries(Executor.of("msiexec", "/a")
|
||||||
|
.addArgument(cmd.outputBundle().normalize())
|
||||||
|
.addArguments("/qn", String.format("TARGETDIR=%s",
|
||||||
|
destinationDir.toAbsolutePath().normalize())));
|
||||||
|
return destinationDir.resolve(getInstallationSubDirectory(cmd));
|
||||||
|
};
|
||||||
|
return msi;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PackageHandlers createExePackageHandlers() {
|
||||||
|
PackageHandlers exe = new PackageHandlers();
|
||||||
|
exe.installHandler = cmd -> {
|
||||||
|
cmd.verifyIsOfType(PackageType.WIN_EXE);
|
||||||
|
new Executor().setExecutable(cmd.outputBundle()).execute();
|
||||||
|
};
|
||||||
|
|
||||||
|
return exe;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getMsiProperty(JPackageCommand cmd, String propertyName) {
|
||||||
|
cmd.verifyIsOfType(PackageType.WIN_MSI);
|
||||||
|
return Executor.of("cscript.exe", "//Nologo")
|
||||||
|
.addArgument(TKit.TEST_SRC_ROOT.resolve("resources/query-msi-property.js"))
|
||||||
|
.addArgument(cmd.outputBundle())
|
||||||
|
.addArgument(propertyName)
|
||||||
|
.dumpOutput()
|
||||||
|
.executeAndGetOutput().stream().collect(Collectors.joining("\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isUserLocalInstall(JPackageCommand cmd) {
|
private static boolean isUserLocalInstall(JPackageCommand cmd) {
|
||||||
return cmd.hasArgument("--win-per-user-install");
|
return cmd.hasArgument("--win-per-user-install");
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AppVerifier {
|
static class DesktopIntegrationVerifier {
|
||||||
|
|
||||||
AppVerifier(JPackageCommand cmd) {
|
DesktopIntegrationVerifier(JPackageCommand cmd) {
|
||||||
cmd.verifyIsOfType(PackageType.WINDOWS);
|
cmd.verifyIsOfType(PackageType.WINDOWS);
|
||||||
this.cmd = cmd;
|
this.cmd = cmd;
|
||||||
verifyStartMenuShortcut();
|
verifyStartMenuShortcut();
|
||||||
@ -201,16 +264,15 @@ public class WindowsHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String queryRegistryValue(String keyPath, String valueName) {
|
private static String queryRegistryValue(String keyPath, String valueName) {
|
||||||
Executor.Result status = new Executor()
|
var status = Executor.of("reg", "query", keyPath, "/v", valueName)
|
||||||
.setExecutable("reg")
|
|
||||||
.saveOutput()
|
.saveOutput()
|
||||||
.addArguments("query", keyPath, "/v", valueName)
|
.executeWithoutExitCodeCheck();
|
||||||
.execute();
|
|
||||||
if (status.exitCode == 1) {
|
if (status.exitCode == 1) {
|
||||||
// Should be the case of no such registry value or key
|
// Should be the case of no such registry value or key
|
||||||
String lookupString = "ERROR: The system was unable to find the specified registry key or value.";
|
String lookupString = "ERROR: The system was unable to find the specified registry key or value.";
|
||||||
status.getOutput().stream().filter(line -> line.equals(lookupString)).findFirst().orElseThrow(
|
TKit.assertTextStream(lookupString)
|
||||||
() -> new RuntimeException(String.format(
|
.predicate(String::equals)
|
||||||
|
.orElseThrow(() -> new RuntimeException(String.format(
|
||||||
"Failed to find [%s] string in the output",
|
"Failed to find [%s] string in the output",
|
||||||
lookupString)));
|
lookupString)));
|
||||||
TKit.trace(String.format(
|
TKit.trace(String.format(
|
||||||
|
@ -56,12 +56,10 @@ public class MaintainerTest {
|
|||||||
.addInitializer(cmd -> {
|
.addInitializer(cmd -> {
|
||||||
cmd.addArguments("--linux-deb-maintainer", MAINTAINER);
|
cmd.addArguments("--linux-deb-maintainer", MAINTAINER);
|
||||||
})
|
})
|
||||||
.addBundlePropertyVerifier("Maintainer", (propName, propValue) -> {
|
.addBundlePropertyVerifier("Maintainer", value -> {
|
||||||
String lookupValue = "<" + MAINTAINER + ">";
|
String lookupValue = "<" + MAINTAINER + ">";
|
||||||
TKit.assertTrue(propValue.endsWith(lookupValue),
|
return value.endsWith(lookupValue);
|
||||||
String.format("Check value of %s property [%s] ends with %s",
|
}, "ends with")
|
||||||
propName, propValue, lookupValue));
|
|
||||||
})
|
|
||||||
.run();
|
.run();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import jdk.jpackage.test.TKit;
|
|||||||
import jdk.jpackage.test.PackageTest;
|
import jdk.jpackage.test.PackageTest;
|
||||||
import jdk.jpackage.test.PackageType;
|
import jdk.jpackage.test.PackageType;
|
||||||
import jdk.jpackage.test.LinuxHelper;
|
import jdk.jpackage.test.LinuxHelper;
|
||||||
|
import jdk.jpackage.test.Annotations.Test;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,41 +51,38 @@ import jdk.jpackage.test.LinuxHelper;
|
|||||||
* @build jdk.jpackage.test.*
|
* @build jdk.jpackage.test.*
|
||||||
* @requires (os.family == "linux")
|
* @requires (os.family == "linux")
|
||||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||||
* @run main/othervm/timeout=360 -Xmx512m PackageDepsTest
|
* @compile PackageDepsTest.java
|
||||||
|
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||||
|
* --jpt-run=PackageDepsTest
|
||||||
*/
|
*/
|
||||||
public class PackageDepsTest {
|
public class PackageDepsTest {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
@Test
|
||||||
// Pick the name of prerequisite package to be alphabetically
|
public static void test() {
|
||||||
// preceeding the main package name.
|
|
||||||
// This is needed to make Bash script batch installing/uninstalling packages
|
|
||||||
// produced by jtreg tests install/uninstall packages in the right order.
|
|
||||||
final String PREREQ_PACKAGE_NAME = "apackagedepstestprereq";
|
final String PREREQ_PACKAGE_NAME = "apackagedepstestprereq";
|
||||||
|
|
||||||
TKit.run(args, () -> {
|
PackageTest test1 = new PackageTest()
|
||||||
new PackageTest()
|
.forTypes(PackageType.LINUX)
|
||||||
.forTypes(PackageType.LINUX)
|
.configureHelloApp()
|
||||||
.configureHelloApp()
|
.addInitializer(cmd -> {
|
||||||
.addInitializer(cmd -> {
|
cmd.setArgumentValue("--name", PREREQ_PACKAGE_NAME);
|
||||||
cmd.setArgumentValue("--name", PREREQ_PACKAGE_NAME);
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
|
|
||||||
new PackageTest()
|
|
||||||
.forTypes(PackageType.LINUX)
|
|
||||||
.configureHelloApp()
|
|
||||||
.addInitializer(cmd -> {
|
|
||||||
cmd.addArguments("--linux-package-deps", PREREQ_PACKAGE_NAME);
|
|
||||||
})
|
|
||||||
.forTypes(PackageType.LINUX)
|
|
||||||
.addBundleVerifier(cmd -> {
|
|
||||||
TKit.assertTrue(
|
|
||||||
LinuxHelper.getPrerequisitePackages(cmd).contains(
|
|
||||||
PREREQ_PACKAGE_NAME), String.format(
|
|
||||||
"Check package depends on [%s] package",
|
|
||||||
PREREQ_PACKAGE_NAME));
|
|
||||||
})
|
|
||||||
.run();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
PackageTest test2 = new PackageTest()
|
||||||
|
.forTypes(PackageType.LINUX)
|
||||||
|
.configureHelloApp()
|
||||||
|
.addInitializer(cmd -> {
|
||||||
|
cmd.addArguments("--linux-package-deps", PREREQ_PACKAGE_NAME);
|
||||||
|
})
|
||||||
|
.forTypes(PackageType.LINUX)
|
||||||
|
.addBundleVerifier(cmd -> {
|
||||||
|
TKit.assertTrue(
|
||||||
|
LinuxHelper.getPrerequisitePackages(cmd).contains(
|
||||||
|
PREREQ_PACKAGE_NAME), String.format(
|
||||||
|
"Check package depends on [%s] package",
|
||||||
|
PREREQ_PACKAGE_NAME));
|
||||||
|
});
|
||||||
|
|
||||||
|
new PackageTest.Group(test1, test2).run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,11 +64,9 @@ public class ReleaseTest {
|
|||||||
.forTypes(PackageType.LINUX_RPM)
|
.forTypes(PackageType.LINUX_RPM)
|
||||||
.addBundlePropertyVerifier("Release", RELEASE)
|
.addBundlePropertyVerifier("Release", RELEASE)
|
||||||
.forTypes(PackageType.LINUX_DEB)
|
.forTypes(PackageType.LINUX_DEB)
|
||||||
.addBundlePropertyVerifier("Version", (propName, propValue) -> {
|
.addBundlePropertyVerifier("Version", propValue -> {
|
||||||
TKit.assertTrue(propValue.endsWith("-" + RELEASE),
|
return propValue.endsWith("-" + RELEASE);
|
||||||
String.format("Check value of %s property [%s] ends with %s",
|
}, "ends with")
|
||||||
propName, propValue, RELEASE));
|
|
||||||
})
|
|
||||||
.run();
|
.run();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,12 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import jdk.jpackage.test.AdditionalLauncher;
|
||||||
import jdk.jpackage.test.FileAssociations;
|
import jdk.jpackage.test.FileAssociations;
|
||||||
import jdk.jpackage.test.PackageType;
|
import jdk.jpackage.test.PackageType;
|
||||||
import jdk.jpackage.test.PackageTest;
|
import jdk.jpackage.test.PackageTest;
|
||||||
@ -127,56 +127,50 @@ public class ShortcutHintTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public static void testAdditionaltLaunchers() {
|
public static void testAdditionaltLaunchers() {
|
||||||
createTest().addInitializer(cmd -> {
|
PackageTest test = createTest();
|
||||||
cmd.setFakeRuntime();
|
|
||||||
|
|
||||||
final String launcherName = "Foo";
|
new AdditionalLauncher("Foo").setIcon(TKit.TEST_SRC_ROOT.resolve(
|
||||||
final Path propsFile = TKit.workDir().resolve(
|
"apps/dukeplug.png")).applyTo(test);
|
||||||
launcherName + ".properties");
|
|
||||||
|
|
||||||
cmd.addArguments("--add-launcher", String.format("%s=%s",
|
test.addInitializer(JPackageCommand::setFakeRuntime).run();
|
||||||
launcherName, propsFile));
|
|
||||||
|
|
||||||
TKit.createPropertiesFile(propsFile, Map.entry("icon",
|
|
||||||
TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png").toString()));
|
|
||||||
}).run();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* .desktop file from resource dir.
|
* .desktop file from resource dir.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public static void testDesktopFileFromResourceDir() {
|
public static void testDesktopFileFromResourceDir() throws IOException {
|
||||||
final String expectedVersionString = "Version=12345678";
|
final String expectedVersionString = "Version=12345678";
|
||||||
TKit.withTempDirectory("resources", tempDir -> {
|
|
||||||
createTest().addInitializer(cmd -> {
|
|
||||||
cmd.setFakeRuntime();
|
|
||||||
|
|
||||||
cmd.addArgument("--linux-shortcut");
|
final Path tempDir = TKit.createTempDirectory("resources");
|
||||||
cmd.addArguments("--resource-dir", tempDir);
|
|
||||||
|
|
||||||
// Create custom .desktop file in resource directory
|
createTest().addInitializer(cmd -> {
|
||||||
TKit.createTextFile(tempDir.resolve(cmd.name() + ".desktop"),
|
cmd.setFakeRuntime();
|
||||||
List.of(
|
|
||||||
"[Desktop Entry]",
|
cmd.addArgument("--linux-shortcut");
|
||||||
"Name=APPLICATION_NAME",
|
cmd.addArguments("--resource-dir", tempDir);
|
||||||
"Exec=APPLICATION_LAUNCHER",
|
|
||||||
"Terminal=false",
|
// Create custom .desktop file in resource directory
|
||||||
"Type=Application",
|
TKit.createTextFile(tempDir.resolve(cmd.name() + ".desktop"),
|
||||||
"Categories=DEPLOY_BUNDLE_CATEGORY",
|
List.of(
|
||||||
expectedVersionString
|
"[Desktop Entry]",
|
||||||
));
|
"Name=APPLICATION_NAME",
|
||||||
})
|
"Exec=APPLICATION_LAUNCHER",
|
||||||
.addInstallVerifier(cmd -> {
|
"Terminal=false",
|
||||||
Path desktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
"Type=Application",
|
||||||
String.format("%s-%s.desktop",
|
"Categories=DEPLOY_BUNDLE_CATEGORY",
|
||||||
LinuxHelper.getPackageName(cmd), cmd.name()));
|
expectedVersionString
|
||||||
TKit.assertFileExists(desktopFile);
|
));
|
||||||
TKit.assertTextStream(expectedVersionString)
|
})
|
||||||
.label(String.format("[%s] file", desktopFile))
|
.addInstallVerifier(cmd -> {
|
||||||
.predicate(String::equals)
|
Path desktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
||||||
.apply(Files.readAllLines(desktopFile).stream());
|
String.format("%s-%s.desktop",
|
||||||
}).run();
|
LinuxHelper.getPackageName(cmd), cmd.name()));
|
||||||
});
|
TKit.assertFileExists(desktopFile);
|
||||||
|
TKit.assertTextStream(expectedVersionString)
|
||||||
|
.label(String.format("[%s] file", desktopFile))
|
||||||
|
.predicate(String::equals)
|
||||||
|
.apply(Files.readAllLines(desktopFile).stream());
|
||||||
|
}).run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,8 +48,7 @@ public class SigningBase {
|
|||||||
.addArguments("--verify", "--deep", "--strict", "--verbose=2",
|
.addArguments("--verify", "--deep", "--strict", "--verbose=2",
|
||||||
target.toString())
|
target.toString())
|
||||||
.saveOutput()
|
.saveOutput()
|
||||||
.execute()
|
.execute(exitCode).getOutput();
|
||||||
.assertExitCodeIs(exitCode).getOutput();
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 3.6 KiB |
@ -41,7 +41,7 @@ find_all_packaging_tests ()
|
|||||||
|
|
||||||
help_usage ()
|
help_usage ()
|
||||||
{
|
{
|
||||||
echo "Usage: `basename $0` [options] [test_names]"
|
echo "Usage: `basename $0` [options] [--] [jtreg_options|test_names]"
|
||||||
echo "Options:"
|
echo "Options:"
|
||||||
echo " -h - print this message"
|
echo " -h - print this message"
|
||||||
echo " -v - verbose output"
|
echo " -v - verbose output"
|
||||||
@ -58,16 +58,12 @@ help_usage ()
|
|||||||
echo ' -l <logfile> - value for `jpackage.test.logfile` property.'
|
echo ' -l <logfile> - value for `jpackage.test.logfile` property.'
|
||||||
echo " Optional, for jtreg tests debug purposes only."
|
echo " Optional, for jtreg tests debug purposes only."
|
||||||
echo " -m <mode> - mode to run jtreg tests."
|
echo " -m <mode> - mode to run jtreg tests."
|
||||||
echo ' Should be one of `create`, `update`, `verify-install` or `verify-uninstall`.'
|
echo ' Should be one of `create`, `update` or `print-default-tests`.'
|
||||||
echo ' Optional, default mode is `update`.'
|
echo ' Optional, default mode is `update`.'
|
||||||
echo ' - `create`'
|
echo ' - `create`'
|
||||||
echo ' Remove all package bundles from the output directory before running jtreg tests.'
|
echo ' Remove all package bundles from the output directory before running jtreg tests.'
|
||||||
echo ' - `update`'
|
echo ' - `update`'
|
||||||
echo ' Run jtreg tests and overrite existing package bundles in the output directory.'
|
echo ' Run jtreg tests and overrite existing package bundles in the output directory.'
|
||||||
echo ' - `verify-install`'
|
|
||||||
echo ' Verify installed packages created with the previous run of the script.'
|
|
||||||
echo ' - `verify-uninstall`'
|
|
||||||
echo ' Verify packages created with the previous run of the script were uninstalled cleanly.'
|
|
||||||
echo ' - `print-default-tests`'
|
echo ' - `print-default-tests`'
|
||||||
echo ' Print default list of packaging tests and exit.'
|
echo ' Print default list of packaging tests and exit.'
|
||||||
}
|
}
|
||||||
@ -135,7 +131,10 @@ mode=update
|
|||||||
# jtreg extra arguments
|
# jtreg extra arguments
|
||||||
declare -a jtreg_args
|
declare -a jtreg_args
|
||||||
|
|
||||||
# Run all tests
|
# Create packages only
|
||||||
|
jtreg_args+=("-Djpackage.test.action=create")
|
||||||
|
|
||||||
|
# run all tests
|
||||||
run_all_tests=
|
run_all_tests=
|
||||||
|
|
||||||
mapfile -t tests < <(find_all_packaging_tests)
|
mapfile -t tests < <(find_all_packaging_tests)
|
||||||
@ -206,10 +205,6 @@ if [ "$mode" = create ]; then
|
|||||||
true
|
true
|
||||||
elif [ "$mode" = update ]; then
|
elif [ "$mode" = update ]; then
|
||||||
true
|
true
|
||||||
elif [ "$mode" = verify-install ]; then
|
|
||||||
jtreg_args+=("-Djpackage.test.action=$mode")
|
|
||||||
elif [ "$mode" = verify-uninstall ]; then
|
|
||||||
jtreg_args+=("-Djpackage.test.action=$mode")
|
|
||||||
else
|
else
|
||||||
fatal_with_help_usage 'Invalid value of -m option:' [$mode]
|
fatal_with_help_usage 'Invalid value of -m option:' [$mode]
|
||||||
fi
|
fi
|
||||||
@ -218,7 +213,11 @@ if [ -z "$run_all_tests" ]; then
|
|||||||
jtreg_args+=(-Djpackage.test.SQETest=yes)
|
jtreg_args+=(-Djpackage.test.SQETest=yes)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# All remaining command line arguments are tests to run that should override the defaults
|
# Drop arguments separator
|
||||||
|
[ "$1" != "--" ] || shift
|
||||||
|
|
||||||
|
# All remaining command line arguments are tests to run
|
||||||
|
# that should override the defaults and explicit jtreg arguments
|
||||||
[ $# -eq 0 ] || tests=($@)
|
[ $# -eq 0 ] || tests=($@)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,12 +27,8 @@ import java.util.Map;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.lang.invoke.MethodHandles;
|
import java.lang.invoke.MethodHandles;
|
||||||
import jdk.jpackage.test.HelloApp;
|
import jdk.jpackage.test.*;
|
||||||
import jdk.jpackage.test.PackageTest;
|
import jdk.jpackage.test.Annotations.*;
|
||||||
import jdk.jpackage.test.PackageType;
|
|
||||||
import jdk.jpackage.test.FileAssociations;
|
|
||||||
import jdk.jpackage.test.Annotations.Test;
|
|
||||||
import jdk.jpackage.test.TKit;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test --add-launcher parameter. Output of the test should be
|
* Test --add-launcher parameter. Output of the test should be
|
||||||
@ -46,11 +42,25 @@ import jdk.jpackage.test.TKit;
|
|||||||
* @test
|
* @test
|
||||||
* @summary jpackage with --add-launcher
|
* @summary jpackage with --add-launcher
|
||||||
* @key jpackagePlatformPackage
|
* @key jpackagePlatformPackage
|
||||||
|
* @requires (jpackage.test.SQETest != null)
|
||||||
* @library ../helpers
|
* @library ../helpers
|
||||||
* @build jdk.jpackage.test.*
|
* @build jdk.jpackage.test.*
|
||||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||||
* @compile AdditionalLaunchersTest.java
|
* @compile AdditionalLaunchersTest.java
|
||||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||||
|
* --jpt-run=AdditionalLaunchersTest.test
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary jpackage with --add-launcher
|
||||||
|
* @key jpackagePlatformPackage
|
||||||
|
* @requires (jpackage.test.SQETest == null)
|
||||||
|
* @library ../helpers
|
||||||
|
* @build jdk.jpackage.test.*
|
||||||
|
* @modules jdk.jpackage/jdk.jpackage.internal
|
||||||
|
* @compile AdditionalLaunchersTest.java
|
||||||
|
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
|
||||||
* --jpt-run=AdditionalLaunchersTest
|
* --jpt-run=AdditionalLaunchersTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -72,87 +82,122 @@ public class AdditionalLaunchersTest {
|
|||||||
MethodHandles.lookup().lookupClass().getSimpleName()).applyTo(
|
MethodHandles.lookup().lookupClass().getSimpleName()).applyTo(
|
||||||
packageTest);
|
packageTest);
|
||||||
|
|
||||||
new AdditionalLauncher("Baz2").setArguments().applyTo(packageTest);
|
new AdditionalLauncher("Baz2")
|
||||||
new AdditionalLauncher("foo").setArguments("yep!").applyTo(packageTest);
|
.setDefaultArguments()
|
||||||
|
.applyTo(packageTest);
|
||||||
|
|
||||||
AdditionalLauncher barLauncher = new AdditionalLauncher("Bar").setArguments(
|
new AdditionalLauncher("foo")
|
||||||
"one", "two", "three");
|
.setDefaultArguments("yep!")
|
||||||
if (TKit.isLinux()) {
|
.applyTo(packageTest);
|
||||||
barLauncher.setIcon(TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png"));
|
|
||||||
}
|
new AdditionalLauncher("Bar")
|
||||||
barLauncher.applyTo(packageTest);
|
.setDefaultArguments("one", "two", "three")
|
||||||
|
.setIcon(GOLDEN_ICON)
|
||||||
|
.applyTo(packageTest);
|
||||||
|
|
||||||
packageTest.run();
|
packageTest.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Path replaceFileName(Path path, String newFileName) {
|
@Test
|
||||||
String fname = path.getFileName().toString();
|
public void bug8230933() {
|
||||||
int lastDotIndex = fname.lastIndexOf(".");
|
PackageTest packageTest = new PackageTest().configureHelloApp();
|
||||||
if (lastDotIndex != -1) {
|
|
||||||
fname = newFileName + fname.substring(lastDotIndex);
|
new AdditionalLauncher("default_icon")
|
||||||
|
.applyTo(packageTest);
|
||||||
|
|
||||||
|
new AdditionalLauncher("no_icon")
|
||||||
|
.setNoIcon().applyTo(packageTest);
|
||||||
|
|
||||||
|
new AdditionalLauncher("custom_icon")
|
||||||
|
.setIcon(GOLDEN_ICON)
|
||||||
|
.applyTo(packageTest);
|
||||||
|
|
||||||
|
packageTest.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
// Regular app
|
||||||
|
@Parameter("Hello")
|
||||||
|
// Modular app
|
||||||
|
@Parameter("com.other/com.other.CiaoBella")
|
||||||
|
public void testJavaOptions(String javaAppDesc) {
|
||||||
|
JPackageCommand cmd = JPackageCommand.helloAppImage(javaAppDesc)
|
||||||
|
.addArguments("--arguments", "courageous")
|
||||||
|
.addArguments("--java-options", "-Dparam1=xxx")
|
||||||
|
.addArguments("--java-options", "-Dparam2=yyy")
|
||||||
|
.addArguments("--java-options", "-Dparam3=zzz");
|
||||||
|
|
||||||
|
new AdditionalLauncher("Jack")
|
||||||
|
.addDefaultArguments("Jack of All Trades", "Master of None")
|
||||||
|
.setJavaOptions("-Dparam1=Contractor")
|
||||||
|
.applyTo(cmd);
|
||||||
|
|
||||||
|
new AdditionalLauncher("Monday")
|
||||||
|
.addDefaultArguments("Knock Your", "Socks Off")
|
||||||
|
.setJavaOptions("-Dparam2=Surprise workers!")
|
||||||
|
.applyTo(cmd);
|
||||||
|
|
||||||
|
// Should inherit default arguments and java options from the main launcher
|
||||||
|
new AdditionalLauncher("void").applyTo(cmd);
|
||||||
|
|
||||||
|
cmd.executeAndAssertHelloAppImageCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test usage of modular and non modular apps in additional launchers.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
@Parameter("true")
|
||||||
|
@Parameter("fase")
|
||||||
|
public void testMainLauncherIsModular(boolean mainLauncherIsModular) {
|
||||||
|
final var nonModularAppDesc = JavaAppDesc.parse("a.b.c.Hello");
|
||||||
|
final var modularAppDesc = JavaAppDesc.parse(
|
||||||
|
"module.jar:com.that/com.that.main.Florence");
|
||||||
|
|
||||||
|
final var nonModularJarCmd = JPackageCommand.helloAppImage(nonModularAppDesc);
|
||||||
|
final var modularJarCmd = JPackageCommand.helloAppImage(modularAppDesc);
|
||||||
|
|
||||||
|
final JPackageCommand cmd;
|
||||||
|
if (mainLauncherIsModular) {
|
||||||
|
// Create non modular jar.
|
||||||
|
nonModularJarCmd.executePrerequisiteActions();
|
||||||
|
|
||||||
|
cmd = modularJarCmd;
|
||||||
|
cmd.addArguments("--description",
|
||||||
|
"Test modular app with multiple add-launchers where one is modular app and other is non modular app");
|
||||||
|
cmd.addArguments("--input", nonModularJarCmd.getArgumentValue(
|
||||||
|
"--input"));
|
||||||
} else {
|
} else {
|
||||||
fname = newFileName;
|
// Create modular jar.
|
||||||
|
modularJarCmd.executePrerequisiteActions();
|
||||||
|
|
||||||
|
cmd = nonModularJarCmd;
|
||||||
|
cmd.addArguments("--description",
|
||||||
|
"Test non modular app with multiple add-launchers where one is modular app and other is non modular app");
|
||||||
|
cmd.addArguments("--module-path", modularJarCmd.getArgumentValue(
|
||||||
|
"--module-path"));
|
||||||
|
cmd.addArguments("--add-modules", modularAppDesc.moduleName());
|
||||||
}
|
}
|
||||||
return path.getParent().resolve(fname);
|
|
||||||
|
new AdditionalLauncher("ModularAppLauncher")
|
||||||
|
.addRawProperties(Map.entry("module", JavaAppDesc.parse(
|
||||||
|
modularAppDesc.toString()).setJarFileName(null).toString()))
|
||||||
|
.addRawProperties(Map.entry("main-jar", ""))
|
||||||
|
.applyTo(cmd);
|
||||||
|
|
||||||
|
new AdditionalLauncher("NonModularAppLauncher")
|
||||||
|
// Use space ( ) character instead of equality sign (=) as
|
||||||
|
// a key/value separator
|
||||||
|
.setPersistenceHandler((path, properties) -> TKit.createTextFile(path,
|
||||||
|
properties.stream().map(entry -> String.join(" ", entry.getKey(),
|
||||||
|
entry.getValue()))))
|
||||||
|
.addRawProperties(Map.entry("main-class", nonModularAppDesc.className()))
|
||||||
|
.addRawProperties(Map.entry("main-jar", nonModularAppDesc.jarFileName()))
|
||||||
|
.applyTo(cmd);
|
||||||
|
|
||||||
|
cmd.executeAndAssertHelloAppImageCreated();
|
||||||
}
|
}
|
||||||
|
|
||||||
static class AdditionalLauncher {
|
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
||||||
|
"resources", "icon" + TKit.ICON_SUFFIX));
|
||||||
AdditionalLauncher(String name) {
|
|
||||||
this.name = name;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdditionalLauncher setArguments(String... args) {
|
|
||||||
arguments = List.of(args);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
AdditionalLauncher setIcon(Path iconPath) {
|
|
||||||
icon = iconPath;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void applyTo(PackageTest test) {
|
|
||||||
final Path propsFile = TKit.workDir().resolve(name + ".properties");
|
|
||||||
|
|
||||||
test.addInitializer(cmd -> {
|
|
||||||
cmd.addArguments("--add-launcher", String.format("%s=%s", name,
|
|
||||||
propsFile));
|
|
||||||
|
|
||||||
Map<String, String> properties = new HashMap<>();
|
|
||||||
if (arguments != null) {
|
|
||||||
properties.put("arguments", String.join(" ",
|
|
||||||
arguments.toArray(String[]::new)));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (icon != null) {
|
|
||||||
properties.put("icon", icon.toAbsolutePath().toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
TKit.createPropertiesFile(propsFile, properties);
|
|
||||||
});
|
|
||||||
test.addInstallVerifier(cmd -> {
|
|
||||||
Path launcherPath = replaceFileName(cmd.appLauncherPath(), name);
|
|
||||||
|
|
||||||
TKit.assertExecutableFileExists(launcherPath);
|
|
||||||
|
|
||||||
if (cmd.isFakeRuntime(String.format(
|
|
||||||
"Not running %s launcher", launcherPath))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
HelloApp.executeAndVerifyOutput(launcherPath,
|
|
||||||
Optional.ofNullable(arguments).orElse(List.of()).toArray(
|
|
||||||
String[]::new));
|
|
||||||
});
|
|
||||||
test.addUninstallVerifier(cmd -> {
|
|
||||||
Path launcherPath = replaceFileName(cmd.appLauncherPath(), name);
|
|
||||||
|
|
||||||
TKit.assertPathExists(launcherPath, false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<String> arguments;
|
|
||||||
private Path icon;
|
|
||||||
private final String name;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import jdk.jpackage.test.TKit;
|
import jdk.jpackage.test.TKit;
|
||||||
import jdk.jpackage.test.PackageTest;
|
|
||||||
import jdk.jpackage.test.PackageType;
|
|
||||||
import jdk.jpackage.test.JPackageCommand;
|
import jdk.jpackage.test.JPackageCommand;
|
||||||
|
import jdk.jpackage.test.PackageTest;
|
||||||
|
import jdk.jpackage.test.Annotations.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test --app-image parameter. The output installer should provide the same
|
* Test --app-image parameter. The output installer should provide the same
|
||||||
@ -41,34 +41,24 @@ import jdk.jpackage.test.JPackageCommand;
|
|||||||
* @requires (jpackage.test.SQETest == null)
|
* @requires (jpackage.test.SQETest == null)
|
||||||
* @build jdk.jpackage.test.*
|
* @build jdk.jpackage.test.*
|
||||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||||
* @run main/othervm/timeout=540 -Xmx512m AppImagePackageTest
|
* @compile AppImagePackageTest.java
|
||||||
|
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
|
||||||
|
* --jpt-run=AppImagePackageTest
|
||||||
*/
|
*/
|
||||||
public class AppImagePackageTest {
|
public class AppImagePackageTest {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
@Test
|
||||||
TKit.run(args, () -> {
|
public static void test() {
|
||||||
Path appimageOutput = Path.of("appimage");
|
Path appimageOutput = TKit.workDir().resolve("appimage");
|
||||||
|
|
||||||
JPackageCommand appImageCmd = JPackageCommand.helloAppImage()
|
JPackageCommand appImageCmd = JPackageCommand.helloAppImage()
|
||||||
.setArgumentValue("--dest", appimageOutput)
|
.setArgumentValue("--dest", appimageOutput);
|
||||||
.addArguments("--type", "app-image");
|
|
||||||
|
|
||||||
PackageTest packageTest = new PackageTest();
|
new PackageTest()
|
||||||
if (packageTest.getAction() == PackageTest.Action.CREATE) {
|
.addRunOnceInitializer(() -> appImageCmd.execute())
|
||||||
appImageCmd.execute();
|
.addInitializer(cmd -> {
|
||||||
}
|
cmd.addArguments("--app-image", appImageCmd.outputBundle());
|
||||||
|
cmd.removeArgumentWithValue("--input");
|
||||||
packageTest.addInitializer(cmd -> {
|
}).addBundleDesktopIntegrationVerifier(false).run();
|
||||||
Path appimageInput = appimageOutput.resolve(appImageCmd.name());
|
|
||||||
|
|
||||||
if (PackageType.MAC.contains(cmd.packageType())) {
|
|
||||||
// Why so complicated on macOS?
|
|
||||||
appimageInput = Path.of(appimageInput.toString() + ".app");
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd.addArguments("--app-image", appimageInput);
|
|
||||||
cmd.removeArgumentWithValue("--input");
|
|
||||||
}).addBundleDesktopIntegrationVerifier(false).run();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,9 @@ public class ArgumentsTest {
|
|||||||
Path launcherPath = cmd.appLauncherPath();
|
Path launcherPath = cmd.appLauncherPath();
|
||||||
if (!cmd.isFakeRuntime(String.format(
|
if (!cmd.isFakeRuntime(String.format(
|
||||||
"Not running [%s] launcher", launcherPath))) {
|
"Not running [%s] launcher", launcherPath))) {
|
||||||
HelloApp.executeAndVerifyOutput(launcherPath, TRICKY_ARGUMENTS);
|
HelloApp.assertApp(launcherPath)
|
||||||
|
.addDefaultArguments(TRICKY_ARGUMENTS)
|
||||||
|
.executeAndVerifyOutput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,72 +22,414 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.io.IOException;
|
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.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import jdk.incubator.jpackage.internal.IOUtils;
|
import jdk.jpackage.test.*;
|
||||||
import jdk.jpackage.test.TKit;
|
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||||
import jdk.jpackage.test.Functional;
|
import jdk.jpackage.test.Functional.ThrowingBiConsumer;
|
||||||
import jdk.jpackage.test.Annotations.*;
|
import jdk.jpackage.test.Annotations.*;
|
||||||
import jdk.jpackage.test.JPackageCommand;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @test
|
* @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
|
* @library ../helpers
|
||||||
* @build jdk.jpackage.test.*
|
* @build jdk.jpackage.test.*
|
||||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||||
* @compile IconTest.java
|
* @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
|
* --jpt-run=IconTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class 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)),
|
enum IconType {
|
||||||
StandardCopyOption.REPLACE_EXISTING);
|
/**
|
||||||
|
* 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
|
@Test
|
||||||
@Parameter("true")
|
public void test() throws IOException {
|
||||||
@Parameter("false")
|
if (appImage) {
|
||||||
public static void testParameter(boolean relativePath) throws IOException {
|
JPackageCommand cmd = initAppImageTest();
|
||||||
final Path iconPath;
|
var result = cmd.executeAndAssertImageCreated();
|
||||||
if (relativePath) {
|
ThrowingConsumer.toConsumer(createInstallVerifier()).accept(cmd);
|
||||||
iconPath = TKit.createRelativePathCopy(GOLDEN_ICON);
|
ThrowingBiConsumer.toBiConsumer(createBundleVerifier()).accept(cmd, result);
|
||||||
} else {
|
} else {
|
||||||
iconPath = GOLDEN_ICON;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
testIt(JPackageCommand.helloAppImage().addArguments("--icon", iconPath));
|
return TKit.assertTextStream(lookupString);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String appIconFileName(JPackageCommand cmd) {
|
private ThrowingConsumer<JPackageCommand> createInstallVerifier() {
|
||||||
return IOUtils.replaceSuffix(cmd.appLauncherPath().getFileName(),
|
LauncherIconVerifier verifier = new LauncherIconVerifier();
|
||||||
TKit.ICON_SUFFIX).toString();
|
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 {
|
||||||
|
TKit.assertPathExists(desktopFile, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void testIt(JPackageCommand cmd) throws IOException {
|
private void initTest(JPackageCommand cmd, PackageTest test) {
|
||||||
cmd.executeAndAssertHelloAppImageCreated();
|
config.entrySet().forEach(ThrowingConsumer.toConsumer(entry -> {
|
||||||
|
initTest(entry.getKey(), entry.getValue(), cmd, test);
|
||||||
|
}));
|
||||||
|
|
||||||
Path iconPath = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
ThrowingConsumer<JPackageCommand> initializer = testCmd -> {
|
||||||
appIconFileName(cmd));
|
testCmd.saveConsoleOutput(true);
|
||||||
|
testCmd.setFakeRuntime();
|
||||||
|
testCmd.addArguments(extraJPackageArgs);
|
||||||
|
};
|
||||||
|
|
||||||
TKit.assertFileExists(iconPath);
|
if (test != null) {
|
||||||
TKit.assertTrue(-1 == Files.mismatch(GOLDEN_ICON, iconPath),
|
test.addInitializer(initializer);
|
||||||
String.format(
|
} else {
|
||||||
"Check application icon file [%s] is a copy of source icon file [%s]",
|
ThrowingConsumer.toConsumer(initializer).accept(cmd);
|
||||||
iconPath, GOLDEN_ICON));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
private static void initTest(Launcher cfg, IconType iconType,
|
||||||
"resources", "icon" + TKit.ICON_SUFFIX));
|
JPackageCommand cmd, PackageTest test) throws IOException {
|
||||||
|
Consumer<AdditionalLauncher> addLauncher = v -> {
|
||||||
|
if (test != null) {
|
||||||
|
v.applyTo(test);
|
||||||
|
} else {
|
||||||
|
v.applyTo(cmd);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (iconType) {
|
||||||
|
case DefaultIcon:
|
||||||
|
if (cfg.launcherName != null) {
|
||||||
|
addLauncher.accept(new AdditionalLauncher(cfg.launcherName));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
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[] ICONS = Stream.of("icon", "icon2", "icon3",
|
||||||
|
"icon4")
|
||||||
|
.map(IconTest::iconPath)
|
||||||
|
.collect(Collectors.toList()).toArray(Path[]::new);
|
||||||
}
|
}
|
||||||
|
@ -126,12 +126,8 @@ public class InstallDirTest {
|
|||||||
cmd.saveConsoleOutput(true);
|
cmd.saveConsoleOutput(true);
|
||||||
})
|
})
|
||||||
.addBundleVerifier((cmd, result) -> {
|
.addBundleVerifier((cmd, result) -> {
|
||||||
String errorMessage = JPackageCommand.filterOutput(
|
TKit.assertTextStream(errorMessageSubstring).apply(
|
||||||
result.getOutput().stream()).filter(line -> line.contains(
|
result.getOutput().stream());
|
||||||
errorMessageSubstring)).findFirst().orElse(null);
|
|
||||||
TKit.assertNotNull(errorMessage, String.format(
|
|
||||||
"Check output contains [%s] substring",
|
|
||||||
errorMessageSubstring));
|
|
||||||
})
|
})
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,10 @@ public class LicenseTest {
|
|||||||
verifyLicenseFileInLinuxPackage(cmd, linuxLicenseFile(cmd));
|
verifyLicenseFileInLinuxPackage(cmd, linuxLicenseFile(cmd));
|
||||||
})
|
})
|
||||||
.addInstallVerifier(cmd -> {
|
.addInstallVerifier(cmd -> {
|
||||||
TKit.assertReadableFileExists(linuxLicenseFile(cmd));
|
Path path = linuxLicenseFile(cmd);
|
||||||
|
if (path != null) {
|
||||||
|
TKit.assertReadableFileExists(path);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.addUninstallVerifier(cmd -> {
|
.addUninstallVerifier(cmd -> {
|
||||||
verifyLicenseFileNotInstalledLinux(linuxLicenseFile(cmd));
|
verifyLicenseFileNotInstalledLinux(linuxLicenseFile(cmd));
|
||||||
@ -110,7 +113,10 @@ public class LicenseTest {
|
|||||||
})
|
})
|
||||||
.forTypes(PackageType.LINUX_RPM)
|
.forTypes(PackageType.LINUX_RPM)
|
||||||
.addInstallVerifier(cmd -> {
|
.addInstallVerifier(cmd -> {
|
||||||
verifyLicenseFileInstalledRpm(rpmLicenseFile(cmd));
|
Path path = rpmLicenseFile(cmd);
|
||||||
|
if (path != null) {
|
||||||
|
verifyLicenseFileInstalledRpm(path);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
@ -124,6 +130,10 @@ public class LicenseTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static Path rpmLicenseFile(JPackageCommand cmd) {
|
private static Path rpmLicenseFile(JPackageCommand cmd) {
|
||||||
|
if (cmd.isPackageUnpacked("Not checking for rpm license file")) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
final Path licenseRoot = Path.of(
|
final Path licenseRoot = Path.of(
|
||||||
new Executor()
|
new Executor()
|
||||||
.setExecutable("rpm")
|
.setExecutable("rpm")
|
||||||
@ -236,7 +246,7 @@ public class LicenseTest {
|
|||||||
|
|
||||||
void run() {
|
void run() {
|
||||||
final Path srcLicenseFile = TKit.workDir().resolve("license");
|
final Path srcLicenseFile = TKit.workDir().resolve("license");
|
||||||
new PackageTest().configureHelloApp().forTypes(PackageType.LINUX_DEB)
|
new PackageTest().forTypes(PackageType.LINUX_DEB).configureHelloApp()
|
||||||
.addInitializer(cmd -> {
|
.addInitializer(cmd -> {
|
||||||
// Create source license file.
|
// Create source license file.
|
||||||
Files.write(srcLicenseFile, List.of(
|
Files.write(srcLicenseFile, List.of(
|
||||||
|
@ -30,6 +30,7 @@ import java.util.List;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.function.Supplier;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
@ -119,6 +120,10 @@ public final class BasicTest {
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void testVerbose() {
|
public void testVerbose() {
|
||||||
JPackageCommand cmd = JPackageCommand.helloAppImage()
|
JPackageCommand cmd = JPackageCommand.helloAppImage()
|
||||||
|
// Disable default logic adding `--verbose` option
|
||||||
|
// to jpackage command line.
|
||||||
|
.ignoreDefaultVerbose(true)
|
||||||
|
.saveConsoleOutput(true)
|
||||||
.setFakeRuntime().executePrerequisiteActions();
|
.setFakeRuntime().executePrerequisiteActions();
|
||||||
|
|
||||||
List<String> expectedVerboseOutputStrings = new ArrayList<>();
|
List<String> expectedVerboseOutputStrings = new ArrayList<>();
|
||||||
@ -139,17 +144,17 @@ public final class BasicTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
|
TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
|
||||||
List<String> nonVerboseOutput = cmd.createExecutor().executeAndGetOutput();
|
List<String> nonVerboseOutput = cmd.execute().getOutput();
|
||||||
List<String>[] verboseOutput = (List<String>[])new List<?>[1];
|
List<String>[] verboseOutput = (List<String>[])new List<?>[1];
|
||||||
|
|
||||||
// Directory clean up is not 100% reliable on Windows because of
|
// Directory clean up is not 100% reliable on Windows because of
|
||||||
// antivirus software that can lock .exe files. Setup
|
// antivirus software that can lock .exe files. Setup
|
||||||
// diffreent output directory instead of cleaning the default one for
|
// different output directory instead of cleaning the default one for
|
||||||
// verbose jpackage run.
|
// verbose jpackage run.
|
||||||
TKit.withTempDirectory("verbose-output", tempDir -> {
|
TKit.withTempDirectory("verbose-output", tempDir -> {
|
||||||
cmd.setArgumentValue("--dest", tempDir);
|
cmd.setArgumentValue("--dest", tempDir);
|
||||||
verboseOutput[0] = cmd.createExecutor().addArgument(
|
cmd.addArgument("--verbose");
|
||||||
"--verbose").executeAndGetOutput();
|
verboseOutput[0] = cmd.execute().getOutput();
|
||||||
});
|
});
|
||||||
|
|
||||||
TKit.assertTrue(nonVerboseOutput.size() < verboseOutput[0].size(),
|
TKit.assertTrue(nonVerboseOutput.size() < verboseOutput[0].size(),
|
||||||
@ -189,7 +194,7 @@ public final class BasicTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// Regular app
|
// Regular app
|
||||||
@Parameter("Hello")
|
@Parameter("Hello")
|
||||||
// Modular app
|
// Modular app
|
||||||
@Parameter("com.other/com.other.Hello")
|
@Parameter("com.other/com.other.Hello")
|
||||||
@ -227,62 +232,66 @@ public final class BasicTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testTemp() throws IOException {
|
public void testTemp() throws IOException {
|
||||||
TKit.withTempDirectory("temp-root", tempRoot -> {
|
final Path tempRoot = TKit.createTempDirectory("temp-root");
|
||||||
Function<JPackageCommand, Path> getTempDir = cmd -> {
|
|
||||||
return tempRoot.resolve(cmd.outputBundle().getFileName());
|
|
||||||
};
|
|
||||||
|
|
||||||
ThrowingConsumer<JPackageCommand> addTempDir = cmd -> {
|
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);
|
Path tempDir = getTempDir.apply(cmd);
|
||||||
Files.createDirectories(tempDir);
|
Files.createDirectories(tempDir);
|
||||||
cmd.addArguments("--temp", tempDir);
|
cmd.addArguments("--temp", tempDir);
|
||||||
};
|
});
|
||||||
|
};
|
||||||
|
|
||||||
new PackageTest().configureHelloApp().addInitializer(addTempDir)
|
createTest.get()
|
||||||
.addBundleVerifier(cmd -> {
|
.addBundleVerifier(cmd -> {
|
||||||
// Check jpackage actually used the supplied directory.
|
// Check jpackage actually used the supplied directory.
|
||||||
Path tempDir = getTempDir.apply(cmd);
|
Path tempDir = getTempDir.apply(cmd);
|
||||||
TKit.assertNotEquals(0, tempDir.toFile().list().length,
|
TKit.assertNotEquals(0, tempDir.toFile().list().length,
|
||||||
String.format(
|
String.format(
|
||||||
"Check jpackage wrote some data in the supplied temporary directory [%s]",
|
"Check jpackage wrote some data in the supplied temporary directory [%s]",
|
||||||
tempDir));
|
tempDir));
|
||||||
})
|
})
|
||||||
.run();
|
.run(PackageTest.Action.CREATE);
|
||||||
|
|
||||||
new PackageTest().configureHelloApp().addInitializer(addTempDir)
|
createTest.get()
|
||||||
.addInitializer(cmd -> {
|
.addInitializer(cmd -> {
|
||||||
// Clean output from the previus jpackage run.
|
// Clean output from the previus jpackage run.
|
||||||
Files.delete(cmd.outputBundle());
|
Files.delete(cmd.outputBundle());
|
||||||
})
|
})
|
||||||
// Temporary directory should not be empty,
|
// Temporary directory should not be empty,
|
||||||
// jpackage should exit with error.
|
// jpackage should exit with error.
|
||||||
.setExpectedExitCode(1)
|
.setExpectedExitCode(1)
|
||||||
.run();
|
.run(PackageTest.Action.CREATE);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testAtFile() throws IOException {
|
public void testAtFile() throws IOException {
|
||||||
JPackageCommand cmd = JPackageCommand.helloAppImage();
|
JPackageCommand cmd = JPackageCommand
|
||||||
|
.helloAppImage()
|
||||||
|
.setArgumentValue("--dest", TKit.createTempDirectory("output"));
|
||||||
|
|
||||||
// Init options file with the list of options configured
|
// Init options file with the list of options configured
|
||||||
// for JPackageCommand instance.
|
// for JPackageCommand instance.
|
||||||
final Path optionsFile = TKit.workDir().resolve("options");
|
final Path optionsFile = TKit.createTempFile(Path.of("options"));
|
||||||
Files.write(optionsFile,
|
Files.write(optionsFile,
|
||||||
List.of(String.join(" ", cmd.getAllArguments())));
|
List.of(String.join(" ", cmd.getAllArguments())));
|
||||||
|
|
||||||
// Build app jar file.
|
// Build app jar file.
|
||||||
cmd.executePrerequisiteActions();
|
cmd.executePrerequisiteActions();
|
||||||
|
|
||||||
// Make sure output directory is empty. Normally JPackageCommand would
|
|
||||||
// do this automatically.
|
|
||||||
TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
|
|
||||||
|
|
||||||
// Instead of running jpackage command through configured
|
// Instead of running jpackage command through configured
|
||||||
// JPackageCommand instance, run vanilla jpackage command with @ file.
|
// JPackageCommand instance, run vanilla jpackage command with @ file.
|
||||||
getJPackageToolProvider()
|
getJPackageToolProvider()
|
||||||
.addArgument(String.format("@%s", optionsFile))
|
.addArgument(String.format("@%s", optionsFile))
|
||||||
.execute().assertExitCodeIsZero();
|
.execute();
|
||||||
|
|
||||||
// Verify output of jpackage command.
|
// Verify output of jpackage command.
|
||||||
cmd.assertImageCreated();
|
cmd.assertImageCreated();
|
||||||
@ -292,50 +301,45 @@ public final class BasicTest {
|
|||||||
@Parameter("Hello")
|
@Parameter("Hello")
|
||||||
@Parameter("com.foo/com.foo.main.Aloha")
|
@Parameter("com.foo/com.foo.main.Aloha")
|
||||||
@Test
|
@Test
|
||||||
public void testJLinkRuntime(String javaAppDesc) {
|
public void testJLinkRuntime(String javaAppDesc) throws IOException {
|
||||||
JPackageCommand cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
JavaAppDesc appDesc = JavaAppDesc.parse(javaAppDesc);
|
||||||
|
|
||||||
// If `--module` parameter was set on jpackage command line, get its
|
JPackageCommand cmd = JPackageCommand.helloAppImage(appDesc);
|
||||||
// value and extract module name.
|
|
||||||
// E.g.: foo.bar2/foo.bar.Buz -> foo.bar2
|
final String moduleName = appDesc.moduleName();
|
||||||
// Note: HelloApp class manages `--module` parameter on jpackage command line
|
|
||||||
final String moduleName = cmd.getArgumentValue("--module", () -> null,
|
|
||||||
(v) -> v.split("/", 2)[0]);
|
|
||||||
|
|
||||||
if (moduleName != null) {
|
if (moduleName != null) {
|
||||||
// Build module jar.
|
// Build module jar.
|
||||||
cmd.executePrerequisiteActions();
|
cmd.executePrerequisiteActions();
|
||||||
}
|
}
|
||||||
|
|
||||||
TKit.withTempDirectory("runtime", tempDir -> {
|
final Path runtimeDir = TKit.createTempDirectory("runtime").resolve("data");
|
||||||
final Path runtimeDir = tempDir.resolve("data");
|
|
||||||
|
|
||||||
// List of modules required for test app.
|
// List of modules required for test app.
|
||||||
final var modules = new String[] {
|
final var modules = new String[] {
|
||||||
"java.base",
|
"java.base",
|
||||||
"java.desktop"
|
"java.desktop"
|
||||||
};
|
};
|
||||||
|
|
||||||
Executor jlink = getToolProvider(JavaTool.JLINK)
|
Executor jlink = getToolProvider(JavaTool.JLINK)
|
||||||
.saveOutput(false)
|
.saveOutput(false)
|
||||||
.addArguments(
|
.addArguments(
|
||||||
"--add-modules", String.join(",", modules),
|
"--add-modules", String.join(",", modules),
|
||||||
"--output", runtimeDir.toString(),
|
"--output", runtimeDir.toString(),
|
||||||
"--strip-debug",
|
"--strip-debug",
|
||||||
"--no-header-files",
|
"--no-header-files",
|
||||||
"--no-man-pages");
|
"--no-man-pages");
|
||||||
|
|
||||||
if (moduleName != null) {
|
if (moduleName != null) {
|
||||||
jlink.addArguments("--add-modules", moduleName, "--module-path",
|
jlink.addArguments("--add-modules", moduleName, "--module-path",
|
||||||
Path.of(cmd.getArgumentValue("--module-path")).resolve(
|
Path.of(cmd.getArgumentValue("--module-path")).resolve(
|
||||||
"hello.jar").toString());
|
"hello.jar").toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
jlink.execute().assertExitCodeIsZero();
|
jlink.execute();
|
||||||
|
|
||||||
cmd.addArguments("--runtime-image", runtimeDir);
|
cmd.addArguments("--runtime-image", runtimeDir);
|
||||||
cmd.executeAndAssertHelloAppImageCreated();
|
cmd.executeAndAssertHelloAppImageCreated();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Executor getJPackageToolProvider() {
|
private static Executor getJPackageToolProvider() {
|
||||||
|
@ -209,8 +209,7 @@ public final class MainClassTest {
|
|||||||
// file nor on command line.
|
// file nor on command line.
|
||||||
List<String> output = cmd
|
List<String> output = cmd
|
||||||
.saveConsoleOutput(true)
|
.saveConsoleOutput(true)
|
||||||
.execute()
|
.execute(1)
|
||||||
.assertExitCodeIs(1)
|
|
||||||
.getOutput();
|
.getOutput();
|
||||||
TKit.assertTextStream(script.expectedErrorMessage).apply(output.stream());
|
TKit.assertTextStream(script.expectedErrorMessage).apply(output.stream());
|
||||||
return;
|
return;
|
||||||
@ -236,7 +235,7 @@ public final class MainClassTest {
|
|||||||
.setDirectory(cmd.outputDir())
|
.setDirectory(cmd.outputDir())
|
||||||
.setExecutable(cmd.appLauncherPath())
|
.setExecutable(cmd.appLauncherPath())
|
||||||
.dumpOutput().saveOutput()
|
.dumpOutput().saveOutput()
|
||||||
.execute().assertExitCodeIs(1).getOutput();
|
.execute(1).getOutput();
|
||||||
TKit.assertTextStream(String.format(
|
TKit.assertTextStream(String.format(
|
||||||
"Error: Could not find or load main class %s",
|
"Error: Could not find or load main class %s",
|
||||||
nonExistingMainClass)).apply(output.stream());
|
nonExistingMainClass)).apply(output.stream());
|
||||||
@ -289,7 +288,7 @@ public final class MainClassTest {
|
|||||||
.addArguments("-v", "-c", "-M", "-f", jarFile.toString())
|
.addArguments("-v", "-c", "-M", "-f", jarFile.toString())
|
||||||
.addArguments("-C", workDir.toString(), ".")
|
.addArguments("-C", workDir.toString(), ".")
|
||||||
.dumpOutput()
|
.dumpOutput()
|
||||||
.execute().assertExitCodeIsZero();
|
.execute();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
package jdk.jpackage.tests;
|
package jdk.jpackage.tests;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -71,7 +72,7 @@ public final class ModulePathTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() throws IOException {
|
||||||
final String moduleName = "com.foo";
|
final String moduleName = "com.foo";
|
||||||
JPackageCommand cmd = JPackageCommand.helloAppImage(
|
JPackageCommand cmd = JPackageCommand.helloAppImage(
|
||||||
"benvenuto.jar:" + moduleName + "/com.foo.Hello");
|
"benvenuto.jar:" + moduleName + "/com.foo.Hello");
|
||||||
@ -88,45 +89,42 @@ public final class ModulePathTest {
|
|||||||
String goodModulePath = Objects.requireNonNull(cmd.getArgumentValue(
|
String goodModulePath = Objects.requireNonNull(cmd.getArgumentValue(
|
||||||
"--module-path"));
|
"--module-path"));
|
||||||
cmd.removeArgumentWithValue("--module-path");
|
cmd.removeArgumentWithValue("--module-path");
|
||||||
TKit.withTempDirectory("empty-dir", emptyDir -> {
|
|
||||||
Path nonExistingDir = TKit.withTempDirectory("non-existing-dir",
|
|
||||||
unused -> {
|
|
||||||
});
|
|
||||||
|
|
||||||
Function<String, String> substitute = str -> {
|
Path emptyDir = TKit.createTempDirectory("empty-dir");
|
||||||
String v = str;
|
Path nonExistingDir = TKit.withTempDirectory("non-existing-dir", x -> {});
|
||||||
v = v.replace(GOOD_PATH, goodModulePath);
|
|
||||||
v = v.replace(EMPTY_DIR, emptyDir.toString());
|
|
||||||
v = v.replace(NON_EXISTING_DIR, nonExistingDir.toString());
|
|
||||||
return v;
|
|
||||||
};
|
|
||||||
|
|
||||||
boolean withGoodPath = modulePathArgs.stream().anyMatch(
|
Function<String, String> substitute = str -> {
|
||||||
s -> s.contains(GOOD_PATH));
|
String v = str;
|
||||||
|
v = v.replace(GOOD_PATH, goodModulePath);
|
||||||
|
v = v.replace(EMPTY_DIR, emptyDir.toString());
|
||||||
|
v = v.replace(NON_EXISTING_DIR, nonExistingDir.toString());
|
||||||
|
return v;
|
||||||
|
};
|
||||||
|
|
||||||
cmd.addArguments(modulePathArgs.stream().map(arg -> Stream.of(
|
boolean withGoodPath = modulePathArgs.stream().anyMatch(
|
||||||
"--module-path", substitute.apply(arg))).flatMap(s -> s).collect(
|
s -> s.contains(GOOD_PATH));
|
||||||
Collectors.toList()));
|
|
||||||
|
|
||||||
if (withGoodPath) {
|
cmd.addArguments(modulePathArgs.stream().map(arg -> Stream.of(
|
||||||
cmd.executeAndAssertHelloAppImageCreated();
|
"--module-path", substitute.apply(arg))).flatMap(s -> s).collect(
|
||||||
|
Collectors.toList()));
|
||||||
|
|
||||||
|
if (withGoodPath) {
|
||||||
|
cmd.executeAndAssertHelloAppImageCreated();
|
||||||
|
} else {
|
||||||
|
final String expectedErrorMessage;
|
||||||
|
if (modulePathArgs.isEmpty()) {
|
||||||
|
expectedErrorMessage = "Error: Missing argument: --runtime-image or --module-path";
|
||||||
} else {
|
} else {
|
||||||
final String expectedErrorMessage;
|
expectedErrorMessage = String.format(
|
||||||
if (modulePathArgs.isEmpty()) {
|
"Error: Module %s not found", moduleName);
|
||||||
expectedErrorMessage = "Error: Missing argument: --runtime-image or --module-path";
|
|
||||||
} else {
|
|
||||||
expectedErrorMessage = String.format(
|
|
||||||
"Error: Module %s not found", moduleName);
|
|
||||||
}
|
|
||||||
|
|
||||||
List<String> output = cmd
|
|
||||||
.saveConsoleOutput(true)
|
|
||||||
.execute()
|
|
||||||
.assertExitCodeIs(1)
|
|
||||||
.getOutput();
|
|
||||||
TKit.assertTextStream(expectedErrorMessage).apply(output.stream());
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
List<String> output = cmd
|
||||||
|
.saveConsoleOutput(true)
|
||||||
|
.execute(1)
|
||||||
|
.getOutput();
|
||||||
|
TKit.assertTextStream(expectedErrorMessage).apply(output.stream());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final List<String> modulePathArgs;
|
private final List<String> modulePathArgs;
|
||||||
|
@ -29,13 +29,20 @@ set_args ()
|
|||||||
local arg_is_output_dir=
|
local arg_is_output_dir=
|
||||||
local arg_is_mode=
|
local arg_is_mode=
|
||||||
local output_dir_set=
|
local output_dir_set=
|
||||||
|
local with_append_actions=yes
|
||||||
for arg in "$@"; do
|
for arg in "$@"; do
|
||||||
if [ "$arg" == "-o" ]; then
|
if [ "$arg" == "-o" ]; then
|
||||||
arg_is_output_dir=yes
|
arg_is_output_dir=yes
|
||||||
output_dir_set=yes
|
output_dir_set=yes
|
||||||
elif [ "$arg" == "-m" ]; then
|
elif [ "$arg" == "-m" ]; then
|
||||||
arg_is_mode=yes
|
arg_is_mode=yes
|
||||||
continue
|
continue
|
||||||
|
elif [ "$arg" == '--' ]; then
|
||||||
|
append_actions
|
||||||
|
with_append_actions=
|
||||||
|
continue
|
||||||
|
elif ! case "$arg" in -Djpackage.test.action=*) false;; esac; then
|
||||||
|
continue
|
||||||
elif [ -n "$arg_is_output_dir" ]; then
|
elif [ -n "$arg_is_output_dir" ]; then
|
||||||
arg_is_output_dir=
|
arg_is_output_dir=
|
||||||
output_dir="$arg"
|
output_dir="$arg"
|
||||||
@ -47,6 +54,13 @@ set_args ()
|
|||||||
args+=( "$arg" )
|
args+=( "$arg" )
|
||||||
done
|
done
|
||||||
[ -n "$output_dir_set" ] || args=( -o "$output_dir" "${args[@]}" )
|
[ -n "$output_dir_set" ] || args=( -o "$output_dir" "${args[@]}" )
|
||||||
|
[ -z "$with_append_actions" ] || append_actions
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
append_actions ()
|
||||||
|
{
|
||||||
|
args+=( '--' '-Djpackage.test.action=create,install,verify-install,uninstall,verify-uninstall' )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -62,7 +76,3 @@ exec_command ()
|
|||||||
set_args "$@"
|
set_args "$@"
|
||||||
basedir="$(dirname $0)"
|
basedir="$(dirname $0)"
|
||||||
exec_command "$basedir/run_tests.sh" -m create "${args[@]}"
|
exec_command "$basedir/run_tests.sh" -m create "${args[@]}"
|
||||||
exec_command "$basedir/manage_packages.sh" -d "$output_dir"
|
|
||||||
exec_command "$basedir/run_tests.sh" -m verify-install "${args[@]}"
|
|
||||||
exec_command "$basedir/manage_packages.sh" -d "$output_dir" -u
|
|
||||||
exec_command "$basedir/run_tests.sh" -m verify-uninstall "${args[@]}"
|
|
||||||
|
@ -26,6 +26,7 @@ import java.io.InputStream;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import jdk.jpackage.test.TKit;
|
import jdk.jpackage.test.TKit;
|
||||||
|
import jdk.jpackage.test.HelloApp;
|
||||||
import jdk.jpackage.test.JPackageCommand;
|
import jdk.jpackage.test.JPackageCommand;
|
||||||
import jdk.jpackage.test.Annotations.Test;
|
import jdk.jpackage.test.Annotations.Test;
|
||||||
import jdk.jpackage.test.Annotations.Parameter;
|
import jdk.jpackage.test.Annotations.Parameter;
|
||||||
@ -58,6 +59,10 @@ public class WinConsoleTest {
|
|||||||
}
|
}
|
||||||
cmd.executeAndAssertHelloAppImageCreated();
|
cmd.executeAndAssertHelloAppImageCreated();
|
||||||
checkSubsystem(cmd.appLauncherPath(), withWinConsole);
|
checkSubsystem(cmd.appLauncherPath(), withWinConsole);
|
||||||
|
|
||||||
|
// Run launcher with a number of arguments to make sure they go through
|
||||||
|
// regardless the launcher has or doesn't have console.
|
||||||
|
HelloApp.executeLauncherAndVerifyOutput(cmd, "a", "b", "c");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkSubsystem(Path path, boolean isConsole) throws
|
private static void checkSubsystem(Path path, boolean isConsole) throws
|
||||||
|
@ -70,7 +70,7 @@ public class WinScriptTest {
|
|||||||
@Test
|
@Test
|
||||||
@Parameter("0")
|
@Parameter("0")
|
||||||
@Parameter("10")
|
@Parameter("10")
|
||||||
public void test(int wsfExitCode) {
|
public void test(int wsfExitCode) throws IOException {
|
||||||
final ScriptData appImageScriptData;
|
final ScriptData appImageScriptData;
|
||||||
if (wsfExitCode != 0 && packageType == PackageType.WIN_EXE) {
|
if (wsfExitCode != 0 && packageType == PackageType.WIN_EXE) {
|
||||||
appImageScriptData = new ScriptData(PackageType.WIN_MSI, 0);
|
appImageScriptData = new ScriptData(PackageType.WIN_MSI, 0);
|
||||||
@ -81,29 +81,32 @@ public class WinScriptTest {
|
|||||||
final ScriptData msiScriptData = new ScriptData(PackageType.WIN_EXE, wsfExitCode);
|
final ScriptData msiScriptData = new ScriptData(PackageType.WIN_EXE, wsfExitCode);
|
||||||
|
|
||||||
test.setExpectedExitCode(wsfExitCode == 0 ? 0 : 1);
|
test.setExpectedExitCode(wsfExitCode == 0 ? 0 : 1);
|
||||||
TKit.withTempDirectory("resources", tempDir -> {
|
|
||||||
test.addInitializer(cmd -> {
|
|
||||||
cmd.addArguments("--resource-dir", tempDir);
|
|
||||||
|
|
||||||
appImageScriptData.createScript(cmd);
|
final Path tempDir = TKit.createTempDirectory("resources");
|
||||||
msiScriptData.createScript(cmd);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (packageType == PackageType.WIN_MSI) {
|
test.addInitializer(cmd -> {
|
||||||
|
cmd.addArguments("--resource-dir", tempDir);
|
||||||
|
|
||||||
|
appImageScriptData.createScript(cmd);
|
||||||
|
msiScriptData.createScript(cmd);
|
||||||
|
});
|
||||||
|
|
||||||
|
switch (packageType) {
|
||||||
|
case WIN_MSI:
|
||||||
test.addBundleVerifier((cmd, result) -> {
|
test.addBundleVerifier((cmd, result) -> {
|
||||||
appImageScriptData.assertJPackageOutput(result.getOutput());
|
appImageScriptData.assertJPackageOutput(result.getOutput());
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
|
|
||||||
if (packageType == PackageType.WIN_EXE) {
|
case WIN_EXE:
|
||||||
test.addBundleVerifier((cmd, result) -> {
|
test.addBundleVerifier((cmd, result) -> {
|
||||||
appImageScriptData.assertJPackageOutput(result.getOutput());
|
appImageScriptData.assertJPackageOutput(result.getOutput());
|
||||||
msiScriptData.assertJPackageOutput(result.getOutput());
|
msiScriptData.assertJPackageOutput(result.getOutput());
|
||||||
});
|
});
|
||||||
}
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
test.run();
|
test.run();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class ScriptData {
|
private static class ScriptData {
|
||||||
|
@ -21,9 +21,16 @@
|
|||||||
* questions.
|
* questions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import jdk.jpackage.test.TKit;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import jdk.jpackage.test.Annotations.Test;
|
||||||
import jdk.jpackage.test.PackageTest;
|
import jdk.jpackage.test.PackageTest;
|
||||||
import jdk.jpackage.test.PackageType;
|
import jdk.jpackage.test.PackageType;
|
||||||
|
import jdk.jpackage.test.WindowsHelper;
|
||||||
|
import jdk.jpackage.test.TKit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test both --win-upgrade-uuid and --app-version parameters. Output of the test
|
* Test both --win-upgrade-uuid and --app-version parameters. Output of the test
|
||||||
@ -41,34 +48,155 @@ import jdk.jpackage.test.PackageType;
|
|||||||
* @summary jpackage with --win-upgrade-uuid and --app-version
|
* @summary jpackage with --win-upgrade-uuid and --app-version
|
||||||
* @library ../helpers
|
* @library ../helpers
|
||||||
* @key jpackagePlatformPackage
|
* @key jpackagePlatformPackage
|
||||||
|
* @requires (jpackage.test.SQETest != null)
|
||||||
* @build jdk.jpackage.test.*
|
* @build jdk.jpackage.test.*
|
||||||
* @requires (os.family == "windows")
|
* @requires (os.family == "windows")
|
||||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||||
* @run main/othervm/timeout=360 -Xmx512m WinUpgradeUUIDTest
|
* @compile WinUpgradeUUIDTest.java
|
||||||
|
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||||
|
* --jpt-run=WinUpgradeUUIDTest.test
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @test
|
||||||
|
* @summary jpackage with --win-upgrade-uuid and --app-version
|
||||||
|
* @library ../helpers
|
||||||
|
* @key jpackagePlatformPackage
|
||||||
|
* @requires (jpackage.test.SQETest == null)
|
||||||
|
* @build jdk.jpackage.test.*
|
||||||
|
* @requires (os.family == "windows")
|
||||||
|
* @modules jdk.jpackage/jdk.jpackage.internal
|
||||||
|
* @compile WinUpgradeUUIDTest.java
|
||||||
|
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
|
||||||
|
* --jpt-run=WinUpgradeUUIDTest
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class WinUpgradeUUIDTest {
|
public class WinUpgradeUUIDTest {
|
||||||
public static void main(String[] args) {
|
|
||||||
TKit.run(args, () -> {
|
@Test
|
||||||
PackageTest test = init();
|
public static void test() {
|
||||||
if (test.getAction() != PackageTest.Action.VERIFY_INSTALL) {
|
Supplier<PackageTest> init = () -> {
|
||||||
test.run();
|
final UUID upgradeCode = UUID.fromString(
|
||||||
|
"F0B18E75-52AD-41A2-BC86-6BE4FCD50BEB");
|
||||||
|
return new PackageTest()
|
||||||
|
.forTypes(PackageType.WINDOWS)
|
||||||
|
.configureHelloApp()
|
||||||
|
.addInitializer(cmd -> cmd.addArguments("--win-upgrade-uuid",
|
||||||
|
upgradeCode.toString()))
|
||||||
|
.forTypes(PackageType.WIN_MSI)
|
||||||
|
.addBundlePropertyVerifier("UpgradeCode", value -> {
|
||||||
|
if (value.startsWith("{")) {
|
||||||
|
value = value.substring(1);
|
||||||
|
}
|
||||||
|
if (value.endsWith("}")) {
|
||||||
|
value = value.substring(0, value.length() - 1);
|
||||||
|
}
|
||||||
|
return UUID.fromString(value).equals(upgradeCode);
|
||||||
|
}, "is a match with");
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replace real uninstall command for the first package with nop action.
|
||||||
|
// It will be uninstalled automatically when the second
|
||||||
|
// package will be installed.
|
||||||
|
// However uninstall verification for the first package will be executed.
|
||||||
|
PackageTest test1 = init.get().setPackageUninstaller(cmd -> {});
|
||||||
|
|
||||||
|
PackageTest test2 = init.get().addInitializer(cmd -> {
|
||||||
|
cmd.setArgumentValue("--app-version", "2.0");
|
||||||
|
cmd.setArgumentValue("--arguments", "bar");
|
||||||
|
});
|
||||||
|
|
||||||
|
new PackageTest.Group(test1, test2).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Running jpackage multiple times with the same parameters should produce
|
||||||
|
* MSI packages with the same UpgradeCode and ProductCode values.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public static void testUUIDs() {
|
||||||
|
Supplier<PackageTest> init = () -> {
|
||||||
|
return new PackageTest()
|
||||||
|
.forTypes(PackageType.WIN_MSI)
|
||||||
|
.configureHelloApp()
|
||||||
|
.addInitializer(cmd -> {
|
||||||
|
cmd.setFakeRuntime();
|
||||||
|
cmd.setArgumentValue("--dest", TKit.createTempDirectory("output"));
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
PackageTest test1 = init.get();
|
||||||
|
PackageTest test2 = init.get();
|
||||||
|
PackageTest test3 = init.get().addInitializer(cmd -> {
|
||||||
|
cmd.addArguments("--app-version", "2.0");
|
||||||
|
});
|
||||||
|
PackageTest test4 = init.get().addInitializer(cmd -> {
|
||||||
|
cmd.addArguments("--app-version", "2.0");
|
||||||
|
cmd.addArguments("--vendor", "Foo Inc.");
|
||||||
|
});
|
||||||
|
|
||||||
|
PackageTest[] tests = new PackageTest[] { test1, test2, test3, test4 };
|
||||||
|
|
||||||
|
var productCodeVerifier = createPropertyVerifier("ProductCode", tests);
|
||||||
|
var upgradeCodeVerifier = createPropertyVerifier("UpgradeCode", tests);
|
||||||
|
|
||||||
|
List.of(tests).forEach(test -> {
|
||||||
|
test.run(PackageTest.Action.CREATE);
|
||||||
|
});
|
||||||
|
|
||||||
|
productCodeVerifier.assertEquals(test1, test2);
|
||||||
|
productCodeVerifier.assertNotEquals(test1, test3);
|
||||||
|
productCodeVerifier.assertNotEquals(test1, test4);
|
||||||
|
productCodeVerifier.assertNotEquals(test3, test4);
|
||||||
|
|
||||||
|
upgradeCodeVerifier.assertEquals(test1, test2);
|
||||||
|
upgradeCodeVerifier.assertEquals(test1, test3);
|
||||||
|
upgradeCodeVerifier.assertNotEquals(test1, test4);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static PropertyVerifier createPropertyVerifier(String propertyName,
|
||||||
|
PackageTest... tests) {
|
||||||
|
Map<PackageTest, Map.Entry<String, String>> properties = new HashMap<>();
|
||||||
|
List.of(tests).forEach(test -> {
|
||||||
|
test.addBundleVerifier(cmd -> {
|
||||||
|
properties.put(test, Map.entry(cmd.getPrintableCommandLine(),
|
||||||
|
WindowsHelper.getMsiProperty(cmd, propertyName)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return new PropertyVerifier() {
|
||||||
|
@Override
|
||||||
|
protected String propertyName() {
|
||||||
|
return propertyName;
|
||||||
}
|
}
|
||||||
|
|
||||||
test = init();
|
@Override
|
||||||
test.addInitializer(cmd -> {
|
protected Map<PackageTest, Map.Entry<String, String>> propertyValues() {
|
||||||
cmd.setArgumentValue("--app-version", "2.0");
|
return properties;
|
||||||
cmd.setArgumentValue("--arguments", "bar");
|
}
|
||||||
});
|
};
|
||||||
test.run();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static PackageTest init() {
|
static abstract class PropertyVerifier {
|
||||||
return new PackageTest()
|
void assertEquals(PackageTest x, PackageTest y) {
|
||||||
.forTypes(PackageType.WINDOWS)
|
var entryX = propertyValues().get(x);
|
||||||
.configureHelloApp()
|
var entryY = propertyValues().get(y);
|
||||||
.addInitializer(cmd -> cmd.addArguments("--win-upgrade-uuid",
|
TKit.assertEquals(entryX.getValue(), entryY.getValue(),
|
||||||
"F0B18E75-52AD-41A2-BC86-6BE4FCD50BEB"));
|
String.format(
|
||||||
|
"Check %s is the same for %s and %s command lines",
|
||||||
|
propertyName(), entryX.getKey(), entryY.getKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void assertNotEquals(PackageTest x, PackageTest y) {
|
||||||
|
var entryX = propertyValues().get(x);
|
||||||
|
var entryY = propertyValues().get(y);
|
||||||
|
TKit.assertNotEquals(entryX.getValue(), entryY.getValue(),
|
||||||
|
String.format(
|
||||||
|
"Check %s is different for %s and %s command lines",
|
||||||
|
propertyName(), entryX.getKey(), entryY.getKey()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract String propertyName();
|
||||||
|
protected abstract Map<PackageTest, Map.Entry<String, String>> propertyValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user