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