8356309: Fix issues uncovered after running jpackage tests locally with installing test packages

Reviewed-by: almatvee
This commit is contained in:
Alexey Semenyuk 2025-05-06 23:40:48 +00:00
parent 9a23f721c7
commit cbbab07d23
7 changed files with 101 additions and 58 deletions

View File

@ -533,7 +533,7 @@ public final class LinuxHelper {
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 @@ public final class LinuxHelper {
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 @@ public final class LinuxHelper {
.executeAndGetFirstLineOfOutput();
}
private static String queryMimeTypeDefaultHandler(String mimeType) {
private static Optional<String> 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 @@ public final class LinuxHelper {
static final Map<String, Scriptlet> RPM_MAP = Stream.of(values()).collect(
Collectors.toMap(v -> v.rpm, v -> v));
};
}
public static String getDefaultPackageArch(PackageType type) {
if (archs == null) {

View File

@ -42,7 +42,6 @@ import java.util.Comparator;
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 final class PackageTest extends RunnablePackageTest {
public static class Group extends RunnablePackageTest {
public Group(PackageTest... tests) {
handlers = Stream.of(tests)
.map(PackageTest::createPackageTypeHandlers)
.flatMap(List<Consumer<Action>>::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<Consumer<Action>> 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<Consumer<Action>> handlers, List<Action> 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<Consumer<Action>> handlers;
private final Map<PackageType, List<Consumer<Action>>> typeHandlers;
}
PackageTest packageHandlers(PackageHandlers v) {
@ -455,16 +464,22 @@ public final class PackageTest extends RunnablePackageTest {
throw new UnsupportedOperationException();
}
private Optional<Consumer<Action>> 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<Consumer<Action>> 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,

View File

@ -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<PListReader, String, ?> queryMethod) {
this.queryMethod = Objects.requireNonNull(queryMethod);
@ -98,7 +98,7 @@ public class PListReaderTest {
} 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 class PListReaderTest {
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 @@ public class PListReaderTest {
testSpec(QueryType.BOOLEAN).xml("<key>foo</key><False/>").create(),
testSpec().expectedValue(List.of("foo", "bar")).xml("<key>foo</key><array><string>foo</string><string>bar</string></array>").create(),
testSpec().expectedValue(List.of()).xml("<key>foo</key><array/>").create(),
testSpec(QueryType.STRING_ARRY).xml("<key>foo</key><Array/>").create(),
testSpec(QueryType.STRING_ARRAY).xml("<key>foo</key><Array/>").create(),
testSpec().expectedValue("A").xml("<key>foo</key><string>A</string><string>B</string>").create(),
testSpec().expectedValue("A").xml("<key>foo</key><string>A</string><key>foo</key><string>B</string>").create()
);

View File

@ -60,6 +60,7 @@ import org.junit.jupiter.params.provider.MethodSource;
public class PathGroupTest {
@Test
public void testNullId() {
assertThrowsExactly(NullPointerException.class, () -> new PathGroup(Map.of()).getPath(null));
}

View File

@ -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 @@ public class EmptyFolderTest {
}
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);

View File

@ -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,27 +44,49 @@ import jdk.jpackage.test.Executor;
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());
public static void test() throws IOException {
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();
}
@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"));
(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);
}
}

View File

@ -40,6 +40,7 @@ import jdk.jpackage.test.JavaTool;
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 class RuntimePackageTest {
.run(Action.CREATE_AND_UNPACK);
}
private static PackageTest init(Set<PackageType> types) {
private static PackageTest init() {
return new PackageTest()
.forTypes(types)
.addInitializer(cmd -> {
final Path runtimeImageDir;
@ -166,8 +166,7 @@ public class RuntimePackageTest {
"Check the package doesn't deliver [%s] copyright file",
copyright));
}
})
.forTypes(types);
});
}
private static Set<Path> listFiles(Path root) throws IOException {