EdgeCases.java revision 4254:d601b22360fa
1/* 2 * Copyright (c) 2015, 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 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311 27 * @summary tests for multi-module mode compilation 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.processing 34 * jdk.compiler/com.sun.tools.javac.util 35 * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask ModuleTestBase 36 * @run main EdgeCases 37 */ 38 39import java.io.BufferedWriter; 40import java.io.Writer; 41import java.nio.file.Files; 42import java.nio.file.Path; 43import java.nio.file.Paths; 44import java.util.Arrays; 45import java.util.HashSet; 46import java.util.List; 47import java.util.Objects; 48import java.util.Set; 49 50import javax.annotation.processing.AbstractProcessor; 51import javax.annotation.processing.RoundEnvironment; 52import javax.annotation.processing.SupportedAnnotationTypes; 53import javax.annotation.processing.SupportedOptions; 54import javax.lang.model.SourceVersion; 55import javax.lang.model.element.Element; 56import javax.lang.model.element.ModuleElement; 57import javax.lang.model.element.ModuleElement.RequiresDirective; 58import javax.lang.model.element.PackageElement; 59import javax.lang.model.element.TypeElement; 60import javax.lang.model.util.ElementFilter; 61import javax.lang.model.util.Elements; 62import javax.tools.JavaCompiler; 63import javax.tools.JavaFileObject; 64import javax.tools.StandardJavaFileManager; 65import javax.tools.ToolProvider; 66 67import com.sun.source.tree.CompilationUnitTree; 68//import com.sun.source.util.JavacTask; // conflicts with toolbox.JavacTask 69import com.sun.tools.javac.api.JavacTaskImpl; 70import com.sun.tools.javac.code.Symbol.ModuleSymbol; 71import com.sun.tools.javac.code.Symtab; 72 73import toolbox.JarTask; 74import toolbox.JavacTask; 75import toolbox.Task; 76import toolbox.Task.Expect; 77import toolbox.Task.OutputKind; 78 79public class EdgeCases extends ModuleTestBase { 80 81 public static void main(String... args) throws Exception { 82 new EdgeCases().runTests(); 83 } 84 85 @Test 86 public void testAddExportUndefinedModule(Path base) throws Exception { 87 Path src = base.resolve("src"); 88 tb.writeJavaFiles(src, "package test; import undefPackage.Any; public class Test {}"); 89 Path classes = base.resolve("classes"); 90 tb.createDirectories(classes); 91 92 List<String> log = new JavacTask(tb) 93 .options("--add-exports", "undefModule/undefPackage=ALL-UNNAMED", 94 "-XDrawDiagnostics") 95 .outdir(classes) 96 .files(findJavaFiles(src)) 97 .run(Task.Expect.FAIL) 98 .writeAll() 99 .getOutputLines(Task.OutputKind.DIRECT); 100 101 List<String> expected = Arrays.asList("- compiler.warn.module.for.option.not.found: --add-exports, undefModule", 102 "Test.java:1:34: compiler.err.doesnt.exist: undefPackage", 103 "1 error", "1 warning"); 104 105 if (!expected.equals(log)) 106 throw new Exception("expected output not found: " + log); 107 } 108 109 @Test 110 public void testModuleSymbolOutterMostClass(Path base) throws Exception { 111 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 112 try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { 113 Path moduleSrc = base.resolve("module-src"); 114 Path m1 = moduleSrc.resolve("m1x"); 115 116 tb.writeJavaFiles(m1, "module m1x { }"); 117 118 Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc)); 119 com.sun.source.util.JavacTask task = 120 (com.sun.source.util.JavacTask) compiler.getTask(null, fm, null, null, null, files); 121 122 task.analyze(); 123 124 ModuleSymbol msym = (ModuleSymbol) task.getElements().getModuleElement("m1x"); 125 126 msym.outermostClass(); 127 } 128 } 129 130 @Test 131 public void testParseEnterAnalyze(Path base) throws Exception { 132 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 133 try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { 134 Path moduleSrc = base.resolve("module-src"); 135 Path m1 = moduleSrc.resolve("m1x"); 136 137 tb.writeJavaFiles(m1, "module m1x { }", 138 "package p;", 139 "package p; class T { }"); 140 141 Path classes = base.resolve("classes"); 142 Iterable<? extends JavaFileObject> files = fm.getJavaFileObjects(findJavaFiles(moduleSrc)); 143 List<String> options = Arrays.asList("-d", classes.toString(), "-Xpkginfo:always"); 144 JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, fm, null, options, null, files); 145 146 Iterable<? extends CompilationUnitTree> parsed = task.parse(); 147 Iterable<? extends Element> entered = task.enter(parsed); 148 Iterable<? extends Element> analyzed = task.analyze(entered); 149 Iterable<? extends JavaFileObject> generatedFiles = task.generate(analyzed); 150 151 Set<String> generated = new HashSet<>(); 152 153 for (JavaFileObject jfo : generatedFiles) { 154 generated.add(jfo.getName()); 155 } 156 157 Set<String> expected = new HashSet<>( 158 Arrays.asList(Paths.get("testParseEnterAnalyze", "classes", "p", "package-info.class").toString(), 159 Paths.get("testParseEnterAnalyze", "classes", "module-info.class").toString(), 160 Paths.get("testParseEnterAnalyze", "classes", "p", "T.class").toString()) 161 ); 162 163 if (!Objects.equals(expected, generated)) 164 throw new AssertionError("Incorrect generated files: " + generated); 165 } 166 } 167 168 @Test 169 public void testModuleImplicitModuleBoundaries(Path base) throws Exception { 170 Path src = base.resolve("src"); 171 Path src_m1 = src.resolve("m1x"); 172 tb.writeJavaFiles(src_m1, 173 "module m1x { exports api1; }", 174 "package api1; public class Api1 { public void call() { } }"); 175 Path src_m2 = src.resolve("m2x"); 176 tb.writeJavaFiles(src_m2, 177 "module m2x { requires m1x; exports api2; }", 178 "package api2; public class Api2 { public static api1.Api1 get() { return null; } }"); 179 Path src_m3 = src.resolve("m3x"); 180 tb.writeJavaFiles(src_m3, 181 "module m3x { requires m2x; }", 182 "package test; public class Test { { api2.Api2.get().call(); api2.Api2.get().toString(); } }"); 183 Path classes = base.resolve("classes"); 184 tb.createDirectories(classes); 185 186 String log = new JavacTask(tb) 187 .options("-XDrawDiagnostics", 188 "--module-source-path", src.toString()) 189 .outdir(classes) 190 .files(findJavaFiles(src)) 191 .run(Task.Expect.FAIL) 192 .writeAll() 193 .getOutput(Task.OutputKind.DIRECT); 194 195 if (!log.contains("Test.java:1:52: compiler.err.not.def.access.class.intf.cant.access.reason: call(), api1.Api1, api1, (compiler.misc.not.def.access.does.not.read: m3x, api1, m1x)") || 196 !log.contains("Test.java:1:76: compiler.err.not.def.access.class.intf.cant.access: toString(), java.lang.Object")) 197 throw new Exception("expected output not found"); 198 } 199 200 @Test 201 public void testAssignClassToAutomaticModule(Path base) throws Exception { 202 //check that if a ClassSymbol belongs to an automatic module, it is properly assigned and not 203 //duplicated when being accessed through a classfile. 204 Path automaticSrc = base.resolve("automaticSrc"); 205 tb.writeJavaFiles(automaticSrc, "package api1; public class Api1 {}"); 206 Path automaticClasses = base.resolve("automaticClasses"); 207 tb.createDirectories(automaticClasses); 208 209 String automaticLog = new JavacTask(tb) 210 .outdir(automaticClasses) 211 .files(findJavaFiles(automaticSrc)) 212 .run() 213 .writeAll() 214 .getOutput(Task.OutputKind.DIRECT); 215 216 if (!automaticLog.isEmpty()) 217 throw new Exception("expected output not found: " + automaticLog); 218 219 Path modulePath = base.resolve("module-path"); 220 221 Files.createDirectories(modulePath); 222 223 Path automaticJar = modulePath.resolve("a-1.0.jar"); 224 225 new JarTask(tb, automaticJar) 226 .baseDir(automaticClasses) 227 .files("api1/Api1.class") 228 .run(); 229 230 Path src = base.resolve("src"); 231 Path src_m2 = src.resolve("m2x"); 232 tb.writeJavaFiles(src_m2, 233 "module m2x { requires a; exports api2; }", 234 "package api2; public class Api2 { public static api1.Api1 get() { return null; } }"); 235 Path src_m3 = src.resolve("m3x"); 236 tb.writeJavaFiles(src_m3, 237 "module m3x { requires a; requires m2x; }", 238 "package test; public class Test { { api2.Api2.get(); api1.Api1 a1; } }"); 239 Path classes = base.resolve("classes"); 240 tb.createDirectories(classes); 241 242 new JavacTask(tb) 243 .options("--module-path", modulePath.toString(), 244 "--module-source-path", src.toString()) 245 .outdir(classes) 246 .files(findJavaFiles(src_m2)) 247 .run() 248 .writeAll(); 249 250 new JavacTask(tb) 251 .options("--module-path", modulePath.toString(), 252 "--module-source-path", src.toString()) 253 .outdir(classes) 254 .files(findJavaFiles(src_m3)) 255 .run() 256 .writeAll(); 257 } 258 259 @Test 260 public void testEmptyImplicitModuleInfo(Path base) throws Exception { 261 Path src = base.resolve("src"); 262 Path src_m1 = src.resolve("m1x"); 263 Files.createDirectories(src_m1); 264 try (Writer w = Files.newBufferedWriter(src_m1.resolve("module-info.java"))) {} 265 tb.writeJavaFiles(src_m1, 266 "package test; public class Test {}"); 267 Path classes = base.resolve("classes"); 268 tb.createDirectories(classes); 269 270 List<String> log = new JavacTask(tb) 271 .options("--source-path", src_m1.toString(), 272 "-XDrawDiagnostics") 273 .outdir(classes) 274 .files(findJavaFiles(src_m1.resolve("test"))) 275 .run(Task.Expect.FAIL) 276 .writeAll() 277 .getOutputLines(OutputKind.DIRECT); 278 279 List<String> expected = Arrays.asList( 280 "- compiler.err.cant.access: module-info, (compiler.misc.bad.source.file.header: module-info.java, (compiler.misc.file.does.not.contain.module))", 281 "1 error"); 282 283 if (!expected.equals(log)) { 284 throw new AssertionError("Unexpected output: " + log); 285 } 286 287 tb.writeJavaFiles(src_m1, 288 "module m1x {}"); 289 290 new JavacTask(tb) 291 .options("--source-path", src_m1.toString()) 292 .outdir(classes) 293 .files(findJavaFiles(src_m1.resolve("test"))) 294 .run() 295 .writeAll(); 296 297 } 298 299 @Test 300 public void testClassPackageClash(Path base) throws Exception { 301 Path src = base.resolve("src"); 302 Path src_m1 = src.resolve("m1x"); 303 tb.writeJavaFiles(src_m1, 304 "module m1x { exports test.m1x; }", 305 "package test.m1x;\n" + 306 "public class Test {}\n"); 307 Path src_m2 = src.resolve("m2x"); 308 tb.writeJavaFiles(src_m2, 309 "module m2x { requires m1x; }", 310 "package test;\n" + 311 "public class m1x {}\n"); 312 Path classes = base.resolve("classes"); 313 tb.createDirectories(classes); 314 315 List<String> log = new JavacTask(tb) 316 .options("--module-source-path", src.toString(), 317 "-XDrawDiagnostics") 318 .outdir(classes) 319 .files(findJavaFiles(src)) 320 .run(Task.Expect.FAIL) 321 .writeAll() 322 .getOutputLines(Task.OutputKind.DIRECT); 323 324 List<String> expected = Arrays.asList( 325 "m1x.java:2:8: compiler.err.clash.with.pkg.of.same.name: kindname.class, test.m1x", 326 "1 error" 327 ); 328 329 if (!expected.equals(log)) { 330 throw new IllegalStateException(log.toString()); 331 } 332 } 333 334 @Test 335 public void testImplicitJavaBase(Path base) throws Exception { 336 Path src = base.resolve("src"); 337 Path src_java_base = src.resolve("java.base"); 338 Files.createDirectories(src_java_base); 339 tb.writeJavaFiles(src_java_base, "module java.base { exports java.lang; }"); 340 tb.writeJavaFiles(src_java_base, 341 "package java.lang; public class Object {}"); 342 Path classes = base.resolve("classes"); 343 tb.createDirectories(classes); 344 345 //module-info from source: 346 new JavacTask(tb) 347 .options("-sourcepath", src_java_base.toString()) 348 .outdir(classes) 349 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 350 .run() 351 .writeAll(); 352 353 //module-info from class: 354 if (!Files.exists(classes.resolve("module-info.class"))) { 355 throw new AssertionError("module-info.class not created!"); 356 } 357 358 new JavacTask(tb) 359 .outdir(classes) 360 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 361 .run() 362 .writeAll(); 363 364 //broken module-info.class: 365 Files.newOutputStream(classes.resolve("module-info.class")).close(); 366 367 List<String> log = new JavacTask(tb) 368 .options("-XDrawDiagnostics") 369 .outdir(classes) 370 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 371 .run(Expect.FAIL) 372 .writeAll() 373 .getOutputLines(OutputKind.DIRECT); 374 375 List<String> expected = Arrays.asList( 376 "- compiler.err.cant.access: <error>.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.illegal.start.of.class.file))", 377 "1 error"); 378 379 if (!expected.equals(log)) { 380 throw new AssertionError("Unexpected output: " + log); 381 } 382 383 //broken module-info.java: 384 Files.delete(classes.resolve("module-info.class")); 385 386 try (Writer out = Files.newBufferedWriter(src_java_base.resolve("module-info.java"))) { 387 out.write("class Broken {}"); 388 } 389 390 log = new JavacTask(tb) 391 .options("-sourcepath", src_java_base.toString(), 392 "-XDrawDiagnostics") 393 .outdir(classes) 394 .files(findJavaFiles(src_java_base.resolve("java").resolve("lang").resolve("Object.java"))) 395 .run(Expect.FAIL) 396 .writeAll() 397 .getOutputLines(OutputKind.DIRECT); 398 399 expected = Arrays.asList("X"); 400 401 if (expected.equals(log)) { 402 throw new AssertionError("Unexpected output: " + log); 403 } 404 } 405 406 @Test 407 public void testModuleInfoNameMismatchSource(Path base) throws Exception { 408 Path src = base.resolve("src"); 409 Path m1 = src.resolve("m1x"); 410 Files.createDirectories(m1); 411 tb.writeJavaFiles(m1, "module other { }", 412 "package test; public class Test {}"); 413 Path classes = base.resolve("classes"); 414 tb.createDirectories(classes); 415 416 List<String> log = new JavacTask(tb) 417 .options("--module-source-path", src.toString(), 418 "-XDrawDiagnostics") 419 .outdir(classes) 420 .files(findJavaFiles(m1.resolve("test").resolve("Test.java"))) 421 .run(Expect.FAIL) 422 .writeAll() 423 .getOutputLines(OutputKind.DIRECT); 424 425 List<String> expected = Arrays.asList( 426 "module-info.java:1:1: compiler.err.module.name.mismatch: other, m1x", 427 "- compiler.err.cant.access: m1x.module-info, (compiler.misc.cant.resolve.modules)", 428 "2 errors"); 429 430 if (!expected.equals(log)) { 431 throw new AssertionError("Unexpected output: " + log); 432 } 433 } 434 435 @Test 436 public void testModuleInfoNameMismatchClass(Path base) throws Exception { 437 Path src = base.resolve("src"); 438 Files.createDirectories(src); 439 tb.writeJavaFiles(src, "module other { }", 440 "package test; public class Test {}"); 441 Path classes = base.resolve("classes"); 442 Path m1Classes = classes.resolve("m1x"); 443 tb.createDirectories(m1Classes); 444 445 new JavacTask(tb) 446 .outdir(m1Classes) 447 .files(findJavaFiles(src)) 448 .run() 449 .writeAll() 450 .getOutputLines(OutputKind.DIRECT); 451 452 Path src2 = base.resolve("src2"); 453 Files.createDirectories(src2); 454 tb.writeJavaFiles(src2, "module use { requires m1x; }"); 455 456 Path classes2 = base.resolve("classes2"); 457 tb.createDirectories(classes2); 458 459 List<String> log = new JavacTask(tb) 460 .options("--module-path", classes.toString(), 461 "-XDrawDiagnostics") 462 .outdir(classes2) 463 .files(findJavaFiles(src2)) 464 .run(Expect.FAIL) 465 .writeAll() 466 .getOutputLines(OutputKind.DIRECT); 467 468 List<String> expected = Arrays.asList( 469 "- compiler.err.cant.access: m1x.module-info, (compiler.misc.bad.class.file.header: module-info.class, (compiler.misc.module.name.mismatch: other, m1x))", 470 "module-info.java:1:1: compiler.err.module.not.found: m1x", 471 "2 errors"); 472 473 if (!expected.equals(log)) { 474 throw new AssertionError("Unexpected output: " + log); 475 } 476 } 477 478 @Test 479 public void testGetDirectivesComplete(Path base) throws Exception { 480 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 481 JavacTaskImpl task = (JavacTaskImpl) compiler.getTask(null, null, null, null, null, null); 482 Symtab syms = Symtab.instance(task.getContext()); 483 484 syms.java_base.getDirectives(); 485 } 486 487 @Test 488 public void testPackageInModuleInfo(Path base) throws Exception { 489 Path src = base.resolve("src"); 490 Files.createDirectories(src); 491 tb.writeJavaFiles(src, "package p; module foo { }"); 492 Path classes = base.resolve("classes"); 493 tb.createDirectories(classes); 494 495 List<String> log = new JavacTask(tb) 496 .options("-XDrawDiagnostics", "-XDshould-stop.ifError=FLOW") 497 .outdir(classes) 498 .files(findJavaFiles(src)) 499 .run(Expect.FAIL) 500 .writeAll() 501 .getOutputLines(OutputKind.DIRECT); 502 503 List<String> expected = Arrays.asList( 504 "module-info.java:1:1: compiler.err.no.pkg.in.module-info.java", 505 "1 error"); 506 507 if (!expected.equals(log)) { 508 throw new AssertionError("Unexpected output: " + log); 509 } 510 } 511 512 @Test 513 public void testInvisibleClassVisiblePackageClash(Path base) throws Exception { 514 Path src = base.resolve("src"); 515 Path src_m1 = src.resolve("m1x"); 516 tb.writeJavaFiles(src_m1, 517 "module m1x { }", 518 "package m1x;\n" + 519 "import m1x.a.*; public class Test { A a; }\n", 520 "package m1x.a;\n" + 521 "public class A { }\n"); 522 Path src_m2 = src.resolve("m2x"); 523 tb.writeJavaFiles(src_m2, 524 "module m2x { }", 525 "package m1x;\n" + 526 "public class a { public static class A { } }\n"); 527 Path classes = base.resolve("classes"); 528 tb.createDirectories(classes); 529 530 new JavacTask(tb) 531 .options("--module-source-path", src.toString(), 532 "-XDrawDiagnostics") 533 .outdir(classes) 534 .files(findJavaFiles(src)) 535 .run() 536 .writeAll(); 537 } 538 539 @Test 540 public void testStripUnknownRequired(Path base) throws Exception { 541 Path src = base.resolve("src"); 542 Path src_m1 = src.resolve("m1x"); 543 tb.writeJavaFiles(src_m1, 544 "module m1x { }"); 545 Path src_m2 = src.resolve("m2x"); 546 tb.writeJavaFiles(src_m2, 547 "module m2x { }"); 548 Path src_m3 = src.resolve("m3x"); 549 tb.writeJavaFiles(src_m3, 550 "module m3x { }"); 551 Path src_m4 = src.resolve("m4x"); 552 tb.writeJavaFiles(src_m4, 553 "module m4x { }"); 554 Path src_test = src.resolve("test"); 555 tb.writeJavaFiles(src_test, 556 "module test { requires m1x; requires m2x; requires java.base; requires m3x; requires m4x; }"); 557 Path src_compile = src.resolve("compile"); 558 tb.writeJavaFiles(src_compile, 559 "module compile { exports p to test; }", 560 "package p; public class Test { }"); 561 Path classes = base.resolve("classes"); 562 tb.createDirectories(classes); 563 564 List<String> log = new JavacTask(tb) 565 .options("-processor", ListRequires.class.getName(), 566 "--module-source-path", src.toString(), 567 "--limit-modules", "compile", 568 "-XDaccessInternalAPI=true") 569 .outdir(classes) 570 .files(findJavaFiles(src_compile)) 571 .run(Expect.FAIL) 572 .writeAll() 573 .getOutputLines(Task.OutputKind.STDOUT); 574 575 List<String> expected = Arrays.asList( 576 "from directives:", 577 "java.base", 578 "from requires:", 579 "java.base" 580 ); 581 if (!Objects.equals(log, expected)) 582 throw new AssertionError("Unexpected output: " + log); 583 } 584 585 @SupportedAnnotationTypes("*") 586 @SupportedOptions("expectedEnclosedElements") 587 public static final class ListRequires extends AbstractProcessor { 588 589 private int round; 590 591 @Override 592 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 593 if (round++ == 0) { 594 ModuleElement compileE = processingEnv.getElementUtils().getModuleElement("compile"); 595 ModuleElement testE = ElementFilter.exportsIn(compileE.getDirectives()).get(0).getTargetModules().get(0); 596 597 System.out.println("from directives:"); 598 for (RequiresDirective rd : ElementFilter.requiresIn(testE.getDirectives())) { 599 System.out.println(rd.getDependency().getQualifiedName()); 600 } 601 602 System.out.println("from requires:"); 603 for (RequiresDirective rd : ((ModuleSymbol) testE).requires) { 604 System.out.println(rd.getDependency().getQualifiedName()); 605 } 606 } 607 608 return false; 609 } 610 611 @Override 612 public SourceVersion getSupportedSourceVersion() { 613 return SourceVersion.latest(); 614 } 615 616 } 617 618 @Test 619 public void testOnDemandCompletionModuleInfoJava(Path base) throws Exception { 620 Path src = base.resolve("src"); 621 Path src_m1 = src.resolve("m1x"); 622 tb.writeJavaFiles(src_m1, 623 "@Deprecated module m1x { }"); 624 Path src_m2 = src.resolve("m2x"); 625 tb.writeJavaFiles(src_m2, 626 "module m2x { requires m1x; }"); 627 Path src_m3 = src.resolve("m3x"); 628 tb.writeJavaFiles(src_m3, 629 "module m3x { requires m2x; requires m1x; }"); 630 Path classes = base.resolve("classes"); 631 tb.createDirectories(classes); 632 633 List<String> log; 634 List<String> expected; 635 636 log = new JavacTask(tb) 637 .options("--module-source-path", src.toString()) 638 .outdir(classes) 639 .files(findJavaFiles(src_m1)) 640 .run() 641 .writeAll() 642 .getOutputLines(Task.OutputKind.DIRECT); 643 644 expected = Arrays.asList(""); 645 646 if (!expected.equals(log)) { 647 throw new IllegalStateException(log.toString()); 648 } 649 650 log = new JavacTask(tb) 651 .options("--module-source-path", src.toString(), 652 "-XDrawDiagnostics", 653 "-Xlint:deprecation") 654 .outdir(classes) 655 .files(findJavaFiles(src_m3)) 656 .run() 657 .writeAll() 658 .getOutputLines(Task.OutputKind.DIRECT); 659 660 expected = Arrays.asList( 661 "module-info.java:1:23: compiler.warn.has.been.deprecated.module: m1x", 662 "module-info.java:1:37: compiler.warn.has.been.deprecated.module: m1x", 663 "2 warnings" 664 ); 665 666 if (!expected.equals(log)) { 667 throw new IllegalStateException(log.toString()); 668 } 669 } 670 671 @Test 672 public void testUnnamedPackage(Path base) throws Exception { 673 List<String> out; 674 List<String> expected; 675 676 //-source 8: 677 Path src8 = base.resolve("src8"); 678 Files.createDirectories(src8); 679 tb.writeJavaFiles(src8, 680 "package test; public class Test {}"); 681 Path classes = base.resolve("classes"); 682 tb.createDirectories(classes); 683 684 out = new JavacTask(tb) 685 .options("--source-path", src8.toString(), 686 "-processor", UnnamedPackageProcessor.class.getName(), 687 "-source", "8") 688 .outdir(classes) 689 .files(findJavaFiles(src8)) 690 .run() 691 .writeAll() 692 .getOutputLines(OutputKind.STDOUT); 693 694 expected = Arrays.asList("noModule"); 695 696 if (!expected.equals(out)) { 697 throw new AssertionError("Unexpected output: " + out); 698 } 699 700 //-source 9, unnamed: 701 Path srcUnnamed = base.resolve("srcUnnamed"); 702 Files.createDirectories(srcUnnamed); 703 tb.writeJavaFiles(srcUnnamed, 704 "public class Test {}"); 705 Path classesUnnamed = base.resolve("classesUnnamed"); 706 tb.createDirectories(classesUnnamed); 707 708 out = new JavacTask(tb) 709 .options("--source-path", srcUnnamed.toString(), 710 "-processor", UnnamedPackageProcessor.class.getName()) 711 .outdir(classesUnnamed) 712 .files(findJavaFiles(srcUnnamed)) 713 .run() 714 .writeAll() 715 .getOutputLines(OutputKind.STDOUT); 716 717 expected = Arrays.asList("unnamedModule"); 718 719 if (!expected.equals(out)) { 720 throw new AssertionError("Unexpected output: " + out); 721 } 722 723 //-source 9, named: 724 Path srcNamed = base.resolve("srcNamed"); 725 Files.createDirectories(srcNamed); 726 tb.writeJavaFiles(srcNamed, 727 "module m {}", 728 "public class Test {}"); 729 Path classesNamed = base.resolve("classesNamed"); 730 tb.createDirectories(classesNamed); 731 732 out = new JavacTask(tb) 733 .options("--source-path", srcNamed.toString(), 734 "-classpath", "", 735 "-processorpath", System.getProperty("test.class.path"), 736 "-processor", UnnamedPackageProcessor.class.getName()) 737 .outdir(classesNamed) 738 .files(findJavaFiles(srcNamed)) 739 .run() 740 .writeAll() 741 .getOutputLines(OutputKind.STDOUT); 742 743 expected = Arrays.asList("m"); 744 745 if (!expected.equals(out)) { 746 throw new AssertionError("Unexpected output: " + out); 747 } 748 749 //-source 9, conflict: 750 Path srcNamed2 = base.resolve("srcNamed2"); 751 Path srcNamed2m1 = srcNamed2.resolve("m1x"); 752 Files.createDirectories(srcNamed2m1); 753 tb.writeJavaFiles(srcNamed2m1, 754 "module m1x {}", 755 "public class Test {}"); 756 Path srcNamed2m2 = srcNamed2.resolve("m2x"); 757 Files.createDirectories(srcNamed2m2); 758 tb.writeJavaFiles(srcNamed2m2, 759 "module m2x {}", 760 "public class Test {}"); 761 Path classesNamed2 = base.resolve("classesNamed2"); 762 tb.createDirectories(classesNamed2); 763 764 out = new JavacTask(tb) 765 .options("--module-source-path", srcNamed2.toString(), 766 "-classpath", "", 767 "-processorpath", System.getProperty("test.class.path"), 768 "-processor", UnnamedPackageProcessor.class.getName(), 769 "-XDshould-stop.ifError=FLOW") 770 .outdir(classesNamed2) 771 .files(findJavaFiles(srcNamed2)) 772 .run(Expect.FAIL) 773 .writeAll() 774 .getOutputLines(OutputKind.STDOUT); 775 776 expected = Arrays.asList("null", 777 "m1x: true", 778 "m2x: true"); 779 780 if (!expected.equals(out)) { 781 throw new AssertionError("Unexpected output: " + out); 782 } 783 } 784 785 @SupportedAnnotationTypes("*") 786 public static final class UnnamedPackageProcessor extends AbstractProcessor { 787 788 int round = 0; 789 790 @Override 791 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 792 if (round++ != 0) 793 return false; 794 795 Elements elements = processingEnv.getElementUtils(); 796 PackageElement pe = elements.getPackageElement(""); 797 798 if (pe == null) { 799 System.out.println("null"); 800 } else { 801 ModuleElement mod = (ModuleElement) pe.getEnclosingElement(); 802 if (mod == null) { 803 System.out.println("noModule"); 804 } else if (mod.isUnnamed()) { 805 System.out.println("unnamedModule"); 806 } else { 807 System.out.println(mod); 808 } 809 } 810 811 ModuleElement m1x = elements.getModuleElement("m1x"); 812 ModuleElement m2x = elements.getModuleElement("m2x"); 813 814 if (m1x != null && m2x != null) { 815 System.out.println("m1x: " + (elements.getPackageElement(m1x, "") != null)); 816 System.out.println("m2x: " + (elements.getPackageElement(m2x, "") != null)); 817 } 818 819 return false; 820 } 821 822 } 823 824 @Test 825 public void testEmptyInExportedPackage(Path base) throws Exception { 826 Path src = base.resolve("src"); 827 Path m = src.resolve("m"); 828 tb.writeJavaFiles(m, 829 "module m { exports api; }"); 830 Path apiFile = m.resolve("api").resolve("Api.java"); 831 Files.createDirectories(apiFile.getParent()); 832 try (BufferedWriter w = Files.newBufferedWriter(apiFile)) { 833 w.write("//no package decl"); 834 } 835 Path classes = base.resolve("classes"); 836 tb.createDirectories(classes); 837 838 List<String> log; 839 List<String> expected = 840 Arrays.asList("module-info.java:1:20: compiler.err.package.empty.or.not.found: api", 841 "1 error"); 842 843 System.err.println("file explicitly specified:"); 844 845 log = new JavacTask(tb) 846 .options("-XDrawDiagnostics", 847 "--module-source-path", src.toString()) 848 .outdir(classes) 849 .files(findJavaFiles(src)) 850 .run(Task.Expect.FAIL) 851 .writeAll() 852 .getOutputLines(Task.OutputKind.DIRECT); 853 854 if (!expected.equals(log)) 855 throw new Exception("expected output not found: " + log); 856 857 System.err.println("file not specified:"); 858 859 tb.cleanDirectory(classes); 860 861 log = new JavacTask(tb) 862 .options("-XDrawDiagnostics", 863 "--module-source-path", src.toString()) 864 .outdir(classes) 865 .files(findJavaFiles(m.resolve("module-info.java"))) 866 .run(Task.Expect.FAIL) 867 .writeAll() 868 .getOutputLines(Task.OutputKind.DIRECT); 869 870 if (!expected.equals(log)) 871 throw new Exception("expected output not found: " + log); 872 } 873 874 @Test 875 public void testJustPackageInExportedPackage(Path base) throws Exception { 876 Path src = base.resolve("src"); 877 Path m = src.resolve("m"); 878 tb.writeJavaFiles(m, 879 "module m { exports api; }"); 880 Path apiFile = m.resolve("api").resolve("Api.java"); 881 Files.createDirectories(apiFile.getParent()); 882 try (BufferedWriter w = Files.newBufferedWriter(apiFile)) { 883 w.write("package api;"); 884 } 885 Path classes = base.resolve("classes"); 886 tb.createDirectories(classes); 887 888 System.err.println("file explicitly specified:"); 889 890 new JavacTask(tb) 891 .options("-XDrawDiagnostics", 892 "--module-source-path", src.toString()) 893 .outdir(classes) 894 .files(findJavaFiles(src)) 895 .run() 896 .writeAll(); 897 898 System.err.println("file not specified:"); 899 900 tb.cleanDirectory(classes); 901 902 new JavacTask(tb) 903 .options("-XDrawDiagnostics", 904 "--module-source-path", src.toString()) 905 .outdir(classes) 906 .files(findJavaFiles(m.resolve("module-info.java"))) 907 .run() 908 .writeAll(); 909 } 910 911 @Test 912 public void testWrongPackageInExportedPackage(Path base) throws Exception { 913 Path src = base.resolve("src"); 914 Path m = src.resolve("m"); 915 tb.writeJavaFiles(m, 916 "module m { exports api; }"); 917 Path apiFile = m.resolve("api").resolve("Api.java"); 918 Files.createDirectories(apiFile.getParent()); 919 try (BufferedWriter w = Files.newBufferedWriter(apiFile)) { 920 w.write("package impl; public class Api { }"); 921 } 922 Path classes = base.resolve("classes"); 923 tb.createDirectories(classes); 924 925 List<String> log; 926 927 List<String> expected = 928 Arrays.asList("module-info.java:1:20: compiler.err.package.empty.or.not.found: api", 929 "1 error"); 930 931 System.err.println("file explicitly specified:"); 932 933 log = new JavacTask(tb) 934 .options("-XDrawDiagnostics", 935 "--module-source-path", src.toString()) 936 .outdir(classes) 937 .files(findJavaFiles(src)) 938 .run(Task.Expect.FAIL) 939 .writeAll() 940 .getOutputLines(Task.OutputKind.DIRECT); 941 942 if (!expected.equals(log)) 943 throw new Exception("expected output not found: " + log); 944 945 System.err.println("file not specified:"); 946 947 tb.cleanDirectory(classes); 948 949 log = new JavacTask(tb) 950 .options("-XDrawDiagnostics", 951 "--module-source-path", src.toString()) 952 .outdir(classes) 953 .files(findJavaFiles(m.resolve("module-info.java"))) 954 .run(Task.Expect.FAIL) 955 .writeAll() 956 .getOutputLines(Task.OutputKind.DIRECT); 957 958 if (!expected.equals(log)) 959 throw new Exception("expected output not found: " + log); 960 } 961 962 @Test 963 public void testDependOnUnnamedAccessibility(Path base) throws Exception { 964 Path unnamedSrc = base.resolve("unnamed-src"); 965 tb.writeJavaFiles(unnamedSrc, 966 "package p1; public class First { public static p2.Second get() { return null; } }", 967 "package p2; public class Second { public void test() { } }"); 968 Path unnamedClasses = base.resolve("unnamed-classes"); 969 tb.createDirectories(unnamedClasses); 970 971 System.err.println("compiling unnamed sources:"); 972 973 new JavacTask(tb) 974 .outdir(unnamedClasses) 975 .files(findJavaFiles(unnamedSrc)) 976 .run() 977 .writeAll(); 978 979 //test sources: 980 Path src = base.resolve("src"); 981 Path m = src.resolve("m"); 982 tb.writeJavaFiles(m, 983 "module m { }", 984 "package p; public class Test { { p1.First.get().test(); } }"); 985 Path classes = base.resolve("classes"); 986 tb.createDirectories(classes); 987 988 System.err.println("compiling test module:"); 989 990 new JavacTask(tb) 991 .options("-classpath", unnamedClasses.toString(), 992 "--add-reads", "m=ALL-UNNAMED") 993 .outdir(classes) 994 .files(findJavaFiles(src)) 995 .run() 996 .writeAll(); 997 } 998 999} 1000