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