AddLimitMods.java revision 3976:8be741555fa6
1/* 2 * Copyright (c) 2016, 2017, 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 8142968 8154956 8170987 8171412 27 * @summary Test --add-modules and --limit-modules; also test the "enabled" modules. 28 * @library /tools/lib 29 * @modules 30 * jdk.compiler/com.sun.tools.javac.api 31 * jdk.compiler/com.sun.tools.javac.code 32 * jdk.compiler/com.sun.tools.javac.main 33 * jdk.compiler/com.sun.tools.javac.model 34 * jdk.compiler/com.sun.tools.javac.processing 35 * jdk.compiler/com.sun.tools.javac.util 36 * jdk.jdeps/com.sun.tools.javap 37 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask toolbox.JavaTask ModuleTestBase 38 * @run main AddLimitMods 39 */ 40 41import java.io.File; 42import java.nio.file.Files; 43import java.nio.file.Path; 44import java.util.AbstractMap.SimpleEntry; 45import java.util.ArrayList; 46import java.util.Arrays; 47import java.util.Collections; 48import java.util.HashSet; 49import java.util.LinkedHashMap; 50import java.util.List; 51import java.util.Map; 52import java.util.Map.Entry; 53import java.util.Objects; 54import java.util.Set; 55 56import javax.annotation.processing.AbstractProcessor; 57import javax.annotation.processing.RoundEnvironment; 58import javax.annotation.processing.SupportedAnnotationTypes; 59import javax.annotation.processing.SupportedOptions; 60import javax.lang.model.SourceVersion; 61import javax.lang.model.element.ModuleElement; 62import javax.lang.model.element.TypeElement; 63 64import com.sun.tools.javac.code.Symbol.ClassSymbol; 65import com.sun.tools.javac.code.Symtab; 66import com.sun.tools.javac.model.JavacElements; 67import com.sun.tools.javac.processing.JavacProcessingEnvironment; 68import com.sun.tools.javac.util.Context; 69 70import toolbox.JarTask; 71import toolbox.JavacTask; 72import toolbox.JavaTask; 73import toolbox.Task; 74 75public class AddLimitMods extends ModuleTestBase { 76 77 public static void main(String... args) throws Exception { 78 AddLimitMods t = new AddLimitMods(); 79 t.runTests(); 80 } 81 82 @Test 83 public void testManual(Path base) throws Exception { 84 Path moduleSrc = base.resolve("module-src"); 85 Path m1 = moduleSrc.resolve("m1x"); 86 87 tb.writeJavaFiles(m1, 88 "module m1x { requires m2x; requires m3x; }"); 89 90 Path m2 = moduleSrc.resolve("m2x"); 91 92 tb.writeJavaFiles(m2, 93 "module m2x { requires m3x; exports m2x; }", 94 "package m2x; public class M2 {}"); 95 96 Path m3 = moduleSrc.resolve("m3x"); 97 98 tb.writeJavaFiles(m3, 99 "module m3x { exports m3x; }", 100 "package m3x; public class M3 {}"); 101 102 Path modulePath = base.resolve("module-path"); 103 104 Files.createDirectories(modulePath); 105 106 new JavacTask(tb) 107 .options("--module-source-path", moduleSrc.toString()) 108 .outdir(modulePath) 109 .files(findJavaFiles(m3)) 110 .run() 111 .writeAll(); 112 113 new JavacTask(tb) 114 .options("--module-source-path", moduleSrc.toString()) 115 .outdir(modulePath) 116 .files(findJavaFiles(m2)) 117 .run() 118 .writeAll(); 119 120 //real test 121 new JavacTask(tb) 122 .options("--module-path", modulePath.toString(), 123 "--should-stop:ifNoError=FLOW", 124 "--limit-modules", "java.base") 125 .outdir(modulePath) 126 .files(findJavaFiles(m1)) 127 .run(Task.Expect.FAIL) 128 .writeAll(); 129 130 new JavacTask(tb) 131 .options("--module-path", modulePath.toString(), 132 "--should-stop:ifNoError=FLOW", 133 "--limit-modules", "java.base", 134 "--add-modules", "m2x") 135 .outdir(modulePath) 136 .files(findJavaFiles(m1)) 137 .run(Task.Expect.FAIL) 138 .writeAll(); 139 140 new JavacTask(tb) 141 .options("--module-path", modulePath.toString(), 142 "--should-stop:ifNoError=FLOW", 143 "--limit-modules", "java.base", 144 "--add-modules", "m2x,m3x") 145 .outdir(modulePath) 146 .files(findJavaFiles(m1)) 147 .run() 148 .writeAll(); 149 150 new JavacTask(tb) 151 .options("--module-path", modulePath.toString(), 152 "--should-stop:ifNoError=FLOW", 153 "--limit-modules", "m2x") 154 .outdir(modulePath) 155 .files(findJavaFiles(m1)) 156 .run() 157 .writeAll(); 158 159 new JavacTask(tb) 160 .options("--module-path", modulePath.toString(), 161 "--should-stop:ifNoError=FLOW", 162 "--limit-modules", "m3x") 163 .outdir(modulePath) 164 .files(findJavaFiles(m1)) 165 .run(Task.Expect.FAIL) 166 .writeAll(); 167 168 new JavacTask(tb) 169 .options("--module-path", modulePath.toString(), 170 "--should-stop:ifNoError=FLOW", 171 "--limit-modules", "m3x", 172 "--add-modules", "m2x") 173 .outdir(modulePath) 174 .files(findJavaFiles(m1)) 175 .run() 176 .writeAll(); 177 } 178 179 @Test 180 public void testObservableForUnnamed(Path base) throws Exception { 181 Path src = base.resolve("src"); 182 183 tb.writeJavaFiles(src, 184 "package test;\n" + 185 "@javax.annotation.Generated(\"test\")\n" + 186 "public class Test {\n" + 187 " com.sun.tools.javac.Main m;\n" + 188 " javax.xml.bind.JAXBException e;\n" + 189 "}\n"); 190 191 Path out = base.resolve("out"); 192 193 Files.createDirectories(out); 194 195 for (Entry<String[], String> variant : variants) { 196 System.err.println("running variant: options=" + Arrays.asList(variant.getKey()) + ", expected log: " + variant.getValue()); 197 198 List<String> options = new ArrayList<>(); 199 options.add("-XDrawDiagnostics"); 200 options.addAll(Arrays.asList(variant.getKey())); 201 202 String log = new JavacTask(tb) 203 .options(options.toArray(new String[0])) 204 .outdir(out) 205 .files(findJavaFiles(src)) 206 .run(variant.getValue() == null ? Task.Expect.SUCCESS : Task.Expect.FAIL) 207 .writeAll() 208 .getOutput(Task.OutputKind.DIRECT); 209 210 log = log.replace(System.getProperty("line.separator"), "\n"); 211 212 if (variant.getValue() != null && !log.equals(variant.getValue())) { 213 throw new AssertionError(); 214 } 215 } 216 } 217 218 private static final List<Entry<String[], String>> variants = Arrays.asList( 219 new SimpleEntry<String[], String>(new String[] {}, 220 "Test.java:2:7: compiler.err.package.not.visible: javax.annotation, (compiler.misc.not.def.access.does.not.read.from.unnamed: javax.annotation, java.xml.ws.annotation)\n" 221 + "Test.java:5:14: compiler.err.package.not.visible: javax.xml.bind, (compiler.misc.not.def.access.does.not.read.from.unnamed: javax.xml.bind, java.xml.bind)\n" 222 + "2 errors\n"), 223 new SimpleEntry<String[], String>(new String[] {"--add-modules", "java.xml.ws.annotation,java.xml.bind"}, 224 null), 225 new SimpleEntry<String[], String>(new String[] {"--limit-modules", "java.xml.ws,jdk.compiler"}, 226 null), 227 new SimpleEntry<String[], String>(new String[] {"--add-modules", "ALL-SYSTEM"}, 228 null) 229 ); 230 231 @Test 232 public void testAllModulePath(Path base) throws Exception { 233 if (Files.isDirectory(base)) 234 tb.cleanDirectory(base); 235 236 Path moduleSrc = base.resolve("module-src"); 237 Path m1 = moduleSrc.resolve("m1x"); 238 239 tb.writeJavaFiles(m1, 240 "module m1x { exports api; }", 241 "package api; public class Api { }"); 242 243 Path modulePath = base.resolve("module-path"); 244 245 Files.createDirectories(modulePath); 246 247 new JavacTask(tb) 248 .options("--module-source-path", moduleSrc.toString()) 249 .outdir(modulePath) 250 .files(findJavaFiles(moduleSrc)) 251 .run() 252 .writeAll(); 253 254 Path cpSrc = base.resolve("cp-src"); 255 tb.writeJavaFiles(cpSrc, "package test; public class Test { api.Api api; }"); 256 257 Path cpOut = base.resolve("cp-out"); 258 259 Files.createDirectories(cpOut); 260 261 new JavacTask(tb) 262 .options("--module-path", modulePath.toString()) 263 .outdir(cpOut) 264 .files(findJavaFiles(cpSrc)) 265 .run(Task.Expect.FAIL) 266 .writeAll(); 267 268 new JavacTask(tb) 269 .options("--module-path", modulePath.toString(), 270 "--add-modules", "ALL-MODULE-PATH") 271 .outdir(cpOut) 272 .files(findJavaFiles(cpSrc)) 273 .run() 274 .writeAll(); 275 276 List<String> actual; 277 List<String> expected = Arrays.asList( 278 "- compiler.err.addmods.all.module.path.invalid", 279 "1 error"); 280 281 actual = new JavacTask(tb) 282 .options("--module-source-path", moduleSrc.toString(), 283 "-XDrawDiagnostics", 284 "--add-modules", "ALL-MODULE-PATH") 285 .outdir(modulePath) 286 .files(findJavaFiles(moduleSrc)) 287 .run(Task.Expect.FAIL) 288 .writeAll() 289 .getOutputLines(Task.OutputKind.DIRECT); 290 291 if (!Objects.equals(actual, expected)) { 292 throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected); 293 } 294 295 actual = new JavacTask(tb) 296 .options("--patch-module", "java.base=" + cpSrc.toString(), 297 "-XDrawDiagnostics", 298 "--add-modules", "ALL-MODULE-PATH") 299 .outdir(cpOut) 300 .files(findJavaFiles(cpSrc)) 301 .run(Task.Expect.FAIL) 302 .writeAll() 303 .getOutputLines(Task.OutputKind.DIRECT); 304 305 if (!Objects.equals(actual, expected)) { 306 throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected); 307 } 308 309 actual = new JavacTask(tb, Task.Mode.CMDLINE) 310 .options("-source", "8", "-target", "8", 311 "-XDrawDiagnostics", 312 "--add-modules", "ALL-MODULE-PATH") 313 .outdir(cpOut) 314 .files(findJavaFiles(cpSrc)) 315 .run(Task.Expect.FAIL) 316 .writeAll() 317 .getOutputLines(Task.OutputKind.DIRECT); 318 319 if (!actual.contains("javac: option --add-modules not allowed with target 1.8")) { 320 throw new IllegalStateException("incorrect errors; actual=" + actual); 321 } 322 323 tb.writeJavaFiles(cpSrc, "module m1x {}"); 324 325 actual = new JavacTask(tb) 326 .options("-XDrawDiagnostics", 327 "--add-modules", "ALL-MODULE-PATH") 328 .outdir(cpOut) 329 .files(findJavaFiles(cpSrc)) 330 .run(Task.Expect.FAIL) 331 .writeAll() 332 .getOutputLines(Task.OutputKind.DIRECT); 333 334 if (!Objects.equals(actual, expected)) { 335 throw new IllegalStateException("incorrect errors; actual=" + actual + "; expected=" + expected); 336 } 337 } 338 339 @Test 340 public void testRuntime2Compile(Path base) throws Exception { 341 Path classpathSrc = base.resolve("classpath-src"); 342 Path classpathOut = base.resolve("classpath-out"); 343 344 tb.writeJavaFiles(classpathSrc, 345 generateCheckAccessibleClass("cp.CP")); 346 347 Files.createDirectories(classpathOut); 348 349 System.err.println("Compiling classpath-src files:"); 350 new JavacTask(tb) 351 .outdir(classpathOut) 352 .files(findJavaFiles(classpathSrc)) 353 .run() 354 .writeAll() 355 .getOutput(Task.OutputKind.DIRECT); 356 357 Path automaticSrc = base.resolve("automatic-src"); 358 Path automaticOut = base.resolve("automatic-out"); 359 360 tb.writeJavaFiles(automaticSrc, 361 generateCheckAccessibleClass("automatic.Automatic")); 362 363 Files.createDirectories(automaticOut); 364 365 System.err.println("Compiling automatic-src files:"); 366 new JavacTask(tb) 367 .outdir(automaticOut) 368 .files(findJavaFiles(automaticSrc)) 369 .run() 370 .writeAll() 371 .getOutput(Task.OutputKind.DIRECT); 372 373 Path modulePath = base.resolve("module-path"); 374 375 Files.createDirectories(modulePath); 376 377 Path automaticJar = modulePath.resolve("automatic.jar"); 378 379 System.err.println("Creating automatic.jar:"); 380 new JarTask(tb, automaticJar) 381 .baseDir(automaticOut) 382 .files("automatic/Automatic.class") 383 .run(); 384 385 Path moduleSrc = base.resolve("module-src"); 386 Path m1 = moduleSrc.resolve("m1x"); 387 388 tb.writeJavaFiles(m1, 389 "module m1x { exports api; }", 390 "package api; public class Api { public void test() { } }"); 391 392 System.err.println("Compiling module-src files:"); 393 new JavacTask(tb) 394 .options("--module-source-path", moduleSrc.toString()) 395 .outdir(modulePath) 396 .files(findJavaFiles(moduleSrc)) 397 .run() 398 .writeAll() 399 .getOutput(Task.OutputKind.DIRECT); 400 401 int index = 0; 402 403 for (String moduleInfo : MODULE_INFO_VARIANTS) { 404 for (String[] options : OPTIONS_VARIANTS) { 405 index++; 406 407 System.err.println("Running check: " + moduleInfo + "; " + Arrays.asList(options)); 408 409 Path m2Runtime = base.resolve(index + "-runtime").resolve("m2x"); 410 Path out = base.resolve(index + "-runtime").resolve("out").resolve("m2x"); 411 412 Files.createDirectories(out); 413 414 StringBuilder testClassNamed = new StringBuilder(); 415 416 testClassNamed.append("package test;\n" + 417 "public class Test {\n" + 418 " public static void main(String... args) throws Exception {\n"); 419 420 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) { 421 testClassNamed.append(" System.err.println(\"visible:" + e.getKey() + ":\" + java.lang.reflect.Layer.boot().findModule(\"" + e.getKey() + "\").isPresent());\n"); 422 } 423 424 testClassNamed.append(" Class<?> cp = Class.forName(Test.class.getClassLoader().getUnnamedModule(), \"cp.CP\");\n"); 425 testClassNamed.append(" cp.getDeclaredMethod(\"runMe\").invoke(null);\n"); 426 427 testClassNamed.append(" Class<?> automatic = Class.forName(java.lang.reflect.Layer.boot().findModule(\"automatic\").get(), \"automatic.Automatic\");\n"); 428 testClassNamed.append(" automatic.getDeclaredMethod(\"runMe\").invoke(null);\n"); 429 430 testClassNamed.append(" }\n" + 431 "}"); 432 433 tb.writeJavaFiles(m2Runtime, moduleInfo, testClassNamed.toString()); 434 435 System.err.println("Compiling " + m2Runtime + " files:"); 436 new JavacTask(tb) 437 .options("--module-path", modulePath.toString()) 438 .outdir(out) 439 .files(findJavaFiles(m2Runtime)) 440 .run() 441 .writeAll(); 442 443 boolean success; 444 String output; 445 446 try { 447 System.err.println("Running m2x/test.Test:"); 448 output = new JavaTask(tb) 449 .vmOptions(augmentOptions(options, 450 Collections.emptyList(), 451 "--module-path", modulePath.toString() + File.pathSeparator + out.getParent().toString(), 452 "--class-path", classpathOut.toString(), 453 "--add-reads", "m2x=ALL-UNNAMED,automatic", 454 "-m", "m2x/test.Test")) 455 .run() 456 .writeAll() 457 .getOutput(Task.OutputKind.STDERR); 458 459 success = true; 460 } catch (Task.TaskError err) { 461 success = false; 462 output = ""; 463 } 464 465 Path m2 = base.resolve(String.valueOf(index)).resolve("m2x"); 466 467 tb.writeJavaFiles(m2, 468 moduleInfo, 469 "package test;\n" + 470 "public class Test {}\n"); 471 472 List<String> auxOptions = success ? Arrays.asList( 473 "--processor-path", System.getProperty("test.class.path"), 474 "-processor", CheckVisibleModule.class.getName(), 475 "-Aoutput=" + output, 476 "-XDaccessInternalAPI=true" 477 ) : Collections.emptyList(); 478 479 System.err.println("Compiling/processing m2x files:"); 480 new JavacTask(tb) 481 .options(augmentOptions(options, 482 auxOptions, 483 "--module-path", modulePath.toString(), 484 "--class-path", classpathOut.toString(), 485 "--should-stop:ifNoError=FLOW")) 486 .outdir(modulePath) 487 .files(findJavaFiles(m2)) 488 .run(success ? Task.Expect.SUCCESS : Task.Expect.FAIL) 489 .writeAll(); 490 } 491 } 492 } 493 494 private String generateCheckAccessibleClass(String fqn) { 495 String packageName = fqn.substring(0, fqn.lastIndexOf('.')); 496 String simpleName = fqn.substring(fqn.lastIndexOf('.') + 1); 497 StringBuilder checkClassesAccessible = new StringBuilder(); 498 checkClassesAccessible.append("package " + packageName + ";" + 499 "public class " + simpleName + " {" + 500 " public static void runMe() throws Exception {"); 501 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) { 502 checkClassesAccessible.append("try {"); 503 checkClassesAccessible.append("Class.forName(\"" + e.getValue() + "\").newInstance();"); 504 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":true\");"); 505 checkClassesAccessible.append("} catch (Exception ex) {"); 506 checkClassesAccessible.append("System.err.println(\"" + fqn + ":" + e.getKey() + ":false\");"); 507 checkClassesAccessible.append("}"); 508 } 509 510 checkClassesAccessible.append(" }\n" + 511 "}"); 512 513 return checkClassesAccessible.toString(); 514 } 515 516 private static final Map<String, String> MODULES_TO_CHECK_TO_SAMPLE_CLASS = new LinkedHashMap<>(); 517 518 static { 519 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m1x", "api.Api"); 520 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("m2x", "test.Test"); 521 MODULES_TO_CHECK_TO_SAMPLE_CLASS.put("java.base", "java.lang.Object"); 522 }; 523 524 @SupportedAnnotationTypes("*") 525 @SupportedOptions("output") 526 public static final class CheckVisibleModule extends AbstractProcessor { 527 528 @Override 529 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 530 String expected = processingEnv.getOptions().get("output"); 531 Set<String> expectedElements = new HashSet<>(Arrays.asList(expected.split(System.getProperty("line.separator")))); 532 Context context = ((JavacProcessingEnvironment) processingEnv).getContext(); 533 Symtab syms = Symtab.instance(context); 534 535 for (Entry<String, String> e : MODULES_TO_CHECK_TO_SAMPLE_CLASS.entrySet()) { 536 String module = e.getKey(); 537 ModuleElement mod = processingEnv.getElementUtils().getModuleElement(module); 538 String visible = "visible:" + module + ":" + (mod != null); 539 540 if (!expectedElements.contains(visible)) { 541 throw new AssertionError("actual: " + visible + "; expected: " + expected); 542 } 543 544 JavacElements javacElements = JavacElements.instance(context); 545 ClassSymbol unnamedClass = javacElements.getTypeElement(syms.unnamedModule, e.getValue()); 546 String unnamed = "cp.CP:" + module + ":" + (unnamedClass != null); 547 548 if (!expectedElements.contains(unnamed)) { 549 throw new AssertionError("actual: " + unnamed + "; expected: " + expected); 550 } 551 552 ModuleElement automaticMod = processingEnv.getElementUtils().getModuleElement("automatic"); 553 ClassSymbol automaticClass = javacElements.getTypeElement(automaticMod, e.getValue()); 554 String automatic = "automatic.Automatic:" + module + ":" + (automaticClass != null); 555 556 if (!expectedElements.contains(automatic)) { 557 throw new AssertionError("actual: " + automatic + "; expected: " + expected); 558 } 559 } 560 561 return false; 562 } 563 564 @Override 565 public SourceVersion getSupportedSourceVersion() { 566 return SourceVersion.latest(); 567 } 568 569 } 570 571 public String[] augmentOptions(String[] options, List<String> auxOptions, String... baseOptions) { 572 List<String> all = new ArrayList<>(); 573 574 all.addAll(Arrays.asList(options)); 575 all.addAll(Arrays.asList(baseOptions)); 576 all.addAll(auxOptions); 577 578 return all.toArray(new String[0]); 579 } 580 581 private static final String[] MODULE_INFO_VARIANTS = { 582 "module m2x { exports test; }", 583 "module m2x { requires m1x; exports test; }" 584 }; 585 586 private static final String[][] OPTIONS_VARIANTS = { 587 {"--add-modules", "automatic"}, 588 {"--add-modules", "m1x,automatic"}, 589 {"--add-modules", "jdk.compiler,automatic"}, 590 {"--add-modules", "m1x,jdk.compiler,automatic"}, 591 {"--add-modules", "ALL-SYSTEM,automatic"}, 592 {"--limit-modules", "java.base", "--add-modules", "automatic"}, 593 {"--limit-modules", "java.base", "--add-modules", "ALL-SYSTEM,automatic"}, 594 {"--limit-modules", "m2x", "--add-modules", "automatic"}, 595 {"--limit-modules", "jdk.compiler", "--add-modules", "automatic"}, 596 }; 597} 598