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