Modules.java revision 4062:ee787e34231d
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 8159305 8166127 8175860 8176481 27 * @summary Tests primarily the module graph computations. 28 * @modules 29 * jdk.javadoc/jdk.javadoc.internal.api 30 * jdk.javadoc/jdk.javadoc.internal.tool 31 * jdk.compiler/com.sun.tools.javac.api 32 * jdk.compiler/com.sun.tools.javac.main 33 * @library /tools/lib 34 * @build toolbox.ToolBox toolbox.TestRunner 35 * @run main Modules 36 */ 37 38import java.io.IOException; 39import java.nio.file.Files; 40import java.nio.file.Path; 41import java.nio.file.Paths; 42 43import toolbox.*; 44import toolbox.Task.Expect; 45import toolbox.Task.OutputKind; 46 47public class Modules extends ModuleTestBase { 48 49 public static void main(String... args) throws Exception { 50 new Modules().runTests(); 51 } 52 53 @Test 54 public void testBasicMoption(Path base) throws Exception { 55 Files.createDirectory(base); 56 Path src = base.resolve("src"); 57 ModuleBuilder mb = new ModuleBuilder(tb, "m1"); 58 mb.comment("The first module.") 59 .exports("pub") 60 .classes("package pub; /** Class A */ public class A {}") 61 .classes("package pro; /** Class B */ public class B {}") 62 .write(src); 63 execTask("--module-source-path", src.toString(), 64 "--module", "m1"); 65 checkModulesSpecified("m1"); 66 checkPackagesIncluded("pub"); 67 checkTypesIncluded("pub.A"); 68 } 69 70 @Test 71 public void testMultipleModulesOption1(Path base) throws Exception { 72 Path src = base.resolve("src"); 73 74 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 75 mb1.comment("The first module.") 76 .exports("m1pub") 77 .requires("m2") 78 .classes("package m1pub; /** Class A */ public class A {}") 79 .classes("package m1pro; /** Class B */ public class B {}") 80 .write(src); 81 82 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 83 mb2.comment("The second module.") 84 .exports("m2pub") 85 .classes("package m2pub; /** Class A */ public class A {}") 86 .classes("package m2pro; /** Class B */ public class B {}") 87 .write(src); 88 execTask("--module-source-path", src.toString(), 89 "--module", "m1,m2"); 90 checkModulesSpecified("m1", "m2"); 91 checkPackagesIncluded("m1pub", "m2pub"); 92 checkTypesIncluded("m1pub.A", "m2pub.A"); 93 94 } 95 96 @Test 97 public void testMissingModuleWithSourcePath(Path base) throws Exception { 98 Path src = base.resolve("src"); 99 Path mod = src.resolve("m1"); 100 101 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 102 mb1.comment("The first module.") 103 .exports("m1pub") 104 .requires("m2") 105 .classes("package m1pub; /** Class A */ public class A {}") 106 .classes("package m1pro; /** Class B */ public class B {}") 107 .write(src); 108 109 Path javafile = Paths.get(mod.toString(), "m1pub/A.java"); 110 111 execNegativeTask("--source-path", mod.toString(), 112 javafile.toString()); 113 114 assertMessagePresent("error: cannot access module-info"); 115 assertMessageNotPresent("error - fatal error encountered"); 116 117 } 118 119 @Test 120 public void testMultipleModulesAggregatedModuleOption(Path base) throws Exception { 121 Path src = base.resolve("src"); 122 123 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 124 mb1.comment("The first module.") 125 .exports("m1pub") 126 .requires("m2") 127 .classes("package m1pub; /** Class A */ public class A {}") 128 .classes("package m1pro; /** Class B */ public class B {}") 129 .write(src); 130 131 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 132 mb2.comment("The second module.") 133 .exports("m2pub") 134 .classes("package m2pub; /** Class A */ public class A {}") 135 .classes("package m2pro; /** Class B */ public class B {}") 136 .write(src); 137 execTask("--module-source-path", src.toString(), 138 "--module", "m1", 139 "--module", "m2"); 140 checkModulesSpecified("m1", "m2"); 141 checkPackagesIncluded("m1pub", "m2pub"); 142 checkTypesIncluded("m1pub.A", "m2pub.A"); 143 144 } 145 146 @Test 147 public void testModulePathOption(Path base) throws Exception { 148 Path src = base.resolve("src"); 149 Path modulePath = base.resolve("modules"); 150 151 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 152 mb1.comment("Module on module path.") 153 .exports("pkg1") 154 .classes("package pkg1; /** Class A */ public class A { }") 155 .build(modulePath); 156 157 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 158 mb2.comment("The second module.") 159 .exports("pkg2") 160 .requires("m1") 161 .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }") 162 .write(src); 163 execTask("--module-source-path", src.toString(), 164 "--module-path", modulePath.toString(), 165 "--module", "m2"); 166 checkModulesSpecified("m2"); 167 checkPackagesIncluded("pkg2"); 168 checkMembersSelected("pkg2.B.f"); 169 170 // module path option "-p" 171 execTask("--module-source-path", src.toString(), 172 "-p", modulePath.toString(), 173 "--module", "m2"); 174 // no module path 175 execNegativeTask("--module-source-path", src.toString(), 176 "--module", "m2"); 177 assertMessagePresent("error: module not found: m1"); 178 } 179 180 @Test 181 public void testUpgradeModulePathOption(Path base) throws Exception { 182 Path src = base.resolve("src"); 183 Path modulePath = base.resolve("modules"); 184 Path upgradePath = base.resolve("upgrades"); 185 186 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 187 mb1.comment("Module on module path.") 188 .exports("pkg1") 189 .classes("package pkg1; /** Class A */ public class A { }") 190 .build(modulePath); 191 192 ModuleBuilder mbUpgrade = new ModuleBuilder(tb, "m1"); 193 mbUpgrade.comment("Module on upgrade module path.") 194 .exports("pkg1") 195 .classes("package pkg1; /** Class C */ public class C { }") 196 .build(upgradePath); 197 198 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 199 mb2.comment("The second module.") 200 .exports("pkg2") 201 .requires("m1") 202 .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.C f; }") 203 .write(src); 204 execTask("--module-source-path", src.toString(), 205 "--module-path", modulePath.toString(), 206 "--upgrade-module-path", upgradePath.toString(), 207 "--module", "m2"); 208 checkModulesSpecified("m2"); 209 checkPackagesIncluded("pkg2"); 210 checkMembersSelected("pkg2.B.f"); 211 212 // no upgrade module path 213 execNegativeTask("--module-source-path", src.toString(), 214 "--module-path", modulePath.toString(), 215 "--module", "m2"); 216 assertMessagePresent("error: cannot find symbol"); 217 218 // dependency from module path 219 ModuleBuilder mb3 = new ModuleBuilder(tb, "m3"); 220 mb3.comment("The third module.") 221 .exports("pkg3") 222 .requires("m1") 223 .classes("package pkg3; /** Class Z */ public class Z { /** Field f */ public pkg1.A f; }") 224 .write(src); 225 execNegativeTask("--module-source-path", src.toString(), 226 "--module-path", modulePath.toString(), 227 "--upgrade-module-path", upgradePath.toString(), 228 "--module", "m3"); 229 assertMessagePresent("Z.java:1: error: cannot find symbol"); 230 } 231 232 @Test 233 public void testAddModulesOption(Path base) throws Exception { 234 Path src = base.resolve("src"); 235 Path modulePath = base.resolve("modules"); 236 237 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 238 mb1.comment("Module on module path.") 239 .exports("pkg1") 240 .classes("package pkg1; /** Class A */ public class A { }") 241 .build(modulePath); 242 243 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 244 mb2.comment("The second module.") 245 .exports("pkg2") 246 .classes("package pkg2; /** @see pkg1.A */ public class B { }") 247 .write(src); 248 249 Path out = base.resolve("out-1"); 250 Files.createDirectories(out); 251 String log = new JavadocTask(tb) 252 .outdir(out) 253 .options("--module-source-path", src.toString(), 254 "--module-path", modulePath.toString(), 255 "--module", "m2") 256 .run(Expect.FAIL) 257 .writeAll() 258 .getOutput(OutputKind.DIRECT); 259 if (!log.contains("B.java:1: error: reference not found")) { 260 throw new Exception("Error not found"); 261 } 262 263 out = base.resolve("out-2"); 264 Files.createDirectories(out); 265 new JavadocTask(tb) 266 .outdir(out) 267 .options("--module-source-path", src.toString(), 268 "--module-path", modulePath.toString(), 269 "--add-modules", "m1", 270 "--module", "m2") 271 .run() 272 .writeAll(); 273 } 274 275 @Test 276 public void testLimitModulesOption(Path base) throws Exception { 277 Path src = base.resolve("src"); 278 Path modulePath = base.resolve("modules"); 279 280 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 281 mb1.comment("Module on module path.") 282 .build(modulePath); 283 284 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 285 mb2.comment("The second module.") 286 .exports("pkg2") 287 .requires("m1") 288 .classes("package pkg2; /** Class B */ public class B { }") 289 .write(src); 290 291 execNegativeTask("--module-source-path", src.toString(), 292 "--module-path", modulePath.toString(), 293 "--limit-modules", "java.base", 294 "--module", "m2"); 295 assertMessagePresent("error: module not found: m1"); 296 } 297 298 @Test 299 public void testAddExportsOption(Path base) throws Exception { 300 Path src = base.resolve("src"); 301 Path modulePath = base.resolve("modules"); 302 303 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 304 mb1.comment("Module on module path.") 305 .classes("package pkg1; /** Class A */ public class A { }") 306 .build(modulePath); 307 308 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 309 mb2.comment("The second module.") 310 .exports("pkg2") 311 .requires("m1") 312 .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }") 313 .write(src); 314 execTask("--module-source-path", src.toString(), 315 "--module-path", modulePath.toString(), 316 "--add-exports", "m1/pkg1=m2", 317 "--module", "m2"); 318 checkModulesSpecified("m2"); 319 checkPackagesIncluded("pkg2"); 320 checkMembersSelected("pkg2.B.f"); 321 } 322 323 @Test 324 public void testAddReadsOption(Path base) throws Exception { 325 Path src = base.resolve("src"); 326 Path modulePath = base.resolve("modules"); 327 328 ModuleBuilder mb1 = new ModuleBuilder(tb, "m1"); 329 mb1.comment("Module on module path.") 330 .exports("pkg1") 331 .classes("package pkg1; /** Class A */ public class A {}") 332 .build(modulePath); 333 334 ModuleBuilder mb2 = new ModuleBuilder(tb, "m2"); 335 mb2.comment("The second module.") 336 .exports("pkg2") 337 .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f;}") 338 .write(src); 339 execTask("--module-source-path", src.toString(), 340 "--module-path", modulePath.toString(), 341 "--add-modules", "m1", 342 "--add-reads", "m2=m1", 343 "--module", "m2"); 344 checkModulesSpecified("m2"); 345 checkPackagesIncluded("pkg2"); 346 checkMembersSelected("pkg2.B.f"); 347 } 348 349 @Test 350 public void testModuleOptionsWithLegacy(Path base) throws Exception { 351 Files.createDirectory(base); 352 Path src = base.resolve("src"); 353 Path classpath = base.resolve("classpath"); 354 Path modulePath = base.resolve("modules"); 355 356 tb.writeJavaFiles(classpath, "package pkg1; /** Class C */ public class C { }"); 357 new JavacTask(tb) 358 .files(classpath.resolve("pkg1/C.java")) 359 .run(); 360 361 ModuleBuilder mb = new ModuleBuilder(tb, "m1"); 362 mb.comment("The first module.") 363 .exports("pub") 364 .classes("package pub; /** Class M */ public class M { }") 365 .build(modulePath); 366 367 tb.writeJavaFiles(src, "package pkg; /** Class L */ public class L { public pkg1.C f1; public pub.M f2; }"); 368 369 execTask("--source-path", src.toString(), 370 "--class-path", classpath.toString(), 371 "--module-path", modulePath.toString(), 372 "--add-modules", "m1", 373 "pkg"); 374 checkPackagesIncluded("pkg"); 375 checkTypesIncluded("pkg.L"); 376 checkMembersSelected("pkg.L.f1"); 377 checkMembersSelected("pkg.L.f2"); 378 assertAbsent("error", OutputKind.DIRECT); 379 } 380 381 /** 382 * Tests diamond graph, inspired by javac diamond tests. 383 * 384 * 385 * Module M : test module, with variable requires 386 * 387 * Module N : 388 * requires transitive O ---> Module O: 389 * requires J ----> Module J: 390 * exports openO exports openJ 391 * 392 * 393 * Module L : 394 * requires transitive P ---> Module P: 395 * exports openP 396 * 397 * 398 */ 399 400 @Test 401 public void testExpandRequiresNone(Path base) throws Exception { 402 Path src = base.resolve("src"); 403 404 createAuxiliaryModules(src); 405 406 new ModuleBuilder(tb, "M") 407 .comment("The M module.") 408 .requires("N", src) 409 .requires("L", src) 410 .requires("O", src) 411 .exports("p") 412 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 413 .write(src); 414 415 execTask("--module-source-path", src.toString(), 416 "--module", "M"); 417 418 checkModulesSpecified("M"); 419 checkModulesIncluded("M"); 420 checkPackagesIncluded("p"); 421 checkTypesIncluded("p.Main"); 422 checkPackagesNotIncluded(".*open.*"); 423 assertMessageNotPresent("warning"); 424 } 425 426 @Test 427 public void testExpandRequiresTransitive(Path base) throws Exception { 428 Path src = base.resolve("src"); 429 430 createAuxiliaryModules(src); 431 432 new ModuleBuilder(tb, "M") 433 .comment("The M module.") 434 .requiresTransitive("N", src) 435 .requires("L", src) 436 .exports("p") 437 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 438 .write(src); 439 440 execTask("--module-source-path", src.toString(), 441 "--module", "M", 442 "--expand-requires", "transitive"); 443 444 checkModulesSpecified("M", "N", "O"); 445 checkModulesNotSpecified("java.base"); 446 checkModulesIncluded("M", "N", "O"); 447 checkModulesNotIncluded("java.base"); 448 checkPackagesIncluded("p", "openN", "openO"); 449 checkTypesIncluded("p.Main", "openN.N", "openO.O"); 450 assertMessageNotPresent("warning"); 451 } 452 453 @Test 454 public void testExpandRequiresTransitiveWithMandated(Path base) throws Exception { 455 Path src = base.resolve("src"); 456 457 createAuxiliaryModules(src); 458 459 Path patchSrc = Paths.get(src.toString(), "patch"); 460 461 new ModuleBuilder(tb, "M") 462 .comment("The M module.") 463 .requiresTransitive("N", src) 464 .requires("L", src) 465 .exports("p") 466 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 467 .write(src); 468 469 // build the patching module 470 tb.writeJavaFiles(patchSrc, "package pkg1;\n" + 471 "/** Class A */ public class A extends java.util.ArrayList { }"); 472 tb.writeJavaFiles(patchSrc, "package pkg1;\n" 473 + "/** Class B */ public class B { }"); 474 475 execTask("--module-source-path", src.toString(), 476 "--patch-module", "java.base=" + patchSrc.toString(), 477 "--module", "M", 478 "--expand-requires", "transitive"); 479 480 checkModulesSpecified("java.base", "M", "N", "O"); 481 checkModulesIncluded("java.base", "M", "N", "O"); 482 checkPackagesIncluded("p", "openN", "openO"); 483 checkTypesIncluded("p.Main", "openN.N", "openO.O"); 484 assertMessageNotPresent("warning"); 485 } 486 487 @Test 488 public void testExpandRequiresAll(Path base) throws Exception { 489 Path src = base.resolve("src"); 490 491 createAuxiliaryModules(src); 492 493 new ModuleBuilder(tb, "M") 494 .comment("The M module.") 495 .requiresTransitive("N", src) 496 .requires("L", src) 497 .requires("O", src) 498 .exports("p") 499 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 500 .write(src); 501 502 execTask("--module-source-path", src.toString(), 503 "--module", "M", 504 "--expand-requires", "all"); 505 506 checkModulesSpecified("M", "N", "L", "O"); 507 checkModulesIncluded("M", "N", "L", "O"); 508 checkModulesNotIncluded("P", "J", "Q"); 509 checkPackagesIncluded("p", "openN", "openL", "openO"); 510 checkPackagesNotIncluded(".*openP.*", ".*openJ.*"); 511 checkTypesIncluded("p.Main", "openN.N", "openL.L", "openO.O"); 512 checkTypesNotIncluded(".*openP.*", ".*openJ.*"); 513 assertMessageNotPresent("warning"); 514 } 515 516 @Test 517 public void testMissingModule(Path base) throws Exception { 518 Path src = base.resolve("src"); 519 520 createAuxiliaryModules(src); 521 522 new ModuleBuilder(tb, "M") 523 .comment("The M module.") 524 .requiresTransitive("N", src) 525 .requires("L", src) 526 .requires("O", src) 527 .exports("p") 528 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 529 .write(src); 530 531 execNegativeTask("--module-source-path", src.toString(), 532 "--module", "MIA", 533 "--expand-requires", "all"); 534 535 assertMessagePresent("javadoc: error - module MIA not found."); 536 } 537 538 @Test 539 public void testMissingModuleMultiModuleCmdline(Path base) throws Exception { 540 Path src = base.resolve("src"); 541 542 createAuxiliaryModules(src); 543 544 new ModuleBuilder(tb, "M") 545 .comment("The M module.") 546 .requiresTransitive("N", src) 547 .requires("L", src) 548 .requires("O", src) 549 .exports("p") 550 .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }") 551 .write(src); 552 553 execNegativeTask("--module-source-path", src.toString(), 554 "--module", "M,N,L,MIA,O,P", 555 "--expand-requires", "all"); 556 557 assertMessagePresent("javadoc: error - module MIA not found"); 558 } 559 560 @Test 561 public void testSingleModuleOptionWithSourcePath(Path base) throws Exception { 562 Path src = base.resolve("src"); 563 Path mod = createSimpleModule(src, "m1"); 564 execTask("--source-path", mod.toString(), 565 "--module", "m1"); 566 checkModulesSpecified("m1"); 567 checkPackagesIncluded("p"); 568 checkTypesIncluded("p.C"); 569 } 570 571 @Test 572 public void testSingleModuleOptionWithMissingModuleInSourcePath(Path base) throws Exception { 573 Path src = base.resolve("src"); 574 Path mod = createSimpleModule(src, "m1"); 575 execNegativeTask("--source-path", mod.toString(), 576 "--module", "m2"); 577 assertMessagePresent("source path does not contain module m2"); 578 } 579 580 @Test 581 public void testMultipleModuleOptionWithSourcePath(Path base) throws Exception { 582 Path src = base.resolve("src"); 583 Path mod = createSimpleModule(src, "m1"); 584 execNegativeTask("--source-path", mod.toString(), 585 "--module", "m1,m2,m3"); 586 assertMessagePresent("cannot use source path for multiple modules m1, m2, m3"); 587 } 588 589 @Test 590 public void testSingleModuleOptionWithNoModuleOnSourcePath(Path base) throws Exception { 591 Path src = base.resolve("src"); 592 Path mod1 = Paths.get(src.toString(), "m1"); 593 execNegativeTask("--source-path", mod1.toString(), 594 "--module", "m1"); 595 assertMessagePresent("module m1 not found on source path"); 596 } 597 598 Path createSimpleModule(Path src, String mname) throws IOException { 599 Path mpath = Paths.get(src.toString(), mname); 600 tb.writeJavaFiles(mpath, 601 "module " + mname + " { exports p; }", 602 "package p; public class C { }"); 603 return mpath; 604 } 605 606 void createAuxiliaryModules(Path src) throws IOException { 607 608 new ModuleBuilder(tb, "J") 609 .comment("The J module.") 610 .exports("openJ") 611 .classes("package openJ; /** Class J open. */ public class J { }") 612 .classes("package closedJ; /** Class J closed. */ public class J { }") 613 .write(src); 614 615 new ModuleBuilder(tb, "L") 616 .comment("The L module.") 617 .exports("openL") 618 .requiresTransitive("P") 619 .classes("package openL; /** Class L open */ public class L { }") 620 .classes("package closedL; /** Class L closed */ public class L { }") 621 .write(src); 622 623 new ModuleBuilder(tb, "N") 624 .comment("The N module.") 625 .exports("openN") 626 .requiresTransitive("O") 627 .classes("package openN; /** Class N open */ public class N { }") 628 .classes("package closedN; /** Class N closed */ public class N { }") 629 .write(src); 630 631 new ModuleBuilder(tb, "O") 632 .comment("The O module.") 633 .exports("openO") 634 .requires("J") 635 .classes("package openO; /** Class O open. */ public class O { openJ.J j; }") 636 .classes("package closedO; /** Class O closed. */ public class O { }") 637 .write(src); 638 639 new ModuleBuilder(tb, "P") 640 .comment("The P module.") 641 .exports("openP") 642 .requires("J") 643 .classes("package openP; /** Class O open. */ public class O { openJ.J j; }") 644 .classes("package closedP; /** Class O closed. */ public class O { }") 645 .write(src); 646 647 new ModuleBuilder(tb, "Q") 648 .comment("The Q module.") 649 .exports("openQ") 650 .requires("J") 651 .classes("package openQ; /** Class Q open. */ public class Q { openJ.J j; }") 652 .classes("package closedQ; /** Class Q closed. */ public class Q { }") 653 .write(src); 654 655 } 656} 657