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);
|
||||
verifyActions = new Actions(cmd.verifyActions);
|
||||
appLayoutAsserts = cmd.appLayoutAsserts;
|
||||
outputValidator = cmd.outputValidator;
|
||||
executeInDirectory = cmd.executeInDirectory;
|
||||
}
|
||||
|
||||
@ -739,6 +740,24 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
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() {
|
||||
return Optional.ofNullable(withToolProvider).orElse(
|
||||
defaultWithToolProvider);
|
||||
@ -817,6 +836,10 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
.createExecutor()
|
||||
.execute(expectedExitCode);
|
||||
|
||||
if (outputValidator != null) {
|
||||
outputValidator.accept(result.getOutput().stream());
|
||||
}
|
||||
|
||||
if (result.exitCode == 0) {
|
||||
executeVerifyActions();
|
||||
}
|
||||
@ -1187,6 +1210,7 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
private final Actions verifyActions;
|
||||
private Path executeInDirectory;
|
||||
private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values());
|
||||
private Consumer<Stream<String>> outputValidator;
|
||||
private static boolean defaultWithToolProvider;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
return orElseThrow(() -> v);
|
||||
}
|
||||
@ -956,9 +966,22 @@ public final class TKit {
|
||||
}
|
||||
|
||||
public void apply(Stream<String> lines) {
|
||||
String matchedStr = lines.filter(line -> predicate.test(line, value)).findFirst().orElse(
|
||||
null);
|
||||
String labelStr = Optional.ofNullable(label).orElse("output");
|
||||
final String matchedStr;
|
||||
|
||||
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) {
|
||||
String msg = String.format(
|
||||
"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 String label;
|
||||
private boolean negate;
|
||||
private Supplier<RuntimeException> createException;
|
||||
private Consumer<? super Stream<String>> anotherVerifier;
|
||||
private final String value;
|
||||
}
|
||||
|
||||
|
@ -24,9 +24,13 @@
|
||||
|
||||
import java.util.Collection;
|
||||
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.CannedFormattedString;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/*
|
||||
@ -53,81 +57,85 @@ import jdk.jpackage.test.TKit;
|
||||
|
||||
public final class ErrorTest {
|
||||
|
||||
private final String expectedError;
|
||||
private final JPackageCommand cmd;
|
||||
|
||||
@Parameters
|
||||
public static Collection input() {
|
||||
return List.of(new Object[][]{
|
||||
// non-existent arg
|
||||
{"Hello",
|
||||
new String[]{"--no-such-argument"},
|
||||
null,
|
||||
"Invalid Option: [--no-such-argument]"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidOption", "--no-such-argument")},
|
||||
// no main jar
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--main-jar"},
|
||||
"--main-jar or --module"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_NoEntryPoint")},
|
||||
// no main-class
|
||||
{"Hello",
|
||||
null,
|
||||
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
|
||||
{"Hello",
|
||||
new String[]{"--main-jar", "non-existent.jar"},
|
||||
null,
|
||||
"main jar does not exist"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("error.main-jar-does-not-exist", "non-existent.jar")},
|
||||
// non-existent runtime
|
||||
{"Hello",
|
||||
new String[]{"--runtime-image", "non-existent.runtime"},
|
||||
null,
|
||||
"does not exist"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("message.runtime-image-dir-does-not-exist", "runtime-image", "non-existent.runtime")},
|
||||
// non-existent resource-dir
|
||||
{"Hello",
|
||||
new String[]{"--resource-dir", "non-existent.dir"},
|
||||
null,
|
||||
"does not exist"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("message.resource-dir-does-not-exist", "resource-dir", "non-existent.dir")},
|
||||
// invalid type
|
||||
{"Hello",
|
||||
new String[]{"--type", "invalid-type"},
|
||||
null,
|
||||
"Invalid or unsupported type: [invalid-type]"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidInstallerType", "invalid-type")},
|
||||
// no --input
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--input"},
|
||||
"Missing argument: --input"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--input")},
|
||||
// no --module-path
|
||||
{"com.other/com.other.Hello",
|
||||
null,
|
||||
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
|
||||
public void test() {
|
||||
List<String> output = cmd.execute(1).getOutput();
|
||||
TKit.assertNotNull(output, "output is null");
|
||||
TKit.assertTextStream(expectedError).apply(output.stream());
|
||||
}
|
||||
@ParameterSupplier("input")
|
||||
public static void test(String javaAppDesc, String[] jpackageArgs,
|
||||
String[] removeArgs, CannedFormattedString... expectedErrors) {
|
||||
// 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…
Reference in New Issue
Block a user