mirror of
https://github.com/openjdk/jdk.git
synced 2026-01-28 12:09:14 +00:00
8351372: Improve negative tests coverage of jpackage
Reviewed-by: almatvee
This commit is contained in:
parent
3239919a5a
commit
3aa6d62afe
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -166,8 +166,7 @@ public class DeployParams {
|
||||
}
|
||||
} else {
|
||||
if (!hasInput && !hasAppImage) {
|
||||
throw new PackagerException(
|
||||
"ERR_MissingArgument", "--input");
|
||||
throw new PackagerException("error.no-input-parameter");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -57,9 +57,7 @@ final class DottedVersion {
|
||||
if (!greedy) {
|
||||
return null;
|
||||
} else {
|
||||
throw new IllegalArgumentException(MessageFormat.format(I18N.
|
||||
getString("error.version-string-zero-length-component"),
|
||||
version));
|
||||
ds.throwException();
|
||||
}
|
||||
}
|
||||
|
||||
@ -77,8 +75,7 @@ final class DottedVersion {
|
||||
}).takeWhile(Objects::nonNull).toArray(BigInteger[]::new);
|
||||
suffix = ds.getUnprocessedString();
|
||||
if (!suffix.isEmpty() && greedy) {
|
||||
throw new IllegalArgumentException(MessageFormat.format(I18N.getString(
|
||||
"error.version-string-invalid-component"), version, suffix));
|
||||
ds.throwException();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,7 +86,7 @@ final class DottedVersion {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public String getNextDigits() {
|
||||
String getNextDigits() {
|
||||
if (stoped) {
|
||||
return null;
|
||||
}
|
||||
@ -130,10 +127,29 @@ final class DottedVersion {
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getUnprocessedString() {
|
||||
String getUnprocessedString() {
|
||||
return input.substring(cursor);
|
||||
}
|
||||
|
||||
void throwException() {
|
||||
final String tail;
|
||||
if (lastDotPos >= 0) {
|
||||
tail = input.substring(lastDotPos + 1);
|
||||
} else {
|
||||
tail = getUnprocessedString();
|
||||
}
|
||||
|
||||
final String errMessage;
|
||||
if (tail.isEmpty()) {
|
||||
errMessage = MessageFormat.format(I18N.getString(
|
||||
"error.version-string-zero-length-component"), input);
|
||||
} else {
|
||||
errMessage = MessageFormat.format(I18N.getString(
|
||||
"error.version-string-invalid-component"), input, tail);
|
||||
}
|
||||
throw new IllegalArgumentException(errMessage);
|
||||
}
|
||||
|
||||
private int cursor;
|
||||
private int lastDotPos = -1;
|
||||
private boolean stoped;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020, 2023, 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
|
||||
@ -185,10 +185,6 @@ final class LauncherData {
|
||||
}
|
||||
|
||||
Path mainJarDir = StandardBundlerParam.SOURCE_DIR.fetchFrom(params);
|
||||
if (mainJarDir == null && launcherData.qualifiedClassName == null) {
|
||||
throw new ConfigException(I18N.getString("error.no-input-parameter"),
|
||||
null);
|
||||
}
|
||||
|
||||
final Path mainJarPath;
|
||||
if (launcherData.mainJarName != null && mainJarDir != null) {
|
||||
|
||||
@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 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. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* 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.internal.util;
|
||||
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class TokenReplace {
|
||||
|
||||
private record TokenCut(String[] main, String[] sub) {
|
||||
static String[] orderTokens(String... tokens) {
|
||||
if (tokens.length == 0) {
|
||||
throw new IllegalArgumentException("Empty token list");
|
||||
}
|
||||
|
||||
final var orderedTokens = Stream.of(tokens)
|
||||
.sorted(Comparator.<String>naturalOrder().thenComparing(Comparator.comparingInt(String::length)))
|
||||
.distinct()
|
||||
.toArray(String[]::new);
|
||||
|
||||
if (orderedTokens[0].isEmpty()) {
|
||||
throw new IllegalArgumentException("Empty token in the list of tokens");
|
||||
}
|
||||
|
||||
return orderedTokens;
|
||||
}
|
||||
|
||||
static TokenCut createFromOrderedTokens(String... tokens) {
|
||||
final List<Integer> subTokens = new ArrayList<>();
|
||||
|
||||
for (var i = 0; i < tokens.length - 1; ++i) {
|
||||
final var x = tokens[i];
|
||||
for (var j = i + 1; j < tokens.length; ++j) {
|
||||
final var y = tokens[j];
|
||||
if (y.contains(x)) {
|
||||
subTokens.add(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (subTokens.isEmpty()) {
|
||||
return new TokenCut(tokens, null);
|
||||
} else {
|
||||
final var main = IntStream.range(0, tokens.length)
|
||||
.mapToObj(Integer::valueOf)
|
||||
.filter(Predicate.not(subTokens::contains))
|
||||
.map(i -> {
|
||||
return tokens[i];
|
||||
}).toArray(String[]::new);
|
||||
final var sub = subTokens.stream().map(i -> {
|
||||
return tokens[i];
|
||||
}).toArray(String[]::new);
|
||||
return new TokenCut(main, sub);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("TokenCut(main=%s, sub=%s)", Arrays.toString(main), Arrays.toString(sub));
|
||||
}
|
||||
}
|
||||
|
||||
public TokenReplace(String... tokens) {
|
||||
tokens = TokenCut.orderTokens(tokens);
|
||||
|
||||
this.tokens = tokens;
|
||||
regexps = new ArrayList<>();
|
||||
|
||||
for(;;) {
|
||||
final var tokenCut = TokenCut.createFromOrderedTokens(tokens);
|
||||
regexps.add(Pattern.compile(Stream.of(tokenCut.main()).map(Pattern::quote).collect(joining("|", "(", ")"))));
|
||||
|
||||
if (tokenCut.sub() == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
tokens = tokenCut.sub();
|
||||
}
|
||||
}
|
||||
|
||||
public String applyTo(String str, Function<String, Object> tokenValueSupplier) {
|
||||
Objects.requireNonNull(str);
|
||||
Objects.requireNonNull(tokenValueSupplier);
|
||||
for (final var regexp : regexps) {
|
||||
str = regexp.matcher(str).replaceAll(mr -> {
|
||||
final var token = mr.group();
|
||||
return Matcher.quoteReplacement(Objects.requireNonNull(tokenValueSupplier.apply(token), () -> {
|
||||
return String.format("Null value for token [%s]", token);
|
||||
}).toString());
|
||||
});
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public String recursiveApplyTo(String str, Function<String, Object> tokenValueSupplier) {
|
||||
String newStr;
|
||||
int counter = tokens.length + 1;
|
||||
while (!(newStr = applyTo(str, tokenValueSupplier)).equals(str)) {
|
||||
str = newStr;
|
||||
if (counter-- == 0) {
|
||||
throw new IllegalStateException("Infinite recursion");
|
||||
}
|
||||
}
|
||||
return newStr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
// Auto generated code
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + Arrays.hashCode(tokens);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
// Auto generated code
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
TokenReplace other = (TokenReplace) obj;
|
||||
return Arrays.equals(tokens, other.tokens);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TokenReplace(" + String.join("|", tokens) + ")";
|
||||
}
|
||||
|
||||
public static TokenReplace combine(TokenReplace x, TokenReplace y) {
|
||||
return new TokenReplace(Stream.of(x.tokens, y.tokens).flatMap(Stream::of).toArray(String[]::new));
|
||||
}
|
||||
|
||||
public static Function<String, Object> createCachingTokenValueSupplier(Map<String, Supplier<Object>> tokenValueSuppliers) {
|
||||
Objects.requireNonNull(tokenValueSuppliers);
|
||||
final Map<String, Object> cache = new HashMap<>();
|
||||
return token -> {
|
||||
final var value = cache.computeIfAbsent(token, k -> {
|
||||
final var tokenValueSupplier = Objects.requireNonNull(tokenValueSuppliers.get(token), () -> {
|
||||
return String.format("No token value supplier for token [%s]", token);
|
||||
});
|
||||
return Optional.ofNullable(tokenValueSupplier.get()).orElse(NULL_SUPPLIED);
|
||||
});
|
||||
|
||||
if (value == NULL_SUPPLIED) {
|
||||
throw new NullPointerException(String.format("Null value for token [%s]", token));
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
}
|
||||
|
||||
private final String[] tokens;
|
||||
private final transient List<Pattern> regexps;
|
||||
private final static Object NULL_SUPPLIED = new Object();
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2011, 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
|
||||
@ -25,15 +25,16 @@
|
||||
|
||||
package jdk.jpackage.main;
|
||||
|
||||
import jdk.internal.opt.CommandLine;
|
||||
import jdk.jpackage.internal.Arguments;
|
||||
import jdk.jpackage.internal.Log;
|
||||
import jdk.jpackage.internal.CLIHelp;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ResourceBundle;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ResourceBundle;
|
||||
import jdk.internal.opt.CommandLine;
|
||||
import jdk.jpackage.internal.Arguments;
|
||||
import jdk.jpackage.internal.CLIHelp;
|
||||
import jdk.jpackage.internal.Log;
|
||||
|
||||
public class Main {
|
||||
|
||||
@ -69,7 +70,7 @@ public class Main {
|
||||
String[] newArgs;
|
||||
try {
|
||||
newArgs = CommandLine.parse(args);
|
||||
} catch (FileNotFoundException fnfe) {
|
||||
} catch (FileNotFoundException|NoSuchFileException fnfe) {
|
||||
Log.fatalError(MessageFormat.format(I18N.getString(
|
||||
"ERR_CannotParseOptions"), fnfe.getMessage()));
|
||||
return 1;
|
||||
|
||||
@ -97,12 +97,12 @@ public class PackageTestTest extends JUnitAdapter {
|
||||
private final int tickCount;
|
||||
}
|
||||
|
||||
private final static int ERROR_EXIT_CODE_JPACKAGE = 35;
|
||||
private final static int ERROR_EXIT_CODE_INSTALL = 27;
|
||||
private static final int ERROR_EXIT_CODE_JPACKAGE = 35;
|
||||
private static final int ERROR_EXIT_CODE_INSTALL = 27;
|
||||
|
||||
private final static CallbackFactory NEVER = new CallbackFactory(0);
|
||||
private final static CallbackFactory ONCE = new CallbackFactory(1);
|
||||
private final static CallbackFactory TWICE = new CallbackFactory(2);
|
||||
private static final CallbackFactory NEVER = new CallbackFactory(0);
|
||||
private static final CallbackFactory ONCE = new CallbackFactory(1);
|
||||
private static final CallbackFactory TWICE = new CallbackFactory(2);
|
||||
|
||||
enum BundleVerifier {
|
||||
ONCE_SUCCESS(ONCE),
|
||||
@ -238,7 +238,7 @@ public class PackageTestTest extends JUnitAdapter {
|
||||
private final int expectedJPackageExitCode;
|
||||
}
|
||||
|
||||
private final static class CountingInstaller extends TickCounter implements Function<JPackageCommand, Integer> {
|
||||
private static final class CountingInstaller extends TickCounter implements Function<JPackageCommand, Integer> {
|
||||
|
||||
@Override
|
||||
public Integer apply(JPackageCommand cmd) {
|
||||
@ -376,7 +376,7 @@ public class PackageTestTest extends JUnitAdapter {
|
||||
};
|
||||
}).setExpectedExitCode(expectedJPackageExitCode)
|
||||
.setExpectedInstallExitCode(handlersSpec.installExitCode)
|
||||
.isPackageTypeSupported(type -> true)
|
||||
.isPackageTypeEnabled(type -> true)
|
||||
.forTypes().packageHandlers(handlers);
|
||||
}
|
||||
|
||||
@ -439,7 +439,7 @@ public class PackageTestTest extends JUnitAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
private final static class TestSpecBuilder {
|
||||
private static final class TestSpecBuilder {
|
||||
|
||||
TestSpecBuilder type(PackageType v) {
|
||||
type = Objects.requireNonNull(v);
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 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
|
||||
@ -22,20 +22,60 @@
|
||||
*/
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class CannedFormattedString {
|
||||
public record CannedFormattedString(BiFunction<String, Object[], String> formatter, String key, Object[] args) {
|
||||
|
||||
CannedFormattedString(BiFunction<String, Object[], String> formatter,
|
||||
String key, Object[] args) {
|
||||
this.formatter = formatter;
|
||||
this.key = key;
|
||||
this.args = args;
|
||||
@FunctionalInterface
|
||||
public interface CannedArgument {
|
||||
public String value();
|
||||
}
|
||||
|
||||
public static Object cannedArgument(Supplier<Object> supplier, String label) {
|
||||
Objects.requireNonNull(supplier);
|
||||
Objects.requireNonNull(label);
|
||||
return new CannedArgument() {
|
||||
|
||||
@Override
|
||||
public String value() {
|
||||
return supplier.get().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
return label;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static Object cannedAbsolutePath(Path v) {
|
||||
return cannedArgument(() -> v.toAbsolutePath(), String.format("AbsolutePath(%s)", v));
|
||||
}
|
||||
|
||||
public static Object cannedAbsolutePath(String v) {
|
||||
return cannedAbsolutePath(Path.of(v));
|
||||
}
|
||||
|
||||
public CannedFormattedString {
|
||||
Objects.requireNonNull(formatter);
|
||||
Objects.requireNonNull(key);
|
||||
Objects.requireNonNull(args);
|
||||
List.of(args).forEach(Objects::requireNonNull);
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return formatter.apply(key, args);
|
||||
return formatter.apply(key, Stream.of(args).map(arg -> {
|
||||
if (arg instanceof CannedArgument cannedArg) {
|
||||
return cannedArg.value();
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
}).toArray());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -46,8 +86,4 @@ public final class CannedFormattedString {
|
||||
return String.format("%s+%s", key, List.of(args));
|
||||
}
|
||||
}
|
||||
|
||||
private final BiFunction<String, Object[], String> formatter;
|
||||
private final String key;
|
||||
private final Object[] args;
|
||||
}
|
||||
|
||||
@ -33,8 +33,10 @@ import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
@ -92,6 +94,13 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
|
||||
public Executor removeEnvVar(String envVarName) {
|
||||
removeEnvVars.add(Objects.requireNonNull(envVarName));
|
||||
setEnvVars.remove(envVarName);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Executor setEnvVar(String envVarName, String envVarValue) {
|
||||
setEnvVars.put(Objects.requireNonNull(envVarName), Objects.requireNonNull(envVarValue));
|
||||
removeEnvVars.remove(envVarName);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -370,11 +379,27 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
builder.directory(directory.toFile());
|
||||
sb.append(String.format("; in directory [%s]", directory));
|
||||
}
|
||||
if (!removeEnvVars.isEmpty()) {
|
||||
final var envComm = Comm.compare(builder.environment().keySet(), removeEnvVars);
|
||||
builder.environment().keySet().removeAll(envComm.common());
|
||||
if (!setEnvVars.isEmpty()) {
|
||||
final var defaultEnv = builder.environment();
|
||||
final var envComm = Comm.compare(defaultEnv.keySet(), setEnvVars.keySet());
|
||||
envComm.unique2().forEach(envVar -> {
|
||||
trace(String.format("Adding %s=[%s] to environment", envVar, setEnvVars.get(envVar)));
|
||||
});
|
||||
envComm.common().forEach(envVar -> {
|
||||
TKit.trace(String.format("Clearing %s in environment", envVar));
|
||||
final var curValue = defaultEnv.get(envVar);
|
||||
final var newValue = setEnvVars.get(envVar);
|
||||
if (!curValue.equals(newValue)) {
|
||||
trace(String.format("Setting %s=[%s] in environment", envVar, setEnvVars.get(envVar)));
|
||||
}
|
||||
});
|
||||
defaultEnv.putAll(setEnvVars);
|
||||
}
|
||||
if (!removeEnvVars.isEmpty()) {
|
||||
final var defaultEnv = builder.environment().keySet();
|
||||
final var envComm = Comm.compare(defaultEnv, removeEnvVars);
|
||||
defaultEnv.removeAll(envComm.common());
|
||||
envComm.common().forEach(envVar -> {
|
||||
trace(String.format("Clearing %s in environment", envVar));
|
||||
});
|
||||
}
|
||||
|
||||
@ -515,6 +540,7 @@ public final class Executor extends CommandArguments<Executor> {
|
||||
private Set<SaveOutputType> saveOutputType;
|
||||
private Path directory;
|
||||
private Set<String> removeEnvVars = new HashSet<>();
|
||||
private Map<String, String> setEnvVars = new HashMap<>();
|
||||
private boolean winEnglishOutput;
|
||||
private String winTmpDir = null;
|
||||
|
||||
|
||||
@ -31,6 +31,7 @@ import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Predicate;
|
||||
@ -350,6 +351,7 @@ public final class HelloApp {
|
||||
this.launcherPath = helloAppLauncher;
|
||||
this.outputFilePath = TKit.workDir().resolve(OUTPUT_FILENAME);
|
||||
this.params = new HashMap<>();
|
||||
this.env = new HashMap<>();
|
||||
this.defaultLauncherArgs = new ArrayList<>();
|
||||
}
|
||||
|
||||
@ -363,6 +365,16 @@ public final class HelloApp {
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppOutputVerifier addEnvironment(Map<String, String> v) {
|
||||
env.putAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppOutputVerifier addEnvironmentVar(String name, String value) {
|
||||
env.put(Objects.requireNonNull(name), Objects.requireNonNull(name));
|
||||
return this;
|
||||
}
|
||||
|
||||
public AppOutputVerifier addDefaultArguments(String... v) {
|
||||
return addDefaultArguments(List.of(v));
|
||||
}
|
||||
@ -466,6 +478,10 @@ public final class HelloApp {
|
||||
.setExecutable(executablePath)
|
||||
.addArguments(List.of(args));
|
||||
|
||||
env.forEach((envVarName, envVarValue) -> {
|
||||
executor.setEnvVar(envVarName, envVarValue);
|
||||
});
|
||||
|
||||
return configureEnvironment(executor);
|
||||
}
|
||||
|
||||
@ -476,6 +492,7 @@ public final class HelloApp {
|
||||
private int expectedExitCode;
|
||||
private final List<String> defaultLauncherArgs;
|
||||
private final Map<String, String> params;
|
||||
private final Map<String, String> env;
|
||||
}
|
||||
|
||||
public static AppOutputVerifier assertApp(Path helloAppLauncher) {
|
||||
|
||||
@ -76,7 +76,7 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
prerequisiteActions = new Actions(cmd.prerequisiteActions);
|
||||
verifyActions = new Actions(cmd.verifyActions);
|
||||
appLayoutAsserts = cmd.appLayoutAsserts;
|
||||
outputValidator = cmd.outputValidator;
|
||||
outputValidators = cmd.outputValidators;
|
||||
executeInDirectory = cmd.executeInDirectory;
|
||||
winMsiLogFile = cmd.winMsiLogFile;
|
||||
}
|
||||
@ -218,26 +218,27 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public String name() {
|
||||
String appImage = getArgumentValue("--app-image");
|
||||
if (appImage != null) {
|
||||
String name = AppImageFile.load(Path.of(appImage)).mainLauncherName();
|
||||
// can be null if using foreign app-image
|
||||
return ((name != null) ? name : getArgumentValue("--name"));
|
||||
}
|
||||
return getArgumentValue("--name", () -> getArgumentValue("--main-class"));
|
||||
return nameFromAppImage().or(this::nameFromBasicArgs).or(this::nameFromRuntimeImage).orElseThrow();
|
||||
}
|
||||
|
||||
public String installerName() {
|
||||
verifyIsOfType(PackageType.NATIVE);
|
||||
String installerName = getArgumentValue("--name",
|
||||
() -> getArgumentValue("--main-class", () -> null));
|
||||
if (installerName == null) {
|
||||
String appImage = getArgumentValue("--app-image");
|
||||
if (appImage != null) {
|
||||
installerName = AppImageFile.load(Path.of(appImage)).mainLauncherName();
|
||||
}
|
||||
}
|
||||
return installerName;
|
||||
return nameFromBasicArgs().or(this::nameFromAppImage).or(this::nameFromRuntimeImage).orElseThrow();
|
||||
}
|
||||
|
||||
private Optional<String> nameFromAppImage() {
|
||||
return Optional.ofNullable(getArgumentValue("--app-image"))
|
||||
.map(Path::of).map(AppImageFile::load).map(AppImageFile::mainLauncherName);
|
||||
}
|
||||
|
||||
private Optional<String> nameFromRuntimeImage() {
|
||||
return Optional.ofNullable(getArgumentValue("--runtime-image"))
|
||||
.map(Path::of).map(Path::getFileName).map(Path::toString);
|
||||
}
|
||||
|
||||
private Optional<String> nameFromBasicArgs() {
|
||||
return Optional.ofNullable(getArgumentValue("--name")).or(
|
||||
() -> Optional.ofNullable(getArgumentValue("--main-class")));
|
||||
}
|
||||
|
||||
public boolean isRuntime() {
|
||||
@ -273,7 +274,7 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
};
|
||||
|
||||
addPrerequisiteAction(cmd -> {
|
||||
Path fakeRuntimeDir = TKit.workDir().resolve("fake_runtime");
|
||||
Path fakeRuntimeDir = TKit.createTempDirectory("fake_runtime");
|
||||
|
||||
TKit.trace(String.format("Init fake runtime in [%s] directory",
|
||||
fakeRuntimeDir));
|
||||
@ -703,21 +704,53 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
}
|
||||
|
||||
public JPackageCommand validateOutput(TKit.TextStreamVerifier validator) {
|
||||
return JPackageCommand.this.validateOutput(validator::apply);
|
||||
return validateOutput(validator::apply);
|
||||
}
|
||||
|
||||
public JPackageCommand validateOutput(Consumer<Stream<String>> validator) {
|
||||
if (validator != null) {
|
||||
saveConsoleOutput(true);
|
||||
outputValidator = validator;
|
||||
} else {
|
||||
outputValidator = null;
|
||||
}
|
||||
Objects.requireNonNull(validator);
|
||||
saveConsoleOutput(true);
|
||||
outputValidators.add(validator);
|
||||
return this;
|
||||
}
|
||||
|
||||
public JPackageCommand validateOutput(CannedFormattedString str) {
|
||||
return JPackageCommand.this.validateOutput(TKit.assertTextStream(str.getValue()));
|
||||
@FunctionalInterface
|
||||
public interface CannedArgument {
|
||||
public String value(JPackageCommand cmd);
|
||||
}
|
||||
|
||||
public static Object cannedArgument(Function<JPackageCommand, Object> supplier, String label) {
|
||||
Objects.requireNonNull(supplier);
|
||||
Objects.requireNonNull(label);
|
||||
return new CannedArgument() {
|
||||
@Override
|
||||
public String value(JPackageCommand cmd) {
|
||||
return supplier.apply(cmd).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString( ) {
|
||||
return label;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getValue(CannedFormattedString str) {
|
||||
return new CannedFormattedString(str.formatter(), str.key(), Stream.of(str.args()).map(arg -> {
|
||||
if (arg instanceof CannedArgument cannedArg) {
|
||||
return cannedArg.value(this);
|
||||
} else {
|
||||
return arg;
|
||||
}
|
||||
}).toArray()).getValue();
|
||||
}
|
||||
|
||||
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)
|
||||
.map(TKit::assertTextStream)
|
||||
.reduce(TKit.TextStreamVerifier::andThen).get());
|
||||
}
|
||||
|
||||
public boolean isWithToolProvider() {
|
||||
@ -798,7 +831,7 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
.createExecutor()
|
||||
.execute(expectedExitCode);
|
||||
|
||||
if (outputValidator != null) {
|
||||
for (final var outputValidator: outputValidators) {
|
||||
outputValidator.accept(result.getOutput().stream());
|
||||
}
|
||||
|
||||
@ -876,6 +909,9 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
copy.immutable = false;
|
||||
copy.removeArgumentWithValue("--runtime-image");
|
||||
copy.dmgInstallDir = cmd.appInstallationDirectory();
|
||||
if (!copy.hasArgument("--name")) {
|
||||
copy.addArguments("--name", cmd.nameFromRuntimeImage().orElseThrow());
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -1022,7 +1058,7 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
// to allow the jlink process to print exception stacktraces on any failure
|
||||
addArgument("-J-Djlink.debug=true");
|
||||
}
|
||||
if (!hasArgument("--runtime-image") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) {
|
||||
if (!hasArgument("--runtime-image") && !hasArgument("--jlink-options") && !hasArgument("--app-image") && DEFAULT_RUNTIME_IMAGE != null && !ignoreDefaultRuntime) {
|
||||
addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE);
|
||||
}
|
||||
|
||||
@ -1195,14 +1231,14 @@ public class JPackageCommand extends CommandArguments<JPackageCommand> {
|
||||
private Path executeInDirectory;
|
||||
private Path winMsiLogFile;
|
||||
private Set<AppLayoutAssert> appLayoutAsserts = Set.of(AppLayoutAssert.values());
|
||||
private Consumer<Stream<String>> outputValidator;
|
||||
private List<Consumer<Stream<String>>> outputValidators = new ArrayList<>();
|
||||
private static boolean defaultWithToolProvider;
|
||||
|
||||
private static final Map<String, PackageType> PACKAGE_TYPES = Functional.identity(
|
||||
() -> {
|
||||
Map<String, PackageType> reply = new HashMap<>();
|
||||
for (PackageType type : PackageType.values()) {
|
||||
reply.put(type.getName(), type);
|
||||
reply.put(type.getType(), type);
|
||||
}
|
||||
return reply;
|
||||
}).get();
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2024, 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
|
||||
@ -64,7 +64,7 @@ public enum JPackageStringBundle {
|
||||
}
|
||||
}
|
||||
|
||||
public CannedFormattedString cannedFormattedString(String key, String ... args) {
|
||||
public CannedFormattedString cannedFormattedString(String key, Object ... args) {
|
||||
return new CannedFormattedString(this::getFormattedString, key, args);
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -23,6 +23,10 @@
|
||||
|
||||
package jdk.jpackage.test;
|
||||
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static jdk.jpackage.test.TestBuilder.CMDLINE_ARG_PREFIX;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayDeque;
|
||||
@ -32,9 +36,7 @@ import java.util.Deque;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
import static java.util.stream.Collectors.toCollection;
|
||||
import java.util.stream.Stream;
|
||||
import static jdk.jpackage.test.TestBuilder.CMDLINE_ARG_PREFIX;
|
||||
|
||||
|
||||
public final class Main {
|
||||
@ -88,9 +90,7 @@ public final class Main {
|
||||
TKit.unbox(throwable);
|
||||
} finally {
|
||||
if (!success) {
|
||||
TKit.log(
|
||||
String.format("Error processing parameter=[%s]",
|
||||
arg));
|
||||
TKit.log(String.format("Error processing parameter=[%s]", arg));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -104,6 +104,13 @@ public final class Main {
|
||||
// Just list the tests
|
||||
orderedTests.forEach(test -> System.out.println(String.format(
|
||||
"%s; workDir=[%s]", test.fullName(), test.workDir())));
|
||||
}
|
||||
|
||||
orderedTests.stream().collect(toMap(TestInstance::fullName, x -> x, (x, y) -> {
|
||||
throw new IllegalArgumentException(String.format("Multiple tests with the same description: [%s]", x.fullName()));
|
||||
}));
|
||||
|
||||
if (listTests) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -71,7 +71,7 @@ import jdk.jpackage.internal.util.function.ThrowingRunnable;
|
||||
public final class PackageTest extends RunnablePackageTest {
|
||||
|
||||
public PackageTest() {
|
||||
isPackageTypeSupported = PackageType::isSupported;
|
||||
isPackageTypeEnabled = PackageType::isEnabled;
|
||||
jpackageFactory = JPackageCommand::new;
|
||||
packageHandlers = new HashMap<>();
|
||||
disabledInstallers = new HashSet<>();
|
||||
@ -102,7 +102,7 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
newTypes = Stream.of(types).collect(Collectors.toSet());
|
||||
}
|
||||
currentTypes = newTypes.stream()
|
||||
.filter(isPackageTypeSupported)
|
||||
.filter(isPackageTypeEnabled)
|
||||
.filter(Predicate.not(excludeTypes::contains))
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
return this;
|
||||
@ -394,9 +394,9 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
PackageTest isPackageTypeSupported(Predicate<PackageType> v) {
|
||||
PackageTest isPackageTypeEnabled(Predicate<PackageType> v) {
|
||||
Objects.requireNonNull(v);
|
||||
isPackageTypeSupported = v;
|
||||
isPackageTypeEnabled = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -505,7 +505,7 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
case UNPACK -> {
|
||||
cmd.setUnpackedPackageLocation(null);
|
||||
final var unpackRootDir = TKit.createTempDirectory(
|
||||
String.format("unpacked-%s", type.getName()));
|
||||
String.format("unpacked-%s", type.getType()));
|
||||
final Path unpackDir = packageHandlers.unpack(cmd, unpackRootDir);
|
||||
if (!unpackDir.startsWith(TKit.workDir())) {
|
||||
state.deleteUnpackDirs.add(unpackDir);
|
||||
@ -618,7 +618,7 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
return processed(Action.UNPACK) && packageHandlers.unpackHandler().isEmpty();
|
||||
}
|
||||
|
||||
private final static class State {
|
||||
private static final class State {
|
||||
private final Set<Action> packageActions = new HashSet<>();
|
||||
private final List<Path> deleteUnpackDirs = new ArrayList<>();
|
||||
}
|
||||
@ -918,7 +918,7 @@ public final class PackageTest extends RunnablePackageTest {
|
||||
private final Map<PackageType, PackageHandlers> packageHandlers;
|
||||
private final Set<PackageType> disabledInstallers;
|
||||
private final Set<PackageType> disabledUninstallers;
|
||||
private Predicate<PackageType> isPackageTypeSupported;
|
||||
private Predicate<PackageType> isPackageTypeEnabled;
|
||||
private Supplier<JPackageCommand> jpackageFactory;
|
||||
private boolean ignoreBundleOutputDir;
|
||||
private boolean createMsiLog;
|
||||
|
||||
@ -26,6 +26,7 @@ import java.io.PrintWriter;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -48,19 +49,23 @@ public enum PackageType {
|
||||
TKit.isLinux() ? "jdk.jpackage.internal.LinuxRpmBundler" : null),
|
||||
MAC_DMG(".dmg", TKit.isOSX() ? "jdk.jpackage.internal.MacDmgBundler" : null),
|
||||
MAC_PKG(".pkg", TKit.isOSX() ? "jdk.jpackage.internal.MacPkgBundler" : null),
|
||||
IMAGE("app-image", null, null);
|
||||
IMAGE;
|
||||
|
||||
PackageType() {
|
||||
type = "app-image";
|
||||
suffix = null;
|
||||
supported = true;
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
PackageType(String packageName, String bundleSuffix, String bundlerClass) {
|
||||
name = packageName;
|
||||
suffix = bundleSuffix;
|
||||
if (bundlerClass != null && !Inner.DISABLED_PACKAGERS.contains(getName())) {
|
||||
supported = isBundlerSupported(bundlerClass);
|
||||
} else {
|
||||
supported = false;
|
||||
}
|
||||
type = Objects.requireNonNull(packageName);
|
||||
suffix = Objects.requireNonNull(bundleSuffix);
|
||||
supported = Optional.ofNullable(bundlerClass).map(PackageType::isBundlerSupported).orElse(false);
|
||||
enabled = supported && !Inner.DISABLED_PACKAGERS.contains(getType());
|
||||
|
||||
if (suffix != null && supported) {
|
||||
TKit.trace(String.format("Bundler %s supported", getName()));
|
||||
if (suffix != null && enabled) {
|
||||
TKit.trace(String.format("Bundler %s enabled", getType()));
|
||||
}
|
||||
}
|
||||
|
||||
@ -69,30 +74,23 @@ public enum PackageType {
|
||||
}
|
||||
|
||||
void applyTo(JPackageCommand cmd) {
|
||||
cmd.setArgumentValue("--type", getName());
|
||||
cmd.setArgumentValue("--type", getType());
|
||||
}
|
||||
|
||||
String getSuffix() {
|
||||
return suffix;
|
||||
return Optional.ofNullable(suffix).orElseThrow(UnsupportedOperationException::new);
|
||||
}
|
||||
|
||||
boolean isSupported() {
|
||||
public boolean isSupported() {
|
||||
return supported;
|
||||
}
|
||||
|
||||
String getName() {
|
||||
return name;
|
||||
public boolean isEnabled() {
|
||||
return supported;
|
||||
}
|
||||
|
||||
static PackageType fromSuffix(String packageFilename) {
|
||||
if (packageFilename != null) {
|
||||
for (PackageType v : values()) {
|
||||
if (packageFilename.endsWith(v.getSuffix())) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
private static boolean isBundlerSupportedImpl(String bundlerClass) {
|
||||
@ -133,8 +131,9 @@ public enum PackageType {
|
||||
return reply.get();
|
||||
}
|
||||
|
||||
private final String name;
|
||||
private final String type;
|
||||
private final String suffix;
|
||||
private final boolean enabled;
|
||||
private final boolean supported;
|
||||
|
||||
public static final Set<PackageType> LINUX = Set.of(LINUX_DEB, LINUX_RPM);
|
||||
|
||||
@ -31,6 +31,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@ -119,12 +120,24 @@ final class TestInstance implements ThrowingRunnable {
|
||||
return String.format("%s(length=%d)", asString, Array.getLength(v));
|
||||
}
|
||||
return String.format("%s", v);
|
||||
}).collect(Collectors.joining(", "));
|
||||
}).collect(Collectors.joining(", ")).transform(str -> {
|
||||
final var sb = new StringBuilder();
|
||||
for (var chr : str.toCharArray()) {
|
||||
if (chr != ' ' && (Character.isWhitespace(chr) || Character.isISOControl(chr))) {
|
||||
sb.append("\\u").append(ARGS_CHAR_FORMATTER.toHexDigits(chr));
|
||||
} else {
|
||||
sb.append(chr);
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
});
|
||||
}
|
||||
|
||||
private List<Object> ctorArgs;
|
||||
private List<Object> methodArgs;
|
||||
private Method method;
|
||||
|
||||
private static final HexFormat ARGS_CHAR_FORMATTER = HexFormat.of().withUpperCase();
|
||||
}
|
||||
|
||||
static TestDesc create(Method m, Object... args) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -107,7 +107,7 @@ public class WindowsHelper {
|
||||
final Optional<Path> msiLogFile;
|
||||
if (createMsiLog) {
|
||||
msiLogFile = Optional.of(TKit.createTempFile(String.format("logs\\%s-msi.log",
|
||||
cmd.packageType().getName())));
|
||||
cmd.packageType().getType())));
|
||||
} else {
|
||||
msiLogFile = Optional.empty();
|
||||
}
|
||||
@ -175,13 +175,19 @@ public class WindowsHelper {
|
||||
Path installationSubDirectory = getInstallationSubDirectory(cmd);
|
||||
Path from = Path.of(extraPathComponent).resolve(installationSubDirectory);
|
||||
Path to = installationSubDirectory;
|
||||
TKit.trace(String.format("Convert [%s] into [%s] in [%s] directory", from, to,
|
||||
unpackDir));
|
||||
|
||||
ThrowingRunnable.toRunnable(() -> {
|
||||
Files.createDirectories(unpackDir.resolve(to).getParent());
|
||||
Files.move(unpackDir.resolve(from), unpackDir.resolve(to));
|
||||
TKit.deleteDirectoryRecursive(unpackDir.resolve(extraPathComponent));
|
||||
}).run();
|
||||
|
||||
// Files.move() occasionally results into java.nio.file.AccessDeniedException
|
||||
Executor.tryRunMultipleTimes(ThrowingRunnable.toRunnable(() -> {
|
||||
TKit.trace(String.format("Convert [%s] into [%s] in [%s] directory", from, to, unpackDir));
|
||||
final var dstDir = unpackDir.resolve(to);
|
||||
TKit.deleteDirectoryRecursive(dstDir);
|
||||
Files.move(unpackDir.resolve(from), dstDir);
|
||||
TKit.deleteDirectoryRecursive(unpackDir.resolve(extraPathComponent));
|
||||
}), 3, 5);
|
||||
}
|
||||
}
|
||||
return destinationDir;
|
||||
@ -656,7 +662,7 @@ public class WindowsHelper {
|
||||
private final RegValuePath reg;
|
||||
private final Optional<SpecialFolderDotNet> alt;
|
||||
|
||||
private final static Map<SpecialFolder, Path> CACHE = new ConcurrentHashMap<>();
|
||||
private static final Map<SpecialFolder, Path> CACHE = new ConcurrentHashMap<>();
|
||||
}
|
||||
|
||||
private static final class ShortPathUtils {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -22,8 +22,10 @@
|
||||
*/
|
||||
package jdk.jpackage.internal;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
@ -112,28 +114,57 @@ public class DottedVersionTest {
|
||||
return data;
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
public void testInvalid(String str) {
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> new DottedVersion(str));
|
||||
record InvalidVersionTestSpec(String version, String invalidComponent) {
|
||||
public InvalidVersionTestSpec {
|
||||
Objects.requireNonNull(version);
|
||||
Objects.requireNonNull(invalidComponent);
|
||||
}
|
||||
|
||||
InvalidVersionTestSpec(String version) {
|
||||
this(version, "");
|
||||
}
|
||||
|
||||
void run() {
|
||||
final String expectedErrorMsg;
|
||||
if (invalidComponent.isEmpty()) {
|
||||
expectedErrorMsg = MessageFormat.format(I18N.getString("error.version-string-zero-length-component"), version);
|
||||
} else {
|
||||
expectedErrorMsg = MessageFormat.format(I18N.getString("error.version-string-invalid-component"), version, invalidComponent);
|
||||
}
|
||||
|
||||
final var ex = assertThrowsExactly(IllegalArgumentException.class, () -> new DottedVersion(version));
|
||||
|
||||
assertEquals(expectedErrorMsg, ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private static Stream<String> testInvalid() {
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
public void testInvalid(InvalidVersionTestSpec testSpec) {
|
||||
testSpec.run();
|
||||
}
|
||||
|
||||
private static Stream<InvalidVersionTestSpec> testInvalid() {
|
||||
return Stream.of(
|
||||
"1.-1",
|
||||
"5.",
|
||||
"4.2.",
|
||||
"3..2",
|
||||
"2.a",
|
||||
"0a",
|
||||
".",
|
||||
" ",
|
||||
" 1",
|
||||
"1. 2",
|
||||
"+1",
|
||||
"-1",
|
||||
"-0",
|
||||
"+0"
|
||||
new InvalidVersionTestSpec("1.-1", "-1"),
|
||||
new InvalidVersionTestSpec("5."),
|
||||
new InvalidVersionTestSpec("4.2."),
|
||||
new InvalidVersionTestSpec("3..2", ".2"),
|
||||
new InvalidVersionTestSpec("3...2", "..2"),
|
||||
new InvalidVersionTestSpec("2.a", "a"),
|
||||
new InvalidVersionTestSpec("0a", "a"),
|
||||
new InvalidVersionTestSpec("1.0a", "0a"),
|
||||
new InvalidVersionTestSpec(".", "."),
|
||||
new InvalidVersionTestSpec("..", ".."),
|
||||
new InvalidVersionTestSpec(".a.b", ".a.b"),
|
||||
new InvalidVersionTestSpec(".1.2", ".1.2"),
|
||||
new InvalidVersionTestSpec(" ", " "),
|
||||
new InvalidVersionTestSpec(" 1", " 1"),
|
||||
new InvalidVersionTestSpec("1. 2", " 2"),
|
||||
new InvalidVersionTestSpec("+1", "+1"),
|
||||
new InvalidVersionTestSpec("-1", "-1"),
|
||||
new InvalidVersionTestSpec("-0", "-0"),
|
||||
new InvalidVersionTestSpec("+0", "+0")
|
||||
);
|
||||
}
|
||||
|
||||
@ -145,7 +176,8 @@ public class DottedVersionTest {
|
||||
|
||||
@Test
|
||||
public void testEmptyGreedy() {
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> DottedVersion.greedy(""), "Version may not be empty string");
|
||||
final var ex = assertThrowsExactly(IllegalArgumentException.class, () -> DottedVersion.greedy(""));
|
||||
assertEquals(I18N.getString("error.version-string-empty"), ex.getMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -0,0 +1,290 @@
|
||||
/*
|
||||
* Copyright (c) 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.
|
||||
*/
|
||||
|
||||
package jdk.jpackage.internal.util;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Stream;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
public class TokenReplaceTest {
|
||||
|
||||
public record TestSpec(String str, Optional<String> expectedStr, Optional<Exception> expectedCtorException,
|
||||
Optional<Exception> expectedApplyToException, Map<String, String> tokenWithValues, boolean recursive) {
|
||||
|
||||
public TestSpec {
|
||||
Objects.requireNonNull(expectedStr);
|
||||
Objects.requireNonNull(expectedCtorException);
|
||||
Objects.requireNonNull(expectedApplyToException);
|
||||
Objects.requireNonNull(tokenWithValues);
|
||||
tokenWithValues.values().forEach(Objects::requireNonNull);
|
||||
|
||||
if (expectedStr.isPresent()) {
|
||||
if (!(expectedCtorException.isEmpty() && expectedApplyToException.isEmpty())) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
} else if (expectedCtorException.isEmpty() == expectedApplyToException.isEmpty()) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
|
||||
static final class Builder {
|
||||
|
||||
Builder str(String v) {
|
||||
str = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder recursive(boolean v) {
|
||||
recursive = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder recursive() {
|
||||
return recursive(true);
|
||||
}
|
||||
|
||||
Builder expect(String v) {
|
||||
expectedStr = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder expectCtorThrow(String v) {
|
||||
expectedCtorException = new IllegalArgumentException(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder expectApplyToNPE() {
|
||||
expectedApplyToException = new NullPointerException();
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder expectInfiniteRecursion() {
|
||||
expectedApplyToException = new IllegalStateException("Infinite recursion");
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder token(String token, String value) {
|
||||
tokenWithValues.put(token, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
TestSpec create() {
|
||||
return new TestSpec(str, expectedStr(), Optional.ofNullable(expectedCtorException),
|
||||
Optional.ofNullable(expectedApplyToException), tokenWithValues, recursive);
|
||||
}
|
||||
|
||||
private Optional<String> expectedStr() {
|
||||
if (expectedCtorException == null && expectedApplyToException == null) {
|
||||
return Optional.ofNullable(expectedStr).or(() -> Optional.of(str));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean recursive;
|
||||
private String str;
|
||||
private String expectedStr;
|
||||
private Exception expectedCtorException;
|
||||
private Exception expectedApplyToException;
|
||||
private final Map<String, String> tokenWithValues = new HashMap<>();
|
||||
}
|
||||
|
||||
void test() {
|
||||
final var tokens = tokenWithValues.keySet().toArray(String[]::new);
|
||||
expectedStr.ifPresent(expected -> {
|
||||
final var tokenReplace = new TokenReplace(tokens);
|
||||
final String actual;
|
||||
if (recursive) {
|
||||
actual = tokenReplace.recursiveApplyTo(str, tokenWithValues::get);
|
||||
} else {
|
||||
actual = tokenReplace.applyTo(str, tokenWithValues::get);
|
||||
}
|
||||
assertEquals(expected, actual);
|
||||
});
|
||||
|
||||
expectedCtorException.ifPresent(expected -> {
|
||||
final var ex = assertThrows(expected.getClass(), () -> {
|
||||
new TokenReplace(tokens);
|
||||
});
|
||||
assertEquals(expected.getMessage(), ex.getMessage());
|
||||
});
|
||||
|
||||
expectedApplyToException.ifPresent(expected -> {
|
||||
final var tokenReplace = new TokenReplace(tokens);
|
||||
final var ex = assertThrows(expected.getClass(), () -> {
|
||||
if (recursive) {
|
||||
tokenReplace.recursiveApplyTo(str, tokenWithValues::get);
|
||||
} else {
|
||||
tokenReplace.applyTo(str, tokenWithValues::get);
|
||||
}
|
||||
});
|
||||
assertEquals(expected.getMessage(), ex.getMessage());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource
|
||||
public void test(TestSpec spec) {
|
||||
spec.test();
|
||||
}
|
||||
|
||||
public static Stream<TestSpec> test() {
|
||||
return Stream.of(
|
||||
testSpec("foo").token("", "B").expectCtorThrow("Empty token in the list of tokens"),
|
||||
testSpec("foo").expectCtorThrow("Empty token list"),
|
||||
testSpec("a").expect("a").token("b", "B"),
|
||||
testSpec("a").expect("A").token("a", "A"),
|
||||
testSpec("aaa").expect("AAA").token("a", "A"),
|
||||
testSpec("aaa").recursive().expect("{B}{B}{B}").token("a", "b").token("b", "{B}"),
|
||||
testSpec("aaa").token("a", "aa").token("aa", "C").expect("Caa"),
|
||||
testSpec("aaa").token("a", "aa").token("aa", "C").expect("CC").recursive(),
|
||||
testSpec("aaa").expect("A2A").token("a", "A").token("aa", "A2"),
|
||||
testSpec("aaa").token("a", "b").token("b", "c").token("c", "a").expect("bbb"),
|
||||
testSpec("aaa").token("a", "b").token("b", "").recursive().expect(""),
|
||||
testSpec("aaa").token("a", "").recursive().expect(""),
|
||||
testSpec("aaa").token("a", "b").token("b", "c").token("c", "a").expectInfiniteRecursion().recursive(),
|
||||
testSpec(null).token("a", "b").expectApplyToNPE(),
|
||||
testSpec("abc").expect("abc").token(".", "A"),
|
||||
testSpec("abc.").expect("abcD").token(".", "D")
|
||||
).map(TestSpec.Builder::create);
|
||||
}
|
||||
|
||||
private static final class CountingSupplier implements Supplier<Object> {
|
||||
|
||||
CountingSupplier(Object value, int expectedCount) {
|
||||
this.value = value;
|
||||
this.expectedCount = expectedCount;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object get() {
|
||||
counter++;
|
||||
return value;
|
||||
}
|
||||
|
||||
public Object value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
void verifyCount() {
|
||||
assertEquals(expectedCount, counter);
|
||||
}
|
||||
|
||||
private final Object value;
|
||||
private int counter;
|
||||
private final int expectedCount;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombine() {
|
||||
final var x = new TokenReplace("a");
|
||||
final var y = new TokenReplace("aa");
|
||||
|
||||
final var xy = TokenReplace.combine(x, y);
|
||||
|
||||
assertEquals(xy, new TokenReplace("aa", "a"));
|
||||
assertEquals(xy, new TokenReplace("a", "aa"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombine2() {
|
||||
final var x = new TokenReplace("a");
|
||||
final var y = new TokenReplace("a");
|
||||
|
||||
final var xy = TokenReplace.combine(x, y);
|
||||
|
||||
assertEquals(xy, new TokenReplace("a", "a"));
|
||||
assertEquals(xy, new TokenReplace("a"));
|
||||
assertEquals(xy, x);
|
||||
assertEquals(xy, y);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombine3() {
|
||||
final var x = new TokenReplace("a");
|
||||
final var y = new TokenReplace("b");
|
||||
|
||||
final var xy = TokenReplace.combine(x, y);
|
||||
|
||||
assertEquals(xy, new TokenReplace("a", "b"));
|
||||
assertEquals(xy, new TokenReplace("b", "a"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEquals() {
|
||||
final var x = new TokenReplace("x");
|
||||
final var y = new TokenReplace("y");
|
||||
final var y2 = new TokenReplace("y");
|
||||
|
||||
assertNotEquals(x, y);
|
||||
assertNotEquals(x, null);
|
||||
assertNotEquals(null, x);
|
||||
assertNotEquals(x, "x");
|
||||
|
||||
assertEquals(y, y2);
|
||||
assertEquals(y, y);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateCachingTokenValueSupplier() {
|
||||
final var neverCalledSupplier = new CountingSupplier("", 0);
|
||||
final var calledOnceSupplier = new CountingSupplier("foo", 1);
|
||||
final var calledOnceNullSupplier = new CountingSupplier(null, 1);
|
||||
|
||||
final var supplier = TokenReplace.createCachingTokenValueSupplier(Map.of(
|
||||
"never", neverCalledSupplier,
|
||||
"once", calledOnceSupplier,
|
||||
"onceNull", calledOnceNullSupplier
|
||||
));
|
||||
|
||||
for (int i = 0; i != 2; i++) {
|
||||
assertEquals(calledOnceSupplier.value(), supplier.apply("once"));
|
||||
|
||||
final var ex = assertThrows(NullPointerException.class, () -> supplier.apply("onceNull"));
|
||||
assertEquals("Null value for token [onceNull]", ex.getMessage());
|
||||
}
|
||||
|
||||
final var ex = assertThrows(NullPointerException.class, () -> supplier.apply("foo"));
|
||||
assertEquals("No token value supplier for token [foo]", ex.getMessage());
|
||||
|
||||
neverCalledSupplier.verifyCount();
|
||||
calledOnceSupplier.verifyCount();
|
||||
calledOnceNullSupplier.verifyCount();
|
||||
}
|
||||
|
||||
private static TestSpec.Builder testSpec(String str) {
|
||||
return new TestSpec.Builder().str(str);
|
||||
}
|
||||
}
|
||||
@ -21,14 +21,19 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static jdk.jpackage.test.JPackageStringBundle.MAIN;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.LinuxHelper;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.LinuxHelper;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import java.util.List;
|
||||
import jdk.jpackage.test.RunnablePackageTest.Action;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@ -55,48 +60,47 @@ public class LinuxResourceTest {
|
||||
})
|
||||
.forTypes(PackageType.LINUX_DEB)
|
||||
.addInitializer(cmd -> {
|
||||
Path controlFile = Path.of(cmd.getArgumentValue("--resource-dir"),
|
||||
"control");
|
||||
Path controlFile = Path.of(cmd.getArgumentValue("--resource-dir"), "control");
|
||||
|
||||
final var packageProp = property("Package", "dont-install-me");
|
||||
final var verProp = property("Version", "1.2.3-R2");
|
||||
final var arhProp = property("Architecture", "bar");
|
||||
|
||||
TKit.createTextFile(controlFile, List.of(
|
||||
"Package: dont-install-me",
|
||||
"Version: 1.2.3-R2",
|
||||
packageProp.format(),
|
||||
verProp.format(),
|
||||
"Section: APPLICATION_SECTION",
|
||||
"Maintainer: APPLICATION_MAINTAINER",
|
||||
"Priority: optional",
|
||||
"Architecture: bar",
|
||||
arhProp.format(),
|
||||
"Provides: dont-install-me",
|
||||
"Description: APPLICATION_DESCRIPTION",
|
||||
"Installed-Size: APPLICATION_INSTALLED_SIZE",
|
||||
"Depends: PACKAGE_DEFAULT_DEPENDENCIES"
|
||||
));
|
||||
})
|
||||
.addBundleVerifier((cmd, result) -> {
|
||||
TKit.assertTextStream("Using custom package resource [DEB control file]")
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(String.format(
|
||||
"Expected value of \"Package\" property is [%s]. Actual value in output package is [dont-install-me]",
|
||||
LinuxHelper.getPackageName(cmd)))
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(
|
||||
"Expected value of \"Version\" property is [1.0]. Actual value in output package is [1.2.3-R2]")
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(String.format(
|
||||
"Expected value of \"Architecture\" property is [%s]. Actual value in output package is [bar]",
|
||||
LinuxHelper.getDefaultPackageArch(cmd.packageType())))
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
|
||||
cmd.validateOutput(MAIN.cannedFormattedString(
|
||||
"message.using-custom-resource",
|
||||
String.format("[%s]", MAIN.cannedFormattedString("resource.deb-control-file").getValue()),
|
||||
controlFile.getFileName()));
|
||||
|
||||
packageProp.expectedValue(LinuxHelper.getPackageName(cmd)).token("APPLICATION_PACKAGE").resourceDirFile(controlFile).validateOutput(cmd);
|
||||
verProp.expectedValue(cmd.version()).token("APPLICATION_VERSION_WITH_RELEASE").resourceDirFile(controlFile).validateOutput(cmd);
|
||||
arhProp.expectedValue(LinuxHelper.getDefaultPackageArch(cmd.packageType())).token("APPLICATION_ARCH").resourceDirFile(controlFile).validateOutput(cmd);
|
||||
})
|
||||
.forTypes(PackageType.LINUX_RPM)
|
||||
.addInitializer(cmd -> {
|
||||
Path specFile = Path.of(cmd.getArgumentValue("--resource-dir"),
|
||||
LinuxHelper.getPackageName(cmd) + ".spec");
|
||||
|
||||
final var packageProp = property("Name", "dont-install-me");
|
||||
final var verProp = property("Version", "1.2.3");
|
||||
final var releaseProp = property("Release", "R2");
|
||||
|
||||
TKit.createTextFile(specFile, List.of(
|
||||
"Name: dont-install-me",
|
||||
"Version: 1.2.3",
|
||||
"Release: R2",
|
||||
packageProp.format(),
|
||||
verProp.format(),
|
||||
releaseProp.format(),
|
||||
"Summary: APPLICATION_SUMMARY",
|
||||
"License: APPLICATION_LICENSE_TYPE",
|
||||
"Prefix: %{dirname:APPLICATION_DIRECTORY}",
|
||||
@ -113,25 +117,77 @@ public class LinuxResourceTest {
|
||||
"%files",
|
||||
"APPLICATION_DIRECTORY"
|
||||
));
|
||||
|
||||
cmd.validateOutput(MAIN.cannedFormattedString(
|
||||
"message.using-custom-resource",
|
||||
String.format("[%s]", MAIN.cannedFormattedString("resource.rpm-spec-file").getValue()),
|
||||
specFile.getFileName()));
|
||||
|
||||
packageProp.expectedValue(LinuxHelper.getPackageName(cmd)).token("APPLICATION_PACKAGE").resourceDirFile(specFile).validateOutput(cmd);
|
||||
verProp.expectedValue(cmd.version()).token("APPLICATION_VERSION").resourceDirFile(specFile).validateOutput(cmd);
|
||||
releaseProp.expectedValue("1").token("APPLICATION_RELEASE").resourceDirFile(specFile).validateOutput(cmd);
|
||||
})
|
||||
.addBundleVerifier((cmd, result) -> {
|
||||
TKit.assertTextStream("Using custom package resource [RPM spec file]")
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(String.format(
|
||||
"Expected value of \"Name\" property is [%s]. Actual value in output package is [dont-install-me]",
|
||||
LinuxHelper.getPackageName(cmd)))
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(
|
||||
"Expected value of \"Version\" property is [1.0]. Actual value in output package is [1.2.3]")
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(
|
||||
"Expected value of \"Release\" property is [1]. Actual value in output package is [R2]")
|
||||
.predicate(String::contains)
|
||||
.apply(result.getOutput().stream());
|
||||
})
|
||||
.run();
|
||||
.run(Action.CREATE);
|
||||
}
|
||||
|
||||
private static final class PropertyValidator {
|
||||
|
||||
PropertyValidator name(String v) {
|
||||
name = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
PropertyValidator customValue(String v) {
|
||||
customValue = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
PropertyValidator expectedValue(String v) {
|
||||
expectedValue = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
PropertyValidator token(String v) {
|
||||
token = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
PropertyValidator resourceDirFile(Path v) {
|
||||
resourceDirFile = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
String format() {
|
||||
Objects.requireNonNull(name);
|
||||
Objects.requireNonNull(customValue);
|
||||
return String.format("%s: %s", name, customValue);
|
||||
}
|
||||
|
||||
void validateOutput(JPackageCommand cmd) {
|
||||
Objects.requireNonNull(name);
|
||||
Objects.requireNonNull(customValue);
|
||||
Objects.requireNonNull(expectedValue);
|
||||
Objects.requireNonNull(token);
|
||||
Objects.requireNonNull(resourceDirFile);
|
||||
|
||||
final var customResourcePath = customResourcePath();
|
||||
cmd.validateOutput(
|
||||
MAIN.cannedFormattedString("error.unexpected-package-property", name, expectedValue, customValue, customResourcePath),
|
||||
MAIN.cannedFormattedString("error.unexpected-package-property.advice", token, customValue, name, customResourcePath));
|
||||
}
|
||||
|
||||
private Path customResourcePath() {
|
||||
return resourceDirFile.getFileName();
|
||||
}
|
||||
|
||||
private String name;
|
||||
private String customValue;
|
||||
private String expectedValue;
|
||||
private String token;
|
||||
private Path resourceDirFile;
|
||||
}
|
||||
|
||||
private static PropertyValidator property(String name, String customValue) {
|
||||
return new PropertyValidator().name(name).customValue(customValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2022, 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
|
||||
@ -25,9 +25,7 @@ import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
|
||||
/**
|
||||
* Tests generation of app image with --mac-app-store and --jlink-options. jpackage should able
|
||||
* to generate app image if "--strip-native-commands" is specified for --jlink-options and should
|
||||
* fail if it is not specified.
|
||||
* Tests generation of app image with --mac-app-store and --jlink-options.
|
||||
*/
|
||||
|
||||
/*
|
||||
@ -50,13 +48,4 @@ public class MacAppStoreJLinkOptionsTest {
|
||||
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testWithoutStripNativeCommands() throws Exception {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage();
|
||||
cmd.addArguments("--mac-app-store", "--jlink-options",
|
||||
"--strip-debug --no-man-pages --no-header-files");
|
||||
|
||||
cmd.execute(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,100 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.
|
||||
*/
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.Executor;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.JavaTool;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
|
||||
|
||||
/**
|
||||
* Tests generation of app image with --mac-app-store and --runtime-image. jpackage should able
|
||||
* to generate app image if runtime image does not have "bin" folder and fail otherwise.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary jpackage with --mac-app-store and --runtime-image
|
||||
* @library /test/jdk/tools/jpackage/helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @build MacAppStoreRuntimeTest
|
||||
* @requires (os.family == "mac")
|
||||
* @run main/othervm -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=MacAppStoreRuntimeTest
|
||||
*/
|
||||
public class MacAppStoreRuntimeTest {
|
||||
|
||||
private static String getRuntimeImage(boolean stripNativeCommands) throws IOException {
|
||||
final Path workDir = TKit.createTempDirectory("runtime").resolve("data");
|
||||
final Path jlinkOutputDir = workDir.resolve("temp.runtime");
|
||||
Files.createDirectories(jlinkOutputDir.getParent());
|
||||
|
||||
// List of modules required for test app.
|
||||
final var modules = new String[] {
|
||||
"java.base",
|
||||
"java.desktop"
|
||||
};
|
||||
|
||||
List<String> jlinkArgs = new ArrayList<>();
|
||||
jlinkArgs.add("--output");
|
||||
jlinkArgs.add(jlinkOutputDir.toString());
|
||||
jlinkArgs.add("--add-modules");
|
||||
jlinkArgs.add(String.join(",", modules));
|
||||
jlinkArgs.add("--strip-debug");
|
||||
jlinkArgs.add("--no-header-files");
|
||||
jlinkArgs.add("--no-man-pages");
|
||||
if (stripNativeCommands) {
|
||||
jlinkArgs.add("--strip-native-commands");
|
||||
}
|
||||
|
||||
new Executor()
|
||||
.setToolProvider(JavaTool.JLINK)
|
||||
.dumpOutput()
|
||||
.addArguments(jlinkArgs)
|
||||
.execute();
|
||||
|
||||
return jlinkOutputDir.toString();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Parameter("true")
|
||||
@Parameter("false")
|
||||
public static void test(boolean stripNativeCommands) throws Exception {
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage();
|
||||
cmd.addArguments("--mac-app-store", "--runtime-image", getRuntimeImage(stripNativeCommands));
|
||||
|
||||
if (stripNativeCommands) {
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
} else {
|
||||
cmd.execute(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -62,17 +62,15 @@ public class SigningAppImageTest {
|
||||
@Test
|
||||
// ({"sign or not", "signing-key or sign-identity", "certificate index"})
|
||||
// Sign, signing-key and ASCII certificate
|
||||
@Parameter({"true", "true", SigningBase.ASCII_INDEX})
|
||||
@Parameter({"true", "true", "ASCII_INDEX"})
|
||||
// Sign, signing-key and UNICODE certificate
|
||||
@Parameter({"true", "true", SigningBase.UNICODE_INDEX})
|
||||
@Parameter({"true", "true", "UNICODE_INDEX"})
|
||||
// Sign, signing-indentity and UNICODE certificate
|
||||
@Parameter({"true", "false", SigningBase.UNICODE_INDEX})
|
||||
@Parameter({"true", "false", "UNICODE_INDEX"})
|
||||
// Unsigned
|
||||
@Parameter({"false", "true", "-1"})
|
||||
public void test(String... testArgs) throws Exception {
|
||||
boolean doSign = Boolean.parseBoolean(testArgs[0]);
|
||||
boolean signingKey = Boolean.parseBoolean(testArgs[1]);
|
||||
int certIndex = Integer.parseInt(testArgs[2]);
|
||||
@Parameter({"false", "true", "INVALID_INDEX"})
|
||||
public void test(boolean doSign, boolean signingKey, SigningBase.CertIndex certEnum) throws Exception {
|
||||
final var certIndex = certEnum.value();
|
||||
|
||||
SigningCheck.checkCertificates(certIndex);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -110,27 +110,24 @@ public class SigningPackageTest {
|
||||
return SigningBase.getDevNameIndex(devName);
|
||||
} else {
|
||||
// Signing-indentity
|
||||
return Integer.valueOf(SigningBase.UNICODE_INDEX);
|
||||
return SigningBase.CertIndex.UNICODE_INDEX.value();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
// ("signing-key or sign-identity", "sign app-image", "sign pkg", "certificate index"})
|
||||
// Signing-key and ASCII certificate
|
||||
@Parameter({"true", "true", "true", SigningBase.ASCII_INDEX})
|
||||
@Parameter({"true", "true", "true", "ASCII_INDEX"})
|
||||
// Signing-key and UNICODE certificate
|
||||
@Parameter({"true", "true", "true", SigningBase.UNICODE_INDEX})
|
||||
@Parameter({"true", "true", "true", "UNICODE_INDEX"})
|
||||
// Signing-indentity and UNICODE certificate
|
||||
@Parameter({"false", "true", "true", SigningBase.UNICODE_INDEX})
|
||||
@Parameter({"false", "true", "true", "UNICODE_INDEX"})
|
||||
// Signing-indentity, but sign app-image only and UNICODE certificate
|
||||
@Parameter({"false", "true", "false", SigningBase.UNICODE_INDEX})
|
||||
@Parameter({"false", "true", "false", "UNICODE_INDEX"})
|
||||
// Signing-indentity, but sign pkg only and UNICODE certificate
|
||||
@Parameter({"false", "false", "true", SigningBase.UNICODE_INDEX})
|
||||
public static void test(String... testArgs) throws Exception {
|
||||
boolean signingKey = Boolean.parseBoolean(testArgs[0]);
|
||||
boolean signAppImage = Boolean.parseBoolean(testArgs[1]);
|
||||
boolean signPKG = Boolean.parseBoolean(testArgs[2]);
|
||||
int certIndex = Integer.parseInt(testArgs[3]);
|
||||
@Parameter({"false", "false", "true", "UNICODE_INDEX"})
|
||||
public static void test(boolean signingKey, boolean signAppImage, boolean signPKG, SigningBase.CertIndex certEnum) throws Exception {
|
||||
final var certIndex = certEnum.value();
|
||||
|
||||
SigningCheck.checkCertificates(certIndex);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -32,9 +32,23 @@ import jdk.jpackage.test.Executor.Result;
|
||||
|
||||
public class SigningBase {
|
||||
|
||||
enum CertIndex {
|
||||
ASCII_INDEX(0),
|
||||
UNICODE_INDEX(1),
|
||||
INVALID_INDEX(-1);
|
||||
|
||||
CertIndex(int value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
int value() {
|
||||
return value;
|
||||
}
|
||||
|
||||
private final int value;
|
||||
}
|
||||
|
||||
public static int DEFAULT_INDEX = 0;
|
||||
public static final String ASCII_INDEX = "0";
|
||||
public static final String UNICODE_INDEX = "0";
|
||||
private static String [] DEV_NAMES = {
|
||||
"jpackage.openjdk.java.net",
|
||||
"jpackage.openjdk.java.net (ö)",
|
||||
|
||||
@ -25,10 +25,13 @@ import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import jdk.jpackage.internal.util.XmlUtils;
|
||||
import jdk.jpackage.test.AppImageFile;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
import jdk.jpackage.test.CannedFormattedString;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.RunnablePackageTest.Action;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
@ -106,17 +109,16 @@ public class AppImagePackageTest {
|
||||
public static void testBadAppImage() throws IOException {
|
||||
Path appImageDir = TKit.createTempDirectory("appimage");
|
||||
Files.createFile(appImageDir.resolve("foo"));
|
||||
configureAppImageWithoutJPackageXMLFile(appImageDir).addInitializer(
|
||||
cmd -> {
|
||||
cmd.removeArgumentWithValue("--name");
|
||||
}).run(Action.CREATE);
|
||||
configureBadAppImage(appImageDir).addInitializer(cmd -> {
|
||||
cmd.removeArgumentWithValue("--name");
|
||||
}).run(Action.CREATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testBadAppImage2() throws IOException {
|
||||
Path appImageDir = TKit.createTempDirectory("appimage");
|
||||
Files.createFile(appImageDir.resolve("foo"));
|
||||
configureAppImageWithoutJPackageXMLFile(appImageDir).run(Action.CREATE);
|
||||
configureBadAppImage(appImageDir).run(Action.CREATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -126,29 +128,45 @@ public class AppImagePackageTest {
|
||||
JPackageCommand appImageCmd = JPackageCommand.helloAppImage().
|
||||
setFakeRuntime().setArgumentValue("--dest", appImageDir);
|
||||
|
||||
configureAppImageWithoutJPackageXMLFile(appImageCmd.outputBundle()).
|
||||
addRunOnceInitializer(() -> {
|
||||
appImageCmd.execute();
|
||||
Files.delete(AppImageFile.getPathInAppImage(appImageCmd.
|
||||
outputBundle()));
|
||||
}).run(Action.CREATE);
|
||||
configureBadAppImage(appImageCmd.outputBundle()).addRunOnceInitializer(() -> {
|
||||
appImageCmd.execute();
|
||||
Files.delete(AppImageFile.getPathInAppImage(appImageCmd.outputBundle()));
|
||||
}).run(Action.CREATE);
|
||||
}
|
||||
|
||||
private static PackageTest configureAppImageWithoutJPackageXMLFile(
|
||||
Path appImageDir) {
|
||||
return new PackageTest()
|
||||
.addInitializer(cmd -> {
|
||||
cmd.saveConsoleOutput(true);
|
||||
cmd.addArguments("--app-image", appImageDir);
|
||||
cmd.removeArgumentWithValue("--input");
|
||||
cmd.ignoreDefaultVerbose(true); // no "--verbose" option
|
||||
})
|
||||
.addBundleVerifier((cmd, result) -> {
|
||||
TKit.assertTextStream(
|
||||
"Error: Missing .jpackage.xml file in app-image dir").apply(
|
||||
result.getOutput().stream());
|
||||
})
|
||||
.setExpectedExitCode(1);
|
||||
@Test
|
||||
public static void testBadAppImageFile() throws IOException {
|
||||
final var appImageRoot = TKit.createTempDirectory("appimage");
|
||||
|
||||
final var appImageCmd = JPackageCommand.helloAppImage().
|
||||
setFakeRuntime().setArgumentValue("--dest", appImageRoot);
|
||||
|
||||
final var appImageDir = appImageCmd.outputBundle();
|
||||
|
||||
final var expectedError = JPackageStringBundle.MAIN.cannedFormattedString(
|
||||
"error.invalid-app-image", appImageDir, AppImageFile.getPathInAppImage(appImageDir));
|
||||
|
||||
configureBadAppImage(appImageDir, expectedError).addRunOnceInitializer(() -> {
|
||||
appImageCmd.execute();
|
||||
XmlUtils.createXml(AppImageFile.getPathInAppImage(appImageDir), xml -> {
|
||||
xml.writeStartElement("jpackage-state");
|
||||
xml.writeEndElement();
|
||||
});
|
||||
}).run(Action.CREATE);
|
||||
}
|
||||
|
||||
private static PackageTest configureBadAppImage(Path appImageDir) {
|
||||
return configureBadAppImage(appImageDir,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("error.foreign-app-image", appImageDir));
|
||||
}
|
||||
|
||||
private static PackageTest configureBadAppImage(Path appImageDir, CannedFormattedString expectedError) {
|
||||
return new PackageTest().addInitializer(cmd -> {
|
||||
cmd.addArguments("--app-image", appImageDir);
|
||||
cmd.removeArgumentWithValue("--input");
|
||||
cmd.ignoreDefaultVerbose(true); // no "--verbose" option
|
||||
cmd.validateOutput(expectedError);
|
||||
}).setExpectedExitCode(1);
|
||||
}
|
||||
|
||||
private static Path iconPath(String name) {
|
||||
|
||||
@ -31,7 +31,6 @@ import jdk.jpackage.test.AppImageFile;
|
||||
import jdk.jpackage.test.Annotations.Parameters;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.TKit;
|
||||
|
||||
/*
|
||||
@ -70,19 +69,6 @@ public final class AppVersionTest {
|
||||
"--app-version", "7.5.81"}}
|
||||
}));
|
||||
|
||||
// These are invalid version strings.
|
||||
// Don't need to test all invalid input as this is handled in
|
||||
// PlatformVersionTest unit test
|
||||
if (TKit.isWindows()) {
|
||||
data.addAll(List.of(new Object[][]{
|
||||
{null, "Hello", new String[]{"--app-version", "256"}}
|
||||
}));
|
||||
} else if (TKit.isOSX()) {
|
||||
data.addAll(List.of(new Object[][]{
|
||||
{null, "Hello", new String[]{"--app-version", "0.2"}}
|
||||
}));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -95,17 +81,6 @@ public final class AppVersionTest {
|
||||
|
||||
@Test
|
||||
public void test() throws XPathExpressionException, IOException {
|
||||
if (expectedVersion == null) {
|
||||
new PackageTest()
|
||||
.setExpectedExitCode(1)
|
||||
.configureHelloApp(javaAppDesc)
|
||||
.addInitializer(cmd -> {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
})
|
||||
.run();
|
||||
return;
|
||||
}
|
||||
|
||||
JPackageCommand cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
||||
if (jpackageArgs != null) {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
|
||||
@ -36,6 +36,7 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.JavaAppDesc;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.HelloApp;
|
||||
@ -381,7 +382,10 @@ public final class BasicTest {
|
||||
);
|
||||
|
||||
if (TestTempType.TEMPDIR_NOT_EMPTY.equals(type)) {
|
||||
pkgTest.setExpectedExitCode(1).addBundleVerifier(cmd -> {
|
||||
pkgTest.setExpectedExitCode(1).addInitializer(cmd -> {
|
||||
cmd.validateOutput(JPackageStringBundle.MAIN.cannedFormattedString(
|
||||
"ERR_BuildRootInvalid", cmd.getArgumentValue("--temp")));
|
||||
}).addBundleVerifier(cmd -> {
|
||||
// Check jpackage didn't use the supplied directory.
|
||||
Path tempDir = Path.of(cmd.getArgumentValue("--temp"));
|
||||
TKit.assertDirectoryContent(tempDir).match(Path.of("foo.txt"));
|
||||
|
||||
@ -22,19 +22,32 @@
|
||||
*/
|
||||
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
import static jdk.internal.util.OperatingSystem.LINUX;
|
||||
import static jdk.internal.util.OperatingSystem.MACOS;
|
||||
import static jdk.internal.util.OperatingSystem.WINDOWS;
|
||||
import static jdk.jpackage.test.CannedFormattedString.cannedAbsolutePath;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
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;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.RunnablePackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import static jdk.internal.util.OperatingSystem.WINDOWS;
|
||||
|
||||
/*
|
||||
* @test
|
||||
@ -42,7 +55,7 @@ import static jdk.internal.util.OperatingSystem.WINDOWS;
|
||||
* @library /test/jdk/tools/jpackage/helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @compile -Xlint:all -Werror ErrorTest.java
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=ErrorTest
|
||||
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault
|
||||
*/
|
||||
@ -53,101 +66,566 @@ import static jdk.internal.util.OperatingSystem.WINDOWS;
|
||||
* @library /test/jdk/tools/jpackage/helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @compile -Xlint:all -Werror ErrorTest.java
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=ErrorTest
|
||||
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault
|
||||
*/
|
||||
|
||||
public final class ErrorTest {
|
||||
|
||||
public static Collection<?> input() {
|
||||
return List.of(new Object[][]{
|
||||
enum Token {
|
||||
JAVA_HOME(cmd -> {
|
||||
return System.getProperty("java.home");
|
||||
}),
|
||||
APP_IMAGE(cmd -> {
|
||||
final var appImageRoot = TKit.createTempDirectory("appimage");
|
||||
|
||||
final var appImageCmd = JPackageCommand.helloAppImage()
|
||||
.setFakeRuntime().setArgumentValue("--dest", appImageRoot);
|
||||
|
||||
appImageCmd.execute();
|
||||
|
||||
return appImageCmd.outputBundle().toString();
|
||||
}),
|
||||
ADD_LAUNCHER_PROPERTY_FILE;
|
||||
|
||||
private Token() {
|
||||
this.valueSupplier = Optional.empty();
|
||||
}
|
||||
|
||||
private Token(Function<JPackageCommand, Object> valueSupplier) {
|
||||
this.valueSupplier = Optional.of(valueSupplier);
|
||||
}
|
||||
|
||||
String token() {
|
||||
return makeToken(name());
|
||||
}
|
||||
|
||||
TokenReplace asTokenReplace() {
|
||||
return tokenReplace;
|
||||
}
|
||||
|
||||
Optional<Object> expand(JPackageCommand cmd) {
|
||||
return valueSupplier.map(func -> func.apply(cmd));
|
||||
}
|
||||
|
||||
private static String makeToken(String v) {
|
||||
Objects.requireNonNull(v);
|
||||
return String.format("@@%s@@", v);
|
||||
}
|
||||
|
||||
private final Optional<Function<JPackageCommand, Object>> valueSupplier;
|
||||
private final TokenReplace tokenReplace = new TokenReplace(token());
|
||||
}
|
||||
|
||||
public record TestSpec(Optional<PackageType> type, Optional<String> appDesc, List<String> addArgs,
|
||||
List<String> removeArgs, List<CannedFormattedString> expectedErrors) {
|
||||
|
||||
static final class Builder {
|
||||
|
||||
Builder type(PackageType v) {
|
||||
type = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder notype() {
|
||||
return type(null);
|
||||
}
|
||||
|
||||
Builder nativeType() {
|
||||
return type(NATIVE_TYPE);
|
||||
}
|
||||
|
||||
Builder appDesc(String v) {
|
||||
appDesc = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder noAppDesc() {
|
||||
return appDesc(null);
|
||||
}
|
||||
|
||||
Builder setAddArgs(List<String> v) {
|
||||
addArgs.clear();
|
||||
addArgs.addAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setAddArgs(String... v) {
|
||||
return setAddArgs(List.of(v));
|
||||
}
|
||||
|
||||
Builder addArgs(List<String> v) {
|
||||
addArgs.addAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder addArgs(String... v) {
|
||||
return addArgs(List.of(v));
|
||||
}
|
||||
|
||||
Builder setRemoveArgs(List<String> v) {
|
||||
removeArgs.clear();
|
||||
removeArgs.addAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setRemoveArgs(String... v) {
|
||||
return setRemoveArgs(List.of(v));
|
||||
}
|
||||
|
||||
Builder removeArgs(List<String> v) {
|
||||
removeArgs.addAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder removeArgs(String... v) {
|
||||
return removeArgs(List.of(v));
|
||||
}
|
||||
|
||||
Builder setErrors(List<CannedFormattedString> v) {
|
||||
expectedErrors = v;
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder setErrors(CannedFormattedString... v) {
|
||||
return setErrors(List.of(v));
|
||||
}
|
||||
|
||||
Builder errors(List<CannedFormattedString> v) {
|
||||
expectedErrors.addAll(v);
|
||||
return this;
|
||||
}
|
||||
|
||||
Builder errors(CannedFormattedString... v) {
|
||||
return errors(List.of(v));
|
||||
}
|
||||
|
||||
Builder error(String key, Object ... args) {
|
||||
return errors(JPackageStringBundle.MAIN.cannedFormattedString(key, args));
|
||||
}
|
||||
|
||||
Builder invalidTypeArg(String arg, String... otherArgs) {
|
||||
return addArgs(arg).addArgs(otherArgs).error("ERR_InvalidTypeOption", arg, type.getType());
|
||||
}
|
||||
|
||||
Builder unsupportedPlatformOption(String arg, String ... otherArgs) {
|
||||
return addArgs(arg).addArgs(otherArgs).error("ERR_UnsupportedOption", arg);
|
||||
}
|
||||
|
||||
TestSpec create() {
|
||||
return new TestSpec(Optional.ofNullable(type), Optional.ofNullable(appDesc),
|
||||
List.copyOf(addArgs), List.copyOf(removeArgs), List.copyOf(expectedErrors));
|
||||
}
|
||||
|
||||
private PackageType type = PackageType.IMAGE;
|
||||
private String appDesc = DEFAULT_APP_DESC;
|
||||
private List<String> addArgs = new ArrayList<>();
|
||||
private List<String> removeArgs = new ArrayList<>();
|
||||
private List<CannedFormattedString> expectedErrors = new ArrayList<>();
|
||||
}
|
||||
|
||||
public TestSpec {
|
||||
Objects.requireNonNull(type);
|
||||
Objects.requireNonNull(appDesc);
|
||||
Objects.requireNonNull(addArgs);
|
||||
addArgs.forEach(Objects::requireNonNull);
|
||||
Objects.requireNonNull(removeArgs);
|
||||
removeArgs.forEach(Objects::requireNonNull);
|
||||
if (expectedErrors.isEmpty()) {
|
||||
throw new IllegalArgumentException("The list of expected errors must be non-empty");
|
||||
}
|
||||
}
|
||||
|
||||
void test() {
|
||||
test(Map.of());
|
||||
}
|
||||
|
||||
void test(Map<Token, Function<JPackageCommand, Object>> tokenValueSuppliers) {
|
||||
final var cmd = appDesc.map(JPackageCommand::helloAppImage).orElseGet(JPackageCommand::new);
|
||||
type.ifPresent(cmd::setPackageType);
|
||||
|
||||
removeArgs.forEach(cmd::removeArgumentWithValue);
|
||||
cmd.addArguments(addArgs);
|
||||
|
||||
final var tokenValueSupplier = TokenReplace.createCachingTokenValueSupplier(Stream.of(Token.values()).collect(toMap(Token::token, token -> {
|
||||
return () -> {
|
||||
return token.expand(cmd).orElseGet(() -> {
|
||||
final var tvs = Objects.requireNonNull(tokenValueSuppliers.get(token), () -> {
|
||||
return String.format("No token value supplier for token [%s]", token);
|
||||
});
|
||||
return tvs.apply(cmd);
|
||||
});
|
||||
};
|
||||
})));
|
||||
|
||||
for (final var token : Token.values()) {
|
||||
final var newArgs = cmd.getAllArguments().stream().map(arg -> {
|
||||
return token.asTokenReplace().applyTo(arg, tokenValueSupplier);
|
||||
}).toList();
|
||||
cmd.clearArguments().addArguments(newArgs);
|
||||
}
|
||||
|
||||
defaultInit(cmd, expectedErrors);
|
||||
cmd.execute(1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String toString() {
|
||||
final var sb = new StringBuilder();
|
||||
type.ifPresent(v -> {
|
||||
sb.append(v).append("; ");
|
||||
});
|
||||
appDesc.ifPresent(v -> {
|
||||
sb.append("app-desc=").append(v).append("; ");
|
||||
});
|
||||
if (!addArgs.isEmpty()) {
|
||||
sb.append("args-add=").append(addArgs).append("; ");
|
||||
}
|
||||
if (!removeArgs.isEmpty()) {
|
||||
sb.append("args-del=").append(removeArgs).append("; ");
|
||||
}
|
||||
sb.append("errors=").append(expectedErrors);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static final String DEFAULT_APP_DESC = "Hello";
|
||||
}
|
||||
|
||||
private static TestSpec.Builder testSpec() {
|
||||
return new TestSpec.Builder();
|
||||
}
|
||||
|
||||
public static Collection<Object[]> basic() {
|
||||
final List<TestSpec> testCases = new ArrayList<>();
|
||||
|
||||
testCases.addAll(Stream.of(
|
||||
// non-existent arg
|
||||
{"Hello",
|
||||
new String[]{"--no-such-argument"},
|
||||
null,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidOption", "--no-such-argument")},
|
||||
testSpec().addArgs("--no-such-argument")
|
||||
.error("ERR_InvalidOption", "--no-such-argument"),
|
||||
// no main jar
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--main-jar"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_NoEntryPoint")},
|
||||
testSpec().removeArgs("--main-jar").error("ERR_NoEntryPoint"),
|
||||
// no main-class
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--main-class"},
|
||||
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")},
|
||||
testSpec().removeArgs("--main-class")
|
||||
.error("error.no-main-class-with-main-jar", "hello.jar")
|
||||
.error("error.no-main-class-with-main-jar.advice", "hello.jar"),
|
||||
// non-existent main jar
|
||||
{"Hello",
|
||||
new String[]{"--main-jar", "non-existent.jar"},
|
||||
null,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("error.main-jar-does-not-exist", "non-existent.jar")},
|
||||
testSpec().addArgs("--main-jar", "non-existent.jar")
|
||||
.error("error.main-jar-does-not-exist", "non-existent.jar"),
|
||||
// non-existent runtime
|
||||
{"Hello",
|
||||
new String[]{"--runtime-image", "non-existent.runtime"},
|
||||
null,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("message.runtime-image-dir-does-not-exist", "runtime-image", "non-existent.runtime")},
|
||||
testSpec().addArgs("--runtime-image", "non-existent.runtime")
|
||||
.error("message.runtime-image-dir-does-not-exist", "runtime-image", "non-existent.runtime"),
|
||||
// non-existent app image
|
||||
testSpec().noAppDesc().nativeType().addArgs("--name", "foo", "--app-image", "non-existent.appimage")
|
||||
.error("ERR_AppImageNotExist", "non-existent.appimage"),
|
||||
// non-existent resource-dir
|
||||
{"Hello",
|
||||
new String[]{"--resource-dir", "non-existent.dir"},
|
||||
null,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("message.resource-dir-does-not-exist", "resource-dir", "non-existent.dir")},
|
||||
testSpec().addArgs("--resource-dir", "non-existent.dir")
|
||||
.error("message.resource-dir-does-not-exist", "resource-dir", "non-existent.dir"),
|
||||
// non-existent icon
|
||||
testSpec().addArgs("--icon", "non-existent.icon")
|
||||
.error("ERR_IconFileNotExit", cannedAbsolutePath("non-existent.icon")),
|
||||
// non-existent license file
|
||||
testSpec().nativeType().addArgs("--license-file", "non-existent.license")
|
||||
.error("ERR_LicenseFileNotExit"),
|
||||
// invalid type
|
||||
{"Hello",
|
||||
new String[]{"--type", "invalid-type"},
|
||||
null,
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_InvalidInstallerType", "invalid-type")},
|
||||
// no --input
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--input"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--input")},
|
||||
testSpec().addArgs("--type", "invalid-type")
|
||||
.error("ERR_InvalidInstallerType", "invalid-type"),
|
||||
// no --input for non-mudular app
|
||||
testSpec().removeArgs("--input").error("error.no-input-parameter"),
|
||||
// no --module-path
|
||||
{"com.other/com.other.Hello",
|
||||
null,
|
||||
new String[]{"--module-path"},
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("ERR_MissingArgument", "--runtime-image or --module-path")},
|
||||
});
|
||||
testSpec().appDesc("com.other/com.other.Hello").removeArgs("--module-path")
|
||||
.error("ERR_MissingArgument", "--runtime-image or --module-path"),
|
||||
// no main class in module path
|
||||
testSpec().noAppDesc().addArgs("--module", "java.base", "--runtime-image", Token.JAVA_HOME.token())
|
||||
.error("ERR_NoMainClass"),
|
||||
// no module in module path
|
||||
testSpec().noAppDesc().addArgs("--module", "com.foo.bar", "--runtime-image", Token.JAVA_HOME.token())
|
||||
.error("error.no-module-in-path", "com.foo.bar"),
|
||||
// --main-jar and --module-name
|
||||
testSpec().noAppDesc().addArgs("--main-jar", "foo.jar", "--module", "foo.bar")
|
||||
.error("ERR_BothMainJarAndModule"),
|
||||
// non-existing argument file
|
||||
testSpec().noAppDesc().notype().addArgs("@foo")
|
||||
.error("ERR_CannotParseOptions", "foo"),
|
||||
// invalid jlink option
|
||||
testSpec().addArgs("--jlink-options", "--foo")
|
||||
.error("error.jlink.failed", "Error: unknown option: --foo")
|
||||
).map(TestSpec.Builder::create).toList());
|
||||
|
||||
// forbidden jlink options
|
||||
testCases.addAll(Stream.of("--output", "--add-modules", "--module-path").map(opt -> {
|
||||
return testSpec().addArgs("--jlink-options", opt).error("error.blocked.option", opt);
|
||||
}).map(TestSpec.Builder::create).toList());
|
||||
|
||||
// --runtime-image and --app-image are mutually-exclusive
|
||||
testCases.addAll(createRuntimeMutuallyExclusive("--app-image", "app-image"));
|
||||
// --runtime-image and --app-modules are mutually-exclusive
|
||||
testCases.addAll(createRuntimeMutuallyExclusive("--add-modules", "foo.bar", "--module", "foo.bar"));
|
||||
// --runtime-image and --jlink-options are mutually-exclusive
|
||||
testCases.addAll(createRuntimeMutuallyExclusive("--jlink-options", "--bind-services", "--module", "foo.bar"));
|
||||
|
||||
return toTestArgs(testCases.stream());
|
||||
}
|
||||
|
||||
record ArgumentGroup(String arg, String... otherArgs) {
|
||||
ArgumentGroup {
|
||||
Objects.requireNonNull(arg);
|
||||
List.of(otherArgs).forEach(Objects::requireNonNull);
|
||||
}
|
||||
|
||||
String[] asArray() {
|
||||
return Stream.concat(Stream.of(arg), Stream.of(otherArgs)).toArray(String[]::new);
|
||||
}
|
||||
}
|
||||
|
||||
private static List<TestSpec> createRuntimeMutuallyExclusive(String arg, String... otherArgs) {
|
||||
return createMutuallyExclusive(
|
||||
new ArgumentGroup("--runtime-image", Token.JAVA_HOME.token()),
|
||||
new ArgumentGroup(arg, otherArgs)
|
||||
).map(TestSpec.Builder::noAppDesc).map(TestSpec.Builder::nativeType).map(TestSpec.Builder::create).toList();
|
||||
}
|
||||
|
||||
private static Stream<TestSpec.Builder> createMutuallyExclusive(ArgumentGroup firstGroup, ArgumentGroup secondGroup) {
|
||||
final Supplier<TestSpec.Builder> createBuilder = () -> {
|
||||
return testSpec().error("ERR_MutuallyExclusiveOptions", firstGroup.arg(), secondGroup.arg());
|
||||
};
|
||||
return Stream.of(
|
||||
createBuilder.get().addArgs(firstGroup.asArray()).addArgs(secondGroup.asArray()),
|
||||
createBuilder.get().addArgs(secondGroup.asArray()).addArgs(firstGroup.asArray()));
|
||||
}
|
||||
|
||||
public static Collection<Object[]> invalidAppVersion() {
|
||||
return fromTestSpecBuilders(Stream.of(
|
||||
// Invalid app version. Just cover all different error messages.
|
||||
// Extensive testing of invalid version strings is done in DottedVersionTest unit test.
|
||||
testSpec().addArgs("--app-version", "").error("error.version-string-empty"),
|
||||
testSpec().addArgs("--app-version", "1.").error("error.version-string-zero-length-component", "1."),
|
||||
testSpec().addArgs("--app-version", "1.b.3").error("error.version-string-invalid-component", "1.b.3", "b.3")
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@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);
|
||||
|
||||
defaultInit(cmd, expectedErrors);
|
||||
|
||||
// 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));
|
||||
|
||||
cmd.execute(1);
|
||||
@ParameterSupplier("basic")
|
||||
@ParameterSupplier(value="testWindows", ifOS = WINDOWS)
|
||||
@ParameterSupplier(value="testMac", ifOS = MACOS)
|
||||
@ParameterSupplier(value="winOption", ifNotOS = WINDOWS)
|
||||
@ParameterSupplier(value="linuxOption", ifNotOS = LINUX)
|
||||
@ParameterSupplier(value="macOption", ifNotOS = MACOS)
|
||||
@ParameterSupplier(value="invalidAppVersion", ifOS = {WINDOWS,MACOS})
|
||||
public static void test(TestSpec spec) {
|
||||
spec.test();
|
||||
}
|
||||
|
||||
@Test(ifOS = WINDOWS)
|
||||
public static void testWinService() {
|
||||
|
||||
CannedFormattedString[] expectedErrors = new CannedFormattedString[] {
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("error.missing-service-installer"),
|
||||
JPackageStringBundle.MAIN.cannedFormattedString("error.missing-service-installer.advice")
|
||||
};
|
||||
|
||||
new PackageTest().configureHelloApp()
|
||||
.addInitializer(cmd -> {
|
||||
defaultInit(cmd, expectedErrors);
|
||||
cmd.addArgument("--launcher-as-service");
|
||||
})
|
||||
.setExpectedExitCode(1)
|
||||
.run(RunnablePackageTest.Action.CREATE);
|
||||
@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();
|
||||
}
|
||||
|
||||
private static void defaultInit(JPackageCommand cmd, CannedFormattedString... expectedErrors) {
|
||||
@Test
|
||||
@ParameterSupplier
|
||||
public static void testAdditionLaunchers(TestSpec spec) {
|
||||
final Path propsFile = TKit.createTempFile("add-launcher.properties");
|
||||
TKit.createPropertiesFile(propsFile, Map.of());
|
||||
spec.test(Map.of(Token.ADD_LAUNCHER_PROPERTY_FILE, cmd -> propsFile));
|
||||
}
|
||||
|
||||
public static Collection<Object[]> testAdditionLaunchers() {
|
||||
return fromTestSpecBuilders(Stream.of(
|
||||
testSpec().addArgs("--add-launcher", Token.ADD_LAUNCHER_PROPERTY_FILE.token())
|
||||
.error("ERR_NoAddLauncherName"),
|
||||
testSpec().removeArgs("--name").addArgs("--name", "foo", "--add-launcher", "foo=" + Token.ADD_LAUNCHER_PROPERTY_FILE.token())
|
||||
.error("ERR_NoUniqueName")
|
||||
));
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterSupplier("invalidNames")
|
||||
public static void testInvalidAppName(String name) {
|
||||
testSpec().removeArgs("--name").addArgs("--name", name)
|
||||
.error("ERR_InvalidAppName", adjustTextStreamVerifierArg(name)).create().test();
|
||||
}
|
||||
|
||||
@Test
|
||||
@ParameterSupplier("invalidNames")
|
||||
public static void testInvalidAddLauncherName(String name) {
|
||||
testAdditionLaunchers(testSpec()
|
||||
.addArgs("--add-launcher", name + "=" + Token.ADD_LAUNCHER_PROPERTY_FILE.token())
|
||||
.error("ERR_InvalidSLName", adjustTextStreamVerifierArg(name))
|
||||
.create());
|
||||
}
|
||||
|
||||
public static Collection<Object[]> invalidNames() {
|
||||
final List<String> data = new ArrayList<>();
|
||||
data.addAll(List.of("", "foo/bar", "foo\tbar", "foo\rbar", "foo\nbar"));
|
||||
if (TKit.isWindows()) {
|
||||
data.add("foo\\bar");
|
||||
}
|
||||
return toTestArgs(data.stream());
|
||||
}
|
||||
|
||||
public static Collection<Object[]> testWindows() {
|
||||
final List<TestSpec> testCases = new ArrayList<>();
|
||||
|
||||
testCases.addAll(PackageType.WINDOWS.stream().map(type -> {
|
||||
return Stream.of(
|
||||
testSpec().type(type).addArgs("--launcher-as-service")
|
||||
.error("error.missing-service-installer")
|
||||
.error("error.missing-service-installer.advice"),
|
||||
// The below version strings are invalid for msi and exe packaging.
|
||||
// They are valid for app image packaging.
|
||||
testSpec().type(type).addArgs("--app-version", "1234")
|
||||
.error("error.msi-product-version-components", "1234")
|
||||
.error("error.version-string-wrong-format.advice"),
|
||||
testSpec().type(type).addArgs("--app-version", "1.2.3.4.5")
|
||||
.error("error.msi-product-version-components", "1.2.3.4.5")
|
||||
.error("error.version-string-wrong-format.advice"),
|
||||
testSpec().type(type).addArgs("--app-version", "256.1")
|
||||
.error("error.msi-product-version-major-out-of-range", "256.1")
|
||||
.error("error.version-string-wrong-format.advice"),
|
||||
testSpec().type(type).addArgs("--app-version", "1.256")
|
||||
.error("error.msi-product-version-minor-out-of-range", "1.256")
|
||||
.error("error.version-string-wrong-format.advice"),
|
||||
testSpec().type(type).addArgs("--app-version", "1.2.65536")
|
||||
.error("error.msi-product-version-build-out-of-range", "1.2.65536")
|
||||
.error("error.version-string-wrong-format.advice")
|
||||
);
|
||||
}).flatMap(x -> x).map(TestSpec.Builder::create).toList());
|
||||
|
||||
return toTestArgs(testCases.stream());
|
||||
}
|
||||
|
||||
public static Collection<Object[]> testMac() {
|
||||
final List<TestSpec> testCases = new ArrayList<>();
|
||||
|
||||
testCases.addAll(Stream.of(
|
||||
testSpec().addArgs("--app-version", "0.2")
|
||||
.error("message.version-string-first-number-not-zero")
|
||||
.error("error.invalid-cfbundle-version.advice"),
|
||||
testSpec().addArgs("--app-version", "1.2.3.4")
|
||||
.error("message.version-string-too-many-components")
|
||||
.error("error.invalid-cfbundle-version.advice"),
|
||||
testSpec().invalidTypeArg("--mac-installer-sign-identity", "foo"),
|
||||
testSpec().type(PackageType.MAC_DMG).invalidTypeArg("--mac-installer-sign-identity", "foo"),
|
||||
testSpec().invalidTypeArg("--mac-dmg-content", "foo"),
|
||||
testSpec().type(PackageType.MAC_PKG).invalidTypeArg("--mac-dmg-content", "foo"),
|
||||
testSpec().noAppDesc().addArgs("--app-image", Token.APP_IMAGE.token())
|
||||
.error("error.app-image.mac-sign.required"),
|
||||
testSpec().type(PackageType.MAC_PKG).addArgs("--mac-package-identifier", "#1")
|
||||
.error("message.invalid-identifier", "#1"),
|
||||
// Bundle for mac app store should not have runtime commands
|
||||
testSpec().nativeType().addArgs("--mac-app-store", "--jlink-options", "--bind-services")
|
||||
.error("ERR_MissingJLinkOptMacAppStore", "--strip-native-commands"),
|
||||
testSpec().nativeType().addArgs("--mac-app-store", "--runtime-image", Token.JAVA_HOME.token())
|
||||
.error("ERR_MacAppStoreRuntimeBinExists", JPackageCommand.cannedArgument(cmd -> {
|
||||
return Path.of(cmd.getArgumentValue("--runtime-image")).toAbsolutePath();
|
||||
}, Token.JAVA_HOME.token()))
|
||||
).map(TestSpec.Builder::create).toList());
|
||||
|
||||
// Test a few app-image options that should not be used when signing external app image
|
||||
testCases.addAll(Stream.of(
|
||||
new ArgumentGroup("--app-version", "2.0"),
|
||||
new ArgumentGroup("--name", "foo"),
|
||||
new ArgumentGroup("--mac-app-store")
|
||||
).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());
|
||||
|
||||
testCases.addAll(createMutuallyExclusive(
|
||||
new ArgumentGroup("--mac-signing-key-user-name", "foo"),
|
||||
new ArgumentGroup("--mac-app-image-sign-identity", "bar")
|
||||
).map(TestSpec.Builder::create).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());
|
||||
|
||||
return toTestArgs(testCases.stream());
|
||||
}
|
||||
|
||||
private record UnsupportedPlatformOption(String name, Optional<String> value) {
|
||||
UnsupportedPlatformOption {
|
||||
Objects.requireNonNull(name);
|
||||
Objects.requireNonNull(value);
|
||||
}
|
||||
|
||||
UnsupportedPlatformOption(String name) {
|
||||
this(name, Optional.empty());
|
||||
}
|
||||
|
||||
UnsupportedPlatformOption(String name, String value) {
|
||||
this(name, Optional.of(value));
|
||||
}
|
||||
|
||||
TestSpec toTestSpec() {
|
||||
return value.map(v -> testSpec().unsupportedPlatformOption(name, v)).orElseGet(
|
||||
() -> testSpec().unsupportedPlatformOption(name)).create();
|
||||
}
|
||||
|
||||
static Collection<Object[]> createTestArgs(UnsupportedPlatformOption... options) {
|
||||
return toTestArgs(Stream.of(options).map(UnsupportedPlatformOption::toTestSpec));
|
||||
}
|
||||
}
|
||||
|
||||
public static Collection<Object[]> winOption() {
|
||||
return UnsupportedPlatformOption.createTestArgs(
|
||||
new UnsupportedPlatformOption("--win-console"),
|
||||
new UnsupportedPlatformOption("--win-dir-chooser"),
|
||||
new UnsupportedPlatformOption("--win-help-url", "url"),
|
||||
new UnsupportedPlatformOption("--win-menu"),
|
||||
new UnsupportedPlatformOption("--win-menu-group", "name"),
|
||||
new UnsupportedPlatformOption("--win-per-user-install"),
|
||||
new UnsupportedPlatformOption("--win-shortcut"),
|
||||
new UnsupportedPlatformOption("--win-shortcut-prompt"),
|
||||
new UnsupportedPlatformOption("--win-update-url", "url"),
|
||||
new UnsupportedPlatformOption("--win-upgrade-uuid", "uuid")
|
||||
);
|
||||
}
|
||||
|
||||
public static Collection<Object[]> linuxOption() {
|
||||
return UnsupportedPlatformOption.createTestArgs(
|
||||
new UnsupportedPlatformOption("--linux-package-name", "name"),
|
||||
new UnsupportedPlatformOption("--linux-deb-maintainer", "email-address"),
|
||||
new UnsupportedPlatformOption("--linux-menu-group", "menu-group-name"),
|
||||
new UnsupportedPlatformOption("--linux-package-deps", "deps"),
|
||||
new UnsupportedPlatformOption("--linux-rpm-license-type", "type"),
|
||||
new UnsupportedPlatformOption("--linux-app-release", "release"),
|
||||
new UnsupportedPlatformOption("--linux-app-category", "category-value"),
|
||||
new UnsupportedPlatformOption("--linux-shortcut")
|
||||
);
|
||||
}
|
||||
|
||||
public static Collection<Object[]> macOption() {
|
||||
return UnsupportedPlatformOption.createTestArgs(
|
||||
new UnsupportedPlatformOption("--mac-package-identifier", "identifier"),
|
||||
new UnsupportedPlatformOption("--mac-package-name", "name"),
|
||||
new UnsupportedPlatformOption("--mac-package-signing-prefix", "prefix"),
|
||||
new UnsupportedPlatformOption("--mac-sign"),
|
||||
new UnsupportedPlatformOption("--mac-signing-keychain", "keychain-name"),
|
||||
new UnsupportedPlatformOption("--mac-signing-key-user-name", "name"),
|
||||
new UnsupportedPlatformOption("--mac-app-store"),
|
||||
new UnsupportedPlatformOption("--mac-entitlements", "path"),
|
||||
new UnsupportedPlatformOption("--mac-app-category", "category"),
|
||||
new UnsupportedPlatformOption("--mac-dmg-content", "additional-content")
|
||||
);
|
||||
}
|
||||
|
||||
private static void defaultInit(JPackageCommand cmd, List<CannedFormattedString> expectedErrors) {
|
||||
|
||||
// Disable default logic adding `--verbose` option
|
||||
// to jpackage command line.
|
||||
@ -158,11 +636,36 @@ public final class ErrorTest {
|
||||
// with jpackage arguments in this test.
|
||||
cmd.ignoreDefaultRuntime(true);
|
||||
|
||||
// Configure jpackage output verifier to look up the list of provided
|
||||
// errors in the order they are specified.
|
||||
cmd.validateOutput(Stream.of(expectedErrors)
|
||||
.map(CannedFormattedString::getValue)
|
||||
.map(TKit::assertTextStream)
|
||||
.reduce(TKit.TextStreamVerifier::andThen).get());
|
||||
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 <T> Collection<Object[]> toTestArgs(Stream<T> stream) {
|
||||
return stream.map(v -> {
|
||||
return new Object[] {v};
|
||||
}).toList();
|
||||
}
|
||||
|
||||
private static Collection<Object[]> fromTestSpecBuilders(Stream<TestSpec.Builder> stream) {
|
||||
return toTestArgs(stream.map(TestSpec.Builder::create));
|
||||
}
|
||||
|
||||
private static String adjustTextStreamVerifierArg(String str) {
|
||||
return LINE_SEP_REGEXP.split(str)[0];
|
||||
}
|
||||
|
||||
private static final Pattern LINE_SEP_REGEXP = Pattern.compile("\\R");
|
||||
|
||||
private static final PackageType NATIVE_TYPE = defaultNativeType();
|
||||
}
|
||||
|
||||
@ -21,12 +21,14 @@
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static jdk.jpackage.test.JPackageStringBundle.MAIN;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.FileAssociations;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.TKit;
|
||||
@ -111,22 +113,16 @@ public class FileAssociationsTest {
|
||||
public static void testNoMime() {
|
||||
final Path propFile = TKit.workDir().resolve("fa.properties");
|
||||
|
||||
PackageTest packageTest = new PackageTest().excludeTypes(PackageType.MAC);
|
||||
|
||||
packageTest.configureHelloApp().addRunOnceInitializer(() -> {
|
||||
initPackageTest().addRunOnceInitializer(() -> {
|
||||
TKit.createPropertiesFile(propFile, Map.of(
|
||||
"extension", "foo",
|
||||
"description", "bar"
|
||||
));
|
||||
}).addInitializer(cmd -> {
|
||||
cmd.addArguments("--file-associations", propFile).saveConsoleOutput(true);
|
||||
}).setExpectedExitCode(1).addBundleVerifier((cmd, result) -> {
|
||||
TKit.assertTextStream(
|
||||
"No MIME types were specified for File Association number 1")
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(
|
||||
"Advice to fix: Specify MIME type for File Association number 1")
|
||||
.apply(result.getOutput().stream());
|
||||
cmd.addArguments("--file-associations", propFile);
|
||||
cmd.validateOutput(
|
||||
MAIN.cannedFormattedString("error.no-content-types-for-file-association", 1),
|
||||
MAIN.cannedFormattedString("error.no-content-types-for-file-association.advice", 1));
|
||||
}).run();
|
||||
}
|
||||
|
||||
@ -134,23 +130,25 @@ public class FileAssociationsTest {
|
||||
public static void testTooManyMimes() {
|
||||
final Path propFile = TKit.workDir().resolve("fa.properties");
|
||||
|
||||
PackageTest packageTest = new PackageTest().excludeTypes(PackageType.MAC);
|
||||
|
||||
packageTest.configureHelloApp().addRunOnceInitializer(() -> {
|
||||
initPackageTest().addRunOnceInitializer(() -> {
|
||||
TKit.createPropertiesFile(propFile, Map.of(
|
||||
"mime-type", "application/x-jpackage-foo, application/x-jpackage-bar",
|
||||
"extension", "foo",
|
||||
"description", "bar"
|
||||
));
|
||||
}).addInitializer(cmd -> {
|
||||
cmd.addArguments("--file-associations", propFile).saveConsoleOutput(true);
|
||||
}).setExpectedExitCode(1).addBundleVerifier((cmd, result) -> {
|
||||
TKit.assertTextStream(
|
||||
"More than one MIME types was specified for File Association number 1")
|
||||
.apply(result.getOutput().stream());
|
||||
TKit.assertTextStream(
|
||||
"Advice to fix: Specify only one MIME type for File Association number 1")
|
||||
.apply(result.getOutput().stream());
|
||||
cmd.addArguments("--file-associations", propFile);
|
||||
cmd.validateOutput(
|
||||
MAIN.cannedFormattedString("error.too-many-content-types-for-file-association", 1),
|
||||
MAIN.cannedFormattedString("error.too-many-content-types-for-file-association.advice", 1));
|
||||
}).run();
|
||||
}
|
||||
|
||||
private static PackageTest initPackageTest() {
|
||||
return new PackageTest()
|
||||
.excludeTypes(PackageType.MAC)
|
||||
.configureHelloApp()
|
||||
.addInitializer(JPackageCommand::setFakeRuntime)
|
||||
.setExpectedExitCode(1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,7 +154,7 @@ public final class JLinkOptionsTest {
|
||||
}
|
||||
|
||||
private final JPackageCommand createJPackageCommand(String javaAppDesc) {
|
||||
return JPackageCommand.helloAppImage(javaAppDesc).ignoreDefaultRuntime(true);
|
||||
return JPackageCommand.helloAppImage(javaAppDesc);
|
||||
}
|
||||
|
||||
private final Set<String> getModulesInRuntime(String ... jlinkOptions) {
|
||||
|
||||
@ -54,13 +54,13 @@ import jdk.jpackage.test.TKit;
|
||||
|
||||
public class JavaOptionsEqualsTest {
|
||||
|
||||
private final static String OPTION1 =
|
||||
private static final String OPTION1 =
|
||||
"--add-exports=java.base/sun.util=me.mymodule.foo,ALL-UNNAMED";
|
||||
private final static String OPTION2 =
|
||||
private static final String OPTION2 =
|
||||
"--add-exports=java.base/sun.security.util=other.mod.bar,ALL-UNNAMED";
|
||||
private final static String WARNING1 =
|
||||
private static final String WARNING1 =
|
||||
"WARNING: Unknown module: me.mymodule.foo";
|
||||
private final static String WARNING2 =
|
||||
private static final String WARNING2 =
|
||||
"WARNING: Unknown module: other.mod.bar";
|
||||
|
||||
private final JPackageCommand cmd;
|
||||
@ -75,17 +75,13 @@ public class JavaOptionsEqualsTest {
|
||||
}
|
||||
|
||||
public JavaOptionsEqualsTest(String javaAppDesc, String[] jpackageArgs) {
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
||||
if (jpackageArgs != null) {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
}
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc).addArguments(jpackageArgs).ignoreFakeRuntime();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
List<String> output = HelloApp.executeLauncher(cmd).getOutput();
|
||||
TKit.assertNotNull(output, "output is null");
|
||||
TKit.assertTextStream(WARNING1).apply(output.stream());
|
||||
TKit.assertTextStream(WARNING2).apply(output.stream());
|
||||
}
|
||||
|
||||
@ -76,7 +76,7 @@ public class JavaOptionsTest {
|
||||
|
||||
public JavaOptionsTest(String javaAppDesc, String[] jpackageArgs,
|
||||
String[] expectedParams) {
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc);
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc).ignoreFakeRuntime();
|
||||
if (jpackageArgs != null) {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
}
|
||||
@ -90,7 +90,6 @@ public class JavaOptionsTest {
|
||||
|
||||
// 2.) run the launcher it generated
|
||||
List<String> output = HelloApp.executeLauncher(cmd).getOutput();
|
||||
TKit.assertNotNull(output, "output is null");
|
||||
for (String expect : expected) {
|
||||
TKit.assertTextStream(expect).apply(output.stream());
|
||||
}
|
||||
|
||||
@ -39,10 +39,13 @@ import java.util.stream.Stream;
|
||||
import jdk.jpackage.internal.util.function.ThrowingConsumer;
|
||||
import jdk.jpackage.test.Annotations.Parameters;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.CannedFormattedString;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.CfgFile;
|
||||
import jdk.jpackage.test.Executor;
|
||||
import jdk.jpackage.test.HelloApp;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import static jdk.jpackage.test.JPackageCommand.cannedArgument;
|
||||
import jdk.jpackage.test.JavaAppDesc;
|
||||
import jdk.jpackage.test.JavaTool;
|
||||
import jdk.jpackage.test.TKit;
|
||||
@ -87,8 +90,8 @@ public final class MainClassTest {
|
||||
return this;
|
||||
}
|
||||
|
||||
Script expectedErrorMessage(String v) {
|
||||
expectedErrorMessage = v;
|
||||
Script expectedErrorMessage(String key, Object... args) {
|
||||
expectedErrorMessage = JPackageStringBundle.MAIN.cannedFormattedString(key, args);
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -131,7 +134,7 @@ public final class MainClassTest {
|
||||
private boolean withJLink;
|
||||
private MainClassType mainClass;
|
||||
private MainClassType jarMainClass;
|
||||
private String expectedErrorMessage;
|
||||
private CannedFormattedString expectedErrorMessage;
|
||||
}
|
||||
|
||||
public MainClassTest(Script script) {
|
||||
@ -194,11 +197,12 @@ public final class MainClassTest {
|
||||
if (withMainClass.contains(jarMainClass)
|
||||
|| withMainClass.contains(mainClass)) {
|
||||
} else if (modular) {
|
||||
script.expectedErrorMessage(
|
||||
"Error: Main application class is missing");
|
||||
script.expectedErrorMessage("ERR_NoMainClass");
|
||||
} else {
|
||||
script.expectedErrorMessage(
|
||||
"A main class was not specified nor was one found in the jar");
|
||||
"error.no-main-class-with-main-jar", cannedArgument(cmd -> {
|
||||
return cmd.getArgumentValue("--main-jar");
|
||||
}, "MAIN-JAR"));
|
||||
}
|
||||
|
||||
scripts.add(new Script[]{script});
|
||||
@ -218,11 +222,7 @@ public final class MainClassTest {
|
||||
if (script.expectedErrorMessage != null) {
|
||||
// This is the case when main class is not found nor in jar
|
||||
// file nor on command line.
|
||||
List<String> output = cmd
|
||||
.saveConsoleOutput(true)
|
||||
.execute(1)
|
||||
.getOutput();
|
||||
TKit.assertTextStream(script.expectedErrorMessage).apply(output.stream());
|
||||
cmd.validateOutput(script.expectedErrorMessage).execute(1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -30,10 +30,12 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import jdk.jpackage.test.CannedFormattedString;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.JavaAppDesc;
|
||||
import jdk.jpackage.test.HelloApp;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.JPackageStringBundle;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
import jdk.jpackage.test.Annotations.Parameters;
|
||||
@ -121,25 +123,22 @@ public final class ModulePathTest {
|
||||
if (withGoodPath) {
|
||||
cmd.executeAndAssertHelloAppImageCreated();
|
||||
} else {
|
||||
final String expectedErrorMessage;
|
||||
final CannedFormattedString expectedErrorMessage;
|
||||
if (modulePathArgs.isEmpty()) {
|
||||
expectedErrorMessage = "Error: Missing argument: --runtime-image or --module-path";
|
||||
expectedErrorMessage = JPackageStringBundle.MAIN.cannedFormattedString(
|
||||
"ERR_MissingArgument", "--runtime-image or --module-path");
|
||||
} else {
|
||||
expectedErrorMessage = String.format(
|
||||
"Failed to find %s module in module path", appDesc.moduleName());
|
||||
expectedErrorMessage = JPackageStringBundle.MAIN.cannedFormattedString(
|
||||
"error.no-module-in-path", appDesc.moduleName());
|
||||
}
|
||||
|
||||
List<String> output = cmd
|
||||
.saveConsoleOutput(true)
|
||||
.execute(1)
|
||||
.getOutput();
|
||||
TKit.assertTextStream(expectedErrorMessage).apply(output.stream());
|
||||
cmd.validateOutput(expectedErrorMessage).execute(1);
|
||||
}
|
||||
}
|
||||
|
||||
private final List<String> modulePathArgs;
|
||||
|
||||
private final static String GOOD_PATH = "@GoodPath@";
|
||||
private final static String EMPTY_DIR = "@EmptyDir@";
|
||||
private final static String NON_EXISTING_DIR = "@NonExistingDir@";
|
||||
private static final String GOOD_PATH = "@GoodPath@";
|
||||
private static final String EMPTY_DIR = "@EmptyDir@";
|
||||
private static final String NON_EXISTING_DIR = "@NonExistingDir@";
|
||||
}
|
||||
|
||||
@ -1,91 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
* 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 jpackage application version testing
|
||||
* @library /test/jdk/tools/jpackage/helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @compile -Xlint:all -Werror NonExistentTest.java
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=NonExistentTest
|
||||
*/
|
||||
|
||||
public final class NonExistentTest {
|
||||
|
||||
private final String expectedError;
|
||||
private final JPackageCommand cmd;
|
||||
|
||||
@Parameters
|
||||
public static Collection<?> input() {
|
||||
return List.of(new Object[][]{
|
||||
// non-existent icon
|
||||
{"Hello",
|
||||
new String[]{"--icon", "non-existent"},
|
||||
"Error:"},
|
||||
{"com.other/com.other.Hello",
|
||||
new String[]{"--icon", "non-existent"},
|
||||
"Error:"},
|
||||
// non-existent input
|
||||
{"Hello",
|
||||
new String[]{"--input", "non-existent"},
|
||||
"Exception:"},
|
||||
{"com.other/com.other.Hello",
|
||||
new String[]{"--input", "non-existent"},
|
||||
"Exception:"},
|
||||
// non-existent resource-dir
|
||||
{"Hello",
|
||||
new String[]{"--resource-dir", "non-existent"},
|
||||
"Specified resource directory"},
|
||||
{"com.other/com.other.Hello",
|
||||
new String[]{"--resource-dir", "non-existent"},
|
||||
"Specified resource directory"},
|
||||
});
|
||||
}
|
||||
|
||||
public NonExistentTest(String javaAppDesc, String[] jpackageArgs,
|
||||
String expectedError) {
|
||||
this.expectedError = expectedError;
|
||||
|
||||
cmd = JPackageCommand.helloAppImage(javaAppDesc)
|
||||
.saveConsoleOutput(true).dumpOutput(true);
|
||||
if (jpackageArgs != null) {
|
||||
cmd.addArguments(jpackageArgs);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
List<String> output = cmd.execute(1).getOutput();
|
||||
TKit.assertNotNull(output, "output is null");
|
||||
TKit.assertTextStream(expectedError).apply(output.stream());
|
||||
}
|
||||
}
|
||||
@ -1,118 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2022, 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.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import jdk.jpackage.test.AppImageFile;
|
||||
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 output for erroneous input with --type "app-image" and --app-image
|
||||
* @library /test/jdk/tools/jpackage/helpers
|
||||
* @build jdk.jpackage.test.*
|
||||
* @compile -Xlint:all -Werror PredefinedAppImageErrorTest.java
|
||||
*
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=PredefinedAppImageErrorTest
|
||||
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useExecutableByDefault
|
||||
*
|
||||
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
|
||||
* --jpt-run=PredefinedAppImageErrorTest
|
||||
* --jpt-before-run=jdk.jpackage.test.JPackageCommand.useToolProviderByDefault
|
||||
*/
|
||||
|
||||
public final class PredefinedAppImageErrorTest {
|
||||
|
||||
private final String expectedError;
|
||||
private final JPackageCommand cmd;
|
||||
|
||||
@Parameters
|
||||
public static Collection<?> input() throws IOException {
|
||||
return List.of(new Object[][]{
|
||||
// --mac-sign is required
|
||||
{"Hello",
|
||||
null,
|
||||
new String[]{"--input", "--dest", "--name", "--main-jar", "--main-class"},
|
||||
TKit.isOSX() ?
|
||||
"--mac-sign option is required" :
|
||||
"Option [--app-image] is not valid with type [app-image]"
|
||||
},
|
||||
// --mac-app-store is required
|
||||
{"Hello",
|
||||
new String[]{"--mac-sign", "--mac-app-store", "--mac-app-image-sign-identity", "test"},
|
||||
new String[]{"--input", "--dest", "--name", "--main-jar", "--main-class"},
|
||||
TKit.isOSX() ?
|
||||
"Option [--mac-app-store] is not valid" :
|
||||
"Option [--mac-sign] is not valid on this platform"
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
public PredefinedAppImageErrorTest(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() throws IOException {
|
||||
getDummyAppImage(cmd);
|
||||
|
||||
List<String> output = cmd.execute(1).getOutput();
|
||||
TKit.assertNotNull(output, "output is null");
|
||||
TKit.assertTextStream(expectedError).apply(output.stream());
|
||||
}
|
||||
|
||||
private void getDummyAppImage(JPackageCommand cmd) throws IOException {
|
||||
Path dummyAppFolder
|
||||
= TKit.createTempDirectory("DummyAppImage").toAbsolutePath();
|
||||
|
||||
Path dummyAppFile
|
||||
= dummyAppFolder.resolve("DummyAppFile").toAbsolutePath();
|
||||
Files.createFile(dummyAppFile);
|
||||
|
||||
cmd.addArguments("--app-image", dummyAppFolder.toString());
|
||||
new AppImageFile("PredefinedAppImageErrorTest", "Hello").save(dummyAppFolder);
|
||||
}
|
||||
|
||||
}
|
||||
@ -29,10 +29,12 @@ import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import jdk.jpackage.test.PackageType;
|
||||
import jdk.jpackage.test.RunnablePackageTest.Action;
|
||||
import jdk.jpackage.test.PackageTest;
|
||||
import jdk.jpackage.test.JPackageCommand;
|
||||
import jdk.jpackage.test.TKit;
|
||||
import jdk.jpackage.test.Annotations.Test;
|
||||
import jdk.jpackage.test.Annotations.Parameter;
|
||||
import jdk.jpackage.test.Executor;
|
||||
import jdk.jpackage.test.JavaTool;
|
||||
import jdk.jpackage.test.LinuxHelper;
|
||||
@ -83,17 +85,24 @@ public class RuntimePackageTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testUsrInstallDir() {
|
||||
@Parameter("/usr")
|
||||
@Parameter("/usr/lib/Java")
|
||||
public static void testUsrInstallDir(String installDir) {
|
||||
init(PackageType.LINUX)
|
||||
.addInitializer(cmd -> cmd.addArguments("--install-dir", "/usr"))
|
||||
.run();
|
||||
}
|
||||
|
||||
@Test
|
||||
public static void testUsrInstallDir2() {
|
||||
init(PackageType.LINUX)
|
||||
.addInitializer(cmd -> cmd.addArguments("--install-dir", "/usr/lib/Java"))
|
||||
.run();
|
||||
public static void testName() {
|
||||
// Test that jpackage can derive package name from the path to runtime image.
|
||||
init(PackageType.NATIVE)
|
||||
.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`
|
||||
// command line jpackage will create a package named 'sed' that will conflict
|
||||
// with the default 'sed' package.
|
||||
.run(Action.CREATE_AND_UNPACK);
|
||||
}
|
||||
|
||||
private static PackageTest init(Set<PackageType> types) {
|
||||
@ -157,7 +166,8 @@ public class RuntimePackageTest {
|
||||
"Check the package doesn't deliver [%s] copyright file",
|
||||
copyright));
|
||||
}
|
||||
});
|
||||
})
|
||||
.forTypes(types);
|
||||
}
|
||||
|
||||
private static Set<Path> listFiles(Path root) throws IOException {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user