--- old/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java 2019-12-13 13:35:36.289184500 -0500
+++ new/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java 2019-12-13 13:35:35.293820300 -0500
@@ -28,14 +28,13 @@
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 @@
* 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:
- *
Set --input and --dest parameters.
- * 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 @@
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() {
+ @Override
+ public void accept(JPackageCommand unused) throws Throwable {
+ if (!executed) {
+ executed = true;
+ v.run();
+ }
+ }
+
+ private boolean executed;
+ }, id);
+ }
+
public PackageTest addInitializer(ThrowingConsumer v) {
return addInitializer(v, null);
}
+ public PackageTest addRunOnceInitializer(ThrowingRunnable v) {
+ return addRunOnceInitializer(v, null);
+ }
+
public PackageTest addBundleVerifier(
- BiConsumer v) {
- currentTypes.stream().forEach(
- type -> handlers.get(type).addBundleVerifier(v));
+ ThrowingBiConsumer v) {
+ currentTypes.forEach(type -> handlers.get(type).addBundleVerifier(
+ ThrowingBiConsumer.toBiConsumer(v)));
return this;
}
@@ -139,19 +147,26 @@
}
public PackageTest addBundlePropertyVerifier(String propertyName,
- BiConsumer pred) {
+ Predicate 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 PackageTest addInstallVerifier(ThrowingConsumer 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 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 v) {
+ currentTypes.forEach(
+ type -> packageHandlers.get(type).installHandler = v);
+ return this;
+ }
+
+ public PackageTest setPackageUnpacker(
+ BiFunction v) {
+ currentTypes.forEach(type -> packageHandlers.get(type).unpackHandler = v);
+ return this;
+ }
+
+ public PackageTest setPackageUninstaller(Consumer v) {
+ currentTypes.forEach(
+ type -> packageHandlers.get(type).uninstallHandler = v);
return this;
}
static void withTestFileAssociationsFile(FileAssociations fa,
ThrowingConsumer 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 @@
// 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 @@
}
addInstallVerifier(cmd -> {
- if (cmd.isFakeRuntime(noActionMsg)) {
+ if (cmd.isFakeRuntime(noActionMsg) || cmd.isPackageUnpacked(noActionMsg)) {
return;
}
@@ -225,7 +255,8 @@
// 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 @@
return this;
}
- PackageTest forTypes(Collection types, Runnable action) {
+ public PackageTest forTypes(Collection types, Runnable action) {
Set oldTypes = Set.of(currentTypes.toArray(
PackageType[]::new));
try {
@@ -248,17 +279,17 @@
return this;
}
- PackageTest forTypes(PackageType type, Runnable action) {
+ public PackageTest forTypes(PackageType type, Runnable action) {
return forTypes(List.of(type), action);
}
- PackageTest notForTypes(Collection types, Runnable action) {
+ public PackageTest notForTypes(Collection types, Runnable action) {
Set 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 @@
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 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>::stream)
+ .collect(Collectors.toUnmodifiableList());
}
- Supplier 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> 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> handlers;
}
- public PackageTest setAction(Action value) {
- action = value;
- return this;
+ final static class PackageHandlers {
+ Consumer installHandler;
+ Consumer uninstallHandler;
+ BiFunction unpackHandler;
}
- public Action getAction() {
- return action;
+ @Override
+ protected void runActions(List actions) {
+ createPackageTypeHandlers().forEach(
+ handler -> actions.forEach(
+ action -> List.of(action).forEach(handler::accept)));
}
- private class Handler implements Consumer {
+ @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> 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 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 createPackageTypeHandler(
+ PackageType type, Handler handler) {
+ return ThrowingConsumer.toConsumer(new ThrowingConsumer() {
+ @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 {
+
+ Handler() {
initializers = new ArrayList<>();
bundleVerifiers = new ArrayList<>();
installVerifiers = new ArrayList<>();
@@ -342,33 +485,35 @@
}
@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 @@
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 @@
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> initializers;
private final List> bundleVerifiers;
private final List> installVerifiers;
private final List> uninstallVerifiers;
}
+ private static Map createDefaultPackageHandlers() {
+ HashMap 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 currentTypes;
private Set excludeTypes;
private int expectedJPackageExitCode;
private Map handlers;
private Set namedInitializers;
- private Action action;
-
- /**
- * Test action.
- */
- static public enum Action {
- /**
- * Create bundle.
- */
- CREATE,
- /**
- * Verify bundle installed.
- */
- VERIFY_INSTALL,
- /**
- * Verify bundle uninstalled.
- */
- VERIFY_UNINSTALL;
+ private Map packageHandlers;
- @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)));
- }
}