1 /*
   2  * Copyright (c) 2015, 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 /lib/testlibrary /test/lib
  27  * @modules jdk.compiler
  28  * @build LayerAndLoadersTest jdk.test.lib.compiler.CompilerUtils ModuleUtils
  29  * @run testng LayerAndLoadersTest
  30  * @summary Tests for java.lang.ModuleLayer@defineModulesWithXXX methods
  31  */
  32 
  33 import java.io.IOException;
  34 import java.io.InputStream;
  35 import java.lang.module.Configuration;
  36 import java.lang.module.ModuleDescriptor;
  37 import java.lang.module.ModuleFinder;
  38 import java.lang.module.ModuleReference;
  39 import java.lang.reflect.Method;
  40 import java.net.URL;
  41 import java.nio.file.Path;
  42 import java.nio.file.Paths;
  43 import java.util.Enumeration;
  44 import java.util.HashMap;
  45 import java.util.Iterator;
  46 import java.util.Map;
  47 import java.util.Optional;
  48 import java.util.ServiceLoader;
  49 import java.util.Set;
  50 import java.util.stream.Collectors;
  51 import jdk.test.lib.compiler.CompilerUtils;
  52 
  53 import org.testng.annotations.BeforeTest;
  54 import org.testng.annotations.Test;
  55 import static org.testng.Assert.*;
  56 
  57 @Test
  58 public class LayerAndLoadersTest {
  59 
  60     private static final String TEST_SRC = System.getProperty("test.src");
  61 
  62     private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
  63     private static final Path MODS_DIR = Paths.get("mods");
  64 
  65     @BeforeTest
  66     public void setup() throws Exception {
  67 
  68         // javac -d mods --module-source-path src src/**
  69         assertTrue(CompilerUtils.compile(SRC_DIR, MODS_DIR,
  70                 "--module-source-path", SRC_DIR.toString()));
  71     }
  72 
  73 
  74     /**
  75      * Basic test of ModuleLayer.defineModulesWithOneLoader
  76      *
  77      * Test scenario:
  78      *   m1 requires m2 and m3
  79      */
  80     public void testWithOneLoader() throws Exception {
  81 
  82         Configuration cf = resolve("m1");
  83 
  84         ClassLoader scl = ClassLoader.getSystemClassLoader();
  85 
  86         ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
  87 
  88         checkLayer(layer, "m1", "m2", "m3");
  89 
  90         ClassLoader cl1 = layer.findLoader("m1");
  91         ClassLoader cl2 = layer.findLoader("m2");
  92         ClassLoader cl3 = layer.findLoader("m3");
  93 
  94         assertTrue(cl1.getParent() == scl);
  95         assertTrue(cl2 == cl1);
  96         assertTrue(cl3 == cl1);
  97 
  98         invoke(layer, "m1", "p.Main");
  99 
 100     }
 101 
 102 
 103     /**
 104      * Basic test of ModuleLayer.defineModulesWithManyLoaders
 105      *
 106      * Test scenario:
 107      *   m1 requires m2 and m3
 108      */
 109     public void testWithManyLoaders() throws Exception {
 110 
 111         Configuration cf = resolve("m1");
 112 
 113         ClassLoader scl = ClassLoader.getSystemClassLoader();
 114 
 115         ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
 116 
 117         checkLayer(layer, "m1", "m2", "m3");
 118 
 119         ClassLoader cl1 = layer.findLoader("m1");
 120         ClassLoader cl2 = layer.findLoader("m2");
 121         ClassLoader cl3 = layer.findLoader("m3");
 122 
 123         assertTrue(cl1.getParent() == scl);
 124         assertTrue(cl2.getParent() == scl);
 125         assertTrue(cl3.getParent() == scl);
 126         assertTrue(cl2 != cl1);
 127         assertTrue(cl3 != cl1);
 128         assertTrue(cl3 != cl2);
 129 
 130         invoke(layer, "m1", "p.Main");
 131 
 132     }
 133 
 134 
 135     /**
 136      * Basic test of ModuleLayer.defineModulesWithOneLoader where one of the
 137      * modules is a service provider module.
 138      *
 139      * Test scenario:
 140      *    m1 requires m2 and m3
 141      *    m1 uses S
 142      *    m4 provides S with ...
 143      */
 144     public void testServicesWithOneLoader() throws Exception {
 145 
 146         Configuration cf = resolveAndBind("m1");
 147 
 148         ClassLoader scl = ClassLoader.getSystemClassLoader();
 149 
 150         ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
 151 
 152         checkLayer(layer, "m1", "m2", "m3", "m4");
 153 
 154         ClassLoader cl1 = layer.findLoader("m1");
 155         ClassLoader cl2 = layer.findLoader("m2");
 156         ClassLoader cl3 = layer.findLoader("m3");
 157         ClassLoader cl4 = layer.findLoader("m4");
 158 
 159         assertTrue(cl1.getParent() == scl);
 160         assertTrue(cl2 == cl1);
 161         assertTrue(cl3 == cl1);
 162         assertTrue(cl4 == cl1);
 163 
 164         Class<?> serviceType = cl1.loadClass("p.Service");
 165         assertTrue(serviceType.getClassLoader() == cl1);
 166 
 167         Iterator<?> iter = ServiceLoader.load(serviceType, cl1).iterator();
 168         Object provider = iter.next();
 169         assertTrue(serviceType.isInstance(provider));
 170         assertTrue(provider.getClass().getClassLoader() == cl1);
 171         assertFalse(iter.hasNext());
 172 
 173     }
 174 
 175 
 176     /**
 177      * Basic test of ModuleLayer.defineModulesWithManyLoaders where one of the
 178      * modules is a service provider module.
 179      *
 180      * Test scenario:
 181      *    m1 requires m2 and m3
 182      *    m1 uses S
 183      *    m4 provides S with ...
 184      */
 185     public void testServicesWithManyLoaders() throws Exception {
 186 
 187         Configuration cf = resolveAndBind("m1");
 188 
 189         ClassLoader scl = ClassLoader.getSystemClassLoader();
 190 
 191         ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
 192 
 193         checkLayer(layer, "m1", "m2", "m3", "m4");
 194 
 195         ClassLoader cl1 = layer.findLoader("m1");
 196         ClassLoader cl2 = layer.findLoader("m2");
 197         ClassLoader cl3 = layer.findLoader("m3");
 198         ClassLoader cl4 = layer.findLoader("m4");
 199 
 200         assertTrue(cl1.getParent() == scl);
 201         assertTrue(cl2.getParent() == scl);
 202         assertTrue(cl3.getParent() == scl);
 203         assertTrue(cl4.getParent() == scl);
 204         assertTrue(cl2 != cl1);
 205         assertTrue(cl3 != cl1);
 206         assertTrue(cl3 != cl2);
 207         assertTrue(cl4 != cl1);
 208         assertTrue(cl4 != cl2);
 209         assertTrue(cl4 != cl3);
 210 
 211         Class<?> serviceType = cl1.loadClass("p.Service");
 212         assertTrue(serviceType.getClassLoader() == cl1);
 213 
 214         // Test that the service provider can be located via any of
 215         // the class loaders in the layer
 216         for (Module m : layer.modules()) {
 217             ClassLoader loader = m.getClassLoader();
 218             Iterator<?> iter = ServiceLoader.load(serviceType, loader).iterator();
 219             Object provider = iter.next();
 220             assertTrue(serviceType.isInstance(provider));
 221             assertTrue(provider.getClass().getClassLoader() == cl4);
 222             assertFalse(iter.hasNext());
 223         }
 224 
 225     }
 226 
 227 
 228     /**
 229      * Tests that the class loaders created by defineModulesWithXXX delegate
 230      * to the given parent class loader.
 231      */
 232     public void testDelegationToParent() throws Exception {
 233 
 234         Configuration cf = resolve("m1");
 235 
 236         ClassLoader parent = this.getClass().getClassLoader();
 237         String cn = this.getClass().getName();
 238 
 239         // one loader
 240         ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, parent);
 241         testLoad(layer, cn);
 242 
 243          // one loader with boot loader as parent
 244         layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, null);
 245         testLoadFail(layer, cn);
 246 
 247         // many loaders
 248         layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, parent);
 249         testLoad(layer, cn);
 250 
 251         // many loader with boot loader as parent
 252         layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null);
 253         testLoadFail(layer, cn);
 254 
 255     }
 256 
 257 
 258     /**
 259      * Test defineModulesWithXXX when modules that have overlapping packages.
 260      *
 261      * Test scenario:
 262      *   m1 exports p
 263      *   m2 exports p
 264      */
 265     public void testOverlappingPackages() {
 266 
 267         ModuleDescriptor descriptor1
 268             = ModuleDescriptor.newModule("m1").exports("p").build();
 269 
 270         ModuleDescriptor descriptor2
 271             = ModuleDescriptor.newModule("m2").exports("p").build();
 272 
 273         ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2);
 274 
 275         Configuration cf = ModuleLayer.boot()
 276             .configuration()
 277             .resolve(finder, ModuleFinder.of(), Set.of("m1", "m2"));
 278 
 279         // cannot define both module m1 and m2 to the same class loader
 280         try {
 281             ModuleLayer.boot().defineModulesWithOneLoader(cf, null);
 282             assertTrue(false);
 283         } catch (LayerInstantiationException expected) { }
 284 
 285         // should be okay to have one module per class loader
 286         ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, null);
 287         checkLayer(layer, "m1", "m2");
 288 
 289     }
 290 
 291 
 292     /**
 293      * Test ModuleLayer.defineModulesWithXXX with split delegation.
 294      *
 295      * Test scenario:
 296      *   layer1: m1 exports p, m2 exports p
 297      *   layer2: m3 reads m1, m4 reads m2
 298      */
 299     public void testSplitDelegation() {
 300 
 301         ModuleDescriptor descriptor1
 302             = ModuleDescriptor.newModule("m1").exports("p").build();
 303 
 304         ModuleDescriptor descriptor2
 305             = ModuleDescriptor.newModule("m2").exports("p").build();
 306 
 307         ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2);
 308 
 309         Configuration cf1 = ModuleLayer.boot()
 310             .configuration()
 311             .resolve(finder1, ModuleFinder.of(), Set.of("m1", "m2"));
 312 
 313         ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
 314         checkLayer(layer1, "m1", "m2");
 315 
 316         ModuleDescriptor descriptor3
 317             = ModuleDescriptor.newModule("m3").requires("m1").build();
 318 
 319         ModuleDescriptor descriptor4
 320             = ModuleDescriptor.newModule("m4").requires("m2").build();
 321 
 322         ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4);
 323 
 324         Configuration cf2 = cf1.resolve(finder2, ModuleFinder.of(),
 325                                                 Set.of("m3", "m4"));
 326 
 327         // package p cannot be supplied by two class loaders
 328         try {
 329             layer1.defineModulesWithOneLoader(cf2, null);
 330             assertTrue(false);
 331         } catch (LayerInstantiationException expected) { }
 332 
 333         // no split delegation when modules have their own class loader
 334         ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
 335         checkLayer(layer2, "m3", "m4");
 336 
 337     }
 338 
 339 
 340     /**
 341      * Test ModuleLayer.defineModulesWithXXX when the modules that override same
 342      * named modules in the parent layer.
 343      *
 344      * Test scenario:
 345      *   layer1: m1, m2, m3 => same loader
 346      *   layer2: m1, m2, m4 => same loader
 347      */
 348     public void testOverriding1() throws Exception {
 349 
 350         Configuration cf1 = resolve("m1");
 351 
 352         ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null);
 353         checkLayer(layer1, "m1", "m2", "m3");
 354 
 355         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 356         Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
 357                                                 Set.of("m1"));
 358 
 359         ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
 360         checkLayer(layer2, "m1", "m2", "m3");
 361         invoke(layer1, "m1", "p.Main");
 362 
 363         ClassLoader loader1 = layer1.findLoader("m1");
 364         ClassLoader loader2 = layer1.findLoader("m2");
 365         ClassLoader loader3 = layer1.findLoader("m3");
 366 
 367         ClassLoader loader4 = layer2.findLoader("m1");
 368         ClassLoader loader5 = layer2.findLoader("m2");
 369         ClassLoader loader6 = layer2.findLoader("m3");
 370 
 371         assertTrue(loader1 == loader2);
 372         assertTrue(loader1 == loader3);
 373 
 374         assertTrue(loader4 == loader5);
 375         assertTrue(loader4 == loader6);
 376         assertTrue(loader4 != loader1);
 377 
 378         assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
 379         assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1);
 380         assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1);
 381 
 382         assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
 383         assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader4);
 384         assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader4);
 385 
 386     }
 387 
 388 
 389     /**
 390      * Test Layer defineModulesWithXXX when the modules that override same
 391      * named modules in the parent layer.
 392      *
 393      * Test scenario:
 394      *   layer1: m1, m2, m3 => loader pool
 395      *   layer2: m1, m2, m3 => loader pool
 396      */
 397     public void testOverriding2() throws Exception {
 398 
 399         Configuration cf1 = resolve("m1");
 400 
 401         ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
 402         checkLayer(layer1, "m1", "m2", "m3");
 403 
 404         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 405         Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
 406                                                 Set.of("m1"));
 407 
 408         ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
 409         checkLayer(layer2, "m1", "m2", "m3");
 410         invoke(layer1, "m1", "p.Main");
 411 
 412         ClassLoader loader1 = layer1.findLoader("m1");
 413         ClassLoader loader2 = layer1.findLoader("m2");
 414         ClassLoader loader3 = layer1.findLoader("m3");
 415 
 416         ClassLoader loader4 = layer2.findLoader("m1");
 417         ClassLoader loader5 = layer2.findLoader("m2");
 418         ClassLoader loader6 = layer2.findLoader("m3");
 419 
 420         assertTrue(loader4 != loader1);
 421         assertTrue(loader5 != loader2);
 422         assertTrue(loader6 != loader3);
 423 
 424         assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
 425         assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2);
 426         assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3);
 427 
 428         // p.Main is not visible via loader2
 429         try {
 430             loader2.loadClass("p.Main");
 431             assertTrue(false);
 432         } catch (ClassNotFoundException expected) { }
 433 
 434         // w.Hello is not visible via loader2
 435         try {
 436             loader2.loadClass("w.Hello");
 437             assertTrue(false);
 438         } catch (ClassNotFoundException expected) { }
 439 
 440         // p.Main is not visible via loader3
 441         try {
 442             loader3.loadClass("p.Main");
 443             assertTrue(false);
 444         } catch (ClassNotFoundException expected) { }
 445 
 446         // q.Hello is not visible via loader3
 447         try {
 448             loader3.loadClass("q.Hello");
 449             assertTrue(false);
 450         } catch (ClassNotFoundException expected) { }
 451 
 452 
 453         assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
 454         assertTrue(loader5.loadClass("q.Hello").getClassLoader() == loader5);
 455         assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
 456 
 457         // p.Main is not visible via loader5
 458         try {
 459             loader5.loadClass("p.Main");
 460             assertTrue(false);
 461         } catch (ClassNotFoundException expected) { }
 462 
 463         // w.Hello is not visible via loader5
 464         try {
 465             loader5.loadClass("w.Hello");
 466             assertTrue(false);
 467         } catch (ClassNotFoundException expected) { }
 468 
 469         // p.Main is not visible via loader6
 470         try {
 471             loader6.loadClass("p.Main");
 472             assertTrue(false);
 473         } catch (ClassNotFoundException expected) { }
 474 
 475         // q.Hello is not visible via loader6
 476         try {
 477             loader6.loadClass("q.Hello");
 478             assertTrue(false);
 479         } catch (ClassNotFoundException expected) { }
 480 
 481     }
 482 
 483 
 484     /**
 485      * Test ModuleLayer.defineModulesWithXXX when the modules that override same
 486      * named modules in the parent layer.
 487      *
 488      * layer1: m1, m2, m3 => same loader
 489      * layer2: m1, m3 => same loader
 490      */
 491     public void testOverriding3() throws Exception {
 492 
 493         Configuration cf1 = resolve("m1");
 494 
 495         ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithOneLoader(cf1, null);
 496         checkLayer(layer1, "m1", "m2", "m3");
 497 
 498         ModuleFinder finder = finderFor("m1", "m3");
 499 
 500         Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
 501                                                 Set.of("m1"));
 502 
 503         ModuleLayer layer2 = layer1.defineModulesWithOneLoader(cf2, null);
 504         checkLayer(layer2, "m1", "m3");
 505         invoke(layer1, "m1", "p.Main");
 506 
 507         ClassLoader loader1 = layer1.findLoader("m1");
 508         ClassLoader loader2 = layer2.findLoader("m1");
 509 
 510         assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
 511         assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader1);
 512         assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader1);
 513 
 514         assertTrue(loader2.loadClass("p.Main").getClassLoader() == loader2);
 515         assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader1);
 516         assertTrue(loader2.loadClass("w.Hello").getClassLoader() == loader2);
 517 
 518     }
 519 
 520 
 521     /**
 522      * Test Layer defineModulesWithXXX when the modules that override same
 523      * named modules in the parent layer.
 524      *
 525      * layer1: m1, m2, m3 => loader pool
 526      * layer2: m1, m3 => loader pool
 527      */
 528     public void testOverriding4() throws Exception {
 529 
 530         Configuration cf1 = resolve("m1");
 531 
 532         ModuleLayer layer1 = ModuleLayer.boot().defineModulesWithManyLoaders(cf1, null);
 533         checkLayer(layer1, "m1", "m2", "m3");
 534 
 535         ModuleFinder finder = finderFor("m1", "m3");
 536 
 537         Configuration cf2 = cf1.resolve(finder, ModuleFinder.of(),
 538                                                 Set.of("m1"));
 539 
 540         ModuleLayer layer2 = layer1.defineModulesWithManyLoaders(cf2, null);
 541         checkLayer(layer2, "m1", "m3");
 542         invoke(layer1, "m1", "p.Main");
 543 
 544         ClassLoader loader1 = layer1.findLoader("m1");
 545         ClassLoader loader2 = layer1.findLoader("m2");
 546         ClassLoader loader3 = layer1.findLoader("m3");
 547 
 548         ClassLoader loader4 = layer2.findLoader("m1");
 549         ClassLoader loader5 = layer2.findLoader("m2");
 550         ClassLoader loader6 = layer2.findLoader("m3");
 551 
 552         assertTrue(loader4 != loader1);
 553         assertTrue(loader5 == loader2);  // m2 not overridden
 554         assertTrue(loader6 != loader3);
 555 
 556         assertTrue(loader1.loadClass("p.Main").getClassLoader() == loader1);
 557         assertTrue(loader1.loadClass("q.Hello").getClassLoader() == loader2);
 558         assertTrue(loader1.loadClass("w.Hello").getClassLoader() == loader3);
 559 
 560         assertTrue(loader2.loadClass("q.Hello").getClassLoader() == loader2);
 561 
 562         assertTrue(loader3.loadClass("w.Hello").getClassLoader() == loader3);
 563 
 564         assertTrue(loader4.loadClass("p.Main").getClassLoader() == loader4);
 565         assertTrue(loader4.loadClass("q.Hello").getClassLoader() == loader2);
 566         assertTrue(loader4.loadClass("w.Hello").getClassLoader() == loader6);
 567 
 568         assertTrue(loader6.loadClass("w.Hello").getClassLoader() == loader6);
 569 
 570     }
 571 
 572 
 573     /**
 574      * Basic test of resource loading with a class loader created by
 575      * Layer.defineModulesWithOneLoader.
 576      */
 577     public void testResourcesOneLoader() throws Exception {
 578         Configuration cf = resolve("m1");
 579         ClassLoader scl = ClassLoader.getSystemClassLoader();
 580         ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
 581         ClassLoader loader = layer.findLoader("m1");
 582         testResourceLoading(loader, "p/Main.class");
 583     }
 584 
 585     /**
 586      * Basic test of resource loading with a class loader created by
 587      * Layer.defineModulesWithOneLoader.
 588      */
 589     public void testResourcesManyLoaders() throws Exception {
 590         Configuration cf = resolve("m1");
 591         ClassLoader scl = ClassLoader.getSystemClassLoader();
 592         ModuleLayer layer = ModuleLayer.boot().defineModulesWithManyLoaders(cf, scl);
 593         ClassLoader loader = layer.findLoader("m1");
 594         testResourceLoading(loader, "p/Main.class");
 595     }
 596 
 597     /**
 598      * Test that a resource is located by a class loader.
 599      */
 600     private void testResourceLoading(ClassLoader loader, String name)
 601         throws IOException
 602     {
 603         URL url = loader.getResource(name);
 604         assertNotNull(url);
 605 
 606         try (InputStream in = loader.getResourceAsStream(name)) {
 607             assertNotNull(in);
 608         }
 609 
 610         Enumeration<URL> urls = loader.getResources(name);
 611         assertTrue(urls.hasMoreElements());
 612     }
 613 
 614 
 615     // -- supporting methods --
 616 
 617 
 618     /**
 619      * Resolve the given modules, by name, and returns the resulting
 620      * Configuration.
 621      */
 622     private static Configuration resolve(String... roots) {
 623         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 624         return ModuleLayer.boot()
 625             .configuration()
 626             .resolve(finder, ModuleFinder.of(), Set.of(roots));
 627     }
 628 
 629     /**
 630      * Resolve the given modules, by name, and returns the resulting
 631      * Configuration.
 632      */
 633     private static Configuration resolveAndBind(String... roots) {
 634         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 635         return ModuleLayer.boot()
 636             .configuration()
 637             .resolveAndBind(finder, ModuleFinder.of(), Set.of(roots));
 638     }
 639 
 640 
 641     /**
 642      * Invokes the static void main(String[]) method on the given class
 643      * in the given module.
 644      */
 645     private static void invoke(ModuleLayer layer, String mn, String mc) throws Exception {
 646         ClassLoader loader = layer.findLoader(mn);
 647         Class<?> c = loader.loadClass(mc);
 648         Method mainMethod = c.getMethod("main", String[].class);
 649         mainMethod.invoke(null, (Object)new String[0]);
 650     }
 651 
 652 
 653     /**
 654      * Checks that the given layer contains exactly the expected modules
 655      * (by name).
 656      */
 657     private void checkLayer(ModuleLayer layer, String ... expected) {
 658         Set<String> names = layer.modules().stream()
 659                 .map(Module::getName)
 660                 .collect(Collectors.toSet());
 661         assertTrue(names.size() == expected.length);
 662         for (String name : expected) {
 663             assertTrue(names.contains(name));
 664         }
 665     }
 666 
 667 
 668     /**
 669      * Test that a class can be loaded via the class loader of all modules
 670      * in the given layer.
 671      */
 672     static void testLoad(ModuleLayer layer, String cn) throws Exception {
 673         for (Module m : layer.modules()) {
 674             ClassLoader l = m.getClassLoader();
 675             l.loadClass(cn);
 676         }
 677     }
 678 
 679 
 680     /**
 681      * Test that a class cannot be loaded via any of the class loaders of
 682      * the modules in the given layer.
 683      */
 684     static void testLoadFail(ModuleLayer layer, String cn) throws Exception {
 685         for (Module m : layer.modules()) {
 686             ClassLoader l = m.getClassLoader();
 687             try {
 688                 l.loadClass(cn);
 689                 assertTrue(false);
 690             } catch (ClassNotFoundException expected) { }
 691         }
 692     }
 693 
 694 
 695     /**
 696      * Returns a ModuleFinder that only finds the given test modules
 697      */
 698     static ModuleFinder finderFor(String... names) {
 699 
 700         ModuleFinder finder = ModuleFinder.of(MODS_DIR);
 701 
 702         Map<String, ModuleReference> mrefs = new HashMap<>();
 703         for (String name : names) {
 704             Optional<ModuleReference> omref = finder.find(name);
 705             assert omref.isPresent();
 706             mrefs.put(name, omref.get());
 707         }
 708 
 709         return new ModuleFinder() {
 710             @Override
 711             public Optional<ModuleReference> find(String name) {
 712                 ModuleReference mref = mrefs.get(name);
 713                 return Optional.ofNullable(mref);
 714             }
 715             @Override
 716             public Set<ModuleReference> findAll() {
 717                 return mrefs.values().stream().collect(Collectors.toSet());
 718             }
 719         };
 720     }
 721 
 722 }