8194937: Inconsistent behavior of --validate-modules when combined with -m and other options
Reviewed-by: mchung
This commit is contained in:
parent
a6ac56a69e
commit
91d9f3fbe0
@ -136,7 +136,7 @@ public final class ModuleBootstrap {
|
||||
/**
|
||||
* Initialize the module system, returning the boot layer.
|
||||
*
|
||||
* @see java.lang.System#initPhase2()
|
||||
* @see java.lang.System#initPhase2(boolean, boolean)
|
||||
*/
|
||||
public static ModuleLayer boot() throws Exception {
|
||||
|
||||
@ -213,11 +213,13 @@ public final class ModuleBootstrap {
|
||||
Counters.add("jdk.module.boot.2.defineBaseTime", t2);
|
||||
|
||||
|
||||
// Step 2a: If --validate-modules is specified then the VM needs to
|
||||
// start with only system modules, all other options are ignored.
|
||||
// Step 2a: Scan all modules when --validate-modules specified
|
||||
|
||||
if (getAndRemoveProperty("jdk.module.validation") != null) {
|
||||
return createBootLayerForValidation();
|
||||
int errors = ModulePathValidator.scanAllModules(System.out);
|
||||
if (errors > 0) {
|
||||
fail("Validation of module path failed");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -419,26 +421,6 @@ public final class ModuleBootstrap {
|
||||
return bootLayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a boot module layer for validation that resolves all
|
||||
* system modules.
|
||||
*/
|
||||
private static ModuleLayer createBootLayerForValidation() {
|
||||
Set<String> allSystem = ModuleFinder.ofSystem().findAll()
|
||||
.stream()
|
||||
.map(ModuleReference::descriptor)
|
||||
.map(ModuleDescriptor::name)
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
Configuration cf = SharedSecrets.getJavaLangModuleAccess()
|
||||
.resolveAndBind(ModuleFinder.ofSystem(),
|
||||
allSystem,
|
||||
null);
|
||||
|
||||
Function<String, ClassLoader> clf = ModuleLoaderMap.mappingFunction(cf);
|
||||
return ModuleLayer.empty().defineModules(cf, clf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load/register the modules to the built-in class loaders.
|
||||
*/
|
||||
|
@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.internal.module;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.module.FindException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.module.ModuleReference;
|
||||
import java.net.URI;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* A validator to check for errors and conflicts between modules.
|
||||
*/
|
||||
|
||||
class ModulePathValidator {
|
||||
private static final String MODULE_INFO = "module-info.class";
|
||||
private static final String INDENT = " ";
|
||||
|
||||
private final Map<String, ModuleReference> nameToModule;
|
||||
private final Map<String, ModuleReference> packageToModule;
|
||||
private final PrintStream out;
|
||||
|
||||
private int errorCount;
|
||||
|
||||
private ModulePathValidator(PrintStream out) {
|
||||
this.nameToModule = new HashMap<>();
|
||||
this.packageToModule = new HashMap<>();
|
||||
this.out = out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scans and the validates all modules on the module path. The module path
|
||||
* comprises the upgrade module path, system modules, and the application
|
||||
* module path.
|
||||
*
|
||||
* @param out the print stream for output messages
|
||||
* @return the number of errors found
|
||||
*/
|
||||
static int scanAllModules(PrintStream out) {
|
||||
ModulePathValidator validator = new ModulePathValidator(out);
|
||||
|
||||
// upgrade module path
|
||||
String value = System.getProperty("jdk.module.upgrade.path");
|
||||
if (value != null) {
|
||||
Stream.of(value.split(File.pathSeparator))
|
||||
.map(Path::of)
|
||||
.forEach(validator::scan);
|
||||
}
|
||||
|
||||
// system modules
|
||||
ModuleFinder.ofSystem().findAll().stream()
|
||||
.sorted(Comparator.comparing(ModuleReference::descriptor))
|
||||
.forEach(validator::process);
|
||||
|
||||
// application module path
|
||||
value = System.getProperty("jdk.module.path");
|
||||
if (value != null) {
|
||||
Stream.of(value.split(File.pathSeparator))
|
||||
.map(Path::of)
|
||||
.forEach(validator::scan);
|
||||
}
|
||||
|
||||
return validator.errorCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the module location and name.
|
||||
*/
|
||||
private void printModule(ModuleReference mref) {
|
||||
mref.location()
|
||||
.filter(uri -> !isJrt(uri))
|
||||
.ifPresent(uri -> out.print(uri + " "));
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
out.print(descriptor.name());
|
||||
if (descriptor.isAutomatic())
|
||||
out.print(" automatic");
|
||||
out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the module location and name, checks if the module is
|
||||
* shadowed by a previously seen module, and finally checks for
|
||||
* package conflicts with previously seen modules.
|
||||
*/
|
||||
private void process(ModuleReference mref) {
|
||||
String name = mref.descriptor().name();
|
||||
ModuleReference previous = nameToModule.putIfAbsent(name, mref);
|
||||
if (previous != null) {
|
||||
printModule(mref);
|
||||
out.print(INDENT + "shadowed by ");
|
||||
printModule(previous);
|
||||
} else {
|
||||
boolean first = true;
|
||||
|
||||
// check for package conflicts when not shadowed
|
||||
for (String pkg : mref.descriptor().packages()) {
|
||||
previous = packageToModule.putIfAbsent(pkg, mref);
|
||||
if (previous != null) {
|
||||
if (first) {
|
||||
printModule(mref);
|
||||
first = false;
|
||||
errorCount++;
|
||||
}
|
||||
String mn = previous.descriptor().name();
|
||||
out.println(INDENT + "contains " + pkg
|
||||
+ " conflicts with module " + mn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan an element on a module path. The element is a directory
|
||||
* of modules, an exploded module, or a JAR file.
|
||||
*/
|
||||
private void scan(Path entry) {
|
||||
BasicFileAttributes attrs;
|
||||
try {
|
||||
attrs = Files.readAttributes(entry, BasicFileAttributes.class);
|
||||
} catch (NoSuchFileException ignore) {
|
||||
return;
|
||||
} catch (IOException ioe) {
|
||||
out.println(entry + " " + ioe);
|
||||
errorCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = entry.getFileName().toString();
|
||||
if (attrs.isRegularFile() && fn.endsWith(".jar")) {
|
||||
// JAR file, explicit or automatic module
|
||||
scanModule(entry).ifPresent(this::process);
|
||||
} else if (attrs.isDirectory()) {
|
||||
Path mi = entry.resolve(MODULE_INFO);
|
||||
if (Files.exists(mi)) {
|
||||
// exploded module
|
||||
scanModule(entry).ifPresent(this::process);
|
||||
} else {
|
||||
// directory of modules
|
||||
scanDirectory(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the JAR files and exploded modules in a directory.
|
||||
*/
|
||||
private void scanDirectory(Path dir) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
Map<String, Path> moduleToEntry = new HashMap<>();
|
||||
|
||||
for (Path entry : stream) {
|
||||
BasicFileAttributes attrs;
|
||||
try {
|
||||
attrs = Files.readAttributes(entry, BasicFileAttributes.class);
|
||||
} catch (IOException ioe) {
|
||||
out.println(entry + " " + ioe);
|
||||
errorCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ModuleReference mref = null;
|
||||
|
||||
String fn = entry.getFileName().toString();
|
||||
if (attrs.isRegularFile() && fn.endsWith(".jar")) {
|
||||
mref = scanModule(entry).orElse(null);
|
||||
} else if (attrs.isDirectory()) {
|
||||
Path mi = entry.resolve(MODULE_INFO);
|
||||
if (Files.exists(mi)) {
|
||||
mref = scanModule(entry).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (mref != null) {
|
||||
String name = mref.descriptor().name();
|
||||
Path previous = moduleToEntry.putIfAbsent(name, entry);
|
||||
if (previous != null) {
|
||||
// same name as other module in the directory
|
||||
printModule(mref);
|
||||
out.println(INDENT + "contains same module as "
|
||||
+ previous.getFileName());
|
||||
errorCount++;
|
||||
} else {
|
||||
process(mref);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
out.println(dir + " " + ioe);
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a JAR file or exploded module.
|
||||
*/
|
||||
private Optional<ModuleReference> scanModule(Path entry) {
|
||||
ModuleFinder finder = ModuleFinder.of(entry);
|
||||
try {
|
||||
return finder.findAll().stream().findFirst();
|
||||
} catch (FindException e) {
|
||||
out.println(entry);
|
||||
out.println(INDENT + e.getMessage());
|
||||
Throwable cause = e.getCause();
|
||||
if (cause != null) {
|
||||
out.println(INDENT + cause);
|
||||
}
|
||||
errorCount++;
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given URI is a jrt URI
|
||||
*/
|
||||
private static boolean isJrt(URI uri) {
|
||||
return (uri != null && uri.getScheme().equalsIgnoreCase("jrt"));
|
||||
}
|
||||
}
|
@ -44,7 +44,6 @@ import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.FindException;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleDescriptor.Requires;
|
||||
import java.lang.module.ModuleDescriptor.Exports;
|
||||
@ -62,21 +61,16 @@ import java.net.URI;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.text.Normalizer;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Locale.Category;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
@ -1212,197 +1206,4 @@ public final class LauncherHelper {
|
||||
return (uri != null && uri.getScheme().equalsIgnoreCase("jrt"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the launcher to validate the modules on the upgrade and
|
||||
* application module paths.
|
||||
*
|
||||
* @return {@code true} if no errors are found
|
||||
*/
|
||||
private static boolean validateModules() {
|
||||
initOutput(System.out);
|
||||
|
||||
ModuleValidator validator = new ModuleValidator();
|
||||
|
||||
// upgrade module path
|
||||
String value = System.getProperty("jdk.module.upgrade.path");
|
||||
if (value != null) {
|
||||
Stream.of(value.split(File.pathSeparator))
|
||||
.map(Paths::get)
|
||||
.forEach(validator::scan);
|
||||
}
|
||||
|
||||
// system modules
|
||||
ModuleFinder.ofSystem().findAll().stream()
|
||||
.sorted(Comparator.comparing(ModuleReference::descriptor))
|
||||
.forEach(validator::process);
|
||||
|
||||
// application module path
|
||||
value = System.getProperty("jdk.module.path");
|
||||
if (value != null) {
|
||||
Stream.of(value.split(File.pathSeparator))
|
||||
.map(Paths::get)
|
||||
.forEach(validator::scan);
|
||||
}
|
||||
|
||||
return !validator.foundErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple validator to check for errors and conflicts between modules.
|
||||
*/
|
||||
static class ModuleValidator {
|
||||
private static final String MODULE_INFO = "module-info.class";
|
||||
|
||||
private Map<String, ModuleReference> nameToModule = new HashMap<>();
|
||||
private Map<String, ModuleReference> packageToModule = new HashMap<>();
|
||||
private boolean errorFound;
|
||||
|
||||
/**
|
||||
* Returns true if at least one error was found
|
||||
*/
|
||||
boolean foundErrors() {
|
||||
return errorFound;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the module location and name.
|
||||
*/
|
||||
private void printModule(ModuleReference mref) {
|
||||
mref.location()
|
||||
.filter(uri -> !isJrt(uri))
|
||||
.ifPresent(uri -> ostream.print(uri + " "));
|
||||
ModuleDescriptor descriptor = mref.descriptor();
|
||||
ostream.print(descriptor.name());
|
||||
if (descriptor.isAutomatic())
|
||||
ostream.print(" automatic");
|
||||
ostream.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the module location and name, checks if the module is
|
||||
* shadowed by a previously seen module, and finally checks for
|
||||
* package conflicts with previously seen modules.
|
||||
*/
|
||||
void process(ModuleReference mref) {
|
||||
printModule(mref);
|
||||
|
||||
String name = mref.descriptor().name();
|
||||
ModuleReference previous = nameToModule.putIfAbsent(name, mref);
|
||||
if (previous != null) {
|
||||
ostream.print(INDENT + "shadowed by ");
|
||||
printModule(previous);
|
||||
} else {
|
||||
// check for package conflicts when not shadowed
|
||||
for (String pkg : mref.descriptor().packages()) {
|
||||
previous = packageToModule.putIfAbsent(pkg, mref);
|
||||
if (previous != null) {
|
||||
String mn = previous.descriptor().name();
|
||||
ostream.println(INDENT + "contains " + pkg
|
||||
+ " conflicts with module " + mn);
|
||||
errorFound = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan an element on a module path. The element is a directory
|
||||
* of modules, an exploded module, or a JAR file.
|
||||
*/
|
||||
void scan(Path entry) {
|
||||
BasicFileAttributes attrs;
|
||||
try {
|
||||
attrs = Files.readAttributes(entry, BasicFileAttributes.class);
|
||||
} catch (NoSuchFileException ignore) {
|
||||
return;
|
||||
} catch (IOException ioe) {
|
||||
ostream.println(entry + " " + ioe);
|
||||
errorFound = true;
|
||||
return;
|
||||
}
|
||||
|
||||
String fn = entry.getFileName().toString();
|
||||
if (attrs.isRegularFile() && fn.endsWith(".jar")) {
|
||||
// JAR file, explicit or automatic module
|
||||
scanModule(entry).ifPresent(this::process);
|
||||
} else if (attrs.isDirectory()) {
|
||||
Path mi = entry.resolve(MODULE_INFO);
|
||||
if (Files.exists(mi)) {
|
||||
// exploded module
|
||||
scanModule(entry).ifPresent(this::process);
|
||||
} else {
|
||||
// directory of modules
|
||||
scanDirectory(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan the JAR files and exploded modules in a directory.
|
||||
*/
|
||||
private void scanDirectory(Path dir) {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
|
||||
Map<String, Path> moduleToEntry = new HashMap<>();
|
||||
|
||||
for (Path entry : stream) {
|
||||
BasicFileAttributes attrs;
|
||||
try {
|
||||
attrs = Files.readAttributes(entry, BasicFileAttributes.class);
|
||||
} catch (IOException ioe) {
|
||||
ostream.println(entry + " " + ioe);
|
||||
errorFound = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
ModuleReference mref = null;
|
||||
|
||||
String fn = entry.getFileName().toString();
|
||||
if (attrs.isRegularFile() && fn.endsWith(".jar")) {
|
||||
mref = scanModule(entry).orElse(null);
|
||||
} else if (attrs.isDirectory()) {
|
||||
Path mi = entry.resolve(MODULE_INFO);
|
||||
if (Files.exists(mi)) {
|
||||
mref = scanModule(entry).orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (mref != null) {
|
||||
String name = mref.descriptor().name();
|
||||
Path previous = moduleToEntry.putIfAbsent(name, entry);
|
||||
if (previous != null) {
|
||||
// same name as other module in the directory
|
||||
printModule(mref);
|
||||
ostream.println(INDENT + "contains same module as "
|
||||
+ previous.getFileName());
|
||||
errorFound = true;
|
||||
} else {
|
||||
process(mref);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ostream.println(dir + " " + ioe);
|
||||
errorFound = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan a JAR file or exploded module.
|
||||
*/
|
||||
private Optional<ModuleReference> scanModule(Path entry) {
|
||||
ModuleFinder finder = ModuleFinder.of(entry);
|
||||
try {
|
||||
return finder.findAll().stream().findFirst();
|
||||
} catch (FindException e) {
|
||||
ostream.println(entry);
|
||||
ostream.println(INDENT + e.getMessage());
|
||||
Throwable cause = e.getCause();
|
||||
if (cause != null) {
|
||||
ostream.println(INDENT + cause);
|
||||
}
|
||||
errorFound = true;
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -441,14 +441,6 @@ JavaMain(void * _args)
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
// validate modules on the module path, then exit
|
||||
if (validateModules) {
|
||||
jboolean okay = ValidateModules(env);
|
||||
CHECK_EXCEPTION_LEAVE(1);
|
||||
if (!okay) ret = 1;
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
if (printVersion || showVersion) {
|
||||
PrintJavaVersion(env, showVersion);
|
||||
CHECK_EXCEPTION_LEAVE(0);
|
||||
@ -457,6 +449,11 @@ JavaMain(void * _args)
|
||||
}
|
||||
}
|
||||
|
||||
// modules have been validated at startup so exit
|
||||
if (validateModules) {
|
||||
LEAVE();
|
||||
}
|
||||
|
||||
/* If the user specified neither a class name nor a JAR file */
|
||||
if (printXUsage || printUsage || what == 0 || mode == LM_UNKNOWN) {
|
||||
PrintUsage(env, printXUsage);
|
||||
@ -1955,20 +1952,6 @@ DescribeModule(JNIEnv *env, char *optString)
|
||||
(*env)->CallStaticVoidMethod(env, cls, describeModuleID, joptString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate modules
|
||||
*/
|
||||
static jboolean
|
||||
ValidateModules(JNIEnv *env)
|
||||
{
|
||||
jmethodID validateModulesID;
|
||||
jclass cls = GetLauncherHelperClass(env);
|
||||
NULL_CHECK_RETURN_VALUE(cls, JNI_FALSE);
|
||||
validateModulesID = (*env)->GetStaticMethodID(env, cls, "validateModules", "()Z");
|
||||
NULL_CHECK_RETURN_VALUE(cls, JNI_FALSE);
|
||||
return (*env)->CallStaticBooleanMethod(env, cls, validateModulesID);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints default usage or the Xusage message, see sun.launcher.LauncherHelper.java
|
||||
*/
|
||||
|
@ -37,7 +37,8 @@ public class TestValidateModules {
|
||||
public static void main(String... args) throws Exception {
|
||||
ProcessTools.executeTestJava("-XX:+UnlockExperimentalVMOptions",
|
||||
"-XX:+EnableJVMCI",
|
||||
"--validate-modules")
|
||||
"--validate-modules",
|
||||
"--list-modules")
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out)
|
||||
.stdoutShouldContain("java.base")
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2017, 2018, 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,9 +23,10 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8178380 8194937
|
||||
* @modules java.xml
|
||||
* @library /lib/testlibrary
|
||||
* @build ValidateModulesTest JarUtils jdk.testlibrary.*
|
||||
* @library src /lib/testlibrary
|
||||
* @build ValidateModulesTest hello/* JarUtils jdk.testlibrary.*
|
||||
* @run testng ValidateModulesTest
|
||||
* @summary Basic test for java --validate-modules
|
||||
*/
|
||||
@ -45,13 +46,40 @@ import static org.testng.Assert.*;
|
||||
public class ValidateModulesTest {
|
||||
|
||||
/**
|
||||
* Test that the system modules validate.
|
||||
* Basic test --validate-modules when there are no errors.
|
||||
*/
|
||||
public void testSystemModules() throws Exception {
|
||||
run("--validate-modules")
|
||||
.stdoutShouldContain("java.base")
|
||||
.stdoutShouldContain("java.xml")
|
||||
.shouldHaveExitValue(0);
|
||||
public void testNoErrors() throws Exception {
|
||||
String modulePath = System.getProperty("test.module.path");
|
||||
|
||||
test("--validate-modules");
|
||||
|
||||
test("--validate-modules", "-version")
|
||||
.shouldContain("Runtime Environment");
|
||||
|
||||
test("--validate-modules", "--list-modules")
|
||||
.shouldContain("java.base");
|
||||
|
||||
test("--validate-modules", "-d", "java.base")
|
||||
.shouldContain("exports java.lang");
|
||||
|
||||
test("-p", modulePath, "-m", "hello/p.Main")
|
||||
.shouldContain("Hello world");
|
||||
|
||||
test("-p", modulePath, "--validate-modules", "-m", "hello/p.Main")
|
||||
.shouldNotContain("Hello world");
|
||||
|
||||
test("-p", modulePath, "--validate-modules", "--list-modules")
|
||||
.shouldContain("hello");
|
||||
|
||||
test("-p", modulePath, "--validate-modules", "-d", "hello")
|
||||
.shouldContain("hello")
|
||||
.shouldContain("contains p");
|
||||
|
||||
testExpectingError("--validate-modules", "--add-modules", "BAD")
|
||||
.shouldContain("Module BAD not found");
|
||||
|
||||
testExpectingError("--validate-modules", "-m", "BAD")
|
||||
.shouldContain("Module BAD not found");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -68,12 +96,9 @@ public class ValidateModulesTest {
|
||||
Path lib = Files.createDirectory(tmpdir.resolve("lib"));
|
||||
JarUtils.createJarFile(lib.resolve("xml.jar"), classes);
|
||||
|
||||
int exitValue = run("-p", lib.toString(), "--validate-modules")
|
||||
testExpectingError("-p", lib.toString(), "--validate-modules")
|
||||
.shouldContain("xml automatic")
|
||||
.shouldContain("conflicts with module java.xml")
|
||||
.getExitValue();
|
||||
assertTrue(exitValue != 0);
|
||||
|
||||
.shouldContain("conflicts with module java.xml");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -89,10 +114,8 @@ public class ValidateModulesTest {
|
||||
JarUtils.createJarFile(lib.resolve("foo-1.0.jar"), classes);
|
||||
JarUtils.createJarFile(lib.resolve("foo-2.0.jar"), classes);
|
||||
|
||||
int exitValue = run("-p", lib.toString(), "--validate-modules")
|
||||
.shouldContain("contains same module")
|
||||
.getExitValue();
|
||||
assertTrue(exitValue != 0);
|
||||
testExpectingError("-p", lib.toString(), "--validate-modules")
|
||||
.shouldContain("contains same module");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,18 +133,30 @@ public class ValidateModulesTest {
|
||||
Path lib2 = Files.createDirectory(tmpdir.resolve("lib2"));
|
||||
JarUtils.createJarFile(lib2.resolve("foo-2.0.jar"), classes);
|
||||
|
||||
run("-p", lib1 + File.pathSeparator + lib2, "--validate-modules")
|
||||
.shouldContain("shadowed by")
|
||||
.shouldHaveExitValue(0);
|
||||
test("-p", lib1 + File.pathSeparator + lib2, "--validate-modules")
|
||||
.shouldContain("shadowed by");
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the java launcher with the given arguments.
|
||||
* Runs the java launcher with the given arguments, expecting a 0 exit code
|
||||
*/
|
||||
private OutputAnalyzer run(String... args) throws Exception {
|
||||
return ProcessTools.executeTestJava(args)
|
||||
private OutputAnalyzer test(String... args) throws Exception {
|
||||
OutputAnalyzer analyzer = ProcessTools.executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out);
|
||||
assertTrue(analyzer.getExitValue() == 0);
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the java launcher with the given arguments, expecting a non-0 exit code
|
||||
*/
|
||||
private OutputAnalyzer testExpectingError(String... args) throws Exception {
|
||||
OutputAnalyzer analyzer = ProcessTools.executeTestJava(args)
|
||||
.outputTo(System.out)
|
||||
.errorTo(System.out);
|
||||
assertTrue(analyzer.getExitValue() != 0);
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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.
|
||||
*/
|
||||
module hello { }
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2018, 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 p;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Hello world");
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user