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