undefect. CWE-407 — 63 sites patched across 27 ecosystems
Authors: russell@unturf.com · brackishbert@gmail.com · foxhop.net · TimeHexOn.com Patches, unit tests, benchmarks, whitepaper, and outreach briefs. Public domain — no copyright claimed. Use freely.
This commit is contained in:
commit
0a580b313d
70422 changed files with 17213626 additions and 0 deletions
|
|
@ -0,0 +1,706 @@
|
|||
/*
|
||||
* Copyright (c) 2024, Red Hat, Inc.
|
||||
* 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.FileVisitResult;
|
||||
import java.nio.file.FileVisitor;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.SimpleFileVisitor;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
import jdk.tools.jlink.internal.LinkableRuntimeImage;
|
||||
import tests.Helper;
|
||||
import tests.JImageGenerator;
|
||||
import tests.JImageGenerator.JLinkTask;
|
||||
import tests.JImageValidator;
|
||||
|
||||
public abstract class AbstractLinkableRuntimeTest {
|
||||
|
||||
protected static final boolean DEBUG = true;
|
||||
|
||||
public void run() throws Exception {
|
||||
boolean isLinkableRuntime = LinkableRuntimeImage.isLinkableRuntime();
|
||||
Helper helper = Helper.newHelper(isLinkableRuntime);
|
||||
if (helper == null) {
|
||||
System.err.println(AbstractLinkableRuntimeTest.class.getSimpleName() +
|
||||
": Test not run");
|
||||
return;
|
||||
}
|
||||
runTest(helper, isLinkableRuntime);
|
||||
System.out.println(getClass().getSimpleName() + " PASSED!");
|
||||
}
|
||||
|
||||
/**
|
||||
* Main test entry point that actual tests ought to override.
|
||||
*
|
||||
* @param helper The jlink helper
|
||||
* @param isLinkableRuntime {@code true} iff the JDK build under test already
|
||||
* includes the linkable runtime capability in jlink.
|
||||
* @throws Exception
|
||||
*/
|
||||
abstract void runTest(Helper helper, boolean isLinkableRuntime) throws Exception;
|
||||
|
||||
/**
|
||||
* Ensure 'java --list-modules' lists the correct set of modules in the given
|
||||
* image.
|
||||
*
|
||||
* @param jlinkImage
|
||||
* @param expectedModules
|
||||
*/
|
||||
protected void verifyListModules(Path image,
|
||||
List<String> expectedModules) throws Exception {
|
||||
OutputAnalyzer out = runJavaCmd(image, List.of("--list-modules"));
|
||||
List<String> actual = parseListMods(out.getStdout());
|
||||
Collections.sort(actual);
|
||||
if (!expectedModules.equals(actual)) {
|
||||
throw new AssertionError("Different modules! Expected " + expectedModules + " got: " + actual);
|
||||
}
|
||||
}
|
||||
|
||||
protected OutputAnalyzer runJavaCmd(Path image, List<String> options) throws Exception {
|
||||
Path targetJava = image.resolve("bin").resolve(getJava());
|
||||
List<String> cmd = new ArrayList<>();
|
||||
cmd.add(targetJava.toString());
|
||||
for (String opt: options) {
|
||||
cmd.add(opt);
|
||||
}
|
||||
List<String> javaCmd = Collections.unmodifiableList(cmd);
|
||||
OutputAnalyzer out;
|
||||
try {
|
||||
out = ProcessTools.executeCommand(javaCmd.toArray(new String[0]));
|
||||
} catch (Throwable e) {
|
||||
throw new Exception("Process failed to execute", e);
|
||||
}
|
||||
if (out.getExitValue() != 0) {
|
||||
if (DEBUG) {
|
||||
System.err.println("Process stdout was: ");
|
||||
System.err.println(out.getStdout());
|
||||
System.err.println("Process stderr was: ");
|
||||
System.err.println(out.getStderr());
|
||||
}
|
||||
throw new AssertionError("'" + javaCmd.stream().collect(Collectors.joining(" ")) + "'"
|
||||
+ " expected to succeed!");
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
protected Path createJavaImageRuntimeLink(BaseJlinkSpec baseSpec) throws Exception {
|
||||
return createJavaImageRuntimeLink(baseSpec, Collections.emptySet() /* exclude all jmods */);
|
||||
}
|
||||
|
||||
protected Path createJavaImageRuntimeLink(BaseJlinkSpec baseSpec, Set<String> excludedJmods) throws Exception {
|
||||
// Be sure we have a JDK without JMODs
|
||||
Path runtimeJlinkImage = createRuntimeLinkImage(baseSpec, excludedJmods);
|
||||
|
||||
// On Windows jvm.dll is in 'bin' after the jlink
|
||||
Path libjvm = Path.of((isWindows() ? "bin" : "lib"), "server", System.mapLibraryName("jvm"));
|
||||
JlinkSpecBuilder builder = new JlinkSpecBuilder();
|
||||
// And expect libjvm (not part of the jimage) to be present in the resulting image
|
||||
builder.expectedFile(libjvm.toString())
|
||||
.helper(baseSpec.getHelper())
|
||||
.name(baseSpec.getName())
|
||||
.validatingModule(baseSpec.getValidatingModule())
|
||||
.imagePath(runtimeJlinkImage)
|
||||
.expectedLocation("/java.base/java/lang/String.class");
|
||||
for (String m: baseSpec.getModules()) {
|
||||
builder.addModule(m);
|
||||
}
|
||||
for (String extra: baseSpec.getExtraOptions()) {
|
||||
builder.extraJlinkOpt(extra);
|
||||
}
|
||||
return jlinkUsingImage(builder.build());
|
||||
}
|
||||
|
||||
protected Path jlinkUsingImage(JlinkSpec spec) throws Exception {
|
||||
return jlinkUsingImage(spec, new RuntimeLinkOutputAnalyzerHandler());
|
||||
}
|
||||
|
||||
protected Path jlinkUsingImage(JlinkSpec spec, OutputAnalyzerHandler handler) throws Exception {
|
||||
return jlinkUsingImage(spec, handler, new DefaultSuccessExitPredicate());
|
||||
}
|
||||
|
||||
protected Path jlinkUsingImage(JlinkSpec spec, OutputAnalyzerHandler handler, Predicate<OutputAnalyzer> exitChecker) throws Exception {
|
||||
String generatedImage = "target-run-time-" + spec.getName();
|
||||
Path targetImageDir = spec.getHelper().createNewImageDir(generatedImage);
|
||||
Path targetJlink = spec.getImageToUse().resolve("bin").resolve(getJlink());
|
||||
String[] jlinkCmdArray = new String[] {
|
||||
targetJlink.toString(),
|
||||
"--output", targetImageDir.toString(),
|
||||
"--verbose",
|
||||
"--add-modules", spec.getModules().stream().collect(Collectors.joining(","))
|
||||
};
|
||||
List<String> jlinkCmd = new ArrayList<>();
|
||||
jlinkCmd.addAll(Arrays.asList(jlinkCmdArray));
|
||||
if (spec.getExtraJlinkOpts() != null && !spec.getExtraJlinkOpts().isEmpty()) {
|
||||
jlinkCmd.addAll(spec.getExtraJlinkOpts());
|
||||
}
|
||||
if (spec.getModulePath() != null) {
|
||||
for (String mp: spec.getModulePath()) {
|
||||
jlinkCmd.add("--module-path");
|
||||
jlinkCmd.add(mp);
|
||||
}
|
||||
}
|
||||
jlinkCmd = Collections.unmodifiableList(jlinkCmd); // freeze
|
||||
System.out.println("DEBUG: run-time image based jlink command: " +
|
||||
jlinkCmd.stream().collect(Collectors.joining(" ")));
|
||||
OutputAnalyzer analyzer = null;
|
||||
try {
|
||||
analyzer = ProcessTools.executeProcess(jlinkCmd.toArray(new String[0]));
|
||||
} catch (Throwable t) {
|
||||
throw new AssertionError("Executing process failed!", t);
|
||||
}
|
||||
if (!exitChecker.test(analyzer)) {
|
||||
if (DEBUG) {
|
||||
System.err.println("Process stdout was: ");
|
||||
System.err.println(analyzer.getStdout());
|
||||
System.err.println("Process stderr was: ");
|
||||
System.err.println(analyzer.getStderr());
|
||||
}
|
||||
// if the exit checker failed, we expected the other outcome
|
||||
// i.e. fail for success and success for fail.
|
||||
boolean successExit = analyzer.getExitValue() == 0;
|
||||
String msg = String.format("Expected jlink to %s given a linkable run-time image. " +
|
||||
"Exit code was: %d",
|
||||
(successExit ? "fail" : "pass"), analyzer.getExitValue());
|
||||
throw new AssertionError(msg);
|
||||
}
|
||||
handler.handleAnalyzer(analyzer); // Give tests a chance to process in/output
|
||||
|
||||
// validate the resulting image; Includes running 'java -version', only do this
|
||||
// if the jlink succeeded.
|
||||
if (analyzer.getExitValue() == 0) {
|
||||
JImageValidator validator = new JImageValidator(spec.getValidatingModule(), spec.getExpectedLocations(),
|
||||
targetImageDir.toFile(), spec.getUnexpectedLocations(), Collections.emptyList(), spec.getExpectedFiles());
|
||||
validator.validate(); // This doesn't validate locations
|
||||
if (!spec.getExpectedLocations().isEmpty() || !spec.getUnexpectedLocations().isEmpty()) {
|
||||
JImageValidator.validate(targetImageDir.resolve("lib").resolve("modules"), spec.getExpectedLocations(), spec.getUnexpectedLocations());
|
||||
}
|
||||
}
|
||||
return targetImageDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the test for execution. This assumes the current runtime
|
||||
* supports linking from it. However, since the 'jmods' dir might be present
|
||||
* (default jmods module path), the 'jmods' directory needs to get removed
|
||||
* to provoke actual linking from the run-time image.
|
||||
*
|
||||
* @param baseSpec
|
||||
* @return A path to a JDK that is capable for linking from the run-time
|
||||
* image.
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Path createRuntimeLinkImage(BaseJlinkSpec baseSpec) throws Exception {
|
||||
return createRuntimeLinkImage(baseSpec, Collections.emptySet() /* exclude all jmods */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the test for execution. Creates a JDK with a jlink that has the
|
||||
* capability to link from the run-time image (if needed). It further
|
||||
* ensures that if packaged modules ('jmods' dir) are present, to remove
|
||||
* them entirely or as specified in the {@link excludedJmodFiles} set. If
|
||||
* that set is empty, all packaged modules will be removed. Note that with
|
||||
* packaged modules present no run-time image based linking would be done.
|
||||
*
|
||||
* @param baseSpec
|
||||
* The specification for the custom - run-time image link capable
|
||||
* - JDK to create via jlink (if any)
|
||||
* @param excludedJmods
|
||||
* The set of jmod files to exclude in the base JDK. Empty set if
|
||||
* all JMODs should be removed.
|
||||
* @return A path to a JDK, including jdk.jlink, that has the run-time image
|
||||
* link capability.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Path createRuntimeLinkImage(BaseJlinkSpec baseSpec,
|
||||
Set<String> excludedJmodFiles) throws Exception {
|
||||
// Depending on the shape of the JDK under test, we either only filter
|
||||
// jmod files or create a run-time image link capable JDK on-the-fly.
|
||||
Path from = null;
|
||||
Path runtimeJlinkImage = null;
|
||||
String finalName = baseSpec.getName() + "-jlink";
|
||||
if (baseSpec.isLinkableRuntime()) {
|
||||
// The build is already run-time image link capable
|
||||
String javaHome = System.getProperty("java.home");
|
||||
from = Path.of(javaHome);
|
||||
} else {
|
||||
// Create a run-time image capable JDK using --generate-linkable-runtime
|
||||
Path tempRuntimeImage = Path.of(finalName + "-tmp");
|
||||
JLinkTask task = JImageGenerator.getJLinkTask();
|
||||
task.output(tempRuntimeImage)
|
||||
.addMods("jdk.jlink") // jdk.jlink module is always needed for the test
|
||||
.option("--generate-linkable-runtime");
|
||||
if (baseJDKhasPackagedModules()) {
|
||||
Path jmodsPath = tempRuntimeImage.resolve("jmods");
|
||||
task.option("--keep-packaged-modules=" + jmodsPath);
|
||||
}
|
||||
for (String module: baseSpec.getModules()) {
|
||||
task.addMods(module);
|
||||
}
|
||||
task.call().assertSuccess();
|
||||
from = tempRuntimeImage;
|
||||
}
|
||||
|
||||
// Create the target directory
|
||||
runtimeJlinkImage = baseSpec.getHelper().createNewImageDir(finalName);
|
||||
|
||||
// Remove JMODs as needed for the test
|
||||
copyJDKTreeWithoutSpecificJmods(from, runtimeJlinkImage, excludedJmodFiles);
|
||||
// Verify the base image is actually without desired packaged modules
|
||||
if (excludedJmodFiles.isEmpty()) {
|
||||
if (Files.exists(runtimeJlinkImage.resolve("jmods"))) {
|
||||
throw new AssertionError("Must not contain 'jmods' directory");
|
||||
}
|
||||
} else {
|
||||
Path basePath = runtimeJlinkImage.resolve("jmods");
|
||||
for (String jmodFile: excludedJmodFiles) {
|
||||
Path unexpectedFile = basePath.resolve(Path.of(jmodFile));
|
||||
if (Files.exists(unexpectedFile)) {
|
||||
throw new AssertionError("Must not contain jmod: " + unexpectedFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
return runtimeJlinkImage;
|
||||
}
|
||||
|
||||
private boolean baseJDKhasPackagedModules() {
|
||||
Path jmodsPath = Path.of(System.getProperty("java.home"), "jmods");
|
||||
return jmodsPath.toFile().exists();
|
||||
}
|
||||
|
||||
private void copyJDKTreeWithoutSpecificJmods(Path from,
|
||||
Path to,
|
||||
Set<String> excludedJmods) throws Exception {
|
||||
if (Files.exists(to)) {
|
||||
throw new AssertionError("Expected target dir '" + to + "' to exist");
|
||||
}
|
||||
FileVisitor<Path> fileVisitor = null;
|
||||
if (excludedJmods.isEmpty()) {
|
||||
fileVisitor = new ExcludeAllJmodsFileVisitor(from, to);
|
||||
} else {
|
||||
fileVisitor = new FileExcludingFileVisitor(excludedJmods,
|
||||
from,
|
||||
to);
|
||||
}
|
||||
Files.walkFileTree(from, fileVisitor);
|
||||
}
|
||||
|
||||
private List<String> parseListMods(String output) throws Exception {
|
||||
List<String> outputLines = new ArrayList<>();
|
||||
try (Scanner lineScan = new Scanner(output)) {
|
||||
while (lineScan.hasNextLine()) {
|
||||
outputLines.add(lineScan.nextLine());
|
||||
}
|
||||
}
|
||||
return outputLines.stream()
|
||||
.map(a -> { return a.split("@", 2)[0];})
|
||||
.filter(a -> !a.isBlank())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String getJlink() {
|
||||
return getBinary("jlink");
|
||||
}
|
||||
|
||||
private String getJava() {
|
||||
return getBinary("java");
|
||||
}
|
||||
|
||||
private String getBinary(String binary) {
|
||||
return isWindows() ? binary + ".exe" : binary;
|
||||
}
|
||||
|
||||
protected static boolean isWindows() {
|
||||
return System.getProperty("os.name").startsWith("Windows");
|
||||
}
|
||||
|
||||
static class ExcludeAllJmodsFileVisitor extends SimpleFileVisitor<Path> {
|
||||
private final Path root;
|
||||
private final Path destination;
|
||||
|
||||
private ExcludeAllJmodsFileVisitor(Path root,
|
||||
Path destination) {
|
||||
this.destination = destination;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs) throws IOException {
|
||||
Objects.requireNonNull(dir);
|
||||
Path relative = root.relativize(dir);
|
||||
if (relative.getFileName().equals(Path.of("jmods"))) {
|
||||
return FileVisitResult.SKIP_SUBTREE;
|
||||
}
|
||||
// Create dir in destination location
|
||||
Path targetDir = destination.resolve(relative);
|
||||
if (!Files.exists(targetDir)) {
|
||||
Files.createDirectory(targetDir);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
throws IOException {
|
||||
Path relative = root.relativize(file);
|
||||
Files.copy(file, destination.resolve(relative), StandardCopyOption.REPLACE_EXISTING);
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
}
|
||||
|
||||
static class FileExcludingFileVisitor extends SimpleFileVisitor<Path> {
|
||||
|
||||
private final Set<String> filesToExclude;
|
||||
private final Path root;
|
||||
private final Path destination;
|
||||
|
||||
private FileExcludingFileVisitor(Set<String> filesToExclude,
|
||||
Path root,
|
||||
Path destination) {
|
||||
this.filesToExclude = filesToExclude;
|
||||
this.destination = destination;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult preVisitDirectory(Path dir,
|
||||
BasicFileAttributes attrs) throws IOException {
|
||||
Objects.requireNonNull(dir);
|
||||
Path relative = root.relativize(dir);
|
||||
// Create dir in destination location
|
||||
Path targetDir = destination.resolve(relative);
|
||||
if (!Files.exists(targetDir)) {
|
||||
Files.createDirectory(targetDir);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
throws IOException {
|
||||
Path relative = root.relativize(file);
|
||||
// Skip files as determined by the exclude set
|
||||
String fileName = file.getFileName().toString();
|
||||
if (!filesToExclude.contains(fileName)) {
|
||||
Files.copy(file, destination.resolve(relative), StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
return FileVisitResult.CONTINUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class BaseJlinkSpec {
|
||||
final Helper helper;
|
||||
final String name;
|
||||
final String validatingModule;
|
||||
final List<String> modules;
|
||||
final List<String> extraOptions;
|
||||
final boolean isLinkableRuntime;
|
||||
|
||||
BaseJlinkSpec(Helper helper, String name, String validatingModule,
|
||||
List<String> modules, List<String> extraOptions, boolean isLinkableRuntime) {
|
||||
this.helper = helper;
|
||||
this.name = name;
|
||||
this.modules = modules;
|
||||
this.extraOptions = extraOptions;
|
||||
this.validatingModule = validatingModule;
|
||||
this.isLinkableRuntime = isLinkableRuntime;
|
||||
}
|
||||
|
||||
public String getValidatingModule() {
|
||||
return validatingModule;
|
||||
}
|
||||
|
||||
public Helper getHelper() {
|
||||
return helper;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getModules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
public List<String> getExtraOptions() {
|
||||
return extraOptions;
|
||||
}
|
||||
|
||||
public boolean isLinkableRuntime() {
|
||||
return isLinkableRuntime;
|
||||
}
|
||||
}
|
||||
|
||||
static class BaseJlinkSpecBuilder {
|
||||
Helper helper;
|
||||
String name;
|
||||
String validatingModule;
|
||||
List<String> modules = new ArrayList<>();
|
||||
List<String> extraOptions = new ArrayList<>();
|
||||
boolean isLinkableRuntime;
|
||||
|
||||
BaseJlinkSpecBuilder addModule(String module) {
|
||||
modules.add(module);
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpecBuilder addExtraOption(String option) {
|
||||
extraOptions.add(option);
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpecBuilder setLinkableRuntime() {
|
||||
isLinkableRuntime = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpecBuilder helper(Helper helper) {
|
||||
this.helper = helper;
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpecBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpecBuilder validatingModule(String module) {
|
||||
this.validatingModule = module;
|
||||
return this;
|
||||
}
|
||||
|
||||
BaseJlinkSpec build() {
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("Name must be set");
|
||||
}
|
||||
if (helper == null) {
|
||||
throw new IllegalStateException("helper must be set");
|
||||
}
|
||||
if (modules.isEmpty()) {
|
||||
throw new IllegalStateException("modules must be set");
|
||||
}
|
||||
if (validatingModule == null) {
|
||||
throw new IllegalStateException("the module which should get validated must be set");
|
||||
}
|
||||
return new BaseJlinkSpec(helper, name, validatingModule, modules, extraOptions, isLinkableRuntime);
|
||||
}
|
||||
}
|
||||
|
||||
static class JlinkSpec {
|
||||
final Path imageToUse;
|
||||
final Helper helper;
|
||||
final String name;
|
||||
final List<String> modules;
|
||||
final String validatingModule;
|
||||
final List<String> expectedLocations;
|
||||
final List<String> unexpectedLocations;
|
||||
final String[] expectedFiles;
|
||||
final List<String> extraJlinkOpts;
|
||||
final List<String> modulePath;
|
||||
|
||||
JlinkSpec(Path imageToUse, Helper helper, String name, List<String> modules,
|
||||
String validatingModule, List<String> expectedLocations,
|
||||
List<String> unexpectedLocations, String[] expectedFiles,
|
||||
List<String> extraJlinkOpts,
|
||||
List<String> modulePath) {
|
||||
this.imageToUse = imageToUse;
|
||||
this.helper = helper;
|
||||
this.name = name;
|
||||
this.modules = modules;
|
||||
this.validatingModule = validatingModule;
|
||||
this.expectedLocations = expectedLocations;
|
||||
this.unexpectedLocations = unexpectedLocations;
|
||||
this.expectedFiles = expectedFiles;
|
||||
this.extraJlinkOpts = extraJlinkOpts;
|
||||
this.modulePath = modulePath;
|
||||
}
|
||||
|
||||
public Path getImageToUse() {
|
||||
return imageToUse;
|
||||
}
|
||||
|
||||
public Helper getHelper() {
|
||||
return helper;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public List<String> getModules() {
|
||||
return modules;
|
||||
}
|
||||
|
||||
public String getValidatingModule() {
|
||||
return validatingModule;
|
||||
}
|
||||
|
||||
public List<String> getExpectedLocations() {
|
||||
return expectedLocations;
|
||||
}
|
||||
|
||||
public List<String> getUnexpectedLocations() {
|
||||
return unexpectedLocations;
|
||||
}
|
||||
|
||||
public String[] getExpectedFiles() {
|
||||
return expectedFiles;
|
||||
}
|
||||
|
||||
public List<String> getExtraJlinkOpts() {
|
||||
return extraJlinkOpts;
|
||||
}
|
||||
|
||||
public List<String> getModulePath() {
|
||||
return modulePath;
|
||||
}
|
||||
}
|
||||
|
||||
static class JlinkSpecBuilder {
|
||||
Path imageToUse;
|
||||
Helper helper;
|
||||
String name;
|
||||
List<String> modules = new ArrayList<>();
|
||||
String validatingModule;
|
||||
List<String> expectedLocations = new ArrayList<>();
|
||||
List<String> unexpectedLocations = new ArrayList<>();
|
||||
List<String> expectedFiles = new ArrayList<>();
|
||||
List<String> extraJlinkOpts = new ArrayList<>();
|
||||
List<String> modulePath = new ArrayList<>();
|
||||
|
||||
JlinkSpec build() {
|
||||
if (imageToUse == null) {
|
||||
throw new IllegalStateException("No image to use for jlink specified!");
|
||||
}
|
||||
if (helper == null) {
|
||||
throw new IllegalStateException("No helper specified!");
|
||||
}
|
||||
if (name == null) {
|
||||
throw new IllegalStateException("No name for the image location specified!");
|
||||
}
|
||||
if (validatingModule == null) {
|
||||
throw new IllegalStateException("No module specified for after generation validation!");
|
||||
}
|
||||
return new JlinkSpec(imageToUse,
|
||||
helper,
|
||||
name,
|
||||
modules,
|
||||
validatingModule,
|
||||
expectedLocations,
|
||||
unexpectedLocations,
|
||||
expectedFiles.toArray(new String[0]),
|
||||
extraJlinkOpts,
|
||||
modulePath);
|
||||
}
|
||||
|
||||
JlinkSpecBuilder imagePath(Path image) {
|
||||
this.imageToUse = image;
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder helper(Helper helper) {
|
||||
this.helper = helper;
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder name(String name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder addModule(String module) {
|
||||
modules.add(module);
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder validatingModule(String module) {
|
||||
this.validatingModule = module;
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder addModulePath(String modulePath) {
|
||||
this.modulePath.add(modulePath);
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder expectedLocation(String location) {
|
||||
expectedLocations.add(location);
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder unexpectedLocation(String location) {
|
||||
unexpectedLocations.add(location);
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder expectedFile(String file) {
|
||||
expectedFiles.add(file);
|
||||
return this;
|
||||
}
|
||||
|
||||
JlinkSpecBuilder extraJlinkOpt(String opt) {
|
||||
extraJlinkOpts.add(opt);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
static abstract class OutputAnalyzerHandler {
|
||||
|
||||
public abstract void handleAnalyzer(OutputAnalyzer out);
|
||||
|
||||
}
|
||||
|
||||
static class RuntimeLinkOutputAnalyzerHandler extends OutputAnalyzerHandler {
|
||||
|
||||
@Override
|
||||
public void handleAnalyzer(OutputAnalyzer out) {
|
||||
out.shouldContain("Linking based on the current run-time image");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class DefaultSuccessExitPredicate implements Predicate<OutputAnalyzer> {
|
||||
|
||||
@Override
|
||||
public boolean test(OutputAnalyzer t) {
|
||||
return t.getExitValue() == 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue