8352289: [macos] Review skipped tests in tools/jpackage/macosx/SigningPackage*

Reviewed-by: almatvee
This commit is contained in:
Alexey Semenyuk 2025-03-25 01:45:03 +00:00
parent ba658a71ba
commit b2da0d341b
10 changed files with 73 additions and 298 deletions

View File

@ -747,10 +747,10 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
public JPackageCommand validateOutput(CannedFormattedString... str) {
// Will look up the given errors in the order they are specified.
return validateOutput(Stream.of(str)
.map(this::getValue)
Stream.of(str).map(this::getValue)
.map(TKit::assertTextStream)
.reduce(TKit.TextStreamVerifier::andThen).get());
.reduce(TKit.TextStreamVerifier::andThen).ifPresent(this::validateOutput);
return this;
}
public boolean isWithToolProvider() {

View File

@ -397,6 +397,10 @@ public final class MacHelper {
private final org.w3c.dom.Document doc;
}
public static boolean isXcodeDevToolsInstalled() {
return Inner.XCODE_DEV_TOOLS_INSTALLED;
}
private static DocumentBuilder createDocumentBuilder() throws
ParserConfigurationException {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newDefaultInstance();
@ -432,6 +436,11 @@ public final class MacHelper {
}
}
private static final class Inner {
private static final boolean XCODE_DEV_TOOLS_INSTALLED =
Executor.of("/usr/bin/xcrun", "--help").executeWithoutExitCodeCheck().getExitCode() == 0;
}
static final Set<Path> CRITICAL_RUNTIME_FILES = Set.of(Path.of(
"Contents/Home/lib/server/libjvm.dylib"));

View File

@ -46,16 +46,14 @@ import jdk.jpackage.test.AdditionalLauncher;
* @test
* @summary jpackage with --type app-image --mac-sign
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningAppImageTest
* @requires (os.family == "mac")
* @requires (jpackage.test.MacSignTests == "run")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningAppImageTest
* --jpt-before-run=SigningBase.verifySignTestEnvReady
*/
public class SigningAppImageTest {
@ -72,8 +70,6 @@ public class SigningAppImageTest {
public void test(boolean doSign, boolean signingKey, SigningBase.CertIndex certEnum) throws Exception {
final var certIndex = certEnum.value();
SigningCheck.checkCertificates(certIndex);
JPackageCommand cmd = JPackageCommand.helloAppImage();
if (doSign) {
cmd.addArguments("--mac-sign",

View File

@ -47,16 +47,14 @@ import jdk.jpackage.test.AdditionalLauncher;
* @test
* @summary jpackage with --type app-image --app-image "appImage" --mac-sign
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningAppImageTwoStepsTest
* @requires (os.family == "mac")
* @requires (jpackage.test.MacSignTests == "run")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningAppImageTwoStepsTest
* --jpt-before-run=SigningBase.verifySignTestEnvReady
*/
public class SigningAppImageTwoStepsTest {
@ -68,11 +66,7 @@ public class SigningAppImageTwoStepsTest {
@Parameter({"true", "false"})
// Unsigned
@Parameter({"false", "true"})
public void test(String... testArgs) throws Exception {
boolean signAppImage = Boolean.parseBoolean(testArgs[0]);
boolean signingKey = Boolean.parseBoolean(testArgs[1]);
SigningCheck.checkCertificates(SigningBase.DEFAULT_INDEX);
public void test(boolean signAppImage, boolean signingKey) throws Exception {
Path appimageOutput = TKit.createTempDirectory("appimage");

View File

@ -1,151 +0,0 @@
/*
* Copyright (c) 2023, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.Collection;
import java.util.List;
import jdk.jpackage.test.Annotations.Parameters;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.TKit;
/*
* @test
* @summary Test jpackage signing options errors
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build SigningOptionsTest
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningOptionsTest
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault
*/
/*
* @test
* @summary Test jpackage signing options errors
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build SigningOptionsTest
* @requires (os.family == "mac")
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningOptionsTest
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault
*/
public final class SigningOptionsTest {
private final String expectedError;
private final JPackageCommand cmd;
private static final String TEST_DUKE = TKit.TEST_SRC_ROOT.resolve(
"apps/dukeplug.png").toString();
@Parameters
public static Collection<?> input() {
return List.of(new Object[][]{
// --mac-signing-key-user-name and --mac-app-image-sign-identity
{"Hello",
new String[]{"--mac-sign",
"--mac-signing-key-user-name", "test-key",
"--mac-app-image-sign-identity", "test-identity"},
null,
"Mutually exclusive options",
Boolean.FALSE},
// --mac-signing-key-user-name and --mac-installer-sign-identity
{"Hello",
new String[]{"--mac-sign",
"--mac-signing-key-user-name", "test-key",
"--mac-installer-sign-identity", "test-identity"},
null,
"Mutually exclusive options",
Boolean.FALSE},
// --mac-installer-sign-identity and --type app-image
{"Hello",
new String[]{"--mac-sign",
"--mac-installer-sign-identity", "test-identity"},
null,
"Option [--mac-installer-sign-identity] is not valid with type",
Boolean.FALSE},
// --mac-installer-sign-identity and --type dmg
{"Hello",
new String[]{"--type", "dmg",
"--mac-sign",
"--mac-installer-sign-identity", "test-identity"},
new String[]{"--type"},
"Option [--mac-installer-sign-identity] is not valid with type",
Boolean.FALSE},
// --app-content and --type app-image
// JDK-8340802: "codesign" may or may not fail if additional
// content is specified based on macOS version. For example on
// macOS 15 aarch64 "codesign" will not fail with additional content.
// Since we only need to check that warning is displayed when
// "codesign" fails and "--app-content" is provided, lets fail
// "codesign" for some better reason like identity which does not
// exists.
{"Hello",
new String[]{"--app-content", TEST_DUKE,
"--mac-sign",
"--mac-app-image-sign-identity", "test-identity"},
null,
"\"codesign\" failed and additional application content" +
" was supplied via the \"--app-content\" parameter.",
Boolean.TRUE},
});
}
public SigningOptionsTest(String javaAppDesc, String[] jpackageArgs,
String[] removeArgs, String expectedError,
Boolean checkRequirements) {
this.expectedError = expectedError;
if (checkRequirements) {
SigningCheck.isXcodeDevToolsInstalled();
}
cmd = JPackageCommand.helloAppImage(javaAppDesc)
.saveConsoleOutput(true).dumpOutput(true);
if (jpackageArgs != null) {
cmd.addArguments(jpackageArgs);
} if (removeArgs != null) {
for (String arg : removeArgs) {
cmd.removeArgumentWithValue(arg);
}
}
}
@Test
public void test() {
List<String> output = cmd.execute(1).getOutput();
TKit.assertNotNull(output, "output is null");
TKit.assertTextStream(expectedError).apply(output.stream());
}
}

View File

@ -51,17 +51,15 @@ import jdk.jpackage.test.Annotations.Parameter;
* @test
* @summary jpackage with --type pkg,dmg --app-image
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageFromTwoStepAppImageTest
* @requires (os.family == "mac")
* @requires (jpackage.test.MacSignTests == "run")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageFromTwoStepAppImageTest
* --jpt-before-run=SigningBase.verifySignTestEnvReady
*/
public class SigningPackageFromTwoStepAppImageTest {
@ -103,11 +101,7 @@ public class SigningPackageFromTwoStepAppImageTest {
@Parameter({"true", "false"})
// Unsigned
@Parameter({"false", "true"})
public void test(String... testArgs) throws Exception {
boolean signAppImage = Boolean.parseBoolean(testArgs[0]);
boolean signingKey = Boolean.parseBoolean(testArgs[1]);
SigningCheck.checkCertificates(SigningBase.DEFAULT_INDEX);
public void test(boolean signAppImage, boolean signingKey) throws Exception {
Path appimageOutput = TKit.createTempDirectory("appimage");

View File

@ -49,17 +49,15 @@ import jdk.jpackage.test.Annotations.Parameter;
* @test
* @summary jpackage with --type pkg,dmg --mac-sign
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageTest
* @requires (os.family == "mac")
* @requires (jpackage.test.MacSignTests == "run")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageTest
* --jpt-before-run=SigningBase.verifySignTestEnvReady
*/
public class SigningPackageTest {
@ -129,8 +127,6 @@ public class SigningPackageTest {
public static void test(boolean signingKey, boolean signAppImage, boolean signPKG, SigningBase.CertIndex certEnum) throws Exception {
final var certIndex = certEnum.value();
SigningCheck.checkCertificates(certIndex);
new PackageTest()
.configureHelloApp()
.forTypes(PackageType.MAC)

View File

@ -52,17 +52,15 @@ import jdk.jpackage.test.Annotations.Parameter;
* @test
* @summary jpackage with --type pkg,dmg --app-image
* @library /test/jdk/tools/jpackage/helpers
* @library /test/lib
* @library base
* @key jpackagePlatformPackage
* @build SigningBase
* @build SigningCheck
* @build jtreg.SkippedException
* @build jdk.jpackage.test.*
* @build SigningPackageTwoStepTest
* @requires (os.family == "mac")
* @requires (jpackage.test.MacSignTests == "run")
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=SigningPackageTwoStepTest
* --jpt-before-run=SigningBase.verifySignTestEnvReady
*/
public class SigningPackageTwoStepTest {
@ -107,12 +105,7 @@ public class SigningPackageTwoStepTest {
@Parameter({"true", "false"})
// Unsigned
@Parameter({"false", "true"})
public static void test(String... testArgs) throws Exception {
boolean signAppImage = Boolean.parseBoolean(testArgs[0]);
boolean signingKey = Boolean.parseBoolean(testArgs[1]);
SigningCheck.checkCertificates(SigningBase.DEFAULT_INDEX);
public static void test(boolean signAppImage, boolean signingKey) throws Exception {
Path appimageOutput = TKit.createTempDirectory("appimage");
JPackageCommand appImageCmd = JPackageCommand.helloAppImage()

View File

@ -1,97 +0,0 @@
/*
* Copyright (c) 2019, 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
import java.util.List;
import jdk.jpackage.test.TKit;
import jdk.jpackage.test.Executor;
import jdk.jpackage.internal.MacCertificate;
public class SigningCheck {
public static void checkCertificates(int certIndex) {
if (!SigningBase.isDevNameDefault()) {
// Do not validate user supplied certificates.
// User supplied certs whose trust is set to "Use System Defaults"
// will not be listed as trusted by dump-trust-settings, so we
// cannot verify them completely.
return;
}
// Index can be -1 for unsigned tests, but we still skipping test
// if machine is not configured for signing testing, so default it to
// SigningBase.DEFAULT_INDEX
if (certIndex <= -1) {
certIndex = SigningBase.DEFAULT_INDEX;
}
String key = MacCertificate.findCertificateKey(null,
SigningBase.getAppCert(certIndex),
SigningBase.getKeyChain());
validateCertificate(key);
validateCertificateTrust(SigningBase.getAppCert(certIndex));
key = MacCertificate.findCertificateKey(null,
SigningBase.getInstallerCert(certIndex),
SigningBase.getKeyChain());
validateCertificate(key);
validateCertificateTrust(SigningBase.getInstallerCert(certIndex));
}
private static void validateCertificate(String key) {
if (key != null) {
MacCertificate certificate = new MacCertificate(key);
if (!certificate.isValid()) {
TKit.throwSkippedException("Certifcate expired: " + key);
} else {
return;
}
}
TKit.throwSkippedException("Cannot find required certifciates: " + key);
}
private static void validateCertificateTrust(String name) {
// Certificates using the default user name must be trusted by user.
List<String> result = new Executor()
.setExecutable("/usr/bin/security")
.addArguments("dump-trust-settings")
.executeWithoutExitCodeCheckAndGetOutput();
result.stream().forEachOrdered(TKit::trace);
TKit.assertTextStream(name)
.predicate((line, what) -> line.trim().endsWith(what))
.orElseThrow(() -> TKit.throwSkippedException(
"Certifcate not trusted by current user: " + name))
.apply(result.stream());
}
public static void isXcodeDevToolsInstalled() {
int code = Executor.of("/usr/bin/xcrun", "--help")
.executeWithoutExitCodeCheck().getExitCode();
if (code != 0) {
TKit.throwSkippedException("Missing Xcode with command line developer tools");
}
}
}

View File

@ -35,6 +35,7 @@ import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.regex.Pattern;
@ -46,6 +47,7 @@ import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.CannedFormattedString;
import jdk.jpackage.test.JPackageCommand;
import jdk.jpackage.test.JPackageStringBundle;
import jdk.jpackage.test.MacHelper;
import jdk.jpackage.test.PackageType;
import jdk.jpackage.test.TKit;
@ -539,25 +541,64 @@ public final class ErrorTest {
).map(argGroup -> {
return testSpec().noAppDesc().addArgs(argGroup.asArray()).addArgs("--app-image", Token.APP_IMAGE.token())
.error("ERR_InvalidOptionWithAppImageSigning", argGroup.arg());
}).<TestSpec>mapMulti((builder, acc) -> {
// It should bail out with the same error message regardless of `--mac-sign` option.
acc.accept(builder.create());
acc.accept(builder.addArgs("--mac-sign").create());
}).toList());
// It should bail out with the same error message regardless of `--mac-sign` option.
}).mapMulti(ErrorTest::duplicateForMacSign).toList());
testCases.addAll(createMutuallyExclusive(
new ArgumentGroup("--mac-signing-key-user-name", "foo"),
new ArgumentGroup("--mac-app-image-sign-identity", "bar")
).map(TestSpec.Builder::create).toList());
).mapMulti(ErrorTest::duplicateForMacSign).toList());
testCases.addAll(createMutuallyExclusive(
new ArgumentGroup("--mac-signing-key-user-name", "foo"),
new ArgumentGroup("--mac-installer-sign-identity", "bar")
).map(TestSpec.Builder::nativeType).map(TestSpec.Builder::create).toList());
).map(TestSpec.Builder::nativeType).mapMulti(ErrorTest::duplicateForMacSign).toList());
return toTestArgs(testCases.stream());
}
@Test(ifOS = MACOS)
public static void testAppContentWarning() {
// --app-content and --type app-image
// Expect `message.codesign.failed.reason.app.content` message in the log.
// This is not a fatal error, just a warning.
// To make jpackage fail, specify invalid signing identity.
final var cmd = JPackageCommand.helloAppImage()
.addArguments("--app-content", TKit.TEST_SRC_ROOT.resolve("apps/dukeplug.png"))
.addArguments("--mac-sign", "--mac-app-image-sign-identity", "foo");
final List<CannedFormattedString> expectedStrings = new ArrayList<>();
expectedStrings.add(JPackageStringBundle.MAIN.cannedFormattedString("message.codesign.failed.reason.app.content"));
final var xcodeWarning = JPackageStringBundle.MAIN.cannedFormattedString("message.codesign.failed.reason.xcode.tools");
if (!MacHelper.isXcodeDevToolsInstalled()) {
expectedStrings.add(xcodeWarning);
}
defaultInit(cmd, expectedStrings);
if (MacHelper.isXcodeDevToolsInstalled()) {
// Check there is no warning about missing xcode command line developer tools.
cmd.validateOutput(TKit.assertTextStream(xcodeWarning.getValue()).negate());
}
cmd.execute(1);
}
private static void duplicate(TestSpec.Builder builder, Consumer<TestSpec> accumulator, Consumer<TestSpec.Builder> mutator) {
accumulator.accept(builder.create());
mutator.accept(builder);
accumulator.accept(builder.create());
}
private static void duplicateAddArgs(TestSpec.Builder builder, Consumer<TestSpec> accumulator, String...args) {
duplicate(builder, accumulator, b -> b.addArgs(args));
}
private static void duplicateForMacSign(TestSpec.Builder builder, Consumer<TestSpec> accumulator) {
duplicateAddArgs(builder, accumulator, "--mac-sign");
}
private record UnsupportedPlatformOption(String name, Optional<String> value) {
UnsupportedPlatformOption {
Objects.requireNonNull(name);