1 /*
   2  * Copyright (c) 2014, 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  * @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.reflect.Layer
  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.lang.reflect.Layer;
  39 import java.lang.reflect.LayerInstantiationException;
  40 import java.lang.reflect.Module;
  41 import java.util.HashMap;
  42 import java.util.Map;
  43 import java.util.Optional;
  44 import java.util.Set;
  45 import java.util.stream.Collectors;
  46 
  47 import jdk.internal.misc.SharedSecrets;
  48 import org.testng.annotations.Test;
  49 import static org.testng.Assert.*;
  50 
  51 @Test
  52 public class BasicLayerTest {
  53 
  54     /**
  55      * Creates a "non-strict" builder for building a module. This allows the
  56      * test the create ModuleDescriptor objects that do not require java.base.
  57      */
  58     private static ModuleDescriptor.Builder newBuilder(String mn) {
  59         return SharedSecrets.getJavaLangModuleAccess()
  60                 .newModuleBuilder(mn, false, Set.of());
  61     }
  62 
  63     /**
  64      * Exercise Layer.empty()
  65      */
  66     public void testEmpty() {
  67         Layer emptyLayer = Layer.empty();
  68 
  69         assertTrue(emptyLayer.parents().isEmpty());
  70 
  71         assertTrue(emptyLayer.configuration() == Configuration.empty());
  72 
  73         assertTrue(emptyLayer.modules().isEmpty());
  74 
  75         assertFalse(emptyLayer.findModule("java.base").isPresent());
  76 
  77         try {
  78             emptyLayer.findLoader("java.base");
  79             assertTrue(false);
  80         } catch (IllegalArgumentException expected) { }
  81     }
  82 
  83 
  84     /**
  85      * Exercise Layer.boot()
  86      */
  87     public void testBoot() {
  88         Layer bootLayer = Layer.boot();
  89 
  90         // configuration
  91         Configuration cf = bootLayer.configuration();
  92         assertTrue(cf.findModule("java.base").get()
  93                 .reference()
  94                 .descriptor()
  95                 .exports()
  96                 .stream().anyMatch(e -> (e.source().equals("java.lang")
  97                                          && !e.isQualified())));
  98 
  99         // modules
 100         Set<Module> modules = bootLayer.modules();
 101         assertTrue(modules.contains(Object.class.getModule()));
 102         int count = (int) modules.stream().map(Module::getName).count();
 103         assertEquals(count, modules.size()); // module names are unique
 104 
 105         // findModule
 106         Module base = Object.class.getModule();
 107         assertTrue(bootLayer.findModule("java.base").get() == base);
 108         assertTrue(base.getLayer() == bootLayer);
 109 
 110         // findLoader
 111         assertTrue(bootLayer.findLoader("java.base") == null);
 112 
 113         // parents
 114         assertTrue(bootLayer.parents().size() == 1);
 115         assertTrue(bootLayer.parents().get(0) == Layer.empty());
 116     }
 117 
 118 
 119     /**
 120      * Exercise Layer defineModules, created with empty layer as parent
 121      */
 122     public void testLayerOnEmpty() {
 123         ModuleDescriptor descriptor1 = newBuilder("m1")
 124                 .requires("m2")
 125                 .exports("p1")
 126                 .build();
 127 
 128         ModuleDescriptor descriptor2 = newBuilder("m2")
 129                 .requires("m3")
 130                 .build();
 131 
 132         ModuleDescriptor descriptor3 = newBuilder("m3")
 133                 .build();
 134 
 135         ModuleFinder finder
 136             = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3);
 137 
 138         Configuration cf = resolve(finder, "m1");
 139 
 140         // map each module to its own class loader for this test
 141         ClassLoader loader1 = new ClassLoader() { };
 142         ClassLoader loader2 = new ClassLoader() { };
 143         ClassLoader loader3 = new ClassLoader() { };
 144         Map<String, ClassLoader> map = new HashMap<>();
 145         map.put("m1", loader1);
 146         map.put("m2", loader2);
 147         map.put("m3", loader3);
 148 
 149         Layer layer = Layer.empty().defineModules(cf, map::get);
 150 
 151         // configuration
 152         assertTrue(layer.configuration() == cf);
 153         assertTrue(layer.configuration().modules().size() == 3);
 154 
 155         // modules
 156         Set<Module> modules = layer.modules();
 157         assertTrue(modules.size() == 3);
 158         Set<String> names = modules.stream()
 159             .map(Module::getName)
 160             .collect(Collectors.toSet());
 161         assertTrue(names.contains("m1"));
 162         assertTrue(names.contains("m2"));
 163         assertTrue(names.contains("m3"));
 164 
 165         // findModule
 166         Module m1 = layer.findModule("m1").get();
 167         Module m2 = layer.findModule("m2").get();
 168         Module m3 = layer.findModule("m3").get();
 169         assertEquals(m1.getName(), "m1");
 170         assertEquals(m2.getName(), "m2");
 171         assertEquals(m3.getName(), "m3");
 172         assertTrue(m1.getDescriptor() == descriptor1);
 173         assertTrue(m2.getDescriptor() == descriptor2);
 174         assertTrue(m3.getDescriptor() == descriptor3);
 175         assertTrue(m1.getLayer() == layer);
 176         assertTrue(m2.getLayer() == layer);
 177         assertTrue(m3.getLayer() == layer);
 178         assertTrue(modules.contains(m1));
 179         assertTrue(modules.contains(m2));
 180         assertTrue(modules.contains(m3));
 181         assertFalse(layer.findModule("godot").isPresent());
 182 
 183         // findLoader
 184         assertTrue(layer.findLoader("m1") == loader1);
 185         assertTrue(layer.findLoader("m2") == loader2);
 186         assertTrue(layer.findLoader("m3") == loader3);
 187         try {
 188             ClassLoader loader = layer.findLoader("godot");
 189             assertTrue(false);
 190         } catch (IllegalArgumentException ignore) { }
 191 
 192         // parents
 193         assertTrue(layer.parents().size() == 1);
 194         assertTrue(layer.parents().get(0) == Layer.empty());
 195     }
 196 
 197 
 198     /**
 199      * Exercise Layer defineModules, created with boot layer as parent
 200      */
 201     public void testLayerOnBoot() {
 202         ModuleDescriptor descriptor1 = newBuilder("m1")
 203                 .requires("m2")
 204                 .requires("java.base")
 205                 .exports("p1")
 206                 .build();
 207 
 208         ModuleDescriptor descriptor2 = newBuilder("m2")
 209                 .requires("java.base")
 210                 .build();
 211 
 212         ModuleFinder finder
 213             = ModuleUtils.finderOf(descriptor1, descriptor2);
 214 
 215         Configuration parent = Layer.boot().configuration();
 216         Configuration cf = resolve(parent, finder, "m1");
 217 
 218         ClassLoader loader = new ClassLoader() { };
 219 
 220         Layer layer = Layer.boot().defineModules(cf, mn -> loader);
 221 
 222         // configuration
 223         assertTrue(layer.configuration() == cf);
 224         assertTrue(layer.configuration().modules().size() == 2);
 225 
 226         // modules
 227         Set<Module> modules = layer.modules();
 228         assertTrue(modules.size() == 2);
 229         Set<String> names = modules.stream()
 230             .map(Module::getName)
 231             .collect(Collectors.toSet());
 232         assertTrue(names.contains("m1"));
 233         assertTrue(names.contains("m2"));
 234 
 235         // findModule
 236         Module m1 = layer.findModule("m1").get();
 237         Module m2 = layer.findModule("m2").get();
 238         assertEquals(m1.getName(), "m1");
 239         assertEquals(m2.getName(), "m2");
 240         assertTrue(m1.getDescriptor() == descriptor1);
 241         assertTrue(m2.getDescriptor() == descriptor2);
 242         assertTrue(m1.getLayer() == layer);
 243         assertTrue(m2.getLayer() == layer);
 244         assertTrue(modules.contains(m1));
 245         assertTrue(modules.contains(m2));
 246         assertTrue(layer.findModule("java.base").get() == Object.class.getModule());
 247         assertFalse(layer.findModule("godot").isPresent());
 248 
 249         // findLoader
 250         assertTrue(layer.findLoader("m1") == loader);
 251         assertTrue(layer.findLoader("m2") == loader);
 252         assertTrue(layer.findLoader("java.base") == null);
 253 
 254         // parents
 255         assertTrue(layer.parents().size() == 1);
 256         assertTrue(layer.parents().get(0) == Layer.boot());
 257     }
 258 
 259 
 260     /**
 261      * Exercise Layer defineModules with a configuration of two modules that
 262      * have the same module-private package.
 263      */
 264     public void testPackageContainedInSelfAndOther() {
 265         ModuleDescriptor descriptor1 =  newBuilder("m1")
 266                 .requires("m2")
 267                 .packages(Set.of("p"))
 268                 .build();
 269 
 270         ModuleDescriptor descriptor2 = newBuilder("m2")
 271                 .packages(Set.of("p"))
 272                 .build();
 273 
 274         ModuleFinder finder
 275             = ModuleUtils.finderOf(descriptor1, descriptor2);
 276 
 277         Configuration cf = resolve(finder, "m1");
 278         assertTrue(cf.modules().size() == 2);
 279 
 280         // one loader per module, should be okay
 281         Layer.empty().defineModules(cf, mn -> new ClassLoader() { });
 282 
 283         // same class loader
 284         try {
 285             ClassLoader loader = new ClassLoader() { };
 286             Layer.empty().defineModules(cf, mn -> loader);
 287             assertTrue(false);
 288         } catch (LayerInstantiationException expected) { }
 289     }
 290 
 291 
 292     /**
 293      * Exercise Layer defineModules with a configuration that is a partitioned
 294      * graph. The same package is exported in both partitions.
 295      */
 296     public void testSameExportInPartitionedGraph() {
 297 
 298         // m1 reads m2, m2 exports p to m1
 299         ModuleDescriptor descriptor1 =  newBuilder("m1")
 300                 .requires("m2")
 301                 .build();
 302         ModuleDescriptor descriptor2 =  newBuilder("m2")
 303                 .exports("p", Set.of("m1"))
 304                 .build();
 305 
 306         // m3 reads m4, m4 exports p to m3
 307         ModuleDescriptor descriptor3 = newBuilder("m3")
 308                 .requires("m4")
 309                 .build();
 310         ModuleDescriptor descriptor4 = newBuilder("m4")
 311                 .exports("p", Set.of("m3"))
 312                 .build();
 313 
 314         ModuleFinder finder
 315             = ModuleUtils.finderOf(descriptor1,
 316                                    descriptor2,
 317                                    descriptor3,
 318                                    descriptor4);
 319 
 320         Configuration cf = resolve(finder, "m1", "m3");
 321         assertTrue(cf.modules().size() == 4);
 322 
 323         // one loader per module
 324         Layer.empty().defineModules(cf, mn -> new ClassLoader() { });
 325 
 326         // m1 & m2 in one loader, m3 & m4 in another loader
 327         ClassLoader loader1 = new ClassLoader() { };
 328         ClassLoader loader2 = new ClassLoader() { };
 329         Map<String, ClassLoader> map = new HashMap<>();
 330         map.put("m1", loader1);
 331         map.put("m2", loader1);
 332         map.put("m3", loader2);
 333         map.put("m4", loader2);
 334         Layer.empty().defineModules(cf, map::get);
 335 
 336         // same loader
 337         try {
 338             ClassLoader loader = new ClassLoader() { };
 339             Layer.empty().defineModules(cf, mn -> loader);
 340             assertTrue(false);
 341         } catch (LayerInstantiationException expected) { }
 342     }
 343 
 344 
 345     /**
 346      * Exercise Layer defineModules with a configuration with a module that
 347      * contains a package that is the same name as a non-exported package in
 348      * a parent layer.
 349      */
 350     public void testContainsSamePackageAsBootLayer() {
 351 
 352         // check assumption that java.base contains sun.launcher
 353         ModuleDescriptor base = Object.class.getModule().getDescriptor();
 354         assertTrue(base.packages().contains("sun.launcher"));
 355 
 356         ModuleDescriptor descriptor = newBuilder("m1")
 357                .requires("java.base")
 358                .packages(Set.of("sun.launcher"))
 359                .build();
 360 
 361         ModuleFinder finder = ModuleUtils.finderOf(descriptor);
 362 
 363         Configuration parent = Layer.boot().configuration();
 364         Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1"));
 365         assertTrue(cf.modules().size() == 1);
 366 
 367         ClassLoader loader = new ClassLoader() { };
 368         Layer layer = Layer.boot().defineModules(cf, mn -> loader);
 369         assertTrue(layer.modules().size() == 1);
 370    }
 371 
 372 
 373     /**
 374      * Test layers with implied readability.
 375      *
 376      * The test consists of three configurations:
 377      * - Configuration/layer1: m1, m2 requires transitive m1
 378      * - Configuration/layer2: m3 requires m1
 379      */
 380     public void testImpliedReadabilityWithLayers1() {
 381 
 382         // cf1: m1 and m2, m2 requires transitive m1
 383 
 384         ModuleDescriptor descriptor1 = newBuilder("m1")
 385                 .build();
 386 
 387         ModuleDescriptor descriptor2 = newBuilder("m2")
 388                 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
 389                 .build();
 390 
 391         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
 392 
 393         Configuration cf1 = resolve(finder1, "m2");
 394 
 395         ClassLoader cl1 = new ClassLoader() { };
 396         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 397 
 398 
 399         // cf2: m3, m3 requires m2
 400 
 401         ModuleDescriptor descriptor3 = newBuilder("m3")
 402                 .requires("m2")
 403                 .build();
 404 
 405         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3);
 406 
 407         Configuration cf2 = resolve(cf1, finder2, "m3");
 408 
 409         ClassLoader cl2 = new ClassLoader() { };
 410         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 411 
 412         assertTrue(layer1.parents().size() == 1);
 413         assertTrue(layer1.parents().get(0) == Layer.empty());
 414 
 415         assertTrue(layer2.parents().size() == 1);
 416         assertTrue(layer2.parents().get(0) == layer1);
 417 
 418         Module m1 = layer2.findModule("m1").get();
 419         Module m2 = layer2.findModule("m2").get();
 420         Module m3 = layer2.findModule("m3").get();
 421 
 422         assertTrue(m1.getLayer() == layer1);
 423         assertTrue(m2.getLayer() == layer1);
 424         assertTrue(m3.getLayer() == layer2);
 425 
 426         assertTrue(m1.getClassLoader() == cl1);
 427         assertTrue(m2.getClassLoader() == cl1);
 428         assertTrue(m3.getClassLoader() == cl2);
 429 
 430         assertTrue(m1.canRead(m1));
 431         assertFalse(m1.canRead(m2));
 432         assertFalse(m1.canRead(m3));
 433 
 434         assertTrue(m2.canRead(m1));
 435         assertTrue(m2.canRead(m2));
 436         assertFalse(m2.canRead(m3));
 437 
 438         assertTrue(m3.canRead(m1));
 439         assertTrue(m3.canRead(m2));
 440         assertTrue(m3.canRead(m3));
 441     }
 442 
 443 
 444     /**
 445      * Test layers with implied readability.
 446      *
 447      * The test consists of three configurations:
 448      * - Configuration/layer1: m1
 449      * - Configuration/layer2: m2 requires transitive m3, m3 requires m2
 450      */
 451     public void testImpliedReadabilityWithLayers2() {
 452 
 453         // cf1: m1
 454 
 455         ModuleDescriptor descriptor1 = newBuilder("m1").build();
 456 
 457         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
 458 
 459         Configuration cf1 = resolve(finder1, "m1");
 460 
 461         ClassLoader cl1 = new ClassLoader() { };
 462         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 463 
 464 
 465         // cf2: m2, m3: m2 requires transitive m1, m3 requires m2
 466 
 467         ModuleDescriptor descriptor2 = newBuilder("m2")
 468                 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
 469                 .build();
 470 
 471         ModuleDescriptor descriptor3 = newBuilder("m3")
 472                 .requires("m2")
 473                 .build();
 474 
 475         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2, descriptor3);
 476 
 477         Configuration cf2 = resolve(cf1, finder2, "m3");
 478 
 479         ClassLoader cl2 = new ClassLoader() { };
 480         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 481 
 482         assertTrue(layer1.parents().size() == 1);
 483         assertTrue(layer1.parents().get(0) == Layer.empty());
 484 
 485         assertTrue(layer2.parents().size() == 1);
 486         assertTrue(layer2.parents().get(0) == layer1);
 487 
 488         Module m1 = layer2.findModule("m1").get();
 489         Module m2 = layer2.findModule("m2").get();
 490         Module m3 = layer2.findModule("m3").get();
 491 
 492         assertTrue(m1.getLayer() == layer1);
 493         assertTrue(m2.getLayer() == layer2);
 494         assertTrue(m3.getLayer() == layer2);
 495 
 496         assertTrue(m1.canRead(m1));
 497         assertFalse(m1.canRead(m2));
 498         assertFalse(m1.canRead(m3));
 499 
 500         assertTrue(m2.canRead(m1));
 501         assertTrue(m2.canRead(m2));
 502         assertFalse(m2.canRead(m3));
 503 
 504         assertTrue(m3.canRead(m1));
 505         assertTrue(m3.canRead(m2));
 506         assertTrue(m3.canRead(m3));
 507     }
 508 
 509 
 510     /**
 511      * Test layers with implied readability.
 512      *
 513      * The test consists of three configurations:
 514      * - Configuration/layer1: m1
 515      * - Configuration/layer2: m2 requires transitive m1
 516      * - Configuration/layer3: m3 requires m1
 517      */
 518     public void testImpliedReadabilityWithLayers3() {
 519 
 520         // cf1: m1
 521 
 522         ModuleDescriptor descriptor1 = newBuilder("m1").build();
 523 
 524         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1);
 525 
 526         Configuration cf1 = resolve(finder1, "m1");
 527 
 528         ClassLoader cl1 = new ClassLoader() { };
 529         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 530 
 531 
 532         // cf2: m2 requires transitive m1
 533 
 534         ModuleDescriptor descriptor2 = newBuilder("m2")
 535                 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
 536                 .build();
 537 
 538         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2);
 539 
 540         Configuration cf2 = resolve(cf1, finder2, "m2");
 541 
 542         ClassLoader cl2 = new ClassLoader() { };
 543         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 544 
 545 
 546         // cf3: m3 requires m2
 547 
 548         ModuleDescriptor descriptor3 = newBuilder("m3")
 549                 .requires("m2")
 550                 .build();
 551 
 552         ModuleFinder finder3 = ModuleUtils.finderOf(descriptor3);
 553 
 554         Configuration cf3 = resolve(cf2, finder3, "m3");
 555 
 556         ClassLoader cl3 = new ClassLoader() { };
 557         Layer layer3 = layer2.defineModules(cf3, mn -> cl3);
 558 
 559         assertTrue(layer1.parents().size() == 1);
 560         assertTrue(layer1.parents().get(0) == Layer.empty());
 561 
 562         assertTrue(layer2.parents().size() == 1);
 563         assertTrue(layer2.parents().get(0) == layer1);
 564 
 565         assertTrue(layer3.parents().size() == 1);
 566         assertTrue(layer3.parents().get(0) == layer2);
 567 
 568         Module m1 = layer3.findModule("m1").get();
 569         Module m2 = layer3.findModule("m2").get();
 570         Module m3 = layer3.findModule("m3").get();
 571 
 572         assertTrue(m1.getLayer() == layer1);
 573         assertTrue(m2.getLayer() == layer2);
 574         assertTrue(m3.getLayer() == layer3);
 575 
 576         assertTrue(m1.canRead(m1));
 577         assertFalse(m1.canRead(m2));
 578         assertFalse(m1.canRead(m3));
 579 
 580         assertTrue(m2.canRead(m1));
 581         assertTrue(m2.canRead(m2));
 582         assertFalse(m2.canRead(m3));
 583 
 584         assertTrue(m3.canRead(m1));
 585         assertTrue(m3.canRead(m2));
 586         assertTrue(m3.canRead(m3));
 587     }
 588 
 589 
 590     /**
 591      * Test layers with implied readability.
 592      *
 593      * The test consists of two configurations:
 594      * - Configuration/layer1: m1, m2 requires transitive m1
 595      * - Configuration/layer2: m3 requires transitive m2, m4 requires m3
 596      */
 597     public void testImpliedReadabilityWithLayers4() {
 598 
 599         // cf1: m1, m2 requires transitive m1
 600 
 601         ModuleDescriptor descriptor1 = newBuilder("m1")
 602                 .build();
 603 
 604         ModuleDescriptor descriptor2 = newBuilder("m2")
 605                 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1")
 606                 .build();
 607 
 608         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
 609 
 610         Configuration cf1 = resolve(finder1, "m2");
 611 
 612         ClassLoader cl1 = new ClassLoader() { };
 613         Layer layer1 = Layer.empty().defineModules(cf1, mn -> cl1);
 614 
 615 
 616         // cf2: m3 requires transitive m2, m4 requires m3
 617 
 618         ModuleDescriptor descriptor3 = newBuilder("m3")
 619                 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m2")
 620                 .build();
 621 
 622         ModuleDescriptor descriptor4 = newBuilder("m4")
 623                 .requires("m3")
 624                 .build();
 625 
 626 
 627         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
 628 
 629         Configuration cf2 = resolve(cf1, finder2, "m3", "m4");
 630 
 631         ClassLoader cl2 = new ClassLoader() { };
 632         Layer layer2 = layer1.defineModules(cf2, mn -> cl2);
 633 
 634         assertTrue(layer1.parents().size() == 1);
 635         assertTrue(layer1.parents().get(0) == Layer.empty());
 636 
 637         assertTrue(layer2.parents().size() == 1);
 638         assertTrue(layer2.parents().get(0) == layer1);
 639 
 640         Module m1 = layer2.findModule("m1").get();
 641         Module m2 = layer2.findModule("m2").get();
 642         Module m3 = layer2.findModule("m3").get();
 643         Module m4 = layer2.findModule("m4").get();
 644 
 645         assertTrue(m1.getLayer() == layer1);
 646         assertTrue(m2.getLayer() == layer1);
 647         assertTrue(m3.getLayer() == layer2);
 648         assertTrue(m4.getLayer() == layer2);
 649 
 650         assertTrue(m1.canRead(m1));
 651         assertFalse(m1.canRead(m2));
 652         assertFalse(m1.canRead(m3));
 653         assertFalse(m1.canRead(m4));
 654 
 655         assertTrue(m2.canRead(m1));
 656         assertTrue(m2.canRead(m2));
 657         assertFalse(m1.canRead(m3));
 658         assertFalse(m1.canRead(m4));
 659 
 660         assertTrue(m3.canRead(m1));
 661         assertTrue(m3.canRead(m2));
 662         assertTrue(m3.canRead(m3));
 663         assertFalse(m3.canRead(m4));
 664 
 665         assertTrue(m4.canRead(m1));
 666         assertTrue(m4.canRead(m2));
 667         assertTrue(m4.canRead(m3));
 668         assertTrue(m4.canRead(m4));
 669     }
 670 
 671 
 672     /**
 673      * Attempt to use Layer defineModules to create a layer with a module
 674      * defined to a class loader that already has a module of the same name
 675      * defined to the class loader.
 676      */
 677     @Test(expectedExceptions = { LayerInstantiationException.class })
 678     public void testModuleAlreadyDefinedToLoader() {
 679 
 680         ModuleDescriptor md = newBuilder("m")
 681                 .requires("java.base")
 682                 .build();
 683 
 684         ModuleFinder finder = ModuleUtils.finderOf(md);
 685 
 686         Configuration parent = Layer.boot().configuration();
 687 
 688         Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m"));
 689 
 690         ClassLoader loader = new ClassLoader() { };
 691 
 692         Layer.boot().defineModules(cf, mn -> loader);
 693 
 694         // should throw LayerInstantiationException as m1 already defined to loader
 695         Layer.boot().defineModules(cf, mn -> loader);
 696 
 697     }
 698 
 699 
 700     /**
 701      * Attempt to use Layer defineModules to create a Layer with a module
 702      * containing package {@code p} where the class loader already has a module
 703      * defined to it containing package {@code p}.
 704      */
 705     @Test(expectedExceptions = { LayerInstantiationException.class })
 706     public void testPackageAlreadyInNamedModule() {
 707 
 708         ModuleDescriptor md1 = newBuilder("m1")
 709                 .packages(Set.of("p"))
 710                 .requires("java.base")
 711                 .build();
 712 
 713         ModuleDescriptor md2 = newBuilder("m2")
 714                 .packages(Set.of("p"))
 715                 .requires("java.base")
 716                 .build();
 717 
 718         ModuleFinder finder = ModuleUtils.finderOf(md1, md2);
 719 
 720         ClassLoader loader = new ClassLoader() { };
 721 
 722         // define m1 containing package p to class loader
 723 
 724         Configuration parent = Layer.boot().configuration();
 725 
 726         Configuration cf1 = parent.resolve(finder, ModuleFinder.of(), Set.of("m1"));
 727 
 728         Layer layer1 = Layer.boot().defineModules(cf1, mn -> loader);
 729 
 730         // attempt to define m2 containing package p to class loader
 731 
 732         Configuration cf2 = parent.resolve(finder, ModuleFinder.of(), Set.of("m2"));
 733 
 734         // should throw exception because p already in m1
 735         Layer layer2 = Layer.boot().defineModules(cf2, mn -> loader);
 736 
 737     }
 738 
 739 
 740     /**
 741      * Attempt to use Layer defineModules to create a Layer with a module
 742      * containing a package in which a type is already loaded by the class
 743      * loader.
 744      */
 745     @Test(expectedExceptions = { LayerInstantiationException.class })
 746     public void testPackageAlreadyInUnnamedModule() throws Exception {
 747 
 748         Class<?> c = layertest.Test.class;
 749         assertFalse(c.getModule().isNamed());  // in unnamed module
 750 
 751         ModuleDescriptor md = newBuilder("m")
 752                 .packages(Set.of(c.getPackageName()))
 753                 .requires("java.base")
 754                 .build();
 755 
 756         ModuleFinder finder = ModuleUtils.finderOf(md);
 757 
 758         Configuration parent = Layer.boot().configuration();
 759         Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m"));
 760 
 761         Layer.boot().defineModules(cf, mn -> c.getClassLoader());
 762     }
 763 
 764 
 765     /**
 766      * Attempt to create a Layer with a module named "java.base".
 767      */
 768     public void testLayerWithJavaBase() {
 769         ModuleDescriptor descriptor = newBuilder("java.base")
 770                 .exports("java.lang")
 771                 .build();
 772 
 773         ModuleFinder finder = ModuleUtils.finderOf(descriptor);
 774 
 775         Configuration cf = Layer.boot()
 776             .configuration()
 777             .resolve(finder, ModuleFinder.of(), Set.of("java.base"));
 778         assertTrue(cf.modules().size() == 1);
 779 
 780         ClassLoader scl = ClassLoader.getSystemClassLoader();
 781 
 782         try {
 783             Layer.boot().defineModules(cf, mn -> new ClassLoader() { });
 784             assertTrue(false);
 785         } catch (LayerInstantiationException e) { }
 786 
 787         try {
 788             Layer.boot().defineModulesWithOneLoader(cf, scl);
 789             assertTrue(false);
 790         } catch (LayerInstantiationException e) { }
 791 
 792         try {
 793             Layer.boot().defineModulesWithManyLoaders(cf, scl);
 794             assertTrue(false);
 795         } catch (LayerInstantiationException e) { }
 796     }
 797 
 798 
 799     /**
 800      * Attempt to create a Layer with a module containing a "java." package.
 801      * This should only be allowed when the module is defined to the platform
 802      * class loader.
 803      */
 804     @Test(enabled = false)
 805     public void testLayerWithJavaPackage() {
 806         ModuleDescriptor descriptor = newBuilder("foo")
 807                 .packages(Set.of("java.foo"))
 808                 .build();
 809 
 810         ModuleFinder finder = ModuleUtils.finderOf(descriptor);
 811 
 812         Configuration cf = Layer.boot()
 813                 .configuration()
 814                 .resolve(finder, ModuleFinder.of(), Set.of("foo"));
 815         assertTrue(cf.modules().size() == 1);
 816 
 817         ClassLoader pcl = ClassLoader.getPlatformClassLoader();
 818         ClassLoader scl = ClassLoader.getSystemClassLoader();
 819 
 820         try {
 821             Layer.boot().defineModules(cf, mn -> new ClassLoader() { });
 822             assertTrue(false);
 823         } catch (LayerInstantiationException e) { }
 824 
 825         try {
 826             Layer.boot().defineModulesWithOneLoader(cf, scl);
 827             assertTrue(false);
 828         } catch (LayerInstantiationException e) { }
 829 
 830         try {
 831             Layer.boot().defineModulesWithManyLoaders(cf, scl);
 832             assertTrue(false);
 833         } catch (LayerInstantiationException e) { }
 834 
 835         // create layer with module defined to platform class loader
 836         Layer layer = Layer.boot().defineModules(cf, mn -> pcl);
 837         Optional<Module> om = layer.findModule("foo");
 838         assertTrue(om.isPresent());
 839         Module foo = om.get();
 840         assertTrue(foo.getClassLoader() == pcl);
 841         assertTrue(foo.getPackages().length == 1);
 842         assertTrue(foo.getPackages()[0].equals("java.foo"));
 843     }
 844 
 845 
 846     /**
 847      * Attempt to create a Layer with a module defined to the boot loader
 848      */
 849     @Test(expectedExceptions = { LayerInstantiationException.class })
 850     public void testLayerWithBootLoader() {
 851         ModuleDescriptor descriptor = newBuilder("m1")
 852                 .build();
 853 
 854         ModuleFinder finder = ModuleUtils.finderOf(descriptor);
 855 
 856         Configuration cf = Layer.boot()
 857             .configuration()
 858             .resolve(finder, ModuleFinder.of(), Set.of("m1"));
 859         assertTrue(cf.modules().size() == 1);
 860 
 861         Layer.boot().defineModules(cf, mn -> null );
 862     }
 863 
 864 
 865     /**
 866      * Parent of configuration != configuration of parent Layer
 867      */
 868     @Test(expectedExceptions = { IllegalArgumentException.class })
 869     public void testIncorrectParent1() {
 870 
 871         ModuleDescriptor descriptor1 = newBuilder("m1")
 872                 .requires("java.base")
 873                 .build();
 874 
 875         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
 876 
 877         Configuration parent = Layer.boot().configuration();
 878         Configuration cf = parent.resolve(finder, ModuleFinder.of(), Set.of("m1"));
 879 
 880         ClassLoader loader = new ClassLoader() { };
 881         Layer.empty().defineModules(cf, mn -> loader);
 882     }
 883 
 884 
 885     /**
 886      * Parent of configuration != configuration of parent Layer
 887      */
 888     @Test(expectedExceptions = { IllegalArgumentException.class })
 889     public void testIncorrectParent2() {
 890 
 891         ModuleDescriptor descriptor1 = newBuilder("m1")
 892                 .build();
 893 
 894         ModuleFinder finder = ModuleUtils.finderOf(descriptor1);
 895 
 896         Configuration cf = resolve(finder, "m1");
 897 
 898         ClassLoader loader = new ClassLoader() { };
 899         Layer.boot().defineModules(cf, mn -> loader);
 900     }
 901 
 902 
 903     // null handling
 904 
 905     @Test(expectedExceptions = { NullPointerException.class })
 906     public void testCreateWithNull1() {
 907         ClassLoader loader = new ClassLoader() { };
 908         Layer.empty().defineModules(null, mn -> loader);
 909     }
 910 
 911     @Test(expectedExceptions = { NullPointerException.class })
 912     public void testCreateWithNull2() {
 913         Configuration cf = resolve(Layer.boot().configuration(), ModuleFinder.of());
 914         Layer.boot().defineModules(cf, null);
 915     }
 916 
 917     @Test(expectedExceptions = { NullPointerException.class })
 918     public void testCreateWithNull3() {
 919         ClassLoader scl = ClassLoader.getSystemClassLoader();
 920         Layer.empty().defineModulesWithOneLoader(null, scl);
 921     }
 922 
 923     @Test(expectedExceptions = { NullPointerException.class })
 924     public void testCreateWithNull4() {
 925         ClassLoader scl = ClassLoader.getSystemClassLoader();
 926         Layer.empty().defineModulesWithManyLoaders(null, scl);
 927     }
 928 
 929     @Test(expectedExceptions = { NullPointerException.class })
 930     public void testFindModuleWithNull() {
 931         Layer.boot().findModule(null);
 932     }
 933 
 934     @Test(expectedExceptions = { NullPointerException.class })
 935     public void testFindLoaderWithNull() {
 936         Layer.boot().findLoader(null);
 937     }
 938 
 939 
 940     // immutable sets
 941 
 942     @Test(expectedExceptions = { UnsupportedOperationException.class })
 943     public void testImmutableSet() {
 944         Module base = Object.class.getModule();
 945         Layer.boot().modules().add(base);
 946     }
 947 
 948 
 949     /**
 950      * Resolve the given modules, by name, and returns the resulting
 951      * Configuration.
 952      */
 953     private static Configuration resolve(Configuration cf,
 954                                          ModuleFinder finder,
 955                                          String... roots) {
 956         return cf.resolve(finder, ModuleFinder.of(), Set.of(roots));
 957     }
 958 
 959     private static Configuration resolve(ModuleFinder finder,
 960                                          String... roots) {
 961         return resolve(Configuration.empty(), finder, roots);
 962     }
 963 }