From 2f05210f5d602c77e69f1bc21cd8a64216852a9c Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 24 Apr 2025 15:17:10 -0400 Subject: [PATCH 01/10] Bugfix a regression from JDK-8354988 --- .../helpers/jdk/jpackage/test/LinuxHelper.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 8eaec2f0e72b0..0f2951bd062df 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -533,7 +533,7 @@ static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) { TKit.assertEquals(fa.getMime(), mimeType, String.format( "Check mime type of [%s] file", testFile)); - String desktopFileName = queryMimeTypeDefaultHandler(mimeType); + String desktopFileName = queryMimeTypeDefaultHandler(mimeType).orElse(null); Path systemDesktopFile = getSystemDesktopFilesFolder().resolve( desktopFileName); @@ -557,7 +557,7 @@ static void addFileAssociationsVerifier(PackageTest test, FileAssociations fa) { TKit.assertNotEquals(fa.getMime(), mimeType, String.format( "Check mime type of [%s] file", testFile)); - String desktopFileName = queryMimeTypeDefaultHandler(fa.getMime()); + String desktopFileName = queryMimeTypeDefaultHandler(fa.getMime()).orElse(null); TKit.assertNull(desktopFileName, String.format( "Check there is no default handler for [%s] mime type", @@ -584,9 +584,9 @@ private static String queryFileMimeType(Path file) { .executeAndGetFirstLineOfOutput(); } - private static String queryMimeTypeDefaultHandler(String mimeType) { + private static Optional queryMimeTypeDefaultHandler(String mimeType) { return Executor.of("xdg-mime", "query", "default", mimeType) - .executeAndGetFirstLineOfOutput(); + .discardStderr().saveFirstLineOfOutput().execute().findFirstLineOfOutput(); } private static void verifyIconInScriptlet(Scriptlet scriptletType, @@ -708,7 +708,7 @@ private static enum Scriptlet { static final Map RPM_MAP = Stream.of(values()).collect( Collectors.toMap(v -> v.rpm, v -> v)); - }; + } public static String getDefaultPackageArch(PackageType type) { if (archs == null) { From 5ab8c68e8462ff2c724bd610a625e91cae991659 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 23 Apr 2025 18:35:32 -0400 Subject: [PATCH 02/10] PackageTest: fix to make it work when exe and msi packagings are both enabled and when PackageTest.Group is used --- .../jdk/jpackage/test/PackageTest.java | 51 ++++++++++++------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index fd26b4a536833..c1739b9095ab5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -42,7 +42,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.ListIterator; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -365,27 +364,37 @@ public PackageTest addHelloAppInitializer(String javaAppDesc) { public static class Group extends RunnablePackageTest { public Group(PackageTest... tests) { - handlers = Stream.of(tests) - .map(PackageTest::createPackageTypeHandlers) - .flatMap(List>::stream) - .collect(Collectors.toUnmodifiableList()); + typeHandlers = Stream.of(PackageType.values()).map(type -> { + return Map.entry(type, Stream.of(tests).map(test -> { + return test.createPackageTypeHandler(type); + }).filter(Optional::isPresent).map(Optional::orElseThrow).toList()); + }).filter(e -> { + return !e.getValue().isEmpty(); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } @Override protected void runAction(Action... action) { - if (Set.of(action).contains(Action.UNINSTALL)) { - ListIterator> listIterator = handlers.listIterator( - handlers.size()); + typeHandlers.entrySet().stream() + .sorted(Comparator.comparing(Map.Entry::getKey)) + .map(Map.Entry::getValue).forEachOrdered(handlers -> { + runAction(handlers, List.of(action)); + }); + } + + private static void runAction(List> handlers, List actions) { + if (actions.contains(Action.UNINSTALL)) { + final var listIterator = handlers.listIterator(handlers.size()); while (listIterator.hasPrevious()) { - var handler = listIterator.previous(); - List.of(action).forEach(handler::accept); + final var handler = listIterator.previous(); + actions.forEach(handler::accept); } } else { - handlers.forEach(handler -> List.of(action).forEach(handler::accept)); + handlers.forEach(handler -> actions.forEach(handler::accept)); } } - private final List> handlers; + private final Map>> typeHandlers; } PackageTest packageHandlers(PackageHandlers v) { @@ -455,16 +464,22 @@ protected void runAction(Action... action) { throw new UnsupportedOperationException(); } + private Optional> createPackageTypeHandler(PackageType type) { + Objects.requireNonNull(type); + return Optional.ofNullable(handlers.get(type)).filter(Predicate.not(Handler::isVoid)).map(h -> { + return createPackageTypeHandler(type, h); + }); + } + private List> createPackageTypeHandlers() { if (handlers.keySet().stream().noneMatch(isPackageTypeEnabled)) { PackageType.throwSkippedExceptionIfNativePackagingUnavailable(); } - return handlers.entrySet().stream() - .filter(entry -> !entry.getValue().isVoid()) - .sorted(Comparator.comparing(Map.Entry::getKey)) - .map(entry -> { - return createPackageTypeHandler(entry.getKey(), entry.getValue()); - }).toList(); + return Stream.of(PackageType.values()).sorted() + .map(this::createPackageTypeHandler) + .filter(Optional::isPresent) + .map(Optional::orElseThrow) + .toList(); } private record PackageTypePipeline(PackageType type, int expectedJPackageExitCode, From d551aae96d06436ab57c12f9de631c29572fbaeb Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Wed, 23 Apr 2025 17:33:42 -0400 Subject: [PATCH 03/10] EmptyFolderTest: bugfix --- test/jdk/tools/jpackage/share/EmptyFolderTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/jdk/tools/jpackage/share/EmptyFolderTest.java b/test/jdk/tools/jpackage/share/EmptyFolderTest.java index 40a4db03d6f69..f2cb72e097d64 100644 --- a/test/jdk/tools/jpackage/share/EmptyFolderTest.java +++ b/test/jdk/tools/jpackage/share/EmptyFolderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -97,16 +97,21 @@ private static void createDirTree(JPackageCommand cmd) throws IOException { } private static void validateDirTree(JPackageCommand cmd) { + // When MSI package is unpacked and not installed, empty directories are not created. + final boolean emptyDirSupported = !(PackageType.WINDOWS.contains(cmd.packageType()) && cmd.isPackageUnpacked()); + validateDirTree(cmd, emptyDirSupported); + } + + private static void validateDirTree(JPackageCommand cmd, boolean emptyDirSupported) { var outputBaseDir = cmd.appLayout().appDirectory(); var inputBaseDir = cmd.inputDir(); for (var path : DIR_STRUCT) { Path outputPath = outputBaseDir.resolve(path); if (isFile(outputPath)) { TKit.assertFileExists(outputPath); - } else if (!PackageType.WINDOWS.contains(cmd.packageType())) { + } else if (emptyDirSupported) { TKit.assertDirectoryExists(outputPath); } else if (inputBaseDir.resolve(path).toFile().list().length == 0) { - // MSI packages don't support empty folders TKit.assertPathExists(outputPath, false); } else { TKit.assertDirectoryNotEmpty(outputPath); From 8296be7835af41313ea02e182cdfc6e700fba862 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Mon, 31 Mar 2025 20:23:43 -0400 Subject: [PATCH 04/10] Fix typo --- .../jdk/jpackage/internal/util/PListReaderTest.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java index bae4921fda33c..d766505cf1430 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PListReaderTest.java @@ -51,7 +51,7 @@ public class PListReaderTest { enum QueryType { STRING(PListReader::queryValue), BOOLEAN(PListReader::queryBoolValue), - STRING_ARRY(PListReader::queryArrayValue); + STRING_ARRAY(PListReader::queryArrayValue); QueryType(BiFunction queryMethod) { this.queryMethod = Objects.requireNonNull(queryMethod); @@ -98,7 +98,7 @@ Builder expectedValue(Object v) { } else if (v instanceof Boolean) { queryType(QueryType.BOOLEAN); } else if (v instanceof List) { - queryType(QueryType.STRING_ARRY); + queryType(QueryType.STRING_ARRAY); } return this; } @@ -196,7 +196,7 @@ public void testWrongValueType(QueryType queryType) { testSpecs.add(builder.keyName("string-key").create()); testSpecs.add(builder.keyName("array-key").create()); } - case STRING_ARRY -> { + case STRING_ARRAY -> { testSpecs.add(builder.keyName("string-key").create()); testSpecs.add(builder.keyName("boolean-true-key").create()); testSpecs.add(builder.keyName("boolean-false-key").create()); @@ -230,7 +230,7 @@ private static List testQueryValue() { testSpec(QueryType.BOOLEAN).xml("foo").create(), testSpec().expectedValue(List.of("foo", "bar")).xml("foofoobar").create(), testSpec().expectedValue(List.of()).xml("foo").create(), - testSpec(QueryType.STRING_ARRY).xml("foo").create(), + testSpec(QueryType.STRING_ARRAY).xml("foo").create(), testSpec().expectedValue("A").xml("fooAB").create(), testSpec().expectedValue("A").xml("fooAfooB").create() ); From cb04b7eb3b1920a386566b7140444f98c5905757 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 25 Apr 2025 13:26:05 -0400 Subject: [PATCH 05/10] Add missing @Test annotation --- .../jdk.jpackage/jdk/jpackage/internal/util/PathGroupTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathGroupTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathGroupTest.java index 42578227cf555..06627c3578762 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathGroupTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/PathGroupTest.java @@ -48,6 +48,7 @@ public class PathGroupTest { + @Test public void testNullId() { assertThrowsExactly(NullPointerException.class, () -> new PathGroup(Map.of()).getPath(null)); } From c0722abf8a39e8455318abc646737027b26ca8ab Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 25 Apr 2025 13:26:54 -0400 Subject: [PATCH 06/10] Improve RuntimeImageTest --- .../jpackage/share/RuntimeImageTest.java | 36 ++++++++++--------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index 0e30d7ee179c4..a9bc11db333b9 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -44,24 +44,28 @@ public class RuntimeImageTest { @Test public static void test() throws Exception { - final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); - final Path jlinkOutputDir = workDir.resolve("temp.runtime"); - Files.createDirectories(jlinkOutputDir.getParent()); - new Executor() - .setToolProvider(JavaTool.JLINK) - .dumpOutput() - .addArguments( - "--output", jlinkOutputDir.toString(), - "--add-modules", "java.desktop", - "--strip-debug", - "--no-header-files", - "--no-man-pages", - "--strip-native-commands") - .execute(); + JPackageCommand cmd = JPackageCommand.helloAppImage(); - JPackageCommand cmd = JPackageCommand.helloAppImage() - .setArgumentValue("--runtime-image", jlinkOutputDir.toString()); + if (JPackageCommand.DEFAULT_RUNTIME_IMAGE == null) { + final Path workDir = TKit.createTempDirectory("runtime").resolve("data"); + final Path jlinkOutputDir = workDir.resolve("temp.runtime"); + Files.createDirectories(jlinkOutputDir.getParent()); + + new Executor() + .setToolProvider(JavaTool.JLINK) + .dumpOutput() + .addArguments( + "--output", jlinkOutputDir.toString(), + "--add-modules", "java.desktop", + "--strip-debug", + "--no-header-files", + "--no-man-pages", + "--strip-native-commands") + .execute(); + + cmd.setArgumentValue("--runtime-image", jlinkOutputDir.toString()); + } cmd.executeAndAssertHelloAppImageCreated(); } From 68f45aff77f3fa5d8da5f771e44c62efd79bc134 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 20 Feb 2025 16:14:48 -0500 Subject: [PATCH 07/10] Add RuntimeImageTest.testStrippedFiles() test to verify jmods and src.zip files are stripped from copied runtime --- .../jpackage/share/RuntimeImageTest.java | 30 +++++++++++++++++-- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index a9bc11db333b9..0c795e7024813 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -21,13 +21,14 @@ * questions. */ +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; -import jdk.jpackage.test.TKit; import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Executor; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JavaTool; -import jdk.jpackage.test.Executor; +import jdk.jpackage.test.TKit; /* * @test @@ -43,7 +44,7 @@ public class RuntimeImageTest { @Test - public static void test() throws Exception { + public static void test() throws IOException { JPackageCommand cmd = JPackageCommand.helloAppImage(); @@ -70,4 +71,27 @@ public static void test() throws Exception { cmd.executeAndAssertHelloAppImageCreated(); } + @Test + public static void testStrippedFiles() throws IOException { + final var cmd = JPackageCommand.helloAppImage().setFakeRuntime(); + + final var runtimePath = Path.of(cmd.executePrerequisiteActions().getArgumentValue("--runtime-image")); + + Files.createDirectories(runtimePath.resolve("jmods")); + Files.createDirectories(runtimePath.resolve("lib")); + Files.createFile(runtimePath.resolve("lib/src.zip")); + Files.createFile(runtimePath.resolve("src.zip")); + + Files.createDirectories(runtimePath.resolve("foo/bar/src.zip")); + Files.createDirectories(runtimePath.resolve("custom/jmods")); + + (new JPackageCommand()).addArguments(cmd.getAllArguments()).executeAndAssertHelloAppImageCreated(); + + final var appRuntimeDir = cmd.appLayout().runtimeHomeDirectory(); + TKit.assertPathExists(appRuntimeDir.resolve("jmods"), false); + TKit.assertPathExists(appRuntimeDir.resolve("lib/src.zip"), false); + TKit.assertPathExists(appRuntimeDir.resolve("src.zip"), false); + TKit.assertDirectoryExists(appRuntimeDir.resolve("foo/bar/src.zip")); + TKit.assertDirectoryExists(appRuntimeDir.resolve("custom/jmods")); + } } From 4fbfe9ab07776707ef372229fc66efe110582597 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 25 Apr 2025 14:19:58 -0400 Subject: [PATCH 08/10] Better test coverage --- test/jdk/tools/jpackage/share/RuntimeImageTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index 0c795e7024813..1110a813cdee4 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -83,6 +83,8 @@ public static void testStrippedFiles() throws IOException { Files.createFile(runtimePath.resolve("src.zip")); Files.createDirectories(runtimePath.resolve("foo/bar/src.zip")); + Files.createFile(runtimePath.resolve("foo/jmods")); + Files.createFile(runtimePath.resolve("foo/src.zip")); Files.createDirectories(runtimePath.resolve("custom/jmods")); (new JPackageCommand()).addArguments(cmd.getAllArguments()).executeAndAssertHelloAppImageCreated(); @@ -93,5 +95,7 @@ public static void testStrippedFiles() throws IOException { TKit.assertPathExists(appRuntimeDir.resolve("src.zip"), false); TKit.assertDirectoryExists(appRuntimeDir.resolve("foo/bar/src.zip")); TKit.assertDirectoryExists(appRuntimeDir.resolve("custom/jmods")); + TKit.assertFileExists(appRuntimeDir.resolve("foo/jmods")); + TKit.assertFileExists(appRuntimeDir.resolve("foo/src.zip")); } } From a397e7a53043d94952a258676f0a90669ac2b212 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 25 Apr 2025 14:24:03 -0400 Subject: [PATCH 09/10] Bugfix --- test/jdk/tools/jpackage/share/RuntimeImageTest.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/test/jdk/tools/jpackage/share/RuntimeImageTest.java b/test/jdk/tools/jpackage/share/RuntimeImageTest.java index 1110a813cdee4..6ed38f2c5c1d7 100644 --- a/test/jdk/tools/jpackage/share/RuntimeImageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimeImageTest.java @@ -82,20 +82,11 @@ public static void testStrippedFiles() throws IOException { Files.createFile(runtimePath.resolve("lib/src.zip")); Files.createFile(runtimePath.resolve("src.zip")); - Files.createDirectories(runtimePath.resolve("foo/bar/src.zip")); - Files.createFile(runtimePath.resolve("foo/jmods")); - Files.createFile(runtimePath.resolve("foo/src.zip")); - Files.createDirectories(runtimePath.resolve("custom/jmods")); - (new JPackageCommand()).addArguments(cmd.getAllArguments()).executeAndAssertHelloAppImageCreated(); final var appRuntimeDir = cmd.appLayout().runtimeHomeDirectory(); TKit.assertPathExists(appRuntimeDir.resolve("jmods"), false); TKit.assertPathExists(appRuntimeDir.resolve("lib/src.zip"), false); TKit.assertPathExists(appRuntimeDir.resolve("src.zip"), false); - TKit.assertDirectoryExists(appRuntimeDir.resolve("foo/bar/src.zip")); - TKit.assertDirectoryExists(appRuntimeDir.resolve("custom/jmods")); - TKit.assertFileExists(appRuntimeDir.resolve("foo/jmods")); - TKit.assertFileExists(appRuntimeDir.resolve("foo/src.zip")); } } From 778130c5600475823f6cd05fd5aaec2728927af0 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Sun, 27 Apr 2025 22:44:35 -0400 Subject: [PATCH 10/10] Bugfix RuntimePackageTest --- .../jpackage/share/RuntimePackageTest.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java index 9eb4f8d231e55..2af6543c2db39 100644 --- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java @@ -40,6 +40,7 @@ import jdk.jpackage.test.LinuxHelper; import static jdk.jpackage.test.TKit.assertTrue; import static jdk.jpackage.test.TKit.assertFalse; +import static jdk.internal.util.OperatingSystem.LINUX; /** * Test --runtime-image parameter. @@ -81,22 +82,22 @@ public class RuntimePackageTest { @Test public static void test() { - init(PackageType.NATIVE).run(); + init().run(); } - @Test + @Test(ifOS = LINUX) @Parameter("/usr") @Parameter("/usr/lib/Java") public static void testUsrInstallDir(String installDir) { - init(PackageType.LINUX) - .addInitializer(cmd -> cmd.addArguments("--install-dir", "/usr")) + init() + .addInitializer(cmd -> cmd.addArguments("--install-dir", installDir)) .run(); } @Test public static void testName() { // Test that jpackage can derive package name from the path to runtime image. - init(PackageType.NATIVE) + init() .addInitializer(cmd -> cmd.removeArgumentWithValue("--name")) // Don't attempt to install this package as it may have an odd name derived from // the runtime image path. Say, on Linux for `--runtime-image foo/bar/sed` @@ -105,9 +106,8 @@ public static void testName() { .run(Action.CREATE_AND_UNPACK); } - private static PackageTest init(Set types) { + private static PackageTest init() { return new PackageTest() - .forTypes(types) .addInitializer(cmd -> { final Path runtimeImageDir; @@ -166,8 +166,7 @@ private static PackageTest init(Set types) { "Check the package doesn't deliver [%s] copyright file", copyright)); } - }) - .forTypes(types); + }); } private static Set listFiles(Path root) throws IOException {