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