1 /* 2 * Copyright (c) 2014, 2018, 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 * @library /lib/testlibrary 27 * @modules java.base/jdk.internal.misc 28 * @build BasicLayerTest ModuleUtils 29 * @compile layertest/Test.java 30 * @run testng BasicLayerTest 31 * @summary Basic tests for java.lang.ModuleLayer 32 */ 33 34 import java.lang.module.Configuration; 35 import java.lang.module.ModuleDescriptor; 36 import java.lang.module.ModuleDescriptor.Requires; 37 import java.lang.module.ModuleFinder; 38 import java.util.HashMap; 39 import java.util.Map; 40 import java.util.Optional; 41 import java.util.Set; 42 import java.util.stream.Collectors; 43 44 import jdk.internal.misc.SharedSecrets; 45 46 import org.testng.annotations.DataProvider; 47 import org.testng.annotations.Test; 48 import static org.testng.Assert.*; 49 50 @Test 51 public class BasicLayerTest { 52 53 /** 54 * Creates a "non-strict" builder for building a module. This allows the 55 * test the create ModuleDescriptor objects that do not require java.base. 56 */ 57 private static ModuleDescriptor.Builder newBuilder(String mn) { 58 return SharedSecrets.getJavaLangModuleAccess() 59 .newModuleBuilder(mn, false, Set.of()); 60 } 61 62 /** 63 * Exercise ModuleLayer.empty() 64 */ 65 public void testEmpty() { 66 ModuleLayer emptyLayer = ModuleLayer.empty(); 67 68 assertTrue(emptyLayer.parents().isEmpty()); 69 70 assertTrue(emptyLayer.configuration() == Configuration.empty()); 71 72 assertTrue(emptyLayer.modules().isEmpty()); 73 74 assertFalse(emptyLayer.findModule("java.base").isPresent()); 75 76 try { 77 emptyLayer.findLoader("java.base"); 78 assertTrue(false); 79 } catch (IllegalArgumentException expected) { } 80 } 81 82 83 /** 84 * Exercise ModuleLayer.boot() 85 */ 86 public void testBoot() { 87 ModuleLayer bootLayer = ModuleLayer.boot(); 88 89 // configuration 90 Configuration cf = bootLayer.configuration(); 91 assertTrue(cf.findModule("java.base").get() 92 .reference() 93 .descriptor() 94 .exports() 95 .stream().anyMatch(e -> (e.source().equals("java.lang") 96 && !e.isQualified()))); 97 98 // modules 99 Set<Module> modules = bootLayer.modules(); 100 assertTrue(modules.contains(Object.class.getModule())); 101 int count = (int) modules.stream().map(Module::getName).count(); 102 assertEquals(count, modules.size()); // module names are unique 103 104 // findModule 105 Module base = Object.class.getModule(); 106 assertTrue(bootLayer.findModule("java.base").get() == base); 107 assertTrue(base.getLayer() == bootLayer); 108 109 // findLoader 110 assertTrue(bootLayer.findLoader("java.base") == null); 111 112 // parents 113 assertTrue(bootLayer.parents().size() == 1); 114 assertTrue(bootLayer.parents().get(0) == ModuleLayer.empty()); 115 } 116 117 118 /** 119 * Exercise defineModules, created with empty layer as parent 120 */ 121 public void testLayerOnEmpty() { 122 ModuleDescriptor descriptor1 = newBuilder("m1") 123 .requires("m2") 124 .exports("p1") 125 .build(); 126 127 ModuleDescriptor descriptor2 = newBuilder("m2") 128 .requires("m3") 129 .build(); 130 131 ModuleDescriptor descriptor3 = newBuilder("m3") 132 .build(); 133 134 ModuleFinder finder 135 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 136 137 Configuration cf = resolve(finder, "m1"); 138 139 // map each module to its own class loader for this test 140 ClassLoader loader1 = new ClassLoader() { }; 141 ClassLoader loader2 = new ClassLoader() { }; 142 ClassLoader loader3 = new ClassLoader() { }; 143 Map<String, ClassLoader> map = new HashMap<>(); 144 map.put("m1", loader1); 145 map.put("m2", loader2); 146 map.put("m3", loader3); 147 148 ModuleLayer layer = ModuleLayer.empty().defineModules(cf, map::get); 149 150 // configuration 151 assertTrue(layer.configuration() == cf); 152 assertTrue(layer.configuration().modules().size() == 3); 153 154 // modules 155 Set<Module> modules = layer.modules(); 156 assertTrue(modules.size() == 3); 157 Set<String> names = modules.stream() 158 .map(Module::getName) 159 .collect(Collectors.toSet()); 160 assertTrue(names.contains("m1")); 161 assertTrue(names.contains("m2")); 162 assertTrue(names.contains("m3")); 163 164 // findModule 165 Module m1 = layer.findModule("m1").get(); 166 Module m2 = layer.findModule("m2").get(); 167 Module m3 = layer.findModule("m3").get(); 168 assertEquals(m1.getName(), "m1"); 169 assertEquals(m2.getName(), "m2"); 170 assertEquals(m3.getName(), "m3"); 171 assertTrue(m1.getDescriptor() == descriptor1); 172 assertTrue(m2.getDescriptor() == descriptor2); 173 assertTrue(m3.getDescriptor() == descriptor3); 174 assertTrue(m1.getLayer() == layer); 175 assertTrue(m2.getLayer() == layer); 176 assertTrue(m3.getLayer() == layer); 177 assertTrue(modules.contains(m1)); 178 assertTrue(modules.contains(m2)); 179 assertTrue(modules.contains(m3)); 180 assertFalse(layer.findModule("godot").isPresent()); 181 182 // findLoader 183 assertTrue(layer.findLoader("m1") == loader1); 184 assertTrue(layer.findLoader("m2") == loader2); 185 assertTrue(layer.findLoader("m3") == loader3); 186 try { 187 ClassLoader loader = layer.findLoader("godot"); 188 assertTrue(false); 189 } catch (IllegalArgumentException ignore) { } 190 191 // parents 192 assertTrue(layer.parents().size() == 1); 193 assertTrue(layer.parents().get(0) == ModuleLayer.empty()); 194 } 195 196 197 /** 198 * Exercise defineModules, created with boot layer as parent 199 */ 200 public void testLayerOnBoot() { 201 ModuleDescriptor descriptor1 = newBuilder("m1") 202 .requires("m2") 203 .requires("java.base") 204 .exports("p1") 205 .build(); 206 207 ModuleDescriptor descriptor2 = newBuilder("m2") 208 .requires("java.base") 209 .build(); 210 211 ModuleFinder finder 212 = ModuleUtils.finderOf(descriptor1, descriptor2); 213 214 Configuration parent = ModuleLayer.boot().configuration(); 215 Configuration cf = resolve(parent, finder, "m1"); 216 217 ClassLoader loader = new ClassLoader() { }; 218 219 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, mn -> loader); 220 221 // configuration 222 assertTrue(layer.configuration() == cf); 223 assertTrue(layer.configuration().modules().size() == 2); 224 225 // modules 226 Set<Module> modules = layer.modules(); 227 assertTrue(modules.size() == 2); 228 Set<String> names = modules.stream() 229 .map(Module::getName) 230 .collect(Collectors.toSet()); 231 assertTrue(names.contains("m1")); 232 assertTrue(names.contains("m2")); 233 234 // findModule 235 Module m1 = layer.findModule("m1").get(); 236 Module m2 = layer.findModule("m2").get(); 237 assertEquals(m1.getName(), "m1"); 238 assertEquals(m2.getName(), "m2"); 239 assertTrue(m1.getDescriptor() == descriptor1); 240 assertTrue(m2.getDescriptor() == descriptor2); 241 assertTrue(m1.getLayer() == layer); 242 assertTrue(m2.getLayer() == layer); 243 assertTrue(modules.contains(m1)); 244 assertTrue(modules.contains(m2)); 245 assertTrue(layer.findModule("java.base").get() == Object.class.getModule()); 246 assertFalse(layer.findModule("godot").isPresent()); 247 248 // findLoader 249 assertTrue(layer.findLoader("m1") == loader); 250 assertTrue(layer.findLoader("m2") == loader); 251 assertTrue(layer.findLoader("java.base") == null); 252 253 // parents 254 assertTrue(layer.parents().size() == 1); 255 assertTrue(layer.parents().get(0) == ModuleLayer.boot()); 256 } 257 258 259 /** 260 * Exercise defineModules with a configuration of two modules that 261 * have the same module-private package. 262 */ 263 public void testPackageContainedInSelfAndOther() { 264 ModuleDescriptor descriptor1 = newBuilder("m1") 265 .requires("m2") 266 .packages(Set.of("p")) 267 .build(); 268 269 ModuleDescriptor descriptor2 = newBuilder("m2") 270 .packages(Set.of("p")) 271 .build(); 272 273 ModuleFinder finder 274 = ModuleUtils.finderOf(descriptor1, descriptor2); 275 276 Configuration cf = resolve(finder, "m1"); 277 assertTrue(cf.modules().size() == 2); 278 279 // one loader per module, should be okay 280 ModuleLayer.empty().defineModules(cf, mn -> new ClassLoader() { }); 281 282 // same class loader 283 try { 284 ClassLoader loader = new ClassLoader() { }; 285 ModuleLayer.empty().defineModules(cf, mn -> loader); 286 assertTrue(false); 287 } catch (LayerInstantiationException expected) { } 288 } 289 290 291 /** 292 * Exercise defineModules with a configuration that is a partitioned 293 * graph. The same package is exported in both partitions. 294 */ 295 public void testSameExportInPartitionedGraph() { 296 297 // m1 reads m2, m2 exports p to m1 298 ModuleDescriptor descriptor1 = newBuilder("m1") 299 .requires("m2") 300 .build(); 301 ModuleDescriptor descriptor2 = newBuilder("m2") 302 .exports("p", Set.of("m1")) 303 .build(); 304 305 // m3 reads m4, m4 exports p to m3 306 ModuleDescriptor descriptor3 = newBuilder("m3") 307 .requires("m4") 308 .build(); 309 ModuleDescriptor descriptor4 = newBuilder("m4") 310 .exports("p", Set.of("m3")) 311 .build(); 312 313 ModuleFinder finder 314 = ModuleUtils.finderOf(descriptor1, 315 descriptor2, 316 descriptor3, 317 descriptor4); 318 319 Configuration cf = resolve(finder, "m1", "m3"); 320 assertTrue(cf.modules().size() == 4); 321 322 // one loader per module 323 ModuleLayer.empty().defineModules(cf, mn -> new ClassLoader() { }); 324 325 // m1 & m2 in one loader, m3 & m4 in another loader 326 ClassLoader loader1 = new ClassLoader() { }; 327 ClassLoader loader2 = new ClassLoader() { }; 328 Map<String, ClassLoader> map = new HashMap<>(); 329 map.put("m1", loader1); 330 map.put("m2", loader1); 331 map.put("m3", loader2); 332 map.put("m4", loader2); 333 ModuleLayer.empty().defineModules(cf, map::get); 334 335 // same loader 336 try { 337 ClassLoader loader = new ClassLoader() { }; 338 ModuleLayer.empty().defineModules(cf, mn -> loader); 339 assertTrue(false); 340 } catch (LayerInstantiationException expected) { } 341 } 342 343 344 /** 345 * Exercise defineModules with a configuration with a module that 346 * contains a package that is the same name as a non-exported package in 347 * a parent layer. 348 */ 349 public void testContainsSamePackageAsBootLayer() { 350 351 // check assumption that java.base contains sun.launcher 352 ModuleDescriptor base = Object.class.getModule().getDescriptor(); 353 assertTrue(base.packages().contains("sun.launcher")); 354 355 ModuleDescriptor descriptor = newBuilder("m1") 356 .requires("java.base") 357 .packages(Set.of("sun.launcher")) 358 .build(); 359 360 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 361 362 Configuration parent = ModuleLayer.boot().configuration(); 363 Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1")); 364 assertTrue(cf.modules().size() == 1); 365 366 ClassLoader loader = new ClassLoader() { }; 367 ModuleLayer layer = ModuleLayer.boot().defineModules(cf, mn -> loader); 368 assertTrue(layer.modules().size() == 1); 369 } 370 371 372 /** 373 * Test layers with implied readability. 374 * 375 * The test consists of three configurations: 376 * - Configuration/layer1: m1, m2 requires transitive m1 377 * - Configuration/layer2: m3 requires m1 378 */ 379 public void testImpliedReadabilityWithLayers1() { 380 381 // cf1: m1 and m2, m2 requires transitive m1 382 383 ModuleDescriptor descriptor1 = newBuilder("m1") 384 .build(); 385 386 ModuleDescriptor descriptor2 = newBuilder("m2") 387 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 388 .build(); 389 390 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 391 392 Configuration cf1 = resolve(finder1, "m2"); 393 394 ClassLoader cl1 = new ClassLoader() { }; 395 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 396 397 398 // cf2: m3, m3 requires m2 399 400 ModuleDescriptor descriptor3 = newBuilder("m3") 401 .requires("m2") 402 .build(); 403 404 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); 405 406 Configuration cf2 = resolve(cf1, finder2, "m3"); 407 408 ClassLoader cl2 = new ClassLoader() { }; 409 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 410 411 assertTrue(layer1.parents().size() == 1); 412 assertTrue(layer1.parents().get(0) == ModuleLayer.empty()); 413 414 assertTrue(layer2.parents().size() == 1); 415 assertTrue(layer2.parents().get(0) == layer1); 416 417 Module m1 = layer2.findModule("m1").get(); 418 Module m2 = layer2.findModule("m2").get(); 419 Module m3 = layer2.findModule("m3").get(); 420 421 assertTrue(m1.getLayer() == layer1); 422 assertTrue(m2.getLayer() == layer1); 423 assertTrue(m3.getLayer() == layer2); 424 425 assertTrue(m1.getClassLoader() == cl1); 426 assertTrue(m2.getClassLoader() == cl1); 427 assertTrue(m3.getClassLoader() == cl2); 428 429 assertTrue(m1.canRead(m1)); 430 assertFalse(m1.canRead(m2)); 431 assertFalse(m1.canRead(m3)); 432 433 assertTrue(m2.canRead(m1)); 434 assertTrue(m2.canRead(m2)); 435 assertFalse(m2.canRead(m3)); 436 437 assertTrue(m3.canRead(m1)); 438 assertTrue(m3.canRead(m2)); 439 assertTrue(m3.canRead(m3)); 440 } 441 442 443 /** 444 * Test layers with implied readability. 445 * 446 * The test consists of three configurations: 447 * - Configuration/layer1: m1 448 * - Configuration/layer2: m2 requires transitive m3, m3 requires m2 449 */ 450 public void testImpliedReadabilityWithLayers2() { 451 452 // cf1: m1 453 454 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 455 456 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 457 458 Configuration cf1 = resolve(finder1, "m1"); 459 460 ClassLoader cl1 = new ClassLoader() { }; 461 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 462 463 464 // cf2: m2, m3: m2 requires transitive m1, m3 requires m2 465 466 ModuleDescriptor descriptor2 = newBuilder("m2") 467 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 468 .build(); 469 470 ModuleDescriptor descriptor3 = newBuilder("m3") 471 .requires("m2") 472 .build(); 473 474 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2, descriptor3); 475 476 Configuration cf2 = resolve(cf1, finder2, "m3"); 477 478 ClassLoader cl2 = new ClassLoader() { }; 479 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 480 481 assertTrue(layer1.parents().size() == 1); 482 assertTrue(layer1.parents().get(0) == ModuleLayer.empty()); 483 484 assertTrue(layer2.parents().size() == 1); 485 assertTrue(layer2.parents().get(0) == layer1); 486 487 Module m1 = layer2.findModule("m1").get(); 488 Module m2 = layer2.findModule("m2").get(); 489 Module m3 = layer2.findModule("m3").get(); 490 491 assertTrue(m1.getLayer() == layer1); 492 assertTrue(m2.getLayer() == layer2); 493 assertTrue(m3.getLayer() == layer2); 494 495 assertTrue(m1.canRead(m1)); 496 assertFalse(m1.canRead(m2)); 497 assertFalse(m1.canRead(m3)); 498 499 assertTrue(m2.canRead(m1)); 500 assertTrue(m2.canRead(m2)); 501 assertFalse(m2.canRead(m3)); 502 503 assertTrue(m3.canRead(m1)); 504 assertTrue(m3.canRead(m2)); 505 assertTrue(m3.canRead(m3)); 506 } 507 508 509 /** 510 * Test layers with implied readability. 511 * 512 * The test consists of three configurations: 513 * - Configuration/layer1: m1 514 * - Configuration/layer2: m2 requires transitive m1 515 * - Configuration/layer3: m3 requires m1 516 */ 517 public void testImpliedReadabilityWithLayers3() { 518 519 // cf1: m1 520 521 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 522 523 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 524 525 Configuration cf1 = resolve(finder1, "m1"); 526 527 ClassLoader cl1 = new ClassLoader() { }; 528 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 529 530 531 // cf2: m2 requires transitive m1 532 533 ModuleDescriptor descriptor2 = newBuilder("m2") 534 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 535 .build(); 536 537 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 538 539 Configuration cf2 = resolve(cf1, finder2, "m2"); 540 541 ClassLoader cl2 = new ClassLoader() { }; 542 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 543 544 545 // cf3: m3 requires m2 546 547 ModuleDescriptor descriptor3 = newBuilder("m3") 548 .requires("m2") 549 .build(); 550 551 ModuleFinder finder3 = ModuleUtils.finderOf(descriptor3); 552 553 Configuration cf3 = resolve(cf2, finder3, "m3"); 554 555 ClassLoader cl3 = new ClassLoader() { }; 556 ModuleLayer layer3 = layer2.defineModules(cf3, mn -> cl3); 557 558 assertTrue(layer1.parents().size() == 1); 559 assertTrue(layer1.parents().get(0) == ModuleLayer.empty()); 560 561 assertTrue(layer2.parents().size() == 1); 562 assertTrue(layer2.parents().get(0) == layer1); 563 564 assertTrue(layer3.parents().size() == 1); 565 assertTrue(layer3.parents().get(0) == layer2); 566 567 Module m1 = layer3.findModule("m1").get(); 568 Module m2 = layer3.findModule("m2").get(); 569 Module m3 = layer3.findModule("m3").get(); 570 571 assertTrue(m1.getLayer() == layer1); 572 assertTrue(m2.getLayer() == layer2); 573 assertTrue(m3.getLayer() == layer3); 574 575 assertTrue(m1.canRead(m1)); 576 assertFalse(m1.canRead(m2)); 577 assertFalse(m1.canRead(m3)); 578 579 assertTrue(m2.canRead(m1)); 580 assertTrue(m2.canRead(m2)); 581 assertFalse(m2.canRead(m3)); 582 583 assertTrue(m3.canRead(m1)); 584 assertTrue(m3.canRead(m2)); 585 assertTrue(m3.canRead(m3)); 586 } 587 588 589 /** 590 * Test layers with implied readability. 591 * 592 * The test consists of two configurations: 593 * - Configuration/layer1: m1, m2 requires transitive m1 594 * - Configuration/layer2: m3 requires transitive m2, m4 requires m3 595 */ 596 public void testImpliedReadabilityWithLayers4() { 597 598 // cf1: m1, m2 requires transitive m1 599 600 ModuleDescriptor descriptor1 = newBuilder("m1") 601 .build(); 602 603 ModuleDescriptor descriptor2 = newBuilder("m2") 604 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 605 .build(); 606 607 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 608 609 Configuration cf1 = resolve(finder1, "m2"); 610 611 ClassLoader cl1 = new ClassLoader() { }; 612 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 613 614 615 // cf2: m3 requires transitive m2, m4 requires m3 616 617 ModuleDescriptor descriptor3 = newBuilder("m3") 618 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m2") 619 .build(); 620 621 ModuleDescriptor descriptor4 = newBuilder("m4") 622 .requires("m3") 623 .build(); 624 625 626 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 627 628 Configuration cf2 = resolve(cf1, finder2, "m3", "m4"); 629 630 ClassLoader cl2 = new ClassLoader() { }; 631 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 632 633 assertTrue(layer1.parents().size() == 1); 634 assertTrue(layer1.parents().get(0) == ModuleLayer.empty()); 635 636 assertTrue(layer2.parents().size() == 1); 637 assertTrue(layer2.parents().get(0) == layer1); 638 639 Module m1 = layer2.findModule("m1").get(); 640 Module m2 = layer2.findModule("m2").get(); 641 Module m3 = layer2.findModule("m3").get(); 642 Module m4 = layer2.findModule("m4").get(); 643 644 assertTrue(m1.getLayer() == layer1); 645 assertTrue(m2.getLayer() == layer1); 646 assertTrue(m3.getLayer() == layer2); 647 assertTrue(m4.getLayer() == layer2); 648 649 assertTrue(m1.canRead(m1)); 650 assertFalse(m1.canRead(m2)); 651 assertFalse(m1.canRead(m3)); 652 assertFalse(m1.canRead(m4)); 653 654 assertTrue(m2.canRead(m1)); 655 assertTrue(m2.canRead(m2)); 656 assertFalse(m1.canRead(m3)); 657 assertFalse(m1.canRead(m4)); 658 659 assertTrue(m3.canRead(m1)); 660 assertTrue(m3.canRead(m2)); 661 assertTrue(m3.canRead(m3)); 662 assertFalse(m3.canRead(m4)); 663 664 assertTrue(m4.canRead(m1)); 665 assertTrue(m4.canRead(m2)); 666 assertTrue(m4.canRead(m3)); 667 assertTrue(m4.canRead(m4)); 668 } 669 670 671 /** 672 * Test layers with a qualified export. The module exporting the package 673 * does not read the target module. 674 * 675 * m1 { exports p to m2 } 676 * m2 { } 677 */ 678 public void testQualifiedExports1() { 679 ModuleDescriptor descriptor1 = newBuilder("m1"). 680 exports("p", Set.of("m2")) 681 .build(); 682 683 ModuleDescriptor descriptor2 = newBuilder("m2") 684 .build(); 685 686 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 687 688 Configuration cf = resolve(finder1, "m1", "m2"); 689 690 ClassLoader cl = new ClassLoader() { }; 691 ModuleLayer layer = ModuleLayer.empty().defineModules(cf, mn -> cl); 692 assertTrue(layer.modules().size() == 2); 693 694 Module m1 = layer.findModule("m1").get(); 695 Module m2 = layer.findModule("m2").get(); 696 697 // check m1 exports p to m2 698 assertFalse(m1.isExported("p")); 699 assertTrue(m1.isExported("p", m2)); 700 assertFalse(m1.isOpen("p", m2)); 701 } 702 703 704 /** 705 * Test layers with a qualified export. The module exporting the package 706 * reads the target module. 707 * 708 * m1 { exports p to m2; } 709 * m2 { requires m1; } 710 */ 711 public void testQualifiedExports2() { 712 ModuleDescriptor descriptor1 = newBuilder("m1") 713 .exports("p", Set.of("m2")) 714 .build(); 715 716 ModuleDescriptor descriptor2 = newBuilder("m2") 717 .requires("m1") 718 .build(); 719 720 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 721 722 Configuration cf = resolve(finder1, "m2"); 723 ClassLoader cl = new ClassLoader() { }; 724 ModuleLayer layer = ModuleLayer.empty().defineModules(cf, mn -> cl); 725 assertTrue(layer.modules().size() == 2); 726 727 Module m1 = layer.findModule("m1").get(); 728 Module m2 = layer.findModule("m2").get(); 729 730 // check m1 exports p to m2 731 assertFalse(m1.isExported("p")); 732 assertTrue(m1.isExported("p", m2)); 733 assertFalse(m1.isOpen("p", m2)); 734 } 735 736 737 /** 738 * Test layers with a qualified export. The module exporting the package 739 * does not read the target module in the parent layer. 740 * 741 * - Configuration/layer1: m1 { } 742 * - Configuration/layer2: m2 { exports p to m1; } 743 */ 744 public void testQualifiedExports3() { 745 // create layer1 with m1 746 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 747 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 748 Configuration cf1 = resolve(finder1, "m1"); 749 ClassLoader cl1 = new ClassLoader() { }; 750 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 751 assertTrue(layer1.modules().size() == 1); 752 753 // create layer2 with m2 754 ModuleDescriptor descriptor2 = newBuilder("m2") 755 .exports("p", Set.of("m1")) 756 .build(); 757 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 758 Configuration cf2 = resolve(cf1, finder2, "m2"); 759 ClassLoader cl2 = new ClassLoader() { }; 760 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 761 assertTrue(layer2.modules().size() == 1); 762 763 Module m1 = layer1.findModule("m1").get(); 764 Module m2 = layer2.findModule("m2").get(); 765 766 // check m2 exports p to layer1/m1 767 assertFalse(m2.isExported("p")); 768 assertTrue(m2.isExported("p", m1)); 769 assertFalse(m2.isOpen("p", m1)); 770 } 771 772 773 /** 774 * Test layers with a qualified export. The module exporting the package 775 * reads the target module in the parent layer. 776 * 777 * - Configuration/layer1: m1 { } 778 * - Configuration/layer2: m2 { requires m1; exports p to m1; } 779 */ 780 public void testQualifiedExports4() { 781 // create layer1 with m1 782 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 783 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 784 Configuration cf1 = resolve(finder1, "m1"); 785 ClassLoader cl1 = new ClassLoader() { }; 786 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 787 assertTrue(layer1.modules().size() == 1); 788 789 // create layer2 with m2 790 ModuleDescriptor descriptor2 = newBuilder("m2") 791 .requires("m1") 792 .exports("p", Set.of("m1")) 793 .build(); 794 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 795 Configuration cf2 = resolve(cf1, finder2, "m2"); 796 ClassLoader cl2 = new ClassLoader() { }; 797 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 798 assertTrue(layer2.modules().size() == 1); 799 800 Module m1 = layer1.findModule("m1").get(); 801 Module m2 = layer2.findModule("m2").get(); 802 803 // check m2 exports p to layer1/m1 804 assertFalse(m2.isExported("p")); 805 assertTrue(m2.isExported("p", m1)); 806 assertFalse(m2.isOpen("p", m1)); 807 } 808 809 /** 810 * Test layers with a qualified export. The module exporting the package 811 * does not read the target module. 812 * 813 * - Configuration/layer1: m1 814 * - Configuration/layer2: m1, m2 { exports p to m1; } 815 */ 816 public void testQualifiedExports5() { 817 // create layer1 with m1 818 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 819 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 820 Configuration cf1 = resolve(finder1, "m1"); 821 ClassLoader cl1 = new ClassLoader() { }; 822 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 823 assertTrue(layer1.modules().size() == 1); 824 825 // create layer2 with m1 and m2 826 ModuleDescriptor descriptor2 = newBuilder("m2").exports("p", Set.of("m1")).build(); 827 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor2); 828 Configuration cf2 = resolve(cf1, finder2, "m1", "m2"); 829 ClassLoader cl2 = new ClassLoader() { }; 830 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 831 assertTrue(layer2.modules().size() == 2); 832 833 Module m1_v1 = layer1.findModule("m1").get(); 834 Module m1_v2 = layer2.findModule("m1").get(); 835 Module m2 = layer2.findModule("m2").get(); 836 837 // check m2 exports p to layer2/m2 838 assertFalse(m2.isExported("p")); 839 assertTrue(m2.isExported("p", m1_v2)); 840 assertFalse(m2.isExported("p", m1_v1)); 841 } 842 843 844 /** 845 * Test layers with a qualified export. The module exporting the package 846 * reads the target module in the parent layer (due to requires transitive). 847 * 848 * - Configuration/layer1: m1, m2 { requires transitive m1; } 849 * - Configuration/layer2: m1, m3 { requires m2; exports p to m1; } 850 */ 851 public void testQualifiedExports6() { 852 // create layer1 with m1 and m2 853 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 854 ModuleDescriptor descriptor2 = newBuilder("m2") 855 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 856 .build(); 857 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 858 Configuration cf1 = resolve(finder1, "m2"); 859 ClassLoader loader1 = new ClassLoader() { }; 860 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> loader1); 861 assertTrue(layer1.modules().size() == 2); 862 863 // create layer2 with m1 and m3 864 ModuleDescriptor descriptor3 = newBuilder("m3") 865 .requires("m2") 866 .exports("p", Set.of("m1")) 867 .build(); 868 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3); 869 Configuration cf2 = resolve(cf1, finder2, "m1", "m3"); 870 ClassLoader loader2 = new ClassLoader() { }; 871 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> loader2); 872 assertTrue(layer2.modules().size() == 2); 873 874 Module m1_v1 = layer1.findModule("m1").get(); 875 Module m2 = layer1.findModule("m2").get(); 876 877 Module m1_v2 = layer2.findModule("m1").get(); 878 Module m3 = layer2.findModule("m3").get(); 879 880 assertTrue(m3.canRead(m1_v1)); 881 assertFalse(m3.canRead(m1_v2)); 882 883 assertFalse(m3.isExported("p")); 884 assertTrue(m3.isExported("p", m1_v1)); 885 assertFalse(m3.isExported("p", m1_v2)); 886 assertFalse(m3.isExported("p", m2)); 887 } 888 889 890 /** 891 * Test layers with a qualified export. The target module is not in any layer. 892 * 893 * - Configuration/layer1: m1 { } 894 * - Configuration/layer2: m2 { exports p to m3; } 895 */ 896 public void testQualifiedExports7() { 897 // create layer1 with m1 898 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 899 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 900 Configuration cf1 = resolve(finder1, "m1"); 901 ClassLoader cl1 = new ClassLoader() { }; 902 ModuleLayer layer1 = ModuleLayer.empty().defineModules(cf1, mn -> cl1); 903 assertTrue(layer1.modules().size() == 1); 904 905 // create layer2 with m2 906 ModuleDescriptor descriptor2 = newBuilder("m2") 907 .exports("p", Set.of("m3")) 908 .build(); 909 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 910 Configuration cf2 = resolve(cf1, finder2, "m2"); 911 ClassLoader cl2 = new ClassLoader() { }; 912 ModuleLayer layer2 = layer1.defineModules(cf2, mn -> cl2); 913 assertTrue(layer2.modules().size() == 1); 914 915 Module m1 = layer1.findModule("m1").get(); 916 Module m2 = layer2.findModule("m2").get(); 917 918 // check m2 does not export p to anyone 919 assertFalse(m2.isExported("p")); 920 assertFalse(m2.isExported("p", m1)); 921 } 922 923 /** 924 * Attempt to use defineModules to create a layer with a module defined 925 * to a class loader that already has a module of the same name defined 926 * to the class loader. 927 */ 928 @Test(expectedExceptions = { LayerInstantiationException.class }) 929 public void testModuleAlreadyDefinedToLoader() { 930 931 ModuleDescriptor md = newBuilder("m") 932 .requires("java.base") 933 .build(); 934 935 ModuleFinder finder = ModuleUtils.finderOf(md); 936 937 Configuration parent = ModuleLayer.boot().configuration(); 938 939 Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m")); 940 941 ClassLoader loader = new ClassLoader() { }; 942 943 ModuleLayer.boot().defineModules(cf, mn -> loader); 944 945 // should throw LayerInstantiationException as m1 already defined to loader 946 ModuleLayer.boot().defineModules(cf, mn -> loader); 947 948 } 949 950 951 /** 952 * Attempt to use defineModules to create a layer with a module containing 953 * package {@code p} where the class loader already has a module defined 954 * to it containing package {@code p}. 955 */ 956 @Test(expectedExceptions = { LayerInstantiationException.class }) 957 public void testPackageAlreadyInNamedModule() { 958 959 ModuleDescriptor md1 = newBuilder("m1") 960 .packages(Set.of("p")) 961 .requires("java.base") 962 .build(); 963 964 ModuleDescriptor md2 = newBuilder("m2") 965 .packages(Set.of("p")) 966 .requires("java.base") 967 .build(); 968 969 ModuleFinder finder = ModuleUtils.finderOf(md1, md2); 970 971 ClassLoader loader = new ClassLoader() { }; 972 973 // define m1 containing package p to class loader 974 975 Configuration parent = ModuleLayer.boot().configuration(); 976 977 Configuration cf1 = parent.resolve(finder, ModuleFinder.of(), Set.of("m1")); 978 979 ModuleLayer layer1 = ModuleLayer.boot().defineModules(cf1, mn -> loader); 980 981 // attempt to define m2 containing package p to class loader 982 983 Configuration cf2 = parent.resolve(finder, ModuleFinder.of(), Set.of("m2")); 984 985 // should throw exception because p already in m1 986 ModuleLayer layer2 = ModuleLayer.boot().defineModules(cf2, mn -> loader); 987 988 } 989 990 991 /** 992 * Attempt to use defineModules to create a layer with a module 993 * containing a package in which a type is already loaded by the class 994 * loader. 995 */ 996 @Test(expectedExceptions = { LayerInstantiationException.class }) 997 public void testPackageAlreadyInUnnamedModule() throws Exception { 998 999 Class<?> c = layertest.Test.class; 1000 assertFalse(c.getModule().isNamed()); // in unnamed module 1001 1002 ModuleDescriptor md = newBuilder("m") 1003 .packages(Set.of(c.getPackageName())) 1004 .requires("java.base") 1005 .build(); 1006 1007 ModuleFinder finder = ModuleUtils.finderOf(md); 1008 1009 Configuration parent = ModuleLayer.boot().configuration(); 1010 Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m")); 1011 1012 ModuleLayer.boot().defineModules(cf, mn -> c.getClassLoader()); 1013 } 1014 1015 1016 /** 1017 * Attempt to create a layer with a module named "java.base". 1018 */ 1019 public void testLayerWithJavaBase() { 1020 ModuleDescriptor descriptor = newBuilder("java.base") 1021 .exports("java.lang") 1022 .build(); 1023 1024 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 1025 1026 Configuration cf = ModuleLayer.boot() 1027 .configuration() 1028 .resolve(finder, ModuleFinder.of(), Set.of("java.base")); 1029 assertTrue(cf.modules().size() == 1); 1030 1031 ClassLoader scl = ClassLoader.getSystemClassLoader(); 1032 1033 try { 1034 ModuleLayer.boot().defineModules(cf, mn -> new ClassLoader() { }); 1035 assertTrue(false); 1036 } catch (LayerInstantiationException e) { } 1037 1038 try { 1039 ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); 1040 assertTrue(false); 1041 } catch (LayerInstantiationException e) { } 1042 1043 try { 1044 ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); 1045 assertTrue(false); 1046 } catch (LayerInstantiationException e) { } 1047 } 1048 1049 1050 @DataProvider(name = "javaPackages") 1051 public Object[][] javaPackages() { 1052 return new Object[][] { { "m1", "java" }, { "m2", "java.x" } }; 1053 } 1054 1055 /** 1056 * Attempt to create a layer with a module containing a "java" package. 1057 */ 1058 @Test(dataProvider = "javaPackages") 1059 public void testLayerWithJavaPackage(String mn, String pn) { 1060 ModuleDescriptor descriptor = newBuilder(mn).packages(Set.of(pn)).build(); 1061 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 1062 1063 Configuration cf = ModuleLayer.boot() 1064 .configuration() 1065 .resolve(finder, ModuleFinder.of(), Set.of(mn)); 1066 assertTrue(cf.modules().size() == 1); 1067 1068 ClassLoader scl = ClassLoader.getSystemClassLoader(); 1069 1070 try { 1071 ModuleLayer.boot().defineModules(cf, _mn -> new ClassLoader() { }); 1072 assertTrue(false); 1073 } catch (LayerInstantiationException e) { } 1074 1075 try { 1076 ModuleLayer.boot().defineModulesWithOneLoader(cf, scl); 1077 assertTrue(false); 1078 } catch (LayerInstantiationException e) { } 1079 1080 try { 1081 ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl); 1082 assertTrue(false); 1083 } catch (LayerInstantiationException e) { } 1084 } 1085 1086 1087 /** 1088 * Attempt to create a layer with a module defined to the boot loader 1089 */ 1090 @Test(expectedExceptions = { LayerInstantiationException.class }) 1091 public void testLayerWithBootLoader() { 1092 ModuleDescriptor descriptor = newBuilder("m1").build(); 1093 1094 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 1095 1096 Configuration cf = ModuleLayer.boot() 1097 .configuration() 1098 .resolve(finder, ModuleFinder.of(), Set.of("m1")); 1099 assertTrue(cf.modules().size() == 1); 1100 1101 ModuleLayer.boot().defineModules(cf, mn -> null ); 1102 } 1103 1104 1105 /** 1106 * Attempt to create a layer with a module defined to the platform loader 1107 */ 1108 @Test(expectedExceptions = { LayerInstantiationException.class }) 1109 public void testLayerWithPlatformLoader() { 1110 ModuleDescriptor descriptor = newBuilder("m1").build(); 1111 1112 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 1113 1114 Configuration cf = ModuleLayer.boot() 1115 .configuration() 1116 .resolve(finder, ModuleFinder.of(), Set.of("m1")); 1117 assertTrue(cf.modules().size() == 1); 1118 1119 ClassLoader cl = ClassLoader.getPlatformClassLoader(); 1120 ModuleLayer.boot().defineModules(cf, mn -> cl ); 1121 } 1122 1123 1124 /** 1125 * Parent of configuration != configuration of parent layer 1126 */ 1127 @Test(expectedExceptions = { IllegalArgumentException.class }) 1128 public void testIncorrectParent1() { 1129 ModuleDescriptor descriptor1 = newBuilder("m1") 1130 .requires("java.base") 1131 .build(); 1132 1133 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1134 1135 Configuration parent = ModuleLayer.boot().configuration(); 1136 Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1")); 1137 1138 ClassLoader loader = new ClassLoader() { }; 1139 ModuleLayer.empty().defineModules(cf, mn -> loader); 1140 } 1141 1142 1143 /** 1144 * Parent of configuration != configuration of parent layer 1145 */ 1146 @Test(expectedExceptions = { IllegalArgumentException.class }) 1147 public void testIncorrectParent2() { 1148 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1149 1150 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1151 1152 Configuration cf = resolve(finder, "m1"); 1153 1154 ClassLoader loader = new ClassLoader() { }; 1155 ModuleLayer.boot().defineModules(cf, mn -> loader); 1156 } 1157 1158 1159 // null handling 1160 1161 @Test(expectedExceptions = { NullPointerException.class }) 1162 public void testCreateWithNull1() { 1163 ClassLoader loader = new ClassLoader() { }; 1164 ModuleLayer.empty().defineModules(null, mn -> loader); 1165 } 1166 1167 @Test(expectedExceptions = { NullPointerException.class }) 1168 public void testCreateWithNull2() { 1169 Configuration cf = resolve(ModuleLayer.boot().configuration(), ModuleFinder.of()); 1170 ModuleLayer.boot().defineModules(cf, null); 1171 } 1172 1173 @Test(expectedExceptions = { NullPointerException.class }) 1174 public void testCreateWithNull3() { 1175 ClassLoader scl = ClassLoader.getSystemClassLoader(); 1176 ModuleLayer.empty().defineModulesWithOneLoader(null, scl); 1177 } 1178 1179 @Test(expectedExceptions = { NullPointerException.class }) 1180 public void testCreateWithNull4() { 1181 ClassLoader scl = ClassLoader.getSystemClassLoader(); 1182 ModuleLayer.empty().defineModulesWithManyLoaders(null, scl); 1183 } 1184 1185 @Test(expectedExceptions = { NullPointerException.class }) 1186 public void testFindModuleWithNull() { 1187 ModuleLayer.boot().findModule(null); 1188 } 1189 1190 @Test(expectedExceptions = { NullPointerException.class }) 1191 public void testFindLoaderWithNull() { 1192 ModuleLayer.boot().findLoader(null); 1193 } 1194 1195 1196 // immutable sets 1197 1198 @Test(expectedExceptions = { UnsupportedOperationException.class }) 1199 public void testImmutableSet() { 1200 Module base = Object.class.getModule(); 1201 ModuleLayer.boot().modules().add(base); 1202 } 1203 1204 1205 /** 1206 * Resolve the given modules, by name, and returns the resulting 1207 * Configuration. 1208 */ 1209 private static Configuration resolve(Configuration cf, 1210 ModuleFinder finder, 1211 String... roots) { 1212 return cf.resolve(finder, ModuleFinder.of(), Set.of(roots)); 1213 } 1214 1215 private static Configuration resolve(ModuleFinder finder, 1216 String... roots) { 1217 return resolve(Configuration.empty(), finder, roots); 1218 } 1219 }