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