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