InheritRuntimeEnvironmentTest.java revision 3573:c4a18ee691c4
1/* 2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24/** 25 * @test 26 * @bug 8156998 27 * @summary Test --inherit-runtime-environment 28 * @library /tools/lib 29 * @modules 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.main 32 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavaTask ModuleTestBase 33 * @run main InheritRuntimeEnvironmentTest 34 */ 35 36import java.io.IOException; 37import java.nio.file.Files; 38import java.nio.file.Path; 39import java.util.Arrays; 40import java.util.Collections; 41import java.util.List; 42import java.util.stream.Collectors; 43 44import toolbox.ModuleBuilder; 45import toolbox.JavaTask; 46import toolbox.JavacTask; 47import toolbox.Task; 48 49/** 50 * Tests that javac picks up runtime options with --inherit-runtime-environment. 51 * For each option, javac is first run using the option directly, as a control. 52 * javac is then run again, with the same option(s) being passed to the runtime, 53 * and --inherit-runtime-environment being used by javac. 54 * @author jjg 55 */ 56public class InheritRuntimeEnvironmentTest extends ModuleTestBase { 57 public static void main(String... args) throws Exception { 58 InheritRuntimeEnvironmentTest t = new InheritRuntimeEnvironmentTest(); 59 t.runTests(); 60 } 61 62 /** 63 * Tests that code being compiled can access JDK-internal API using -add-exports. 64 * @param base 65 * @throws Exception 66 */ 67 @Test 68 public void testAddExports(Path base) throws Exception { 69 Path src = base.resolve("src"); 70 tb.writeJavaFiles(src, 71 "class C { com.sun.tools.javac.main.Main main; }"); 72 73 new TestCase(base) 74 .testOpts("--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED") 75 .files(findJavaFiles(src)) 76 .run(); 77 } 78 79 /** 80 * Tests that code in the unnamed module can access a module on the module path using --add-modules. 81 */ 82 @Test 83 public void testAddModules(Path base) throws Exception { 84 Path modules = base.resolve("modules"); 85 new ModuleBuilder(tb, "m1") 86 .exports("pkg1") 87 .classes("package pkg1; public class C1 { }") 88 .build(modules); 89 90 Path src = base.resolve("src"); 91 tb.writeJavaFiles(src, 92 "class C { pkg1.C1 c1; }"); 93 94 new TestCase(base) 95 .testOpts("--module-path", modules.toString(), "--add-modules", "m1") 96 .files(findJavaFiles(src)) 97 .run(); 98 } 99 100 /** 101 * Tests that a module on the module path is not visible when --limit-modules is used to 102 * restrict the set of observable modules. 103 */ 104 @Test 105 public void testLimitModules(Path base) throws Exception { 106 Path modules = base.resolve("modules"); 107 new ModuleBuilder(tb, "m1") 108 .exports("pkg1") 109 .classes("package pkg1; public class C1 { }") 110 .build(modules); 111 112 Path src = base.resolve("src"); 113 new ModuleBuilder(tb, "m2") 114 .requires("m1") 115 .classes("package pkg2; public class C2 { pkg1.C1 c1; }") 116 .write(src); 117 118 // This is the control, to verify that by default, the module being compiled will 119 // be able to read modules on the module path 120 new TestCase(base) 121 .testOpts("--module-path", modules.toString()) 122 .otherOpts("--module-source-path", src.toString()) 123 .files(findJavaFiles(src)) 124 .run(); 125 126 // This is the test, to verify that the module being compiled will not be able to read 127 // modules on the module path when a --limit-modules is used 128 new TestCase(base) 129 .testOpts("--module-path", modules.toString(), "--limit-modules", "jdk.compiler") 130 .otherOpts("-XDrawDiagnostics", 131 "--module-source-path", src.toString()) 132 .files(findJavaFiles(src)) 133 .expect(Task.Expect.FAIL, "compiler.err.module.not.found") 134 .run(); 135 } 136 137 /** 138 * Tests that a module being compiled can see another module on the module path 139 * using --module-path. 140 */ 141 @Test 142 public void testModulePath(Path base) throws Exception { 143 Path modules = base.resolve("modules"); 144 new ModuleBuilder(tb, "m1") 145 .exports("pkg1") 146 .classes("package pkg1; public class C1 { }") 147 .build(modules); 148 149 Path src = base.resolve("src"); 150 new ModuleBuilder(tb, "m2") 151 .requires("m1") 152 .classes("package pkg2; public class C2 { pkg1.C1 c1; }") 153 .write(src); 154 155 new TestCase(base) 156 .testOpts("--module-path", modules.toString()) 157 .otherOpts("--module-source-path", src.toString()) 158 .files(findJavaFiles(src)) 159 .run(); 160 } 161 162 /** 163 * Tests that a module being compiled can see classes patches into an existing module 164 * with --patch-module 165 */ 166 @Test 167 public void testPatchModule(Path base) throws Exception { 168 Path patchSrc = base.resolve("patchSrc"); 169 tb.writeJavaFiles(patchSrc, 170 "package java.util; public class Xyzzy { }"); 171 Path patch = base.resolve("patch"); 172 Files.createDirectories(patch); 173 174 new JavacTask(tb) 175 .options("-Xmodule:java.base") 176 .outdir(patch) 177 .sourcepath(patchSrc) 178 .files(findJavaFiles(patchSrc)) 179 .run() 180 .writeAll(); 181 182 Path src = base.resolve("src"); 183 tb.writeJavaFiles(src, 184 "public class C { java.util.Xyzzy x; }"); 185 186 new TestCase(base) 187 .testOpts("--patch-module", "java.base=" + patch) 188 .files(findJavaFiles(src)) 189 .run(); 190 } 191 192 /** 193 * Tests that options in @files are also effective. 194 * The test is similar to testModulePath, except that the test options are provided in an @-file. 195 */ 196 @Test 197 public void testAtFile(Path base) throws Exception { 198 Path modules = base.resolve("modules"); 199 new ModuleBuilder(tb, "m1") 200 .exports("pkg1") 201 .classes("package pkg1; public class C1 { }") 202 .build(modules); 203 204 Path src = base.resolve("src"); 205 new ModuleBuilder(tb, "m2") 206 .requires("m1") 207 .classes("package pkg2; public class C2 { pkg1.C1 c1; }") 208 .write(src); 209 210 Path atFile = base.resolve("atFile"); 211 tb.writeFile(atFile, "--module-path " + modules); 212 213 new TestCase(base) 214 .testOpts("@" + atFile) 215 .otherOpts("--module-source-path", src.toString()) 216 .files(findJavaFiles(src)) 217 .run(); 218 } 219 220 /** 221 * Tests that --inherit-runtime-environment works in conjunction with 222 * environment variables. 223 * This is a variant of testAddExports. 224 * The use of environment variables is sufficiently custom that it is 225 * not easy to do this directly with a simple TestCase. 226 */ 227 @Test 228 public void testEnvVars(Path base) throws Exception { 229 Path src = base.resolve("src"); 230 tb.writeJavaFiles(src, 231 "class C { com.sun.tools.javac.main.Main main; }"); 232 List<String> testOpts = 233 Arrays.asList("--add-exports", "jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED"); 234 List<Path> files = Arrays.asList(findJavaFiles(src)); 235 236 String envName = "_JAVAC_OPTIONS"; 237 String envValue = String.join(" ", testOpts); 238 239 out.println(" javac:"); 240 Path javacOutDir = base.resolve("out-javac"); 241 Files.createDirectories(javacOutDir); 242 243 out.println(" env: " + envName + "=" + envValue); 244 out.println(" outdir: " + javacOutDir); 245 out.println(" files: " + files); 246 247 new JavacTask(tb, Task.Mode.EXEC) 248 .envVar(envName, envValue) 249 .outdir(javacOutDir) 250 .files(files) 251 .run() 252 .writeAll() 253 .getOutput(Task.OutputKind.DIRECT); 254 255 out.println(" java:"); 256 Path javaOutDir = base.resolve("out-java"); 257 Files.createDirectories(javaOutDir); 258 259 Path atFile = base.resolve("atFile"); 260 tb.writeFile(atFile, String.join(" ", testOpts)); 261 262 List<String> vmOpts = Arrays.asList( 263 "@" + atFile, 264 "--module", "jdk.compiler/com.sun.tools.javac.Main" 265 ); 266 267 List<String> classArgs = join( 268 Arrays.asList("-d", javaOutDir.toString()), 269 files.stream() 270 .map(p -> p.toString()) 271 .collect(Collectors.toList()) 272 ); 273 274 envValue = "--inherit-runtime-environment"; 275 276 out.println(" env: " + envName + "=" + envValue); 277 out.println(" vmOpts: " + vmOpts); 278 out.println(" classArgs: " + classArgs); 279 280 new JavaTask(tb) 281 .envVar(envName, envValue) 282 .vmOptions(vmOpts) 283 .classArgs(classArgs) 284 .run() 285 .writeAll() 286 .getOutput(Task.OutputKind.STDERR); 287 } 288 289 /** 290 * Runs javac with given test options, first directly, and then again, specifying the 291 * options to the runtime, and using --inherit-runtime-environment. 292 */ 293 class TestCase { 294 final Path base; 295 List<String> testOpts = Collections.emptyList(); 296 List<String> otherOpts = Collections.emptyList(); 297 List<Path> files = Collections.emptyList(); 298 Task.Expect expect = Task.Expect.SUCCESS; 299 String expectedText; 300 301 /** 302 * Creates a test case, specifying a base directory for work files. 303 */ 304 TestCase(Path base) { 305 this.base = base; 306 } 307 308 /** 309 * Set the "test options" to be passed to javac or to the runtime. 310 */ 311 TestCase testOpts(String... testOpts) { 312 this.testOpts = Arrays.asList(testOpts); 313 return this; 314 } 315 316 /** 317 * Sets additional options required for the compilation. 318 */ 319 TestCase otherOpts(String... otherOpts) { 320 this.otherOpts = Arrays.asList(otherOpts); 321 return this; 322 } 323 324 /** 325 * Sets the files to be compiled. 326 */ 327 TestCase files(Path... files) { 328 this.files = Arrays.asList(files); 329 return this; 330 } 331 332 /** 333 * Sets the expected output, and any expected output from javac. 334 * The default is {@code Expect.SUCCESS} and no specific output expected. 335 */ 336 TestCase expect(Task.Expect expect, String expectedText) { 337 this.expect = expect; 338 this.expectedText = expectedText; 339 return this; 340 } 341 342 /** 343 * Runs the test case. 344 * First, javac is run passing the test options directly to javac. 345 * Then, javac is run again, passing the test options to the runtime, 346 * and using --inherit-runtime-environment. 347 */ 348 void run() throws IOException { 349 runJavac(); 350 runJava(); 351 } 352 353 private void runJavac() throws IOException { 354 out.println(" javac:"); 355 Path javacOutDir = base.resolve("out-javac"); 356 Files.createDirectories(javacOutDir); 357 358 List<String> options = join(testOpts, otherOpts); 359 360 out.println(" options: " + options); 361 out.println(" outdir: " + javacOutDir); 362 out.println(" files: " + files); 363 364 String log = new JavacTask(tb, Task.Mode.CMDLINE) 365 .options(options) 366 .outdir(javacOutDir) 367 .files(files) 368 .run(expect) 369 .writeAll() 370 .getOutput(Task.OutputKind.DIRECT); 371 372 if (expectedText != null && !log.contains(expectedText)) 373 error("expected text not found"); 374 } 375 376 private void runJava() throws IOException { 377 out.println(" java:"); 378 Path javaOutDir = base.resolve("out-java"); 379 Files.createDirectories(javaOutDir); 380 381 List<String> vmOpts = join( 382 testOpts, 383 Arrays.asList("--module", "jdk.compiler/com.sun.tools.javac.Main") 384 ); 385 386 List<String> classArgs = join( 387 Arrays.asList("--inherit-runtime-environment", 388 "-d", javaOutDir.toString()), 389 otherOpts, 390 files.stream() 391 .map(p -> p.toString()) 392 .collect(Collectors.toList()) 393 ); 394 395 out.println(" vmOpts: " + vmOpts); 396 out.println(" classArgs: " + classArgs); 397 398 String log = new JavaTask(tb) 399 .vmOptions(vmOpts) 400 .classArgs(classArgs) 401 .run(expect) 402 .writeAll() 403 .getOutput(Task.OutputKind.STDERR); 404 405 if (expectedText != null && !log.contains(expectedText)) 406 error("expected text not found"); 407 } 408 } 409 410 /** 411 * Join a series of lists. 412 */ 413 @SafeVarargs 414 private <T> List<T> join(List<T>... lists) { 415 return Arrays.stream(lists) 416 .flatMap(list -> list.stream()) 417 .collect(Collectors.toList()); 418 } 419 420} 421 422