8344322: Improve capabilities of jpackage test lib to validate error output of jpackage
Reviewed-by: almatvee
This commit is contained in:
parent
41436bb0e8
commit
0714114fe3
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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.
|
||||||
|
*/
|
||||||
|
package jdk.jpackage.test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
public final class CannedFormattedString {
|
||||||
|
|
||||||
|
CannedFormattedString(BiFunction<String, Object[], String> formatter,
|
||||||
|
String key, Object[] args) {
|
||||||
|
this.formatter = formatter;
|
||||||
|
this.key = key;
|
||||||
|
this.args = args;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return formatter.apply(key, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (args.length == 0) {
|
||||||
|
return String.format("%s", key);
|
||||||
|
} else {
|
||||||
|
return String.format("%s+%s", key, List.of(args));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private final BiFunction<String, Object[], String> formatter;
|
||||||
|
private final String key;
|
||||||
|
private final Object[] args;
|
||||||
|
}
|
@ -78,6 +78,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
prerequisiteActions = new Actions(cmd.prerequisiteActions);
|
prerequisiteActions = new Actions(cmd.prerequisiteActions);
|
||||||
verifyActions = new Actions(cmd.verifyActions);
|
verifyActions = new Actions(cmd.verifyActions);
|
||||||
appLayoutAsserts = cmd.appLayoutAsserts;
|
appLayoutAsserts = cmd.appLayoutAsserts;
|
||||||
|
outputValidator = cmd.outputValidator;
|
||||||
executeInDirectory = cmd.executeInDirectory;
|
executeInDirectory = cmd.executeInDirectory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -739,6 +740,24 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public JPackageCommand validateOutput(TKit.TextStreamVerifier validator) {
|
||||||
|
return JPackageCommand.this.validateOutput(validator::apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPackageCommand validateOutput(Consumer<Stream<String>> validator) {
|
||||||
|
if (validator != null) {
|
||||||
|
saveConsoleOutput(true);
|
||||||
|
outputValidator = validator;
|
||||||
|
} else {
|
||||||
|
outputValidator = null;
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPackageCommand validateOutput(CannedFormattedString str) {
|
||||||
|
return JPackageCommand.this.validateOutput(TKit.assertTextStream(str.getValue()));
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isWithToolProvider() {
|
public boolean isWithToolProvider() {
|
||||||
return Optional.ofNullable(withToolProvider).orElse(
|
return Optional.ofNullable(withToolProvider).orElse(
|
||||||
defaultWithToolProvider);
|
defaultWithToolProvider);
|
||||||
@ -817,6 +836,10 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
.createExecutor()
|
.createExecutor()
|
||||||
.execute(expectedExitCode);
|
.execute(expectedExitCode);
|
||||||
|
|
||||||
|
if (outputValidator != null) {
|
||||||
|
outputValidator.accept(result.getOutput().stream());
|
||||||
|
}
|
||||||
|
|
||||||
if (result.exitCode == 0) {
|
if (result.exitCode == 0) {
|
||||||
executeVerifyActions();
|
executeVerifyActions();
|
||||||
}
|
}
|
||||||
@ -1187,6 +1210,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
|||||||
private final Actions verifyActions;
|
private final Actions verifyActions;
|
||||||
private Path executeInDirectory;
|
private Path executeInDirectory;
|
||||||
private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values());
|
private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values());
|
||||||
|
private Consumer<Stream<String>> outputValidator;
|
||||||
private static boolean defaultWithToolProvider;
|
private static boolean defaultWithToolProvider;
|
||||||
|
|
||||||
private static final Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
private static final Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
||||||
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2024, 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package jdk.jpackage.test;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
|
||||||
|
public enum JPackageStringBundle {
|
||||||
|
|
||||||
|
MAIN("jdk.jpackage.internal.I18N"),
|
||||||
|
;
|
||||||
|
|
||||||
|
JPackageStringBundle(String i18nClassName) {
|
||||||
|
try {
|
||||||
|
i18nClass = Class.forName(i18nClassName);
|
||||||
|
|
||||||
|
i18nClass_getString = i18nClass.getDeclaredMethod("getString", String.class);
|
||||||
|
i18nClass_getString.setAccessible(true);
|
||||||
|
} catch (ClassNotFoundException|NoSuchMethodException ex) {
|
||||||
|
throw Functional.rethrowUnchecked(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string value of the given key from jpackage resources.
|
||||||
|
*/
|
||||||
|
private String getString(String key) {
|
||||||
|
try {
|
||||||
|
return (String)i18nClass_getString.invoke(i18nClass, key);
|
||||||
|
} catch (IllegalAccessException|InvocationTargetException ex) {
|
||||||
|
throw Functional.rethrowUnchecked(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getFormattedString(String key, Object[] args) {
|
||||||
|
return MessageFormat.format(getString(key), args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CannedFormattedString cannedFormattedString(String key, String ... args) {
|
||||||
|
return new CannedFormattedString(this::getFormattedString, key, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Class<?> i18nClass;
|
||||||
|
private final Method i18nClass_getString;
|
||||||
|
}
|
@ -946,6 +946,16 @@ public final class TKit {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TextStreamVerifier andThen(Consumer<? super Stream<String>> anotherVerifier) {
|
||||||
|
this.anotherVerifier = anotherVerifier;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextStreamVerifier andThen(TextStreamVerifier anotherVerifier) {
|
||||||
|
this.anotherVerifier = anotherVerifier::apply;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
public TextStreamVerifier orElseThrow(RuntimeException v) {
|
public TextStreamVerifier orElseThrow(RuntimeException v) {
|
||||||
return orElseThrow(() -> v);
|
return orElseThrow(() -> v);
|
||||||
}
|
}
|
||||||
@ -956,9 +966,22 @@ public final class TKit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void apply(Stream<String> lines) {
|
public void apply(Stream<String> lines) {
|
||||||
String matchedStr = lines.filter(line -> predicate.test(line, value)).findFirst().orElse(
|
final String matchedStr;
|
||||||
null);
|
|
||||||
String labelStr = Optional.ofNullable(label).orElse("output");
|
lines = lines.dropWhile(line -> !predicate.test(line, value));
|
||||||
|
if (anotherVerifier == null) {
|
||||||
|
matchedStr = lines.findFirst().orElse(null);
|
||||||
|
} else {
|
||||||
|
var tail = lines.toList();
|
||||||
|
if (tail.isEmpty()) {
|
||||||
|
matchedStr = null;
|
||||||
|
} else {
|
||||||
|
matchedStr = tail.get(0);
|
||||||
|
}
|
||||||
|
lines = tail.stream().skip(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String labelStr = Optional.ofNullable(label).orElse("output");
|
||||||
if (negate) {
|
if (negate) {
|
||||||
String msg = String.format(
|
String msg = String.format(
|
||||||
"Check %s doesn't contain [%s] string", labelStr, value);
|
"Check %s doesn't contain [%s] string", labelStr, value);
|
||||||
@ -982,12 +1005,17 @@ public final class TKit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anotherVerifier != null) {
|
||||||
|
anotherVerifier.accept(lines);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private BiPredicate<String, String> predicate;
|
private BiPredicate<String, String> predicate;
|
||||||
private String label;
|
private String label;
|
||||||
private boolean negate;
|
private boolean negate;
|
||||||
private Supplier<RuntimeException> createException;
|
private Supplier<RuntimeException> createException;
|
||||||
|
private Consumer<? super Stream<String>> anotherVerifier;
|
||||||
private final String value;
|
private final String value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,9 +24,13 @@
|
|||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jdk.jpackage.test.Annotations.Parameters;
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import jdk.jpackage.test.Annotations.ParameterSupplier;
|
||||||
import jdk.jpackage.test.Annotations.Test;
|
import jdk.jpackage.test.Annotations.Test;
|
||||||
|
import jdk.jpackage.test.CannedFormattedString;
|
||||||
import jdk.jpackage.test.JPackageCommand;
|
import jdk.jpackage.test.JPackageCommand;
|
||||||
|
import jdk.jpackage.test.JPackageStringBundle;
|
||||||
import jdk.jpackage.test.TKit;
|
import jdk.jpackage.test.TKit;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -53,81 +57,85 @@ import jdk.jpackage.test.TKit;
|
|||||||
|
|
||||||
public final class ErrorTest {
|
public final class ErrorTest {
|
||||||
|
|
||||||
private final String expectedError;
|
|
||||||
private final JPackageCommand cmd;
|
|
||||||
|
|
||||||
@Parameters
|
|
||||||
public static Collection input() {
|
public static Collection input() {
|
||||||
return List.of(new Object[][]{
|
return List.of(new Object[][]{
|
||||||
// non-existent arg
|
// non-existent arg
|
||||||
{"Hello",
|
{"Hello",
|
||||||
new String[]{"--no-such-argument"},
|
new String[]{"--no-such-argument"},
|
||||||
null,
|
null,
|
||||||
"Invalid Option: [--no-such-argument]"},
|
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidOption", "--no-such-argument")},
|
||||||
// no main jar
|
// no main jar
|
||||||
{"Hello",
|
{"Hello",
|
||||||
null,
|
null,
|
||||||
new String[]{"--main-jar"},
|
new String[]{"--main-jar"},
|
||||||
"--main-jar or --module"},
|
JPackageStringBundle.MAIN.cannedFormattedString("ERR_NoEntryPoint")},
|
||||||
// no main-class
|
// no main-class
|
||||||
{"Hello",
|
{"Hello",
|
||||||
null,
|
null,
|
||||||
new String[]{"--main-class"},
|
new String[]{"--main-class"},
|
||||||
"main class was not specified"},
|
JPackageStringBundle.MAIN.cannedFormattedString("error.no-main-class-with-main-jar", "hello.jar"),
|
||||||
|
JPackageStringBundle.MAIN.cannedFormattedString("error.no-main-class-with-main-jar.advice", "hello.jar")},
|
||||||
// non-existent main jar
|
// non-existent main jar
|
||||||
{"Hello",
|
{"Hello",
|
||||||
new String[]{"--main-jar", "non-existent.jar"},
|
new String[]{"--main-jar", "non-existent.jar"},
|
||||||
null,
|
null,
|
||||||
"main jar does not exist"},
|
JPackageStringBundle.MAIN.cannedFormattedString("error.main-jar-does-not-exist", "non-existent.jar")},
|
||||||
// non-existent runtime
|
// non-existent runtime
|
||||||
{"Hello",
|
{"Hello",
|
||||||
new String[]{"--runtime-image", "non-existent.runtime"},
|
new String[]{"--runtime-image", "non-existent.runtime"},
|
||||||
null,
|
null,
|
||||||
"does not exist"},
|
JPackageStringBundle.MAIN.cannedFormattedString("message.runtime-image-dir-does-not-exist", "runtime-image", "non-existent.runtime")},
|
||||||
// non-existent resource-dir
|
// non-existent resource-dir
|
||||||
{"Hello",
|
{"Hello",
|
||||||
new String[]{"--resource-dir", "non-existent.dir"},
|
new String[]{"--resource-dir", "non-existent.dir"},
|
||||||
null,
|
null,
|
||||||
"does not exist"},
|
JPackageStringBundle.MAIN.cannedFormattedString("message.resource-dir-does-not-exist", "resource-dir", "non-existent.dir")},
|
||||||
// invalid type
|
// invalid type
|
||||||
{"Hello",
|
{"Hello",
|
||||||
new String[]{"--type", "invalid-type"},
|
new String[]{"--type", "invalid-type"},
|
||||||
null,
|
null,
|
||||||
"Invalid or unsupported type: [invalid-type]"},
|
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidInstallerType", "invalid-type")},
|
||||||
// no --input
|
// no --input
|
||||||
{"Hello",
|
{"Hello",
|
||||||
null,
|
null,
|
||||||
new String[]{"--input"},
|
new String[]{"--input"},
|
||||||
"Missing argument: --input"},
|
JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--input")},
|
||||||
// no --module-path
|
// no --module-path
|
||||||
{"com.other/com.other.Hello",
|
{"com.other/com.other.Hello",
|
||||||
null,
|
null,
|
||||||
new String[]{"--module-path"},
|
new String[]{"--module-path"},
|
||||||
"Missing argument: --runtime-image or --module-path"},
|
JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--runtime-image or --module-path")},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public ErrorTest(String javaAppDesc, String[] jpackageArgs,
|
|
||||||
String[] removeArgs,
|
|
||||||
String expectedError) {
|
|
||||||
this.expectedError = expectedError;
|
|
||||||
|
|
||||||
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
|
@Test
|
||||||
public void test() {
|
@ParameterSupplier("input")
|
||||||
List<String> output = cmd.execute(1).getOutput();
|
public static void test(String javaAppDesc, String[] jpackageArgs,
|
||||||
TKit.assertNotNull(output, "output is null");
|
String[] removeArgs, CannedFormattedString... expectedErrors) {
|
||||||
TKit.assertTextStream(expectedError).apply(output.stream());
|
// Init default jpackage test command line.
|
||||||
}
|
var cmd = JPackageCommand.helloAppImage(javaAppDesc)
|
||||||
|
// Disable default logic adding `--verbose` option
|
||||||
|
// to jpackage command line.
|
||||||
|
// It will affect jpackage error messages if the command line is malformed.
|
||||||
|
.ignoreDefaultVerbose(true)
|
||||||
|
// Ignore external runtime as it will interfer
|
||||||
|
// with jpackage arguments in this test.
|
||||||
|
.ignoreDefaultRuntime(true);
|
||||||
|
|
||||||
|
// Add arguments if requested.
|
||||||
|
Optional.ofNullable(jpackageArgs).ifPresent(cmd::addArguments);
|
||||||
|
|
||||||
|
// Remove arguments if requested.
|
||||||
|
Optional.ofNullable(removeArgs).map(List::of).ifPresent(
|
||||||
|
args -> args.forEach(cmd::removeArgumentWithValue));
|
||||||
|
|
||||||
|
// Configure jpackage output verifier to look up the list of provided
|
||||||
|
// errors in the order they specified.
|
||||||
|
cmd.validateOutput(Stream.of(expectedErrors)
|
||||||
|
.map(CannedFormattedString::getValue)
|
||||||
|
.map(TKit::assertTextStream)
|
||||||
|
.reduce(TKit.TextStreamVerifier::andThen).get());
|
||||||
|
|
||||||
|
cmd.execute(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user