From f9ce2ff0bfc993390309ac8b8bf1c9c69cb2ff81 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 28 Mar 2025 08:11:30 -0400 Subject: [PATCH 1/5] Get rid of dependency on "/test/lib" tets lib --- .../helpers/jdk/jpackage/test/TKit.java | 33 +++++++++++++++++-- .../jdk/tools/jpackage/share/ServiceTest.java | 2 -- .../jpackage/windows/WinLongPathTest.java | 2 -- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index c2c0397116daf..8954665f7c982 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -43,6 +43,7 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Base64; import java.util.Collection; import java.util.Collections; import java.util.Comparator; @@ -518,9 +519,9 @@ public static RuntimeException throwUnknownPlatformError() { } public static RuntimeException throwSkippedException(String reason) { - RuntimeException ex = ThrowingSupplier.toSupplier( - () -> (RuntimeException) Class.forName("jtreg.SkippedException").getConstructor( - String.class).newInstance(reason)).get(); + RuntimeException ex = ThrowingSupplier.toSupplier(() -> { + return JtregSkippedExceptionClass.INSTANCE.getConstructor(String.class).newInstance(reason); + }).get(); return throwSkippedException(ex); } @@ -1140,4 +1141,30 @@ static Set tokenizeConfigProperty(String propertyName) { VERBOSE_TEST_SETUP = isNonOf.test(Set.of("init", "i")); } } + + private final static class JtregSkippedExceptionClass extends ClassLoader { + @SuppressWarnings("unchecked") + JtregSkippedExceptionClass() { + super(TKit.class.getClassLoader()); + + final byte[] bytes = Base64.getDecoder().decode( + // Base64-encoded "jtreg/SkippedException.class" file + // emitted by jdk8's javac from "$OPEN_JDK/test/lib/jtreg/SkippedException.java" + "yv66vgAAADQAFQoABAARCgAEABIHABMHABQBABBzZXJpYWxWZXJzaW9uVUlEAQABSgEADUNvbnN0" + + "YW50VmFsdWUFErH6BHk+kr0BAAY8aW5pdD4BACooTGphdmEvbGFuZy9TdHJpbmc7TGphdmEvbGFu" + + "Zy9UaHJvd2FibGU7KVYBAARDb2RlAQAPTGluZU51bWJlclRhYmxlAQAVKExqYXZhL2xhbmcvU3Ry" + + "aW5nOylWAQAKU291cmNlRmlsZQEAFVNraXBwZWRFeGNlcHRpb24uamF2YQwACgALDAAKAA4BABZq" + + "dHJlZy9Ta2lwcGVkRXhjZXB0aW9uAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24AMQADAAQA" + + "AAABABoABQAGAAEABwAAAAIACAACAAEACgALAAEADAAAACMAAwADAAAAByorLLcAAbEAAAABAA0A" + + "AAAKAAIAAAAiAAYAIwABAAoADgABAAwAAAAiAAIAAgAAAAYqK7cAArEAAAABAA0AAAAKAAIAAAAm" + + "AAUAJwABAA8AAAACABA"); + + clazz = (Class)defineClass("jtreg.SkippedException", bytes, 0, bytes.length); + } + + private final Class clazz; + + final static Class INSTANCE = new JtregSkippedExceptionClass().clazz; + + } } diff --git a/test/jdk/tools/jpackage/share/ServiceTest.java b/test/jdk/tools/jpackage/share/ServiceTest.java index 98cad9fc61094..f11ca628ed4d6 100644 --- a/test/jdk/tools/jpackage/share/ServiceTest.java +++ b/test/jdk/tools/jpackage/share/ServiceTest.java @@ -45,9 +45,7 @@ * @test * @summary Launcher as service packaging test * @library /test/jdk/tools/jpackage/helpers - * @library /test/lib * @build jdk.jpackage.test.* - * @build jtreg.SkippedException * @key jpackagePlatformPackage * @compile -Xlint:all -Werror ServiceTest.java * @run main/othervm/timeout=360 -Xmx512m diff --git a/test/jdk/tools/jpackage/windows/WinLongPathTest.java b/test/jdk/tools/jpackage/windows/WinLongPathTest.java index 8fe347cffda13..e52441b961a42 100644 --- a/test/jdk/tools/jpackage/windows/WinLongPathTest.java +++ b/test/jdk/tools/jpackage/windows/WinLongPathTest.java @@ -40,10 +40,8 @@ * @bug 8289771 * @summary jpackage with long paths on windows * @library /test/jdk/tools/jpackage/helpers - * @library /test/lib * @key jpackagePlatformPackage * @build jdk.jpackage.test.* - * @build jtreg.SkippedException * @requires (os.family == "windows") * @compile -Xlint:all -Werror WinLongPathTest.java * @run main/othervm/timeout=540 -Xmx512m jdk.jpackage.test.Main From d3fa9fdf72516219e3dbb20ba7744a5b8aefbd03 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 28 Mar 2025 08:15:30 -0400 Subject: [PATCH 2/5] Add PackageType.throwSkippedExceptionIfNativePackagingUnavailable(). Stable order of platform package types. Make PackageTest fail if native packagers are unavailable. --- .../jdk/jpackage/test/PackageTest.java | 3 +++ .../jdk/jpackage/test/PackageType.java | 24 +++++++++++++++---- 2 files changed, 23 insertions(+), 4 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 5500b670fbcb9..0152cce1a3471 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -83,6 +83,9 @@ public PackageTest() { namedInitializers = new HashSet<>(); handlers = NATIVE.stream() .collect(Collectors.toMap(v -> v, v -> new Handler())); + if (currentTypes.isEmpty()) { + PackageType.throwSkippedExceptionIfNativePackagingUnavailable(); + } } public PackageTest excludeTypes(PackageType... types) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java index 017796705bf3e..a48798172ddb8 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageType.java @@ -22,10 +22,14 @@ */ package jdk.jpackage.test; +import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; + import java.io.PrintWriter; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -33,7 +37,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.Log; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; /** * jpackage type traits. @@ -93,6 +96,15 @@ public String getType() { return type; } + public static RuntimeException throwSkippedExceptionIfNativePackagingUnavailable() { + if (NATIVE.stream().noneMatch(PackageType::isSupported)) { + TKit.throwSkippedException("None of the native packagers supported in this environment"); + } else if (NATIVE.stream().noneMatch(PackageType::isEnabled)) { + TKit.throwSkippedException("All native packagers supported in this environment are disabled"); + } + return null; + } + private static boolean isBundlerSupportedImpl(String bundlerClass) { try { Class clazz = Class.forName(bundlerClass); @@ -131,14 +143,18 @@ private static boolean isBundlerSupported(String bundlerClass) { return reply.get(); } + private static Set orderedSet(PackageType... types) { + return new LinkedHashSet<>(List.of(types)); + } + private final String type; private final String suffix; private final boolean enabled; private final boolean supported; - public static final Set LINUX = Set.of(LINUX_DEB, LINUX_RPM); - public static final Set WINDOWS = Set.of(WIN_EXE, WIN_MSI); - public static final Set MAC = Set.of(MAC_PKG, MAC_DMG); + public static final Set LINUX = orderedSet(LINUX_DEB, LINUX_RPM); + public static final Set WINDOWS = orderedSet(WIN_MSI, WIN_EXE); + public static final Set MAC = orderedSet(MAC_DMG, MAC_PKG); public static final Set NATIVE = Stream.concat( Stream.concat(LINUX.stream(), WINDOWS.stream()), MAC.stream()).collect(Collectors.toUnmodifiableSet()); From 55b55925d47fbfdf984917c5c1991087b059fb73 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 28 Mar 2025 08:16:01 -0400 Subject: [PATCH 3/5] 8352419: Test tools/jpackage/share/ErrorTest.java#id0 and #id1 fail --- test/jdk/tools/jpackage/share/ErrorTest.java | 138 ++++++++++++++----- 1 file changed, 100 insertions(+), 38 deletions(-) diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index 59b0ccb4bd7b5..0d1e558cfdf8f 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -41,7 +41,6 @@ import java.util.regex.Pattern; import java.util.stream.Stream; import jdk.jpackage.internal.util.TokenReplace; -import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CannedFormattedString; @@ -120,13 +119,71 @@ private static String makeToken(String v) { private final TokenReplace tokenReplace = new TokenReplace(token()); } - public record TestSpec(Optional type, Optional appDesc, List addArgs, + record PackageTypeSpec(Optional type, boolean anyNativeType) implements CannedFormattedString.CannedArgument { + PackageTypeSpec { + Objects.requireNonNull(type); + if (type.isPresent() && anyNativeType) { + throw new IllegalArgumentException(); + } + } + + PackageTypeSpec(PackageType type) { + this(Optional.of(type), false); + } + + boolean isSupported() { + if (anyNativeType) { + return NATIVE_TYPE.isPresent(); + } else { + return type.orElseThrow().isSupported(); + } + } + + PackageType resolvedType() { + return type.or(() -> NATIVE_TYPE).orElseThrow(PackageType::throwSkippedExceptionIfNativePackagingUnavailable); + } + + @Override + public String value() { + return resolvedType().getType(); + } + + @Override + public final String toString() { + if (anyNativeType) { + return "NATIVE"; + } else { + return type.orElseThrow().toString(); + } + } + + private static Optional defaultNativeType() { + final Collection nativeTypes; + if (TKit.isLinux()) { + nativeTypes = PackageType.LINUX; + } else if (TKit.isOSX()) { + nativeTypes = PackageType.MAC; + } else if (TKit.isWindows()) { + nativeTypes = List.of(PackageType.WIN_MSI); + } else { + throw TKit.throwUnknownPlatformError(); + } + + return nativeTypes.stream().filter(PackageType::isSupported).findFirst(); + } + + static final PackageTypeSpec NATIVE = new PackageTypeSpec(Optional.empty(), true); + + static final private Optional NATIVE_TYPE = defaultNativeType(); + } + + public record TestSpec(Optional type, Optional appDesc, List addArgs, List removeArgs, List expectedErrors) { static final class Builder { Builder type(PackageType v) { - type = v; + type = Optional.ofNullable(v).map(PackageTypeSpec::new).orElse(null); return this; } @@ -135,7 +192,8 @@ Builder notype() { } Builder nativeType() { - return type(NATIVE_TYPE); + type = PackageTypeSpec.NATIVE; + return this; } Builder appDesc(String v) { @@ -208,7 +266,8 @@ Builder error(String key, Object ... args) { } Builder invalidTypeArg(String arg, String... otherArgs) { - return addArgs(arg).addArgs(otherArgs).error("ERR_InvalidTypeOption", arg, type.getType()); + Objects.requireNonNull(type); + return addArgs(arg).addArgs(otherArgs).error("ERR_InvalidTypeOption", arg, type); } Builder unsupportedPlatformOption(String arg, String ... otherArgs) { @@ -220,7 +279,7 @@ TestSpec create() { List.copyOf(addArgs), List.copyOf(removeArgs), List.copyOf(expectedErrors)); } - private PackageType type = PackageType.IMAGE; + private PackageTypeSpec type = new PackageTypeSpec(PackageType.IMAGE); private String appDesc = DEFAULT_APP_DESC; private List addArgs = new ArrayList<>(); private List removeArgs = new ArrayList<>(); @@ -243,9 +302,13 @@ void test() { test(Map.of()); } + boolean isSupported() { + return type.map(PackageTypeSpec::isSupported).orElse(true); + } + void test(Map> tokenValueSuppliers) { final var cmd = appDesc.map(JPackageCommand::helloAppImage).orElseGet(JPackageCommand::new); - type.ifPresent(cmd::setPackageType); + type.map(PackageTypeSpec::resolvedType).ifPresent(cmd::setPackageType); removeArgs.forEach(cmd::removeArgumentWithValue); cmd.addArguments(addArgs); @@ -408,6 +471,7 @@ public static Collection invalidAppVersion() { @Test @ParameterSupplier("basic") + @ParameterSupplier("testRuntimeInstallerInvalidOptions") @ParameterSupplier(value="testWindows", ifOS = WINDOWS) @ParameterSupplier(value="testMac", ifOS = MACOS) @ParameterSupplier(value="testLinux", ifOS = LINUX) @@ -419,19 +483,27 @@ public static void test(TestSpec spec) { spec.test(); } - @Test - @Parameter({"--input", "foo"}) - @Parameter({"--module-path", "dir"}) - @Parameter({"--add-modules", "java.base"}) - @Parameter({"--main-class", "Hello"}) - @Parameter({"--arguments", "foo"}) - @Parameter({"--java-options", "-Dfoo.bar=10"}) - @Parameter({"--add-launcher", "foo=foo.properties"}) - @Parameter({"--app-content", "dir"}) - @Parameter(value="--win-console", ifOS = WINDOWS) - public static void testRuntimeInstallerInvalidOptions(String... args) { - testSpec().noAppDesc().nativeType().addArgs("--runtime-image", Token.JAVA_HOME.token()).addArgs(args) - .error("ERR_NoInstallerEntryPoint", args[0]).create().test(); + public static Collection testRuntimeInstallerInvalidOptions() { + Stream> argsStream = Stream.of( + List.of("--input", "foo"), + List.of("--module-path", "dir"), + List.of("--add-modules", "java.base"), + List.of("--main-class", "Hello"), + List.of("--arguments", "foo"), + List.of("--java-options", "-Dfoo.bar=10"), + List.of("--add-launcher", "foo=foo.properties"), + List.of("--app-content", "dir")); + + if (TKit.isWindows()) { + argsStream = Stream.concat(argsStream, Stream.of(List.of("--win-console"))); + } + + return fromTestSpecBuilders(argsStream.map(args -> { + return testSpec().noAppDesc().nativeType() + .addArgs("--runtime-image", Token.JAVA_HOME.token()) + .addArgs(args) + .error("ERR_NoInstallerEntryPoint", args.getFirst()); + })); } @Test @@ -596,9 +668,7 @@ public static Collection testLinux() { testSpec().type(PackageType.LINUX_RPM).addArgs("--linux-package-name", "#") .error("error.rpm-invalid-value-for-package-name", "#") .error("error.rpm-invalid-value-for-package-name.advice") - ).map(TestSpec.Builder::create).filter(spec -> { - return spec.type().orElseThrow().isSupported(); - }).toList()); + ).map(TestSpec.Builder::create).toList()); return toTestArgs(testCases.stream()); } @@ -698,20 +768,14 @@ private static void defaultInit(JPackageCommand cmd, List cmd.validateOutput(expectedErrors.toArray(CannedFormattedString[]::new)); } - private static PackageType defaultNativeType() { - if (TKit.isLinux()) { - return PackageType.LINUX.stream().filter(PackageType::isSupported).findFirst().orElseThrow(); - } else if (TKit.isOSX()) { - return PackageType.MAC_DMG; - } else if (TKit.isWindows()) { - return PackageType.WIN_MSI; - } else { - throw new UnsupportedOperationException(); - } - } - private static Collection toTestArgs(Stream stream) { - return stream.map(v -> { + return stream.filter(v -> { + if (v instanceof TestSpec ts) { + return ts.isSupported(); + } else { + return true; + } + }).map(v -> { return new Object[] {v}; }).toList(); } @@ -725,6 +789,4 @@ private static String adjustTextStreamVerifierArg(String str) { } private static final Pattern LINE_SEP_REGEXP = Pattern.compile("\\R"); - - private static final PackageType NATIVE_TYPE = defaultNativeType(); } From 353e3f3631a61abffa881d66eb23d14a9d1aedf0 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 28 Mar 2025 10:52:10 -0400 Subject: [PATCH 4/5] bash ./bin/blessed-modifier-order.sh test/jdk/tools/jpackage/ --- test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java | 4 ++-- test/jdk/tools/jpackage/share/ErrorTest.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 8954665f7c982..c8972a9791e42 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -1142,7 +1142,7 @@ static Set tokenizeConfigProperty(String propertyName) { } } - private final static class JtregSkippedExceptionClass extends ClassLoader { + private static final class JtregSkippedExceptionClass extends ClassLoader { @SuppressWarnings("unchecked") JtregSkippedExceptionClass() { super(TKit.class.getClassLoader()); @@ -1164,7 +1164,7 @@ private final static class JtregSkippedExceptionClass extends ClassLoader { private final Class clazz; - final static Class INSTANCE = new JtregSkippedExceptionClass().clazz; + static final Class INSTANCE = new JtregSkippedExceptionClass().clazz; } } diff --git a/test/jdk/tools/jpackage/share/ErrorTest.java b/test/jdk/tools/jpackage/share/ErrorTest.java index 0d1e558cfdf8f..26562e1afca07 100644 --- a/test/jdk/tools/jpackage/share/ErrorTest.java +++ b/test/jdk/tools/jpackage/share/ErrorTest.java @@ -174,7 +174,7 @@ private static Optional defaultNativeType() { static final PackageTypeSpec NATIVE = new PackageTypeSpec(Optional.empty(), true); - static final private Optional NATIVE_TYPE = defaultNativeType(); + private static final Optional NATIVE_TYPE = defaultNativeType(); } public record TestSpec(Optional type, Optional appDesc, List addArgs, From b713dea00af28cd863e17bd1455786268df90890 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 1 Apr 2025 14:15:26 -0400 Subject: [PATCH 5/5] Fix failure in PackageTestTest when native packaging is not available --- .../helpers/jdk/jpackage/test/PackageTest.java | 11 +++++------ 1 file changed, 5 insertions(+), 6 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 0152cce1a3471..fd26b4a536833 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -77,15 +77,11 @@ public PackageTest() { disabledInstallers = new HashSet<>(); disabledUninstallers = new HashSet<>(); excludeTypes = new HashSet<>(); + handlers = NATIVE.stream().collect(Collectors.toMap(v -> v, v -> new Handler())); forTypes(); setExpectedExitCode(0); setExpectedInstallExitCode(0); namedInitializers = new HashSet<>(); - handlers = NATIVE.stream() - .collect(Collectors.toMap(v -> v, v -> new Handler())); - if (currentTypes.isEmpty()) { - PackageType.throwSkippedExceptionIfNativePackagingUnavailable(); - } } public PackageTest excludeTypes(PackageType... types) { @@ -105,6 +101,7 @@ public PackageTest forTypes(PackageType... types) { newTypes = Stream.of(types).collect(Collectors.toSet()); } currentTypes = newTypes.stream() + .filter(handlers.keySet()::contains) .filter(isPackageTypeEnabled) .filter(Predicate.not(excludeTypes::contains)) .collect(Collectors.toUnmodifiableSet()); @@ -459,9 +456,11 @@ protected void runAction(Action... action) { } private List> createPackageTypeHandlers() { + if (handlers.keySet().stream().noneMatch(isPackageTypeEnabled)) { + PackageType.throwSkippedExceptionIfNativePackagingUnavailable(); + } return handlers.entrySet().stream() .filter(entry -> !entry.getValue().isVoid()) - .filter(entry -> NATIVE.contains(entry.getKey())) .sorted(Comparator.comparing(Map.Entry::getKey)) .map(entry -> { return createPackageTypeHandler(entry.getKey(), entry.getValue());