blob: b4766d7f5d770785669e4393ae36e9c3037fc560 [file] [log] [blame]
/*
* Copyright (c) 2015, 2016, 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.
*/
/**
* @test
* @bug 8156998
* @summary Test --inherit-runtime-environment
* @library /tools/lib
* @modules
* jdk.compiler/com.sun.tools.javac.api
* jdk.compiler/com.sun.tools.javac.main
* @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavaTask ModuleTestBase
* @run main InheritRuntimeEnvironmentTest
*/
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import toolbox.ModuleBuilder;
import toolbox.JavaTask;
import toolbox.JavacTask;
import toolbox.Task;
/**
* Tests that javac picks up runtime options with --inherit-runtime-environment.
* For each option, javac is first run using the option directly, as a control.
* javac is then run again, with the same option(s) being passed to the runtime,
* and --inherit-runtime-environment being used by javac.
* @author jjg
*/
public class InheritRuntimeEnvironmentTest extends ModuleTestBase {
public static void main(String... args) throws Exception {
InheritRuntimeEnvironmentTest t = new InheritRuntimeEnvironmentTest();
t.runTests();
}
/**
* Tests that code being compiled can access JDK-internal API using -add-exports.
* @param base
* @throws Exception
*/
@Test
public void testAddExports(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"class C { com.sun.tools.javac.main.Main main; }");
new TestCase(base)
.testOpts("--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED")
.files(findJavaFiles(src))
.run();
}
/**
* Tests that code in the unnamed module can access a module on the module path using --add-modules.
*/
@Test
public void testAddModules(Path base) throws Exception {
Path modules = base.resolve("modules");
new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class C1 { }")
.build(modules);
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"class C { pkg1.C1 c1; }");
new TestCase(base)
.testOpts("--module-path", modules.toString(), "--add-modules", "m1")
.files(findJavaFiles(src))
.run();
}
/**
* Tests that a module on the module path is not visible when --limit-modules is used to
* restrict the set of observable modules.
*/
@Test
public void testLimitModules(Path base) throws Exception {
Path modules = base.resolve("modules");
new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class C1 { }")
.build(modules);
Path src = base.resolve("src");
new ModuleBuilder(tb, "m2")
.requires("m1")
.classes("package pkg2; public class C2 { pkg1.C1 c1; }")
.write(src);
// This is the control, to verify that by default, the module being compiled will
// be able to read modules on the module path
new TestCase(base)
.testOpts("--module-path", modules.toString())
.otherOpts("--module-source-path", src.toString())
.files(findJavaFiles(src))
.run();
Path emptyClassPath = base.resolve("emptyClassPath");
Files.createDirectories(emptyClassPath);
// This is the test, to verify that the module being compiled will not be able to read
// modules on the module path when a --limit-modules is used
new TestCase(base)
.testOpts("--module-path", modules.toString(), "--limit-modules", "jdk.compiler")
.otherOpts("-XDrawDiagnostics",
"--module-source-path", src.toString(),
"-classpath", emptyClassPath.toString())
.files(findJavaFiles(src))
.expect(Task.Expect.FAIL, "compiler.err.module.not.found")
.run();
}
/**
* Tests that a module being compiled can see another module on the module path
* using --module-path.
*/
@Test
public void testModulePath(Path base) throws Exception {
Path modules = base.resolve("modules");
new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class C1 { }")
.build(modules);
Path src = base.resolve("src");
new ModuleBuilder(tb, "m2")
.requires("m1")
.classes("package pkg2; public class C2 { pkg1.C1 c1; }")
.write(src);
new TestCase(base)
.testOpts("--module-path", modules.toString())
.otherOpts("--module-source-path", src.toString())
.files(findJavaFiles(src))
.run();
}
/**
* Tests that a module being compiled can see classes patches into an existing module
* with --patch-module
*/
@Test
public void testPatchModule(Path base) throws Exception {
Path patchSrc = base.resolve("patchSrc");
tb.writeJavaFiles(patchSrc,
"package java.util; public class Xyzzy { }");
Path patch = base.resolve("patch");
Files.createDirectories(patch);
new JavacTask(tb)
.options("-Xmodule:java.base")
.outdir(patch)
.sourcepath(patchSrc)
.files(findJavaFiles(patchSrc))
.run()
.writeAll();
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"public class C { java.util.Xyzzy x; }");
new TestCase(base)
.testOpts("--patch-module", "java.base=" + patch)
.files(findJavaFiles(src))
.run();
}
/**
* Tests that options in @files are also effective.
* The test is similar to testModulePath, except that the test options are provided in an @-file.
*/
@Test
public void testAtFile(Path base) throws Exception {
Path modules = base.resolve("modules");
new ModuleBuilder(tb, "m1")
.exports("pkg1")
.classes("package pkg1; public class C1 { }")
.build(modules);
Path src = base.resolve("src");
new ModuleBuilder(tb, "m2")
.requires("m1")
.classes("package pkg2; public class C2 { pkg1.C1 c1; }")
.write(src);
Path atFile = base.resolve("atFile");
tb.writeFile(atFile, "--module-path " + modules);
new TestCase(base)
.testOpts("@" + atFile)
.otherOpts("--module-source-path", src.toString())
.files(findJavaFiles(src))
.run();
}
/**
* Tests that --inherit-runtime-environment works in conjunction with
* environment variables.
* This is a variant of testAddExports.
* The use of environment variables is sufficiently custom that it is
* not easy to do this directly with a simple TestCase.
*/
@Test
public void testEnvVars(Path base) throws Exception {
Path src = base.resolve("src");
tb.writeJavaFiles(src,
"class C { com.sun.tools.javac.main.Main main; }");
List<String> testOpts =
Arrays.asList("--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED");
List<Path> files = Arrays.asList(findJavaFiles(src));
String envName = "_JAVAC_OPTIONS";
String envValue = String.join(" ", testOpts);
out.println(" javac:");
Path javacOutDir = base.resolve("out-javac");
Files.createDirectories(javacOutDir);
out.println(" env: " + envName + "=" + envValue);
out.println(" outdir: " + javacOutDir);
out.println(" files: " + files);
new JavacTask(tb, Task.Mode.EXEC)
.envVar(envName, envValue)
.outdir(javacOutDir)
.files(files)
.run()
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
out.println(" java:");
Path javaOutDir = base.resolve("out-java");
Files.createDirectories(javaOutDir);
Path atFile = base.resolve("atFile");
tb.writeFile(atFile, String.join(" ", testOpts));
List<String> vmOpts = Arrays.asList(
"@" + atFile,
"--module", "jdk.compiler/com.sun.tools.javac.Main"
);
List<String> classArgs = join(
Arrays.asList("-d", javaOutDir.toString()),
files.stream()
.map(p -> p.toString())
.collect(Collectors.toList())
);
envValue = "--inherit-runtime-environment";
out.println(" env: " + envName + "=" + envValue);
out.println(" vmOpts: " + vmOpts);
out.println(" classArgs: " + classArgs);
new JavaTask(tb)
.envVar(envName, envValue)
.vmOptions(vmOpts)
.classArgs(classArgs)
.run()
.writeAll()
.getOutput(Task.OutputKind.STDERR);
}
/**
* Runs javac with given test options, first directly, and then again, specifying the
* options to the runtime, and using --inherit-runtime-environment.
*/
class TestCase {
final Path base;
List<String> testOpts = Collections.emptyList();
List<String> otherOpts = Collections.emptyList();
List<Path> files = Collections.emptyList();
Task.Expect expect = Task.Expect.SUCCESS;
String expectedText;
/**
* Creates a test case, specifying a base directory for work files.
*/
TestCase(Path base) {
this.base = base;
}
/**
* Set the "test options" to be passed to javac or to the runtime.
*/
TestCase testOpts(String... testOpts) {
this.testOpts = Arrays.asList(testOpts);
return this;
}
/**
* Sets additional options required for the compilation.
*/
TestCase otherOpts(String... otherOpts) {
this.otherOpts = Arrays.asList(otherOpts);
return this;
}
/**
* Sets the files to be compiled.
*/
TestCase files(Path... files) {
this.files = Arrays.asList(files);
return this;
}
/**
* Sets the expected output, and any expected output from javac.
* The default is {@code Expect.SUCCESS} and no specific output expected.
*/
TestCase expect(Task.Expect expect, String expectedText) {
this.expect = expect;
this.expectedText = expectedText;
return this;
}
/**
* Runs the test case.
* First, javac is run passing the test options directly to javac.
* Then, javac is run again, passing the test options to the runtime,
* and using --inherit-runtime-environment.
*/
void run() throws IOException {
runJavac();
runJava();
}
private void runJavac() throws IOException {
out.println(" javac:");
Path javacOutDir = base.resolve("out-javac");
Files.createDirectories(javacOutDir);
List<String> options = join(testOpts, otherOpts);
out.println(" options: " + options);
out.println(" outdir: " + javacOutDir);
out.println(" files: " + files);
String log = new JavacTask(tb, Task.Mode.CMDLINE)
.options(options)
.outdir(javacOutDir)
.files(files)
.run(expect)
.writeAll()
.getOutput(Task.OutputKind.DIRECT);
if (expectedText != null && !log.contains(expectedText))
error("expected text not found");
}
private void runJava() throws IOException {
out.println(" java:");
Path javaOutDir = base.resolve("out-java");
Files.createDirectories(javaOutDir);
List<String> vmOpts = join(
testOpts,
Arrays.asList("--module", "jdk.compiler/com.sun.tools.javac.Main")
);
List<String> classArgs = join(
Arrays.asList("--inherit-runtime-environment",
"-d", javaOutDir.toString()),
otherOpts,
files.stream()
.map(p -> p.toString())
.collect(Collectors.toList())
);
out.println(" vmOpts: " + vmOpts);
out.println(" classArgs: " + classArgs);
String log = new JavaTask(tb)
.vmOptions(vmOpts)
.classArgs(classArgs)
.run(expect)
.writeAll()
.getOutput(Task.OutputKind.STDERR);
if (expectedText != null && !log.contains(expectedText))
error("expected text not found");
}
}
/**
* Join a series of lists.
*/
@SafeVarargs
private <T> List<T> join(List<T>... lists) {
return Arrays.stream(lists)
.flatMap(list -> list.stream())
.collect(Collectors.toList());
}
}