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 UTILITY_SCRIPTS = "UTILITY_SCRIPTS";
|
||||
|
||||
DesktopIntegration(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params) {
|
||||
private DesktopIntegration(PlatformPackage thePackage,
|
||||
Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
|
||||
associations = FileAssociation.fetchFrom(params).stream()
|
||||
.filter(fa -> !fa.mimeTypes.isEmpty())
|
||||
@ -60,11 +61,25 @@ final class DesktopIntegration {
|
||||
|
||||
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)
|
||||
.setCategory(I18N.getString("resource.menu-shortcut-descriptor"))
|
||||
.setPublicName(APP_NAME.fetchFrom(params) + ".desktop");
|
||||
@ -79,27 +94,42 @@ final class DesktopIntegration {
|
||||
|
||||
mimeInfoFile = new DesktopFile(mimeInfoFileName);
|
||||
|
||||
if (!associations.isEmpty() || SHORTCUT_HINT.fetchFrom(params) || customIconFile != null) {
|
||||
//
|
||||
// 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
|
||||
//
|
||||
if (withDesktopFile) {
|
||||
desktopFile = new DesktopFile(desktopFileName);
|
||||
iconFile = new DesktopFile(APP_NAME.fetchFrom(params)
|
||||
+ IOUtils.getSuffix(Path.of(DEFAULT_ICON)));
|
||||
|
||||
if (curIconResource == null) {
|
||||
// Create default icon.
|
||||
curIconResource = LinuxAppImageBuilder.createIconResource(
|
||||
DEFAULT_ICON, ICON_PNG, mainParams, null);
|
||||
}
|
||||
} else {
|
||||
desktopFile = null;
|
||||
iconFile = null;
|
||||
}
|
||||
|
||||
iconResource = curIconResource;
|
||||
|
||||
desktopFileData = Collections.unmodifiableMap(
|
||||
createDataForDesktopFile(params));
|
||||
|
||||
nestedIntegrations = launchers.stream().map(
|
||||
launcherParams -> new DesktopIntegration(thePackage,
|
||||
launcherParams)).collect(Collectors.toList());
|
||||
nestedIntegrations = new ArrayList<>();
|
||||
for (var launcherParams : launchers) {
|
||||
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() {
|
||||
|
@ -30,10 +30,10 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
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.StandardBundlerParam.*;
|
||||
@ -45,21 +45,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
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,
|
||||
Path imageOutDir) {
|
||||
return ApplicationLayout.linuxAppImage().resolveAt(
|
||||
@ -113,8 +98,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
@Override
|
||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Map<String, ? super Object> originalParams = new HashMap<>(params);
|
||||
|
||||
appLayout.roots().stream().forEach(dir -> {
|
||||
try {
|
||||
IOUtils.writableOutputDir(dir);
|
||||
@ -124,7 +107,7 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
});
|
||||
|
||||
// create the primary launcher
|
||||
createLauncherForEntryPoint(params);
|
||||
createLauncherForEntryPoint(params, null);
|
||||
|
||||
// Copy library to the launcher folder
|
||||
try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
|
||||
@ -135,23 +118,20 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
List<Map<String, ? super Object>> entryPoints
|
||||
= StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
||||
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
||||
createLauncherForEntryPoint(
|
||||
AddLauncherArguments.merge(originalParams, entryPoint));
|
||||
createLauncherForEntryPoint(AddLauncherArguments.merge(params,
|
||||
entryPoint, ICON.getID(), ICON_PNG.getID()), params);
|
||||
}
|
||||
|
||||
// Copy class path entries to Java folder
|
||||
copyApplication(params);
|
||||
|
||||
// Copy icon to Resources folder
|
||||
copyIcon(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prepareJreFiles(Map<String, ? super Object> params)
|
||||
throws IOException {}
|
||||
|
||||
private void createLauncherForEntryPoint(
|
||||
Map<String, ? super Object> params) throws IOException {
|
||||
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
// Copy executable to launchers folder
|
||||
Path executableFile = appLayout.launchersDirectory().resolve(getLauncherName(params));
|
||||
try (InputStream is_launcher =
|
||||
@ -163,19 +143,15 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
|
||||
executableFile.toFile().setWritable(true, true);
|
||||
|
||||
writeCfgFile(params, getLauncherCfgPath(params).toFile());
|
||||
}
|
||||
|
||||
private void copyIcon(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
|
||||
Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
|
||||
APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
|
||||
DEFAULT_ICON)));
|
||||
|
||||
createResource(DEFAULT_ICON, params)
|
||||
.setCategory("icon")
|
||||
.setExternal(ICON_PNG.fetchFrom(params))
|
||||
.saveToFile(iconTarget);
|
||||
var iconResource = createIconResource(DEFAULT_ICON, ICON_PNG, params,
|
||||
mainParams);
|
||||
if (iconResource != null) {
|
||||
Path iconTarget = appLayout.destktopIntegrationDirectory().resolve(
|
||||
APP_NAME.fetchFrom(params) + IOUtils.getSuffix(Path.of(
|
||||
DEFAULT_ICON)));
|
||||
iconResource.saveToFile(iconTarget);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyApplication(Map<String, ? super Object> params)
|
||||
|
@ -135,11 +135,7 @@ abstract class LinuxPackageBundler extends AbstractBundler {
|
||||
}
|
||||
}
|
||||
|
||||
if (!StandardBundlerParam.isRuntimeInstaller(params)) {
|
||||
desktopIntegration = new DesktopIntegration(thePackage, params);
|
||||
} else {
|
||||
desktopIntegration = null;
|
||||
}
|
||||
desktopIntegration = DesktopIntegration.create(thePackage, params);
|
||||
|
||||
Map<String, String> data = createDefaultReplacementData(params);
|
||||
if (desktopIntegration != null) {
|
||||
|
@ -102,21 +102,6 @@ public class MacAppBundler extends AbstractImageBundler {
|
||||
params -> IDENTIFIER.fetchFrom(params) + ".",
|
||||
(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) {
|
||||
// CFBundleVersion (String - iOS, OS X) specifies the build version
|
||||
// number of the bundle, which identifies an iteration (released or
|
||||
|
@ -29,6 +29,7 @@ import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.text.MessageFormat;
|
||||
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.StandardBundlerParam.*;
|
||||
@ -160,7 +161,7 @@ public class MacDmgBundler extends MacBaseInstallerBundler {
|
||||
|
||||
createResource(TEMPLATE_BUNDLE_ICON, params)
|
||||
.setCategory(I18N.getString("resource.volume-icon"))
|
||||
.setExternal(MacAppBundler.ICON_ICNS.fetchFrom(params))
|
||||
.setExternal(ICON_ICNS.fetchFrom(params))
|
||||
.saveToFile(getConfig_VolumeIcon(params));
|
||||
|
||||
createResource(null, params)
|
||||
|
@ -25,23 +25,21 @@
|
||||
|
||||
package jdk.incubator.jpackage.internal;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.PrintStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
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 static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
|
||||
|
||||
/*
|
||||
* AbstractAppImageBuilder
|
||||
@ -188,4 +186,57 @@ public abstract class AbstractAppImageBuilder {
|
||||
}
|
||||
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.Map;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import jdk.incubator.jpackage.internal.Arguments.CLIOptions;
|
||||
|
||||
/*
|
||||
@ -160,8 +161,10 @@ class AddLauncherArguments {
|
||||
|
||||
static Map<String, ? super Object> merge(
|
||||
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);
|
||||
List.of(exclude).forEach(tmp::remove);
|
||||
|
||||
if (additional.containsKey(CLIOptions.MODULE.getId())) {
|
||||
tmp.remove(CLIOptions.MAIN_JAR.getId());
|
||||
tmp.remove(CLIOptions.APPCLASS.getId());
|
||||
|
@ -30,10 +30,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.incubator.jpackage.internal.StandardBundlerParam.RESOURCE_DIR;
|
||||
@ -64,6 +61,7 @@ final class OverridableResource {
|
||||
|
||||
OverridableResource(String defaultName) {
|
||||
this.defaultName = defaultName;
|
||||
setSourceOrder(Source.values());
|
||||
}
|
||||
|
||||
OverridableResource setSubstitutionData(Map<String, String> v) {
|
||||
@ -90,6 +88,15 @@ final class OverridableResource {
|
||||
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.
|
||||
*
|
||||
@ -104,6 +111,20 @@ final class OverridableResource {
|
||||
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) {
|
||||
externalPath = v;
|
||||
return this;
|
||||
@ -113,57 +134,17 @@ final class OverridableResource {
|
||||
return setExternal(toPath(v));
|
||||
}
|
||||
|
||||
void saveToFile(Path dest) throws IOException {
|
||||
final String printableCategory;
|
||||
if (category != null) {
|
||||
printableCategory = String.format("[%s]", category);
|
||||
} 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);
|
||||
Source saveToFile(Path dest) throws IOException {
|
||||
for (var source: sources) {
|
||||
if (source.getValue().apply(dest)) {
|
||||
return source.getKey();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void saveToFile(File dest) throws IOException {
|
||||
saveToFile(dest.toPath());
|
||||
Source saveToFile(File dest) throws IOException {
|
||||
return saveToFile(toPath(dest));
|
||||
}
|
||||
|
||||
static InputStream readDefault(String resourceName) {
|
||||
@ -176,6 +157,81 @@ final class OverridableResource {
|
||||
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,
|
||||
Map<String, String> substitutionData) {
|
||||
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 String category;
|
||||
private Path resourceDir;
|
||||
private Path publicName;
|
||||
private Path logPublicName;
|
||||
private Path externalPath;
|
||||
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(
|
||||
"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
|
||||
public boolean validate(Map<String, ? super Object> params)
|
||||
throws ConfigException {
|
||||
|
@ -152,11 +152,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
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(
|
||||
Map<String, ? super Object> params) {
|
||||
return new File(getConfigRoot(params),
|
||||
@ -180,8 +175,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
@Override
|
||||
public void prepareApplicationFiles(Map<String, ? super Object> params)
|
||||
throws IOException {
|
||||
Map<String, ? super Object> originalParams = new HashMap<>(params);
|
||||
|
||||
try {
|
||||
IOUtils.writableOutputDir(root);
|
||||
IOUtils.writableOutputDir(binDir);
|
||||
@ -191,7 +184,7 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
AppImageFile.save(root, params);
|
||||
|
||||
// create the .exe launchers
|
||||
createLauncherForEntryPoint(params);
|
||||
createLauncherForEntryPoint(params, null);
|
||||
|
||||
// copy the jars
|
||||
copyApplication(params);
|
||||
@ -207,8 +200,8 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
List<Map<String, ? super Object>> entryPoints =
|
||||
StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
|
||||
for (Map<String, ? super Object> entryPoint : entryPoints) {
|
||||
createLauncherForEntryPoint(
|
||||
AddLauncherArguments.merge(originalParams, entryPoint));
|
||||
createLauncherForEntryPoint(AddLauncherArguments.merge(params,
|
||||
entryPoint, ICON.getID(), ICON_ICO.getID()), params);
|
||||
}
|
||||
}
|
||||
|
||||
@ -272,15 +265,18 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
.saveToFile(getConfig_ExecutableProperties(params));
|
||||
}
|
||||
|
||||
private void createLauncherForEntryPoint(
|
||||
Map<String, ? super Object> params) throws IOException {
|
||||
private void createLauncherForEntryPoint(Map<String, ? super Object> params,
|
||||
Map<String, ? super Object> mainParams) throws IOException {
|
||||
|
||||
File iconTarget = getConfig_AppIcon(params);
|
||||
|
||||
createResource(TEMPLATE_APP_ICON, params)
|
||||
.setCategory("icon")
|
||||
.setExternal(ICON_ICO.fetchFrom(params))
|
||||
.saveToFile(iconTarget);
|
||||
var iconResource = createIconResource(TEMPLATE_APP_ICON, ICON_ICO, params,
|
||||
mainParams);
|
||||
Path iconTarget = null;
|
||||
if (iconResource != null) {
|
||||
iconTarget = binDir.resolve(APP_NAME.fetchFrom(params) + ".ico");
|
||||
if (null == iconResource.saveToFile(iconTarget)) {
|
||||
iconTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
writeCfgFile(params, root.resolve(
|
||||
getLauncherCfgName(params)).toFile());
|
||||
@ -315,8 +311,8 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
|
||||
launcher.setWritable(true);
|
||||
|
||||
if (iconTarget.exists()) {
|
||||
iconSwap(iconTarget.getAbsolutePath(),
|
||||
if (iconTarget != null) {
|
||||
iconSwap(iconTarget.toAbsolutePath().toString(),
|
||||
launcher.getAbsolutePath());
|
||||
}
|
||||
|
||||
@ -336,9 +332,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
|
||||
executableFile.toFile().setReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
Files.copy(iconTarget.toPath(),
|
||||
binDir.resolve(APP_NAME.fetchFrom(params) + ".ico"));
|
||||
}
|
||||
|
||||
private void copyApplication(Map<String, ? super Object> params)
|
||||
|
@ -398,10 +398,6 @@ public class JPackageHelper {
|
||||
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,
|
||||
ModuleArgs moduleArgs, boolean createModularJar) throws Exception {
|
||||
int retVal;
|
||||
|
@ -39,6 +39,11 @@ import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||
|
||||
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() {
|
||||
saveOutputType = new HashSet<>(Set.of(SaveOutputType.NONE));
|
||||
}
|
||||
@ -170,7 +175,7 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
private List<String> output;
|
||||
}
|
||||
|
||||
public Result execute() {
|
||||
public Result executeWithoutExitCodeCheck() {
|
||||
if (toolProvider != null && directory != null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Can't change directory when using tool provider");
|
||||
@ -189,12 +194,20 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
}).get();
|
||||
}
|
||||
|
||||
public Result execute(int expectedCode) {
|
||||
return executeWithoutExitCodeCheck().assertExitCodeIs(expectedCode);
|
||||
}
|
||||
|
||||
public Result execute() {
|
||||
return execute(0);
|
||||
}
|
||||
|
||||
public String executeAndGetFirstLineOfOutput() {
|
||||
return saveFirstLineOfOutput().execute().assertExitCodeIsZero().getFirstLineOfOutput();
|
||||
return saveFirstLineOfOutput().execute().getFirstLineOfOutput();
|
||||
}
|
||||
|
||||
public List<String> executeAndGetOutput() {
|
||||
return saveOutput().execute().assertExitCodeIsZero().getOutput();
|
||||
return saveOutput().execute().getOutput();
|
||||
}
|
||||
|
||||
private boolean withSavedOutput() {
|
||||
@ -203,7 +216,9 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
}
|
||||
|
||||
private Path executablePath() {
|
||||
if (directory == null || executable.isAbsolute()) {
|
||||
if (directory == null
|
||||
|| executable.isAbsolute()
|
||||
|| !Set.of(".", "..").contains(executable.getName(0).toString())) {
|
||||
return executable;
|
||||
}
|
||||
|
||||
@ -237,7 +252,7 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
sb.append(String.format("; in directory [%s]", directory));
|
||||
}
|
||||
|
||||
TKit.trace("Execute " + sb.toString() + "...");
|
||||
trace("Execute " + sb.toString() + "...");
|
||||
Process process = builder.start();
|
||||
|
||||
List<String> outputLines = null;
|
||||
@ -266,7 +281,7 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
}
|
||||
|
||||
Result reply = new Result(process.waitFor());
|
||||
TKit.trace("Done. Exit code: " + reply.exitCode);
|
||||
trace("Done. Exit code: " + reply.exitCode);
|
||||
|
||||
if (outputLines != null) {
|
||||
reply.output = Collections.unmodifiableList(outputLines);
|
||||
@ -275,10 +290,10 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
}
|
||||
|
||||
private Result runToolProvider(PrintStream out, PrintStream err) {
|
||||
TKit.trace("Execute " + getPrintableCommandLine() + "...");
|
||||
trace("Execute " + getPrintableCommandLine() + "...");
|
||||
Result reply = new Result(toolProvider.run(out, err, args.toArray(
|
||||
String[]::new)));
|
||||
TKit.trace("Done. Exit code: " + reply.exitCode);
|
||||
trace("Done. Exit code: " + reply.exitCode);
|
||||
return reply;
|
||||
}
|
||||
|
||||
@ -353,6 +368,10 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
Collectors.joining(" "));
|
||||
}
|
||||
|
||||
private static void trace(String msg) {
|
||||
TKit.trace(String.format("exec: %s", msg));
|
||||
}
|
||||
|
||||
private ToolProvider toolProvider;
|
||||
private Path executable;
|
||||
private Set<SaveOutputType> saveOutputType;
|
||||
|
@ -23,10 +23,7 @@
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.*;
|
||||
|
||||
|
||||
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
|
||||
public interface ThrowingSupplier<T> {
|
||||
T get() throws Throwable;
|
||||
@ -102,6 +114,10 @@ public class Functional {
|
||||
return v;
|
||||
}
|
||||
|
||||
public static <T, U> BiConsumer<T, U> identity(BiConsumer<T, U> v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
public static Runnable identity(Runnable v) {
|
||||
return v;
|
||||
}
|
||||
|
@ -26,16 +26,16 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.Functional.ThrowingFunction;
|
||||
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||
|
||||
public class HelloApp {
|
||||
public final class HelloApp {
|
||||
|
||||
HelloApp(JavaAppDesc appDesc) {
|
||||
if (appDesc == null) {
|
||||
@ -131,13 +131,13 @@ public class HelloApp {
|
||||
|
||||
if (moduleName == null && CLASS_NAME.equals(qualifiedClassName)) {
|
||||
// Use Hello.java as is.
|
||||
cmd.addAction((self) -> {
|
||||
cmd.addPrerequisiteAction((self) -> {
|
||||
Path jarFile = self.inputDir().resolve(jarFileName);
|
||||
createJarBuilder().setOutputJar(jarFile).addSourceFile(
|
||||
HELLO_JAVA).create();
|
||||
});
|
||||
} else {
|
||||
cmd.addAction((self) -> {
|
||||
cmd.addPrerequisiteAction((self) -> {
|
||||
final Path jarFile;
|
||||
if (moduleName == null) {
|
||||
jarFile = self.inputDir().resolve(jarFileName);
|
||||
@ -177,9 +177,11 @@ public class HelloApp {
|
||||
"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()) {
|
||||
verifyOutputFile(outputFile.toAbsolutePath().normalize(), args);
|
||||
verifyOutputFile(outputFile.toAbsolutePath().normalize(), args,
|
||||
params);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -193,38 +195,121 @@ public class HelloApp {
|
||||
String.format("args.length: %d", args.size())
|
||||
));
|
||||
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(
|
||||
"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();
|
||||
if (!cmd.isFakeRuntime(String.format("Not running [%s] launcher",
|
||||
if (cmd.isFakeRuntime(String.format("Not running [%s] launcher",
|
||||
launcherPath))) {
|
||||
executeAndVerifyOutput(launcherPath, cmd.getAllArgumentValues(
|
||||
"--arguments"));
|
||||
return;
|
||||
}
|
||||
|
||||
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,
|
||||
String... defaultLauncherArgs) {
|
||||
executeAndVerifyOutput(helloAppLauncher, List.of(defaultLauncherArgs));
|
||||
public final static class AppOutputVerifier {
|
||||
AppOutputVerifier(Path helloAppLauncher) {
|
||||
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,
|
||||
List<String> defaultLauncherArgs) {
|
||||
// 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);
|
||||
public static AppOutputVerifier assertApp(Path helloAppLauncher) {
|
||||
return new AppOutputVerifier(helloAppLauncher);
|
||||
}
|
||||
|
||||
final static String OUTPUT_FILENAME = "appOutput.txt";
|
||||
|
@ -30,14 +30,15 @@ import java.security.SecureRandom;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.incubator.jpackage.internal.ApplicationLayout;
|
||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||
import jdk.jpackage.test.Functional.ThrowingFunction;
|
||||
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||
|
||||
/**
|
||||
* 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 JPackageCommand() {
|
||||
actions = new ArrayList<>();
|
||||
prerequisiteActions = new Actions();
|
||||
verifyActions = new Actions();
|
||||
}
|
||||
|
||||
public JPackageCommand(JPackageCommand cmd) {
|
||||
this();
|
||||
args.addAll(cmd.args);
|
||||
withToolProvider = cmd.withToolProvider;
|
||||
saveConsoleOutput = cmd.saveConsoleOutput;
|
||||
suppressOutput = cmd.suppressOutput;
|
||||
ignoreDefaultRuntime = cmd.ignoreDefaultRuntime;
|
||||
ignoreDefaultVerbose = cmd.ignoreDefaultVerbose;
|
||||
immutable = cmd.immutable;
|
||||
actionsExecuted = cmd.actionsExecuted;
|
||||
prerequisiteActions = new Actions(cmd.prerequisiteActions);
|
||||
verifyActions = new Actions(cmd.verifyActions);
|
||||
}
|
||||
|
||||
JPackageCommand createImmutableCopy() {
|
||||
@ -204,8 +207,8 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public JPackageCommand setDefaultInputOutput() {
|
||||
addArguments("--input", TKit.defaultInputDir());
|
||||
addArguments("--dest", TKit.defaultOutputDir());
|
||||
setArgumentValue("--input", TKit.workDir().resolve("input"));
|
||||
setArgumentValue("--dest", TKit.workDir().resolve("output"));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -221,7 +224,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
};
|
||||
|
||||
addAction(cmd -> {
|
||||
addPrerequisiteAction(cmd -> {
|
||||
Path fakeRuntimeDir = TKit.workDir().resolve("fake_runtime");
|
||||
|
||||
TKit.trace(String.format("Init fake runtime in [%s] directory",
|
||||
@ -254,9 +257,15 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
return this;
|
||||
}
|
||||
|
||||
JPackageCommand addAction(ThrowingConsumer<JPackageCommand> action) {
|
||||
JPackageCommand addPrerequisiteAction(ThrowingConsumer<JPackageCommand> action) {
|
||||
verifyMutable();
|
||||
actions.add(ThrowingConsumer.toConsumer(action));
|
||||
prerequisiteActions.add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
JPackageCommand addVerifyAction(ThrowingConsumer<JPackageCommand> action) {
|
||||
verifyMutable();
|
||||
verifyActions.add(action);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -363,6 +372,12 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
* `/opt/foo`
|
||||
*/
|
||||
public Path appInstallationDirectory() {
|
||||
Path unpackedDir = getArgumentValue(UNPACKED_PATH_ARGNAME, () -> null,
|
||||
Path::of);
|
||||
if (unpackedDir != null) {
|
||||
return unpackedDir;
|
||||
}
|
||||
|
||||
if (isImagePackageType()) {
|
||||
return null;
|
||||
}
|
||||
@ -426,7 +441,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
launcherName = launcherName + ".exe";
|
||||
}
|
||||
|
||||
if (isImagePackageType()) {
|
||||
if (isImagePackageType() || isPackageUnpacked()) {
|
||||
return appLayout().launchersDirectory().resolve(launcherName);
|
||||
}
|
||||
|
||||
@ -496,6 +511,19 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
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() {
|
||||
defaultWithToolProvider = true;
|
||||
}
|
||||
@ -528,24 +556,28 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
return this;
|
||||
}
|
||||
|
||||
public JPackageCommand ignoreDefaultVerbose(boolean v) {
|
||||
verifyMutable();
|
||||
ignoreDefaultVerbose = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public boolean isWithToolProvider() {
|
||||
return Optional.ofNullable(withToolProvider).orElse(
|
||||
defaultWithToolProvider);
|
||||
}
|
||||
|
||||
public JPackageCommand executePrerequisiteActions() {
|
||||
verifyMutable();
|
||||
if (!actionsExecuted) {
|
||||
actionsExecuted = true;
|
||||
if (actions != null) {
|
||||
actions.stream().forEach(r -> r.accept(this));
|
||||
}
|
||||
}
|
||||
prerequisiteActions.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
public Executor createExecutor() {
|
||||
verifyMutable();
|
||||
public JPackageCommand executeVerifyActions() {
|
||||
verifyActions.run();
|
||||
return this;
|
||||
}
|
||||
|
||||
private Executor createExecutor() {
|
||||
Executor exec = new Executor()
|
||||
.saveOutput(saveConsoleOutput).dumpOutput(!suppressOutput)
|
||||
.addArguments(args);
|
||||
@ -560,27 +592,60 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public Executor.Result execute() {
|
||||
return execute(0);
|
||||
}
|
||||
|
||||
public Executor.Result execute(int expectedExitCode) {
|
||||
executePrerequisiteActions();
|
||||
|
||||
if (isImagePackageType()) {
|
||||
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()
|
||||
.createExecutor()
|
||||
.execute();
|
||||
.execute(expectedExitCode);
|
||||
|
||||
if (result.exitCode == 0) {
|
||||
executeVerifyActions();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public JPackageCommand executeAndAssertHelloAppImageCreated() {
|
||||
executeAndAssertImageCreated();
|
||||
public Executor.Result executeAndAssertHelloAppImageCreated() {
|
||||
Executor.Result result = executeAndAssertImageCreated();
|
||||
HelloApp.executeLauncherAndVerifyOutput(this);
|
||||
return this;
|
||||
return result;
|
||||
}
|
||||
|
||||
public JPackageCommand executeAndAssertImageCreated() {
|
||||
execute().assertExitCodeIsZero();
|
||||
return assertImageCreated();
|
||||
public Executor.Result executeAndAssertImageCreated() {
|
||||
Executor.Result result = execute();
|
||||
assertImageCreated();
|
||||
return result;
|
||||
}
|
||||
|
||||
public JPackageCommand assertImageCreated() {
|
||||
@ -595,23 +660,26 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
return this;
|
||||
}
|
||||
|
||||
JPackageCommand setUnpackedPackageLocation(Path path) {
|
||||
verifyIsOfType(PackageType.NATIVE);
|
||||
setArgumentValue(UNPACKED_PATH_ARGNAME, path);
|
||||
return this;
|
||||
}
|
||||
|
||||
private JPackageCommand adjustArgumentsBeforeExecution() {
|
||||
if (!hasArgument("--runtime-image") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) {
|
||||
addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE);
|
||||
}
|
||||
|
||||
if (!hasArgument("--verbose") && TKit.VERBOSE_JPACKAGE) {
|
||||
if (!hasArgument("--verbose") && TKit.VERBOSE_JPACKAGE && !ignoreDefaultVerbose) {
|
||||
addArgument("--verbose");
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
String getPrintableCommandLine() {
|
||||
return new Executor()
|
||||
.setExecutable(JavaTool.JPACKAGE)
|
||||
.addArguments(args)
|
||||
.getPrintableCommandLine();
|
||||
public String getPrintableCommandLine() {
|
||||
return createExecutor().getPrintableCommandLine();
|
||||
}
|
||||
|
||||
public void verifyIsOfType(Collection<PackageType> types) {
|
||||
@ -699,13 +767,48 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
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 saveConsoleOutput;
|
||||
private boolean suppressOutput;
|
||||
private boolean ignoreDefaultRuntime;
|
||||
private boolean ignoreDefaultVerbose;
|
||||
private boolean immutable;
|
||||
private boolean actionsExecuted;
|
||||
private final List<Consumer<JPackageCommand>> actions;
|
||||
private final Actions prerequisiteActions;
|
||||
private final Actions verifyActions;
|
||||
private static boolean defaultWithToolProvider;
|
||||
|
||||
private final static Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
||||
@ -729,4 +832,6 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
return null;
|
||||
}).get();
|
||||
|
||||
private final static String UNPACKED_PATH_ARGNAME = "jpt-unpacked-folder";
|
||||
}
|
||||
|
@ -67,7 +67,7 @@ public final class JarBuilder {
|
||||
.setToolProvider(JavaTool.JAVAC)
|
||||
.addArguments("-d", workDir.toString())
|
||||
.addPathArguments(sourceFiles)
|
||||
.execute().assertExitCodeIsZero();
|
||||
.execute();
|
||||
}
|
||||
|
||||
Files.createDirectories(outputJar.getParent());
|
||||
@ -87,7 +87,7 @@ public final class JarBuilder {
|
||||
jarExe.addArguments("-e", mainClass);
|
||||
}
|
||||
jarExe.addArguments("-C", workDir.toString(), ".");
|
||||
jarExe.execute().assertExitCodeIsZero();
|
||||
jarExe.execute();
|
||||
});
|
||||
}
|
||||
private List<Path> sourceFiles;
|
||||
|
@ -25,14 +25,11 @@ package jdk.jpackage.test;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||
|
||||
public class LinuxHelper {
|
||||
private static String getRelease(JPackageCommand cmd) {
|
||||
@ -45,6 +42,19 @@ public class LinuxHelper {
|
||||
() -> 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) {
|
||||
cmd.verifyIsOfType(PackageType.LINUX);
|
||||
|
||||
@ -73,18 +83,14 @@ public class LinuxHelper {
|
||||
final PackageType packageType = cmd.packageType();
|
||||
final Path packageFile = cmd.outputBundle();
|
||||
|
||||
Executor exec = new Executor();
|
||||
Executor exec = null;
|
||||
switch (packageType) {
|
||||
case LINUX_DEB:
|
||||
exec.setExecutable("dpkg")
|
||||
.addArgument("--contents")
|
||||
.addArgument(packageFile);
|
||||
exec = Executor.of("dpkg", "--contents").addArgument(packageFile);
|
||||
break;
|
||||
|
||||
case LINUX_RPM:
|
||||
exec.setExecutable("rpm")
|
||||
.addArgument("-qpl")
|
||||
.addArgument(packageFile);
|
||||
exec = Executor.of("rpm", "-qpl").addArgument(packageFile);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -109,8 +115,8 @@ public class LinuxHelper {
|
||||
Collectors.toList());
|
||||
|
||||
case LINUX_RPM:
|
||||
return new Executor().setExecutable("rpm")
|
||||
.addArguments("-qp", "-R", cmd.outputBundle().toString())
|
||||
return Executor.of("rpm", "-qp", "-R")
|
||||
.addArgument(cmd.outputBundle())
|
||||
.executeAndGetOutput();
|
||||
}
|
||||
// Unreachable
|
||||
@ -141,6 +147,57 @@ public class LinuxHelper {
|
||||
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) {
|
||||
cmd.verifyIsOfType(PackageType.LINUX);
|
||||
|
||||
@ -173,20 +230,15 @@ public class LinuxHelper {
|
||||
}
|
||||
|
||||
static String getDebBundleProperty(Path bundle, String fieldName) {
|
||||
return new Executor()
|
||||
.setExecutable("dpkg-deb")
|
||||
.addArguments("-f", bundle.toString(), fieldName)
|
||||
return Executor.of("dpkg-deb", "-f")
|
||||
.addArgument(bundle)
|
||||
.addArgument(fieldName)
|
||||
.executeAndGetFirstLineOfOutput();
|
||||
}
|
||||
|
||||
static String getRpmBundleProperty(Path bundle, String fieldName) {
|
||||
return new Executor()
|
||||
.setExecutable("rpm")
|
||||
.addArguments(
|
||||
"-qp",
|
||||
"--queryformat",
|
||||
String.format("%%{%s}", fieldName),
|
||||
bundle.toString())
|
||||
return Executor.of("rpm", "-qp", "--queryformat", String.format("%%{%s}", fieldName))
|
||||
.addArgument(bundle)
|
||||
.executeAndGetFirstLineOfOutput();
|
||||
}
|
||||
|
||||
@ -264,13 +316,10 @@ public class LinuxHelper {
|
||||
test.addBundleVerifier(cmd -> {
|
||||
TKit.withTempDirectory("dpkg-control-files", tempDir -> {
|
||||
// Extract control Debian package files into temporary directory
|
||||
new Executor()
|
||||
.setExecutable("dpkg")
|
||||
.addArguments(
|
||||
"-e",
|
||||
cmd.outputBundle().toString(),
|
||||
tempDir.toString()
|
||||
).execute().assertExitCodeIsZero();
|
||||
Executor.of("dpkg", "-e")
|
||||
.addArgument(cmd.outputBundle())
|
||||
.addArgument(tempDir)
|
||||
.execute();
|
||||
|
||||
Path controlFile = Path.of("postinst");
|
||||
|
||||
@ -318,6 +367,10 @@ public class LinuxHelper {
|
||||
|
||||
static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) {
|
||||
test.addInstallVerifier(cmd -> {
|
||||
if (cmd.isPackageUnpacked("Not running file associations checks")) {
|
||||
return;
|
||||
}
|
||||
|
||||
PackageTest.withTestFileAssociationsFile(fa, testFile -> {
|
||||
String mimeType = queryFileMimeType(testFile);
|
||||
|
||||
@ -363,16 +416,12 @@ public class LinuxHelper {
|
||||
}
|
||||
|
||||
private static String queryFileMimeType(Path file) {
|
||||
return new Executor()
|
||||
.setExecutable("xdg-mime")
|
||||
.addArguments("query", "filetype", file.toString())
|
||||
return Executor.of("xdg-mime", "query", "filetype").addArgument(file)
|
||||
.executeAndGetFirstLineOfOutput();
|
||||
}
|
||||
|
||||
private static String queryMimeTypeDefaultHandler(String mimeType) {
|
||||
return new Executor()
|
||||
.setExecutable("xdg-mime")
|
||||
.addArguments("query", "default", mimeType)
|
||||
return Executor.of("xdg-mime", "query", "default", mimeType)
|
||||
.executeAndGetFirstLineOfOutput();
|
||||
}
|
||||
|
||||
@ -383,16 +432,14 @@ public class LinuxHelper {
|
||||
|
||||
String arch = archs.get(type);
|
||||
if (arch == null) {
|
||||
Executor exec = new Executor();
|
||||
Executor exec = null;
|
||||
switch (type) {
|
||||
case LINUX_DEB:
|
||||
exec.setExecutable("dpkg").addArgument(
|
||||
"--print-architecture");
|
||||
exec = Executor.of("dpkg", "--print-architecture");
|
||||
break;
|
||||
|
||||
case LINUX_RPM:
|
||||
exec.setExecutable("rpmbuild").addArgument(
|
||||
"--eval=%{_target_cpu}");
|
||||
exec = Executor.of("rpmbuild", "--eval=%{_target_cpu}");
|
||||
break;
|
||||
}
|
||||
arch = exec.executeAndGetFirstLineOfOutput();
|
||||
|
@ -29,6 +29,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
@ -39,6 +40,7 @@ import javax.xml.xpath.XPathConstants;
|
||||
import javax.xml.xpath.XPathFactory;
|
||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||
import jdk.jpackage.test.Functional.ThrowingSupplier;
|
||||
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
public class MacHelper {
|
||||
@ -47,10 +49,12 @@ public class MacHelper {
|
||||
ThrowingConsumer<Path> consumer) {
|
||||
cmd.verifyIsOfType(PackageType.MAC_DMG);
|
||||
|
||||
var plist = readPList(new Executor()
|
||||
.setExecutable("/usr/bin/hdiutil")
|
||||
// Explode DMG assuming this can require interaction, thus use `yes`.
|
||||
var plist = readPList(Executor.of("sh", "-c",
|
||||
String.join(" ", "yes", "|", "/usr/bin/hdiutil", "attach",
|
||||
JPackageCommand.escapeAndJoin(
|
||||
cmd.outputBundle().toString()), "-plist"))
|
||||
.dumpOutput()
|
||||
.addArguments("attach", cmd.outputBundle().toString(), "-plist")
|
||||
.executeAndGetOutput());
|
||||
|
||||
final Path mountPoint = Path.of(plist.queryValue("mount-point"));
|
||||
@ -60,10 +64,7 @@ public class MacHelper {
|
||||
cmd.outputBundle(), dmgImage));
|
||||
ThrowingConsumer.toConsumer(consumer).accept(dmgImage);
|
||||
} finally {
|
||||
new Executor()
|
||||
.setExecutable("/usr/bin/hdiutil")
|
||||
.addArgument("detach").addArgument(mountPoint)
|
||||
.execute().assertExitCodeIsZero();
|
||||
Executor.of("/usr/bin/hdiutil", "detach").addArgument(mountPoint).execute();
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,8 +83,62 @@ public class MacHelper {
|
||||
}
|
||||
|
||||
public static PListWrapper readPList(Stream<String> lines) {
|
||||
return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines.collect(
|
||||
Collectors.joining()))).get();
|
||||
return ThrowingSupplier.toSupplier(() -> new PListWrapper(lines
|
||||
// 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) {
|
||||
|
@ -28,14 +28,13 @@ import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||
import jdk.incubator.jpackage.internal.AppImageFile;
|
||||
import jdk.jpackage.test.Functional.ThrowingBiConsumer;
|
||||
import jdk.jpackage.test.Functional.ThrowingRunnable;
|
||||
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
|
||||
* 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() {
|
||||
action = DEFAULT_ACTION;
|
||||
excludeTypes = new HashSet<>();
|
||||
forTypes();
|
||||
setExpectedExitCode(0);
|
||||
handlers = new HashMap<>();
|
||||
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) {
|
||||
@ -117,19 +107,37 @@ public final class PackageTest {
|
||||
|
||||
namedInitializers.add(id);
|
||||
}
|
||||
currentTypes.stream().forEach(type -> handlers.get(type).addInitializer(
|
||||
currentTypes.forEach(type -> handlers.get(type).addInitializer(
|
||||
ThrowingConsumer.toConsumer(v)));
|
||||
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) {
|
||||
return addInitializer(v, null);
|
||||
}
|
||||
|
||||
public PackageTest addRunOnceInitializer(ThrowingRunnable v) {
|
||||
return addRunOnceInitializer(v, null);
|
||||
}
|
||||
|
||||
public PackageTest addBundleVerifier(
|
||||
BiConsumer<JPackageCommand, Executor.Result> v) {
|
||||
currentTypes.stream().forEach(
|
||||
type -> handlers.get(type).addBundleVerifier(v));
|
||||
ThrowingBiConsumer<JPackageCommand, Executor.Result> v) {
|
||||
currentTypes.forEach(type -> handlers.get(type).addBundleVerifier(
|
||||
ThrowingBiConsumer.toBiConsumer(v)));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -139,19 +147,26 @@ public final class PackageTest {
|
||||
}
|
||||
|
||||
public PackageTest addBundlePropertyVerifier(String propertyName,
|
||||
BiConsumer<String, String> pred) {
|
||||
Predicate<String> pred, String predLabel) {
|
||||
return addBundleVerifier(cmd -> {
|
||||
pred.accept(propertyName,
|
||||
LinuxHelper.getBundleProperty(cmd, propertyName));
|
||||
final String value;
|
||||
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,
|
||||
String expectedPropertyValue) {
|
||||
return addBundlePropertyVerifier(propertyName, (unused, v) -> {
|
||||
TKit.assertEquals(expectedPropertyValue, v, String.format(
|
||||
"Check value of %s property is [%s]", propertyName, v));
|
||||
});
|
||||
return addBundlePropertyVerifier(propertyName,
|
||||
expectedPropertyValue::equals, "is");
|
||||
}
|
||||
|
||||
public PackageTest addBundleDesktopIntegrationVerifier(boolean integrated) {
|
||||
@ -162,24 +177,39 @@ public final class PackageTest {
|
||||
}
|
||||
|
||||
public PackageTest addInstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
||||
currentTypes.stream().forEach(
|
||||
type -> handlers.get(type).addInstallVerifier(
|
||||
ThrowingConsumer.toConsumer(v)));
|
||||
currentTypes.forEach(type -> handlers.get(type).addInstallVerifier(
|
||||
ThrowingConsumer.toConsumer(v)));
|
||||
return this;
|
||||
}
|
||||
|
||||
public PackageTest addUninstallVerifier(ThrowingConsumer<JPackageCommand> v) {
|
||||
currentTypes.stream().forEach(
|
||||
type -> handlers.get(type).addUninstallVerifier(
|
||||
ThrowingConsumer.toConsumer(v)));
|
||||
currentTypes.forEach(type -> handlers.get(type).addUninstallVerifier(
|
||||
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;
|
||||
}
|
||||
|
||||
static void withTestFileAssociationsFile(FileAssociations fa,
|
||||
ThrowingConsumer<Path> consumer) {
|
||||
final String testFileDefaultName = String.join(".", "test",
|
||||
fa.getSuffix());
|
||||
TKit.withTempFile(testFileDefaultName, fa.getSuffix(), testFile -> {
|
||||
final Path testFileDefaultName = Path.of("test" + fa.getSuffix());
|
||||
TKit.withTempFile(testFileDefaultName, testFile -> {
|
||||
if (TKit.isLinux()) {
|
||||
LinuxHelper.initFileAssociationsTestFile(testFile);
|
||||
}
|
||||
@ -192,7 +222,7 @@ public final class PackageTest {
|
||||
|
||||
// Setup test app to have valid jpackage command line before
|
||||
// running check of type of environment.
|
||||
addInitializer(cmd -> new HelloApp(null).addTo(cmd), "HelloApp");
|
||||
addHelloAppInitializer(null);
|
||||
|
||||
String noActionMsg = "Not running file associations test";
|
||||
if (GraphicsEnvironment.isHeadless()) {
|
||||
@ -202,7 +232,7 @@ public final class PackageTest {
|
||||
}
|
||||
|
||||
addInstallVerifier(cmd -> {
|
||||
if (cmd.isFakeRuntime(noActionMsg)) {
|
||||
if (cmd.isFakeRuntime(noActionMsg) || cmd.isPackageUnpacked(noActionMsg)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -225,7 +255,8 @@ public final class PackageTest {
|
||||
// Wait a little bit after file has been created to
|
||||
// make sure there are no pending writes into it.
|
||||
Thread.sleep(3000);
|
||||
HelloApp.verifyOutputFile(appOutput, expectedArgs);
|
||||
HelloApp.verifyOutputFile(appOutput, expectedArgs,
|
||||
Collections.emptyMap());
|
||||
});
|
||||
});
|
||||
|
||||
@ -236,7 +267,7 @@ public final class PackageTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageTest forTypes(Collection<PackageType> types, Runnable action) {
|
||||
public PackageTest forTypes(Collection<PackageType> types, Runnable action) {
|
||||
Set<PackageType> oldTypes = Set.of(currentTypes.toArray(
|
||||
PackageType[]::new));
|
||||
try {
|
||||
@ -248,17 +279,17 @@ public final class PackageTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageTest forTypes(PackageType type, Runnable action) {
|
||||
public PackageTest forTypes(PackageType type, Runnable 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);
|
||||
workset.removeAll(types);
|
||||
return forTypes(workset, action);
|
||||
}
|
||||
|
||||
PackageTest notForTypes(PackageType type, Runnable action) {
|
||||
public PackageTest notForTypes(PackageType type, Runnable action) {
|
||||
return notForTypes(List.of(type), action);
|
||||
}
|
||||
|
||||
@ -266,55 +297,167 @@ public final class PackageTest {
|
||||
return configureHelloApp(null);
|
||||
}
|
||||
|
||||
public PackageTest configureHelloApp(String encodedName) {
|
||||
addInitializer(
|
||||
cmd -> new HelloApp(JavaAppDesc.parse(encodedName)).addTo(cmd));
|
||||
public PackageTest configureHelloApp(String javaAppDesc) {
|
||||
addHelloAppInitializer(javaAppDesc);
|
||||
addInstallVerifier(HelloApp::executeLauncherAndVerifyOutput);
|
||||
return this;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
List<Handler> supportedHandlers = handlers.values().stream()
|
||||
.filter(entry -> !entry.isVoid())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (supportedHandlers.isEmpty()) {
|
||||
// No handlers with initializers found. Nothing to do.
|
||||
return;
|
||||
public final static class Group extends RunnablePackageTest {
|
||||
public Group(PackageTest... tests) {
|
||||
handlers = Stream.of(tests)
|
||||
.map(PackageTest::createPackageTypeHandlers)
|
||||
.flatMap(List<Consumer<Action>>::stream)
|
||||
.collect(Collectors.toUnmodifiableList());
|
||||
}
|
||||
|
||||
Supplier<JPackageCommand> initializer = new Supplier<>() {
|
||||
@Override
|
||||
public JPackageCommand get() {
|
||||
JPackageCommand cmd = new JPackageCommand().setDefaultInputOutput();
|
||||
if (bundleOutputDir != null) {
|
||||
cmd.setArgumentValue("--dest", bundleOutputDir.toString());
|
||||
@Override
|
||||
protected void runAction(Action... action) {
|
||||
if (Set.of(action).contains(Action.UNINSTALL)) {
|
||||
ListIterator<Consumer<Action>> listIterator = handlers.listIterator(
|
||||
handlers.size());
|
||||
while (listIterator.hasPrevious()) {
|
||||
var handler = listIterator.previous();
|
||||
List.of(action).forEach(handler::accept);
|
||||
}
|
||||
cmd.setDefaultAppName();
|
||||
return cmd;
|
||||
} else {
|
||||
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) {
|
||||
action = value;
|
||||
return this;
|
||||
final static class PackageHandlers {
|
||||
Consumer<JPackageCommand> installHandler;
|
||||
Consumer<JPackageCommand> uninstallHandler;
|
||||
BiFunction<JPackageCommand, Path, Path> unpackHandler;
|
||||
}
|
||||
|
||||
public Action getAction() {
|
||||
return action;
|
||||
@Override
|
||||
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) {
|
||||
if (!PackageType.NATIVE.contains(type)) {
|
||||
throw new IllegalArgumentException(
|
||||
"Attempt to configure a test for image packaging");
|
||||
private void addHelloAppInitializer(String javaAppDesc) {
|
||||
addInitializer(
|
||||
cmd -> new HelloApp(JavaAppDesc.parse(javaAppDesc)).addTo(cmd),
|
||||
"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<>();
|
||||
bundleVerifiers = new ArrayList<>();
|
||||
installVerifiers = new ArrayList<>();
|
||||
@ -342,33 +485,35 @@ public final class PackageTest {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(JPackageCommand cmd) {
|
||||
type.applyTo(cmd);
|
||||
|
||||
initializers.stream().forEach(v -> v.accept(cmd));
|
||||
cmd.executePrerequisiteActions();
|
||||
|
||||
public void accept(Action action, JPackageCommand cmd) {
|
||||
switch (action) {
|
||||
case INITIALIZE:
|
||||
initializers.forEach(v -> v.accept(cmd));
|
||||
if (cmd.isImagePackageType()) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
cmd.executePrerequisiteActions();
|
||||
break;
|
||||
|
||||
case CREATE:
|
||||
Executor.Result result = cmd.execute();
|
||||
result.assertExitCodeIs(expectedJPackageExitCode);
|
||||
Executor.Result result = cmd.execute(expectedJPackageExitCode);
|
||||
if (expectedJPackageExitCode == 0) {
|
||||
TKit.assertFileExists(cmd.outputBundle());
|
||||
} else {
|
||||
TKit.assertPathExists(cmd.outputBundle(), false);
|
||||
}
|
||||
verifyPackageBundle(cmd.createImmutableCopy(), result);
|
||||
verifyPackageBundle(cmd, result);
|
||||
break;
|
||||
|
||||
case VERIFY_INSTALL:
|
||||
if (expectedJPackageExitCode == 0) {
|
||||
verifyPackageInstalled(cmd.createImmutableCopy());
|
||||
verifyPackageInstalled(cmd);
|
||||
}
|
||||
break;
|
||||
|
||||
case VERIFY_UNINSTALL:
|
||||
if (expectedJPackageExitCode == 0) {
|
||||
verifyPackageUninstalled(cmd.createImmutableCopy());
|
||||
verifyPackageUninstalled(cmd);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -381,25 +526,33 @@ public final class PackageTest {
|
||||
LinuxHelper.verifyPackageBundleEssential(cmd);
|
||||
}
|
||||
}
|
||||
bundleVerifiers.stream().forEach(v -> v.accept(cmd, result));
|
||||
bundleVerifiers.forEach(v -> v.accept(cmd, result));
|
||||
}
|
||||
|
||||
private void verifyPackageInstalled(JPackageCommand cmd) {
|
||||
TKit.trace(String.format("Verify installed: %s",
|
||||
cmd.getPrintableCommandLine()));
|
||||
final String formatString;
|
||||
if (cmd.isPackageUnpacked()) {
|
||||
formatString = "Verify unpacked: %s";
|
||||
} else {
|
||||
formatString = "Verify installed: %s";
|
||||
}
|
||||
TKit.trace(String.format(formatString, cmd.getPrintableCommandLine()));
|
||||
|
||||
TKit.assertDirectoryExists(cmd.appRuntimeDirectory());
|
||||
if (!cmd.isRuntime()) {
|
||||
TKit.assertExecutableFileExists(cmd.appLauncherPath());
|
||||
|
||||
if (PackageType.WINDOWS.contains(cmd.packageType())) {
|
||||
new WindowsHelper.AppVerifier(cmd);
|
||||
if (PackageType.WINDOWS.contains(cmd.packageType())
|
||||
&& !cmd.isPackageUnpacked(
|
||||
"Not verifying desktop integration")) {
|
||||
new WindowsHelper.DesktopIntegrationVerifier(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
TKit.assertPathExists(AppImageFile.getPathInAppImage(
|
||||
cmd.appInstallationDirectory()), false);
|
||||
|
||||
installVerifiers.stream().forEach(v -> v.accept(cmd));
|
||||
installVerifiers.forEach(v -> v.accept(cmd));
|
||||
}
|
||||
|
||||
private void verifyPackageUninstalled(JPackageCommand cmd) {
|
||||
@ -409,79 +562,63 @@ public final class PackageTest {
|
||||
TKit.assertPathExists(cmd.appLauncherPath(), false);
|
||||
|
||||
if (PackageType.WINDOWS.contains(cmd.packageType())) {
|
||||
new WindowsHelper.AppVerifier(cmd);
|
||||
new WindowsHelper.DesktopIntegrationVerifier(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
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<BiConsumer<JPackageCommand, Executor.Result>> bundleVerifiers;
|
||||
private final List<Consumer<JPackageCommand>> installVerifiers;
|
||||
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 Set<PackageType> excludeTypes;
|
||||
private int expectedJPackageExitCode;
|
||||
private Map<PackageType, Handler> handlers;
|
||||
private Set<String> namedInitializers;
|
||||
private Action action;
|
||||
private Map<PackageType, PackageHandlers> packageHandlers;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private final static File BUNDLE_OUTPUT_DIR;
|
||||
|
||||
static {
|
||||
final String propertyName = "output";
|
||||
String val = TKit.getConfigProperty(propertyName);
|
||||
if (val == null) {
|
||||
bundleOutputDir = null;
|
||||
BUNDLE_OUTPUT_DIR = null;
|
||||
} else {
|
||||
bundleOutputDir = new File(val).getAbsoluteFile();
|
||||
BUNDLE_OUTPUT_DIR = new File(val).getAbsoluteFile();
|
||||
|
||||
if (!bundleOutputDir.isDirectory()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Invalid value of %s sytem property: [%s]. Should be existing directory",
|
||||
if (!BUNDLE_OUTPUT_DIR.isDirectory()) {
|
||||
throw new IllegalArgumentException(String.format("Invalid value of %s sytem property: [%s]. Should be existing directory",
|
||||
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) {
|
||||
cmd.addArguments("--type", getName());
|
||||
cmd.setArgumentValue("--type", getName());
|
||||
}
|
||||
|
||||
String getSuffix() {
|
||||
|
@ -52,7 +52,7 @@ final public class TKit {
|
||||
|
||||
for (int i = 0; i != 10; ++i) {
|
||||
if (root.resolve("apps").toFile().isDirectory()) {
|
||||
return root.toAbsolutePath();
|
||||
return root.normalize().toAbsolutePath();
|
||||
}
|
||||
root = root.resolve("..");
|
||||
}
|
||||
@ -60,6 +60,10 @@ final public class TKit {
|
||||
throw new RuntimeException("Failed to locate apps directory");
|
||||
}).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(() -> {
|
||||
if (isOSX()) {
|
||||
return ".icns";
|
||||
@ -150,14 +154,6 @@ final public class TKit {
|
||||
return currentTest.workDir();
|
||||
}
|
||||
|
||||
static Path defaultInputDir() {
|
||||
return workDir().resolve("input");
|
||||
}
|
||||
|
||||
static Path defaultOutputDir() {
|
||||
return workDir().resolve("output");
|
||||
}
|
||||
|
||||
static String getCurrentDefaultAppName() {
|
||||
// Construct app name from swapping and joining test base name
|
||||
// and test function name.
|
||||
@ -275,18 +271,16 @@ final public class TKit {
|
||||
return Files.createDirectory(createUniqueFileName(role));
|
||||
}
|
||||
|
||||
public static Path createTempFile(String role, String suffix) throws
|
||||
public static Path createTempFile(Path templateFile) throws
|
||||
IOException {
|
||||
if (role == null) {
|
||||
return Files.createTempFile(workDir(), TEMP_FILE_PREFIX, suffix);
|
||||
}
|
||||
return Files.createFile(createUniqueFileName(role));
|
||||
return Files.createFile(createUniqueFileName(
|
||||
templateFile.getFileName().toString()));
|
||||
}
|
||||
|
||||
public static Path withTempFile(String role, String suffix,
|
||||
public static Path withTempFile(Path templateFile,
|
||||
ThrowingConsumer<Path> action) {
|
||||
final Path tempFile = ThrowingSupplier.toSupplier(() -> createTempFile(
|
||||
role, suffix)).get();
|
||||
templateFile)).get();
|
||||
boolean keepIt = true;
|
||||
try {
|
||||
ThrowingConsumer.toConsumer(action).accept(tempFile);
|
||||
@ -449,10 +443,11 @@ final public class TKit {
|
||||
}
|
||||
|
||||
public static Path createRelativePathCopy(final Path file) {
|
||||
Path fileCopy = workDir().resolve(file.getFileName()).toAbsolutePath().normalize();
|
||||
|
||||
ThrowingRunnable.toRunnable(() -> Files.copy(file, fileCopy,
|
||||
StandardCopyOption.REPLACE_EXISTING)).run();
|
||||
Path fileCopy = ThrowingSupplier.toSupplier(() -> {
|
||||
Path localPath = createTempFile(file);
|
||||
Files.copy(file, localPath, StandardCopyOption.REPLACE_EXISTING);
|
||||
return localPath;
|
||||
}).get().toAbsolutePath().normalize();
|
||||
|
||||
final Path basePath = Path.of(".").toAbsolutePath().normalize();
|
||||
try {
|
||||
@ -713,32 +708,32 @@ final public class TKit {
|
||||
}
|
||||
}
|
||||
|
||||
public final static class TextStreamAsserter {
|
||||
TextStreamAsserter(String value) {
|
||||
public final static class TextStreamVerifier {
|
||||
TextStreamVerifier(String value) {
|
||||
this.value = value;
|
||||
predicate(String::contains);
|
||||
}
|
||||
|
||||
public TextStreamAsserter label(String v) {
|
||||
public TextStreamVerifier label(String v) {
|
||||
label = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextStreamAsserter predicate(BiPredicate<String, String> v) {
|
||||
public TextStreamVerifier predicate(BiPredicate<String, String> v) {
|
||||
predicate = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextStreamAsserter negate() {
|
||||
public TextStreamVerifier negate() {
|
||||
negate = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public TextStreamAsserter orElseThrow(RuntimeException v) {
|
||||
public TextStreamVerifier orElseThrow(RuntimeException v) {
|
||||
return orElseThrow(() -> v);
|
||||
}
|
||||
|
||||
public TextStreamAsserter orElseThrow(Supplier<RuntimeException> v) {
|
||||
public TextStreamVerifier orElseThrow(Supplier<RuntimeException> v) {
|
||||
createException = v;
|
||||
return this;
|
||||
}
|
||||
@ -779,8 +774,8 @@ final public class TKit {
|
||||
final private String value;
|
||||
}
|
||||
|
||||
public static TextStreamAsserter assertTextStream(String what) {
|
||||
return new TextStreamAsserter(what);
|
||||
public static TextStreamVerifier assertTextStream(String what) {
|
||||
return new TextStreamVerifier(what);
|
||||
}
|
||||
|
||||
private static PrintStream openLogStream() {
|
||||
@ -809,13 +804,23 @@ final public class TKit {
|
||||
return "jpackage.test." + propertyName;
|
||||
}
|
||||
|
||||
static Set<String> tokenizeConfigProperty(String propertyName) {
|
||||
static List<String> tokenizeConfigPropertyAsList(String propertyName) {
|
||||
final String val = TKit.getConfigProperty(propertyName);
|
||||
if (val == null) {
|
||||
return null;
|
||||
}
|
||||
return Stream.of(val.toLowerCase().split(",")).map(String::strip).filter(
|
||||
Predicate.not(String::isEmpty)).collect(Collectors.toSet());
|
||||
return Stream.of(val.toLowerCase().split(","))
|
||||
.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(() -> {
|
||||
|
@ -68,11 +68,11 @@ final class TestBuilder implements AutoCloseable {
|
||||
|
||||
CMDLINE_ARG_PREFIX + "exclude",
|
||||
arg -> (excludedTests = Optional.ofNullable(
|
||||
excludedTests).orElse(new HashSet<String>())).add(arg),
|
||||
excludedTests).orElseGet(() -> new HashSet<String>())).add(arg),
|
||||
|
||||
CMDLINE_ARG_PREFIX + "include",
|
||||
arg -> (includedTests = Optional.ofNullable(
|
||||
includedTests).orElse(new HashSet<String>())).add(arg),
|
||||
includedTests).orElseGet(() -> new HashSet<String>())).add(arg),
|
||||
|
||||
CMDLINE_ARG_PREFIX + "space-subst",
|
||||
arg -> spaceSubstitute = arg,
|
||||
@ -127,8 +127,7 @@ final class TestBuilder implements AutoCloseable {
|
||||
// Log all matches before returning from the function
|
||||
return tests.filter(test -> {
|
||||
String testDescription = test.createDescription().testFullName();
|
||||
boolean match = filters.stream().anyMatch(
|
||||
v -> testDescription.contains(v));
|
||||
boolean match = filters.stream().anyMatch(testDescription::contains);
|
||||
if (match) {
|
||||
trace(String.format(logMsg + ": %s", testDescription));
|
||||
}
|
||||
@ -159,7 +158,7 @@ final class TestBuilder implements AutoCloseable {
|
||||
|
||||
private void flushTestGroup() {
|
||||
if (testGroup != null) {
|
||||
filterTestGroup().forEach(testBody -> createTestInstance(testBody));
|
||||
filterTestGroup().forEach(this::createTestInstance);
|
||||
clear();
|
||||
}
|
||||
}
|
||||
@ -170,7 +169,7 @@ final class TestBuilder implements AutoCloseable {
|
||||
|
||||
Method testMethod = testBody.getMethod();
|
||||
if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch(
|
||||
type -> testMethod.isAnnotationPresent(type))) {
|
||||
testMethod::isAnnotationPresent)) {
|
||||
curBeforeActions = beforeActions;
|
||||
curAfterActions = afterActions;
|
||||
} else {
|
||||
@ -286,7 +285,7 @@ final class TestBuilder implements AutoCloseable {
|
||||
List<Method> methods = Stream.of(methodClass.getMethods()).filter(
|
||||
(m) -> filterMethod(methodName, m)).collect(Collectors.toList());
|
||||
if (methods.isEmpty()) {
|
||||
new ParseException(String.format(
|
||||
throw new ParseException(String.format(
|
||||
"Method [%s] not found in [%s] class;",
|
||||
methodName, className));
|
||||
}
|
||||
|
@ -236,7 +236,13 @@ final class TestInstance implements ThrowingRunnable {
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -26,8 +26,11 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.Functional.ThrowingRunnable;
|
||||
import jdk.jpackage.test.PackageTest.PackageHandlers;
|
||||
|
||||
public class WindowsHelper {
|
||||
|
||||
@ -38,22 +41,82 @@ public class WindowsHelper {
|
||||
}
|
||||
|
||||
static Path getInstallationDirectory(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(PackageType.WINDOWS);
|
||||
Path installDir = Path.of(
|
||||
cmd.getArgumentValue("--install-dir", () -> cmd.name()));
|
||||
Path installSubDir = getInstallationSubDirectory(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) {
|
||||
return cmd.hasArgument("--win-per-user-install");
|
||||
}
|
||||
|
||||
static class AppVerifier {
|
||||
static class DesktopIntegrationVerifier {
|
||||
|
||||
AppVerifier(JPackageCommand cmd) {
|
||||
DesktopIntegrationVerifier(JPackageCommand cmd) {
|
||||
cmd.verifyIsOfType(PackageType.WINDOWS);
|
||||
this.cmd = cmd;
|
||||
verifyStartMenuShortcut();
|
||||
@ -201,16 +264,15 @@ public class WindowsHelper {
|
||||
}
|
||||
|
||||
private static String queryRegistryValue(String keyPath, String valueName) {
|
||||
Executor.Result status = new Executor()
|
||||
.setExecutable("reg")
|
||||
var status = Executor.of("reg", "query", keyPath, "/v", valueName)
|
||||
.saveOutput()
|
||||
.addArguments("query", keyPath, "/v", valueName)
|
||||
.execute();
|
||||
.executeWithoutExitCodeCheck();
|
||||
if (status.exitCode == 1) {
|
||||
// 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.";
|
||||
status.getOutput().stream().filter(line -> line.equals(lookupString)).findFirst().orElseThrow(
|
||||
() -> new RuntimeException(String.format(
|
||||
TKit.assertTextStream(lookupString)
|
||||
.predicate(String::equals)
|
||||
.orElseThrow(() -> new RuntimeException(String.format(
|
||||
"Failed to find [%s] string in the output",
|
||||
lookupString)));
|
||||
TKit.trace(String.format(
|
||||
|
@ -56,12 +56,10 @@ public class MaintainerTest {
|
||||
.addInitializer(cmd -> {
|
||||
cmd.addArguments("--linux-deb-maintainer", MAINTAINER);
|
||||
})
|
||||
.addBundlePropertyVerifier("Maintainer", (propName, propValue) -> {
|
||||
.addBundlePropertyVerifier("Maintainer", value -> {
|
||||
String lookupValue = "<" + MAINTAINER + ">";
|
||||
TKit.assertTrue(propValue.endsWith(lookupValue),
|
||||
String.format("Check value of %s property [%s] ends with %s",
|
||||
propName, propValue, lookupValue));
|
||||
})
|
||||
return value.endsWith(lookupValue);
|
||||
}, "ends with")
|
||||
.run();
|
||||
});
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.LinuxHelper;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
|
||||
|
||||
/**
|
||||
@ -50,41 +51,38 @@ import jdk.jpackage.test.LinuxHelper;
|
||||
* @build jdk.jpackage.test.*
|
||||
* @requires (os.family == "linux")
|
||||
* @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 static void main(String[] args) {
|
||||
// Pick the name of prerequisite package to be alphabetically
|
||||
// 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.
|
||||
@Test
|
||||
public static void test() {
|
||||
final String PREREQ_PACKAGE_NAME = "apackagedepstestprereq";
|
||||
|
||||
TKit.run(args, () -> {
|
||||
new PackageTest()
|
||||
.forTypes(PackageType.LINUX)
|
||||
.configureHelloApp()
|
||||
.addInitializer(cmd -> {
|
||||
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 test1 = new PackageTest()
|
||||
.forTypes(PackageType.LINUX)
|
||||
.configureHelloApp()
|
||||
.addInitializer(cmd -> {
|
||||
cmd.setArgumentValue("--name", PREREQ_PACKAGE_NAME);
|
||||
});
|
||||
|
||||
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)
|
||||
.addBundlePropertyVerifier("Release", RELEASE)
|
||||
.forTypes(PackageType.LINUX_DEB)
|
||||
.addBundlePropertyVerifier("Version", (propName, propValue) -> {
|
||||
TKit.assertTrue(propValue.endsWith("-" + RELEASE),
|
||||
String.format("Check value of %s property [%s] ends with %s",
|
||||
propName, propValue, RELEASE));
|
||||
})
|
||||
.addBundlePropertyVerifier("Version", propValue -> {
|
||||
return propValue.endsWith("-" + RELEASE);
|
||||
}, "ends with")
|
||||
.run();
|
||||
});
|
||||
}
|
||||
|
@ -21,12 +21,12 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Map;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.jpackage.test.AdditionalLauncher;
|
||||
import jdk.jpackage.test.FileAssociations;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
@ -127,56 +127,50 @@ public class ShortcutHintTest {
|
||||
*/
|
||||
@Test
|
||||
public static void testAdditionaltLaunchers() {
|
||||
createTest().addInitializer(cmd -> {
|
||||
cmd.setFakeRuntime();
|
||||
PackageTest test = createTest();
|
||||
|
||||
final String launcherName = "Foo";
|
||||
final Path propsFile = TKit.workDir().resolve(
|
||||
launcherName + ".properties");
|
||||
new AdditionalLauncher("Foo").setIcon(TKit.TEST_SRC_ROOT.resolve(
|
||||
"apps/dukeplug.png")).applyTo(test);
|
||||
|
||||
cmd.addArguments("--add-launcher", String.format("%s=%s",
|
||||
launcherName, propsFile));
|
||||
|
||||
TKit.createPropertiesFile(propsFile, Map.entry("icon",
|
||||
TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png").toString()));
|
||||
}).run();
|
||||
test.addInitializer(JPackageCommand::setFakeRuntime).run();
|
||||
}
|
||||
|
||||
/**
|
||||
* .desktop file from resource dir.
|
||||
*/
|
||||
@Test
|
||||
public static void testDesktopFileFromResourceDir() {
|
||||
public static void testDesktopFileFromResourceDir() throws IOException {
|
||||
final String expectedVersionString = "Version=12345678";
|
||||
TKit.withTempDirectory("resources", tempDir -> {
|
||||
createTest().addInitializer(cmd -> {
|
||||
cmd.setFakeRuntime();
|
||||
|
||||
cmd.addArgument("--linux-shortcut");
|
||||
cmd.addArguments("--resource-dir", tempDir);
|
||||
final Path tempDir = TKit.createTempDirectory("resources");
|
||||
|
||||
// Create custom .desktop file in resource directory
|
||||
TKit.createTextFile(tempDir.resolve(cmd.name() + ".desktop"),
|
||||
List.of(
|
||||
"[Desktop Entry]",
|
||||
"Name=APPLICATION_NAME",
|
||||
"Exec=APPLICATION_LAUNCHER",
|
||||
"Terminal=false",
|
||||
"Type=Application",
|
||||
"Categories=DEPLOY_BUNDLE_CATEGORY",
|
||||
expectedVersionString
|
||||
));
|
||||
})
|
||||
.addInstallVerifier(cmd -> {
|
||||
Path desktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
||||
String.format("%s-%s.desktop",
|
||||
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();
|
||||
});
|
||||
createTest().addInitializer(cmd -> {
|
||||
cmd.setFakeRuntime();
|
||||
|
||||
cmd.addArgument("--linux-shortcut");
|
||||
cmd.addArguments("--resource-dir", tempDir);
|
||||
|
||||
// Create custom .desktop file in resource directory
|
||||
TKit.createTextFile(tempDir.resolve(cmd.name() + ".desktop"),
|
||||
List.of(
|
||||
"[Desktop Entry]",
|
||||
"Name=APPLICATION_NAME",
|
||||
"Exec=APPLICATION_LAUNCHER",
|
||||
"Terminal=false",
|
||||
"Type=Application",
|
||||
"Categories=DEPLOY_BUNDLE_CATEGORY",
|
||||
expectedVersionString
|
||||
));
|
||||
})
|
||||
.addInstallVerifier(cmd -> {
|
||||
Path desktopFile = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
||||
String.format("%s-%s.desktop",
|
||||
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",
|
||||
target.toString())
|
||||
.saveOutput()
|
||||
.execute()
|
||||
.assertExitCodeIs(exitCode).getOutput();
|
||||
.execute(exitCode).getOutput();
|
||||
|
||||
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 ()
|
||||
{
|
||||
echo "Usage: `basename $0` [options] [test_names]"
|
||||
echo "Usage: `basename $0` [options] [--] [jtreg_options|test_names]"
|
||||
echo "Options:"
|
||||
echo " -h - print this message"
|
||||
echo " -v - verbose output"
|
||||
@ -58,16 +58,12 @@ help_usage ()
|
||||
echo ' -l <logfile> - value for `jpackage.test.logfile` property.'
|
||||
echo " Optional, for jtreg tests debug purposes only."
|
||||
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 ' - `create`'
|
||||
echo ' Remove all package bundles from the output directory before running jtreg tests.'
|
||||
echo ' - `update`'
|
||||
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 list of packaging tests and exit.'
|
||||
}
|
||||
@ -135,7 +131,10 @@ mode=update
|
||||
# jtreg extra arguments
|
||||
declare -a jtreg_args
|
||||
|
||||
# Run all tests
|
||||
# Create packages only
|
||||
jtreg_args+=("-Djpackage.test.action=create")
|
||||
|
||||
# run all tests
|
||||
run_all_tests=
|
||||
|
||||
mapfile -t tests < <(find_all_packaging_tests)
|
||||
@ -206,10 +205,6 @@ if [ "$mode" = create ]; then
|
||||
true
|
||||
elif [ "$mode" = update ]; then
|
||||
true
|
||||
elif [ "$mode" = verify-install ]; then
|
||||
jtreg_args+=("-Djpackage.test.action=$mode")
|
||||
elif [ "$mode" = verify-uninstall ]; then
|
||||
jtreg_args+=("-Djpackage.test.action=$mode")
|
||||
else
|
||||
fatal_with_help_usage 'Invalid value of -m option:' [$mode]
|
||||
fi
|
||||
@ -218,7 +213,11 @@ if [ -z "$run_all_tests" ]; then
|
||||
jtreg_args+=(-Djpackage.test.SQETest=yes)
|
||||
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=($@)
|
||||
|
||||
|
||||
|
@ -27,12 +27,8 @@ import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import jdk.jpackage.test.HelloApp;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.FileAssociations;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.*;
|
||||
import jdk.jpackage.test.Annotations.*;
|
||||
|
||||
/**
|
||||
* Test --add-launcher parameter. Output of the test should be
|
||||
@ -46,11 +42,25 @@ import jdk.jpackage.test.TKit;
|
||||
* @test
|
||||
* @summary jpackage with --add-launcher
|
||||
* @key jpackagePlatformPackage
|
||||
* @requires (jpackage.test.SQETest != null)
|
||||
* @library ../helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||
* @compile AdditionalLaunchersTest.java
|
||||
* @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
|
||||
*/
|
||||
|
||||
@ -72,87 +82,122 @@ public class AdditionalLaunchersTest {
|
||||
MethodHandles.lookup().lookupClass().getSimpleName()).applyTo(
|
||||
packageTest);
|
||||
|
||||
new AdditionalLauncher("Baz2").setArguments().applyTo(packageTest);
|
||||
new AdditionalLauncher("foo").setArguments("yep!").applyTo(packageTest);
|
||||
new AdditionalLauncher("Baz2")
|
||||
.setDefaultArguments()
|
||||
.applyTo(packageTest);
|
||||
|
||||
AdditionalLauncher barLauncher = new AdditionalLauncher("Bar").setArguments(
|
||||
"one", "two", "three");
|
||||
if (TKit.isLinux()) {
|
||||
barLauncher.setIcon(TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png"));
|
||||
}
|
||||
barLauncher.applyTo(packageTest);
|
||||
new AdditionalLauncher("foo")
|
||||
.setDefaultArguments("yep!")
|
||||
.applyTo(packageTest);
|
||||
|
||||
new AdditionalLauncher("Bar")
|
||||
.setDefaultArguments("one", "two", "three")
|
||||
.setIcon(GOLDEN_ICON)
|
||||
.applyTo(packageTest);
|
||||
|
||||
packageTest.run();
|
||||
}
|
||||
|
||||
private static Path replaceFileName(Path path, String newFileName) {
|
||||
String fname = path.getFileName().toString();
|
||||
int lastDotIndex = fname.lastIndexOf(".");
|
||||
if (lastDotIndex != -1) {
|
||||
fname = newFileName + fname.substring(lastDotIndex);
|
||||
@Test
|
||||
public void bug8230933() {
|
||||
PackageTest packageTest = new PackageTest().configureHelloApp();
|
||||
|
||||
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 {
|
||||
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 {
|
||||
|
||||
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;
|
||||
}
|
||||
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
||||
"resources", "icon" + TKit.ICON_SUFFIX));
|
||||
}
|
||||
|
@ -23,9 +23,9 @@
|
||||
|
||||
import java.nio.file.Path;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
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
|
||||
@ -41,34 +41,24 @@ import jdk.jpackage.test.JPackageCommand;
|
||||
* @requires (jpackage.test.SQETest == null)
|
||||
* @build jdk.jpackage.test.*
|
||||
* @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 static void main(String[] args) {
|
||||
TKit.run(args, () -> {
|
||||
Path appimageOutput = Path.of("appimage");
|
||||
@Test
|
||||
public static void test() {
|
||||
Path appimageOutput = TKit.workDir().resolve("appimage");
|
||||
|
||||
JPackageCommand appImageCmd = JPackageCommand.helloAppImage()
|
||||
.setArgumentValue("--dest", appimageOutput)
|
||||
.addArguments("--type", "app-image");
|
||||
JPackageCommand appImageCmd = JPackageCommand.helloAppImage()
|
||||
.setArgumentValue("--dest", appimageOutput);
|
||||
|
||||
PackageTest packageTest = new PackageTest();
|
||||
if (packageTest.getAction() == PackageTest.Action.CREATE) {
|
||||
appImageCmd.execute();
|
||||
}
|
||||
|
||||
packageTest.addInitializer(cmd -> {
|
||||
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();
|
||||
});
|
||||
new PackageTest()
|
||||
.addRunOnceInitializer(() -> appImageCmd.execute())
|
||||
.addInitializer(cmd -> {
|
||||
cmd.addArguments("--app-image", appImageCmd.outputBundle());
|
||||
cmd.removeArgumentWithValue("--input");
|
||||
}).addBundleDesktopIntegrationVerifier(false).run();
|
||||
}
|
||||
}
|
||||
|
@ -81,7 +81,9 @@ public class ArgumentsTest {
|
||||
Path launcherPath = cmd.appLauncherPath();
|
||||
if (!cmd.isFakeRuntime(String.format(
|
||||
"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.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.function.Consumer;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import jdk.incubator.jpackage.internal.IOUtils;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.Functional;
|
||||
import jdk.jpackage.test.*;
|
||||
import jdk.jpackage.test.Functional.ThrowingConsumer;
|
||||
import jdk.jpackage.test.Functional.ThrowingBiConsumer;
|
||||
import jdk.jpackage.test.Annotations.*;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary jpackage create image with custom icon
|
||||
* @summary jpackage create image and package with custom icons for the main and additional launcher
|
||||
* @library ../helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
|
||||
* @compile IconTest.java
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=IconTest
|
||||
*/
|
||||
|
||||
public class IconTest {
|
||||
@Test
|
||||
public static void testResourceDir() throws IOException {
|
||||
TKit.withTempDirectory("resources", tempDir -> {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage()
|
||||
.addArguments("--resource-dir", tempDir);
|
||||
|
||||
Files.copy(GOLDEN_ICON, tempDir.resolve(appIconFileName(cmd)),
|
||||
StandardCopyOption.REPLACE_EXISTING);
|
||||
enum IconType {
|
||||
/**
|
||||
* Icon not specified.
|
||||
*/
|
||||
DefaultIcon,
|
||||
|
||||
testIt(cmd);
|
||||
});
|
||||
/**
|
||||
* Explicit no icon.
|
||||
*/
|
||||
NoIcon,
|
||||
|
||||
/**
|
||||
* Custom icon on command line.
|
||||
*/
|
||||
CustomIcon,
|
||||
|
||||
/**
|
||||
* Custom icon in resource dir.
|
||||
*/
|
||||
ResourceDirIcon,
|
||||
|
||||
/**
|
||||
* Custom icon on command line and in resource dir.
|
||||
*/
|
||||
CustomWithResourceDirIcon
|
||||
}
|
||||
|
||||
enum BundleType { AppImage, Package }
|
||||
|
||||
public IconTest(BundleType bundleType, IconType mainLauncherIconType,
|
||||
IconType additionalLauncherIconType, String[] extraJPackageArgs) {
|
||||
this.appImage = (bundleType == BundleType.AppImage);
|
||||
this.extraJPackageArgs = extraJPackageArgs;
|
||||
config = Map.of(
|
||||
Launcher.Main, mainLauncherIconType,
|
||||
Launcher.Additional, additionalLauncherIconType);
|
||||
}
|
||||
|
||||
public IconTest(BundleType bundleType, IconType mainLauncherIconType,
|
||||
IconType additionalLauncherIconType) {
|
||||
this.appImage = (bundleType == BundleType.AppImage);
|
||||
this.extraJPackageArgs = new String[0];
|
||||
config = Map.of(
|
||||
Launcher.Main, mainLauncherIconType,
|
||||
Launcher.Additional, additionalLauncherIconType);
|
||||
}
|
||||
|
||||
public IconTest(BundleType bundleType, IconType mainLauncherIconType) {
|
||||
this.appImage = (bundleType == BundleType.AppImage);
|
||||
this.extraJPackageArgs = new String[0];
|
||||
config = Map.of(Launcher.Main, mainLauncherIconType);
|
||||
}
|
||||
|
||||
@Parameters
|
||||
public static Collection data() {
|
||||
List<Object[]> data = new ArrayList<>();
|
||||
|
||||
var withLinuxShortcut = Set.of(IconType.DefaultIcon, IconType.NoIcon);
|
||||
|
||||
for (var bundleType : BundleType.values()) {
|
||||
if (TKit.isWindows() && bundleType == BundleType.Package) {
|
||||
// On Windows icons are embedded in launcher executables in
|
||||
// application image. Nothing is changed when app image is
|
||||
// packed in msi/exe package bundle, so skip testing of package
|
||||
// bundle.
|
||||
continue;
|
||||
}
|
||||
for (var mainLauncherIconType : IconType.values()) {
|
||||
if (mainLauncherIconType == IconType.NoIcon) {
|
||||
// `No icon` setting is not applicable for the main launcher.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (TKit.isOSX()) {
|
||||
// Custom icons not supported for additional launchers on Mac.
|
||||
data.add(new Object[]{bundleType, mainLauncherIconType});
|
||||
continue;
|
||||
}
|
||||
|
||||
for (var additionalLauncherIconType : IconType.values()) {
|
||||
data.add(new Object[]{bundleType, mainLauncherIconType,
|
||||
additionalLauncherIconType});
|
||||
|
||||
if (TKit.isLinux() && bundleType == BundleType.Package
|
||||
&& withLinuxShortcut.contains(mainLauncherIconType)
|
||||
&& withLinuxShortcut.contains(
|
||||
additionalLauncherIconType)) {
|
||||
data.add(new Object[]{bundleType, mainLauncherIconType,
|
||||
additionalLauncherIconType, new String[]{
|
||||
"--linux-shortcut"}});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameter("true")
|
||||
@Parameter("false")
|
||||
public static void testParameter(boolean relativePath) throws IOException {
|
||||
final Path iconPath;
|
||||
if (relativePath) {
|
||||
iconPath = TKit.createRelativePathCopy(GOLDEN_ICON);
|
||||
public void test() throws IOException {
|
||||
if (appImage) {
|
||||
JPackageCommand cmd = initAppImageTest();
|
||||
var result = cmd.executeAndAssertImageCreated();
|
||||
ThrowingConsumer.toConsumer(createInstallVerifier()).accept(cmd);
|
||||
ThrowingBiConsumer.toBiConsumer(createBundleVerifier()).accept(cmd, result);
|
||||
} else {
|
||||
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) {
|
||||
return IOUtils.replaceSuffix(cmd.appLauncherPath().getFileName(),
|
||||
TKit.ICON_SUFFIX).toString();
|
||||
private ThrowingConsumer<JPackageCommand> createInstallVerifier() {
|
||||
LauncherIconVerifier verifier = new LauncherIconVerifier();
|
||||
switch (config.get(Launcher.Main)) {
|
||||
case NoIcon:
|
||||
verifier.setExpectedIcon(null);
|
||||
break;
|
||||
|
||||
case DefaultIcon:
|
||||
verifier.setExpectedDefaultIcon();
|
||||
break;
|
||||
|
||||
case CustomIcon:
|
||||
verifier.setExpectedIcon(Launcher.Main.cmdlineIcon);
|
||||
break;
|
||||
|
||||
case ResourceDirIcon:
|
||||
verifier.setExpectedIcon(Launcher.Main.resourceDirIcon);
|
||||
break;
|
||||
|
||||
case CustomWithResourceDirIcon:
|
||||
verifier.setExpectedIcon(Launcher.Main2.cmdlineIcon);
|
||||
break;
|
||||
}
|
||||
|
||||
return cmd -> {
|
||||
verifier.applyTo(cmd);
|
||||
if (TKit.isLinux() && !cmd.isImagePackageType()) {
|
||||
Path desktopFile = LinuxHelper.getDesktopFile(cmd);
|
||||
if (isWithDesktopIntegration(config.get(Launcher.Main))) {
|
||||
TKit.assertFileExists(desktopFile);
|
||||
} else {
|
||||
TKit.assertPathExists(desktopFile, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static void testIt(JPackageCommand cmd) throws IOException {
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
private void initTest(JPackageCommand cmd, PackageTest test) {
|
||||
config.entrySet().forEach(ThrowingConsumer.toConsumer(entry -> {
|
||||
initTest(entry.getKey(), entry.getValue(), cmd, test);
|
||||
}));
|
||||
|
||||
Path iconPath = cmd.appLayout().destktopIntegrationDirectory().resolve(
|
||||
appIconFileName(cmd));
|
||||
ThrowingConsumer<JPackageCommand> initializer = testCmd -> {
|
||||
testCmd.saveConsoleOutput(true);
|
||||
testCmd.setFakeRuntime();
|
||||
testCmd.addArguments(extraJPackageArgs);
|
||||
};
|
||||
|
||||
TKit.assertFileExists(iconPath);
|
||||
TKit.assertTrue(-1 == Files.mismatch(GOLDEN_ICON, iconPath),
|
||||
String.format(
|
||||
"Check application icon file [%s] is a copy of source icon file [%s]",
|
||||
iconPath, GOLDEN_ICON));
|
||||
if (test != null) {
|
||||
test.addInitializer(initializer);
|
||||
} else {
|
||||
ThrowingConsumer.toConsumer(initializer).accept(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
private final static Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of(
|
||||
"resources", "icon" + TKit.ICON_SUFFIX));
|
||||
private static void initTest(Launcher cfg, IconType iconType,
|
||||
JPackageCommand cmd, PackageTest test) throws IOException {
|
||||
Consumer<AdditionalLauncher> addLauncher = v -> {
|
||||
if (test != null) {
|
||||
v.applyTo(test);
|
||||
} else {
|
||||
v.applyTo(cmd);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
})
|
||||
.addBundleVerifier((cmd, result) -> {
|
||||
String errorMessage = JPackageCommand.filterOutput(
|
||||
result.getOutput().stream()).filter(line -> line.contains(
|
||||
errorMessageSubstring)).findFirst().orElse(null);
|
||||
TKit.assertNotNull(errorMessage, String.format(
|
||||
"Check output contains [%s] substring",
|
||||
errorMessageSubstring));
|
||||
TKit.assertTextStream(errorMessageSubstring).apply(
|
||||
result.getOutput().stream());
|
||||
})
|
||||
.run();
|
||||
}
|
||||
|
@ -99,7 +99,10 @@ public class LicenseTest {
|
||||
verifyLicenseFileInLinuxPackage(cmd, linuxLicenseFile(cmd));
|
||||
})
|
||||
.addInstallVerifier(cmd -> {
|
||||
TKit.assertReadableFileExists(linuxLicenseFile(cmd));
|
||||
Path path = linuxLicenseFile(cmd);
|
||||
if (path != null) {
|
||||
TKit.assertReadableFileExists(path);
|
||||
}
|
||||
})
|
||||
.addUninstallVerifier(cmd -> {
|
||||
verifyLicenseFileNotInstalledLinux(linuxLicenseFile(cmd));
|
||||
@ -110,7 +113,10 @@ public class LicenseTest {
|
||||
})
|
||||
.forTypes(PackageType.LINUX_RPM)
|
||||
.addInstallVerifier(cmd -> {
|
||||
verifyLicenseFileInstalledRpm(rpmLicenseFile(cmd));
|
||||
Path path = rpmLicenseFile(cmd);
|
||||
if (path != null) {
|
||||
verifyLicenseFileInstalledRpm(path);
|
||||
}
|
||||
})
|
||||
.run();
|
||||
}
|
||||
@ -124,6 +130,10 @@ public class LicenseTest {
|
||||
}
|
||||
|
||||
private static Path rpmLicenseFile(JPackageCommand cmd) {
|
||||
if (cmd.isPackageUnpacked("Not checking for rpm license file")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final Path licenseRoot = Path.of(
|
||||
new Executor()
|
||||
.setExecutable("rpm")
|
||||
@ -236,7 +246,7 @@ public class LicenseTest {
|
||||
|
||||
void run() {
|
||||
final Path srcLicenseFile = TKit.workDir().resolve("license");
|
||||
new PackageTest().configureHelloApp().forTypes(PackageType.LINUX_DEB)
|
||||
new PackageTest().forTypes(PackageType.LINUX_DEB).configureHelloApp()
|
||||
.addInitializer(cmd -> {
|
||||
// Create source license file.
|
||||
Files.write(srcLicenseFile, List.of(
|
||||
|
@ -30,6 +30,7 @@ import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -119,6 +120,10 @@ public final class BasicTest {
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testVerbose() {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage()
|
||||
// Disable default logic adding `--verbose` option
|
||||
// to jpackage command line.
|
||||
.ignoreDefaultVerbose(true)
|
||||
.saveConsoleOutput(true)
|
||||
.setFakeRuntime().executePrerequisiteActions();
|
||||
|
||||
List<String> expectedVerboseOutputStrings = new ArrayList<>();
|
||||
@ -139,17 +144,17 @@ public final class BasicTest {
|
||||
}
|
||||
|
||||
TKit.deleteDirectoryContentsRecursive(cmd.outputDir());
|
||||
List<String> nonVerboseOutput = cmd.createExecutor().executeAndGetOutput();
|
||||
List<String> nonVerboseOutput = cmd.execute().getOutput();
|
||||
List<String>[] verboseOutput = (List<String>[])new List<?>[1];
|
||||
|
||||
// Directory clean up is not 100% reliable on Windows because of
|
||||
// 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.
|
||||
TKit.withTempDirectory("verbose-output", tempDir -> {
|
||||
cmd.setArgumentValue("--dest", tempDir);
|
||||
verboseOutput[0] = cmd.createExecutor().addArgument(
|
||||
"--verbose").executeAndGetOutput();
|
||||
cmd.addArgument("--verbose");
|
||||
verboseOutput[0] = cmd.execute().getOutput();
|
||||
});
|
||||
|
||||
TKit.assertTrue(nonVerboseOutput.size() < verboseOutput[0].size(),
|
||||
@ -189,7 +194,7 @@ public final class BasicTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
// Regular app
|
||||
// Regular app
|
||||
@Parameter("Hello")
|
||||
// Modular app
|
||||
@Parameter("com.other/com.other.Hello")
|
||||
@ -227,62 +232,66 @@ public final class BasicTest {
|
||||
*/
|
||||
@Test
|
||||
public void testTemp() throws IOException {
|
||||
TKit.withTempDirectory("temp-root", tempRoot -> {
|
||||
Function<JPackageCommand, Path> getTempDir = cmd -> {
|
||||
return tempRoot.resolve(cmd.outputBundle().getFileName());
|
||||
};
|
||||
final Path tempRoot = TKit.createTempDirectory("temp-root");
|
||||
|
||||
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);
|
||||
Files.createDirectories(tempDir);
|
||||
cmd.addArguments("--temp", tempDir);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
new PackageTest().configureHelloApp().addInitializer(addTempDir)
|
||||
.addBundleVerifier(cmd -> {
|
||||
// Check jpackage actually used the supplied directory.
|
||||
Path tempDir = getTempDir.apply(cmd);
|
||||
TKit.assertNotEquals(0, tempDir.toFile().list().length,
|
||||
String.format(
|
||||
"Check jpackage wrote some data in the supplied temporary directory [%s]",
|
||||
tempDir));
|
||||
})
|
||||
.run();
|
||||
createTest.get()
|
||||
.addBundleVerifier(cmd -> {
|
||||
// Check jpackage actually used the supplied directory.
|
||||
Path tempDir = getTempDir.apply(cmd);
|
||||
TKit.assertNotEquals(0, tempDir.toFile().list().length,
|
||||
String.format(
|
||||
"Check jpackage wrote some data in the supplied temporary directory [%s]",
|
||||
tempDir));
|
||||
})
|
||||
.run(PackageTest.Action.CREATE);
|
||||
|
||||
new PackageTest().configureHelloApp().addInitializer(addTempDir)
|
||||
.addInitializer(cmd -> {
|
||||
// Clean output from the previus jpackage run.
|
||||
Files.delete(cmd.outputBundle());
|
||||
})
|
||||
// Temporary directory should not be empty,
|
||||
// jpackage should exit with error.
|
||||
.setExpectedExitCode(1)
|
||||
.run();
|
||||
});
|
||||
createTest.get()
|
||||
.addInitializer(cmd -> {
|
||||
// Clean output from the previus jpackage run.
|
||||
Files.delete(cmd.outputBundle());
|
||||
})
|
||||
// Temporary directory should not be empty,
|
||||
// jpackage should exit with error.
|
||||
.setExpectedExitCode(1)
|
||||
.run(PackageTest.Action.CREATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAtFile() throws IOException {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage();
|
||||
JPackageCommand cmd = JPackageCommand
|
||||
.helloAppImage()
|
||||
.setArgumentValue("--dest", TKit.createTempDirectory("output"));
|
||||
|
||||
// Init options file with the list of options configured
|
||||
// for JPackageCommand instance.
|
||||
final Path optionsFile = TKit.workDir().resolve("options");
|
||||
final Path optionsFile = TKit.createTempFile(Path.of("options"));
|
||||
Files.write(optionsFile,
|
||||
List.of(String.join(" ", cmd.getAllArguments())));
|
||||
|
||||
// Build app jar file.
|
||||
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
|
||||
// JPackageCommand instance, run vanilla jpackage command with @ file.
|
||||
getJPackageToolProvider()
|
||||
.addArgument(String.format("@%s", optionsFile))
|
||||
.execute().assertExitCodeIsZero();
|
||||
.execute();
|
||||
|
||||
// Verify output of jpackage command.
|
||||
cmd.assertImageCreated();
|
||||
@ -292,50 +301,45 @@ public final class BasicTest {
|
||||
@Parameter("Hello")
|
||||
@Parameter("com.foo/com.foo.main.Aloha")
|
||||
@Test
|
||||
public void testJLinkRuntime(String javaAppDesc) {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
||||
public void testJLinkRuntime(String javaAppDesc) throws IOException {
|
||||
JavaAppDesc appDesc = JavaAppDesc.parse(javaAppDesc);
|
||||
|
||||
// If `--module` parameter was set on jpackage command line, get its
|
||||
// value and extract module name.
|
||||
// E.g.: foo.bar2/foo.bar.Buz -> foo.bar2
|
||||
// Note: HelloApp class manages `--module` parameter on jpackage command line
|
||||
final String moduleName = cmd.getArgumentValue("--module", () -> null,
|
||||
(v) -> v.split("/", 2)[0]);
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage(appDesc);
|
||||
|
||||
final String moduleName = appDesc.moduleName();
|
||||
|
||||
if (moduleName != null) {
|
||||
// Build module jar.
|
||||
cmd.executePrerequisiteActions();
|
||||
}
|
||||
|
||||
TKit.withTempDirectory("runtime", tempDir -> {
|
||||
final Path runtimeDir = tempDir.resolve("data");
|
||||
final Path runtimeDir = TKit.createTempDirectory("runtime").resolve("data");
|
||||
|
||||
// List of modules required for test app.
|
||||
final var modules = new String[] {
|
||||
"java.base",
|
||||
"java.desktop"
|
||||
};
|
||||
// List of modules required for test app.
|
||||
final var modules = new String[] {
|
||||
"java.base",
|
||||
"java.desktop"
|
||||
};
|
||||
|
||||
Executor jlink = getToolProvider(JavaTool.JLINK)
|
||||
.saveOutput(false)
|
||||
.addArguments(
|
||||
"--add-modules", String.join(",", modules),
|
||||
"--output", runtimeDir.toString(),
|
||||
"--strip-debug",
|
||||
"--no-header-files",
|
||||
"--no-man-pages");
|
||||
Executor jlink = getToolProvider(JavaTool.JLINK)
|
||||
.saveOutput(false)
|
||||
.addArguments(
|
||||
"--add-modules", String.join(",", modules),
|
||||
"--output", runtimeDir.toString(),
|
||||
"--strip-debug",
|
||||
"--no-header-files",
|
||||
"--no-man-pages");
|
||||
|
||||
if (moduleName != null) {
|
||||
jlink.addArguments("--add-modules", moduleName, "--module-path",
|
||||
Path.of(cmd.getArgumentValue("--module-path")).resolve(
|
||||
"hello.jar").toString());
|
||||
}
|
||||
if (moduleName != null) {
|
||||
jlink.addArguments("--add-modules", moduleName, "--module-path",
|
||||
Path.of(cmd.getArgumentValue("--module-path")).resolve(
|
||||
"hello.jar").toString());
|
||||
}
|
||||
|
||||
jlink.execute().assertExitCodeIsZero();
|
||||
jlink.execute();
|
||||
|
||||
cmd.addArguments("--runtime-image", runtimeDir);
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
});
|
||||
cmd.addArguments("--runtime-image", runtimeDir);
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
}
|
||||
|
||||
private static Executor getJPackageToolProvider() {
|
||||
|
@ -209,8 +209,7 @@ public final class MainClassTest {
|
||||
// file nor on command line.
|
||||
List<String> output = cmd
|
||||
.saveConsoleOutput(true)
|
||||
.execute()
|
||||
.assertExitCodeIs(1)
|
||||
.execute(1)
|
||||
.getOutput();
|
||||
TKit.assertTextStream(script.expectedErrorMessage).apply(output.stream());
|
||||
return;
|
||||
@ -236,7 +235,7 @@ public final class MainClassTest {
|
||||
.setDirectory(cmd.outputDir())
|
||||
.setExecutable(cmd.appLauncherPath())
|
||||
.dumpOutput().saveOutput()
|
||||
.execute().assertExitCodeIs(1).getOutput();
|
||||
.execute(1).getOutput();
|
||||
TKit.assertTextStream(String.format(
|
||||
"Error: Could not find or load main class %s",
|
||||
nonExistingMainClass)).apply(output.stream());
|
||||
@ -289,7 +288,7 @@ public final class MainClassTest {
|
||||
.addArguments("-v", "-c", "-M", "-f", jarFile.toString())
|
||||
.addArguments("-C", workDir.toString(), ".")
|
||||
.dumpOutput()
|
||||
.execute().assertExitCodeIsZero();
|
||||
.execute();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -24,6 +24,7 @@
|
||||
package jdk.jpackage.tests;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@ -71,7 +72,7 @@ public final class ModulePathTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void test() throws IOException {
|
||||
final String moduleName = "com.foo";
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage(
|
||||
"benvenuto.jar:" + moduleName + "/com.foo.Hello");
|
||||
@ -88,45 +89,42 @@ public final class ModulePathTest {
|
||||
String goodModulePath = Objects.requireNonNull(cmd.getArgumentValue(
|
||||
"--module-path"));
|
||||
cmd.removeArgumentWithValue("--module-path");
|
||||
TKit.withTempDirectory("empty-dir", emptyDir -> {
|
||||
Path nonExistingDir = TKit.withTempDirectory("non-existing-dir",
|
||||
unused -> {
|
||||
});
|
||||
|
||||
Function<String, String> substitute = str -> {
|
||||
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;
|
||||
};
|
||||
Path emptyDir = TKit.createTempDirectory("empty-dir");
|
||||
Path nonExistingDir = TKit.withTempDirectory("non-existing-dir", x -> {});
|
||||
|
||||
boolean withGoodPath = modulePathArgs.stream().anyMatch(
|
||||
s -> s.contains(GOOD_PATH));
|
||||
Function<String, String> substitute = str -> {
|
||||
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(
|
||||
"--module-path", substitute.apply(arg))).flatMap(s -> s).collect(
|
||||
Collectors.toList()));
|
||||
boolean withGoodPath = modulePathArgs.stream().anyMatch(
|
||||
s -> s.contains(GOOD_PATH));
|
||||
|
||||
if (withGoodPath) {
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
cmd.addArguments(modulePathArgs.stream().map(arg -> Stream.of(
|
||||
"--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 {
|
||||
final String expectedErrorMessage;
|
||||
if (modulePathArgs.isEmpty()) {
|
||||
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());
|
||||
expectedErrorMessage = String.format(
|
||||
"Error: Module %s not found", moduleName);
|
||||
}
|
||||
});
|
||||
|
||||
List<String> output = cmd
|
||||
.saveConsoleOutput(true)
|
||||
.execute(1)
|
||||
.getOutput();
|
||||
TKit.assertTextStream(expectedErrorMessage).apply(output.stream());
|
||||
}
|
||||
}
|
||||
|
||||
private final List<String> modulePathArgs;
|
||||
|
@ -29,13 +29,20 @@ set_args ()
|
||||
local arg_is_output_dir=
|
||||
local arg_is_mode=
|
||||
local output_dir_set=
|
||||
local with_append_actions=yes
|
||||
for arg in "$@"; do
|
||||
if [ "$arg" == "-o" ]; then
|
||||
arg_is_output_dir=yes
|
||||
output_dir_set=yes
|
||||
elif [ "$arg" == "-m" ]; then
|
||||
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
|
||||
arg_is_output_dir=
|
||||
output_dir="$arg"
|
||||
@ -47,6 +54,13 @@ set_args ()
|
||||
args+=( "$arg" )
|
||||
done
|
||||
[ -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 "$@"
|
||||
basedir="$(dirname $0)"
|
||||
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.IOException;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.HelloApp;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
@ -58,6 +59,10 @@ public class WinConsoleTest {
|
||||
}
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
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
|
||||
|
@ -70,7 +70,7 @@ public class WinScriptTest {
|
||||
@Test
|
||||
@Parameter("0")
|
||||
@Parameter("10")
|
||||
public void test(int wsfExitCode) {
|
||||
public void test(int wsfExitCode) throws IOException {
|
||||
final ScriptData appImageScriptData;
|
||||
if (wsfExitCode != 0 && packageType == PackageType.WIN_EXE) {
|
||||
appImageScriptData = new ScriptData(PackageType.WIN_MSI, 0);
|
||||
@ -81,29 +81,32 @@ public class WinScriptTest {
|
||||
final ScriptData msiScriptData = new ScriptData(PackageType.WIN_EXE, wsfExitCode);
|
||||
|
||||
test.setExpectedExitCode(wsfExitCode == 0 ? 0 : 1);
|
||||
TKit.withTempDirectory("resources", tempDir -> {
|
||||
test.addInitializer(cmd -> {
|
||||
cmd.addArguments("--resource-dir", tempDir);
|
||||
|
||||
appImageScriptData.createScript(cmd);
|
||||
msiScriptData.createScript(cmd);
|
||||
});
|
||||
final Path tempDir = TKit.createTempDirectory("resources");
|
||||
|
||||
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) -> {
|
||||
appImageScriptData.assertJPackageOutput(result.getOutput());
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
if (packageType == PackageType.WIN_EXE) {
|
||||
case WIN_EXE:
|
||||
test.addBundleVerifier((cmd, result) -> {
|
||||
appImageScriptData.assertJPackageOutput(result.getOutput());
|
||||
msiScriptData.assertJPackageOutput(result.getOutput());
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
test.run();
|
||||
});
|
||||
test.run();
|
||||
}
|
||||
|
||||
private static class ScriptData {
|
||||
|
@ -21,9 +21,16 @@
|
||||
* 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.PackageType;
|
||||
import jdk.jpackage.test.WindowsHelper;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @library ../helpers
|
||||
* @key jpackagePlatformPackage
|
||||
* @requires (jpackage.test.SQETest != null)
|
||||
* @build jdk.jpackage.test.*
|
||||
* @requires (os.family == "windows")
|
||||
* @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 static void main(String[] args) {
|
||||
TKit.run(args, () -> {
|
||||
PackageTest test = init();
|
||||
if (test.getAction() != PackageTest.Action.VERIFY_INSTALL) {
|
||||
test.run();
|
||||
|
||||
@Test
|
||||
public static void test() {
|
||||
Supplier<PackageTest> init = () -> {
|
||||
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();
|
||||
test.addInitializer(cmd -> {
|
||||
cmd.setArgumentValue("--app-version", "2.0");
|
||||
cmd.setArgumentValue("--arguments", "bar");
|
||||
});
|
||||
test.run();
|
||||
});
|
||||
@Override
|
||||
protected Map<PackageTest, Map.Entry<String, String>> propertyValues() {
|
||||
return properties;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static PackageTest init() {
|
||||
return new PackageTest()
|
||||
.forTypes(PackageType.WINDOWS)
|
||||
.configureHelloApp()
|
||||
.addInitializer(cmd -> cmd.addArguments("--win-upgrade-uuid",
|
||||
"F0B18E75-52AD-41A2-BC86-6BE4FCD50BEB"));
|
||||
static abstract class PropertyVerifier {
|
||||
void assertEquals(PackageTest x, PackageTest y) {
|
||||
var entryX = propertyValues().get(x);
|
||||
var entryY = propertyValues().get(y);
|
||||
TKit.assertEquals(entryX.getValue(), entryY.getValue(),
|
||||
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