< prev index next >

test/java/lang/module/AutomaticModulesTest.java

Print this page


   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  * @build AutomaticModulesTest ModuleUtils JarUtils
  28  * @run testng AutomaticModulesTest
  29  * @summary Basic tests for automatic modules
  30  */
  31 
  32 import java.io.IOException;
  33 import java.lang.module.Configuration;
  34 import java.lang.module.FindException;
  35 import java.lang.module.ModuleDescriptor;
  36 import java.lang.module.ModuleDescriptor.Exports;
  37 import java.lang.module.ModuleDescriptor.Requires.Modifier;
  38 import java.lang.module.ModuleFinder;
  39 import java.lang.module.ModuleReference;

  40 import java.lang.module.ResolvedModule;
  41 import java.lang.reflect.Layer;
  42 import java.lang.reflect.Module;
  43 import java.nio.file.Files;
  44 import java.nio.file.Path;
  45 import java.nio.file.Paths;
  46 import java.util.Optional;
  47 import java.util.Set;
  48 import java.util.jar.Attributes;
  49 import java.util.jar.Manifest;
  50 import java.util.stream.Collectors;
  51 import java.util.stream.Stream;
  52 
  53 import org.testng.annotations.DataProvider;
  54 import org.testng.annotations.Test;
  55 import static org.testng.Assert.*;
  56 
  57 @Test
  58 public class AutomaticModulesTest {
  59 


 120     @Test(dataProvider = "names")
 121     public void testNames(String fn, String mid) throws IOException {
 122         String[] s = mid.split("/");
 123         String mn = s[0];
 124         String vs = (s.length == 2) ? s[1] : null;
 125 
 126         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 127         Path jf = dir.resolve(fn);
 128 
 129         // create empty JAR file
 130         createDummyJarFile(jf);
 131 
 132         // create a ModuleFinder to find modules in the directory
 133         ModuleFinder finder = ModuleFinder.of(dir);
 134 
 135         // a module with the expected name should be found
 136         Optional<ModuleReference> mref = finder.find(mn);
 137         assertTrue(mref.isPresent(), mn + " not found");
 138 
 139         ModuleDescriptor descriptor = mref.get().descriptor();

 140         assertEquals(descriptor.name(), mn);
 141         if (vs == null) {
 142             assertFalse(descriptor.version().isPresent());
 143         } else {
 144             assertEquals(descriptor.version().get().toString(), vs);
 145         }
 146     }
 147 
 148 
 149     /**
 150      * Test impossible mapping of JAR files to modules names
 151      */
 152     @Test(dataProvider = "badnames", expectedExceptions = FindException.class)
 153     public void testBadNames(String fn, String ignore) throws IOException {
 154         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 155         Path jf = dir.resolve(fn);
 156 
 157         // create empty JAR file
 158         createDummyJarFile(jf);
 159 
 160         // should throw FindException
 161         ModuleFinder.of(dir).findAll();
 162     }
 163 
 164 
 165     /**
 166      * Test all packages are exported
 167      */
 168     public void testPackages() throws IOException {
 169         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 170         createDummyJarFile(dir.resolve("m.jar"),
 171                            "p/C1.class", "p/C2.class", "q/C1.class");
 172 
 173         ModuleFinder finder = ModuleFinder.of(dir);
 174         Optional<ModuleReference> mref = finder.find("m");
 175         assertTrue(mref.isPresent(), "m not found");
 176 
 177         ModuleDescriptor descriptor = mref.get().descriptor();

 178 
 179         assertTrue(descriptor.packages().size() == 2);
 180         assertTrue(descriptor.packages().contains("p"));
 181         assertTrue(descriptor.packages().contains("q"));
 182 
 183         Set<String> exports = descriptor.exports().stream()
 184                 .map(Exports::source)
 185                 .collect(Collectors.toSet());
 186         assertTrue(exports.size() == 2);
 187         assertTrue(exports.contains("p"));
 188         assertTrue(exports.contains("q"));
 189     }
 190 
 191     /**
 192      * Test class files in JAR file where the entry does not correspond to a
 193      * legal package name.
 194      */
 195     public void testBadPackage() throws IOException {
 196         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 197         createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p-/C2.class");
 198 
 199         ModuleFinder finder = ModuleFinder.of(dir);
 200         Optional<ModuleReference> mref = finder.find("m");
 201         assertTrue(mref.isPresent(), "m not found");
 202 
 203         ModuleDescriptor descriptor = mref.get().descriptor();

 204 
 205         assertTrue(descriptor.packages().size() == 1);
 206         assertTrue(descriptor.packages().contains("p"));
 207 
 208         Set<String> exports = descriptor.exports().stream()
 209                 .map(Exports::source)
 210                 .collect(Collectors.toSet());
 211         assertTrue(exports.size() == 1);
 212         assertTrue(exports.contains("p"));
 213     }
 214 
 215     /**
 216      * Test non-class resources in a JAR file.
 217      */
 218     public void testNonClassResources() throws IOException {
 219         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 220         createDummyJarFile(dir.resolve("m.jar"),
 221                 "LICENSE",
 222                 "README",
 223                 "WEB-INF/tags",
 224                 "p/Type.class",
 225                 "p/resources/m.properties");
 226 
 227         ModuleFinder finder = ModuleFinder.of(dir);
 228         Optional<ModuleReference> mref = finder.find("m");
 229         assertTrue(mref.isPresent(), "m not found");
 230 
 231         ModuleDescriptor descriptor = mref.get().descriptor();

 232 
 233         assertTrue(descriptor.packages().size() == 2);
 234         assertTrue(descriptor.packages().contains("p"));
 235         assertTrue(descriptor.packages().contains("p.resources"));
 236     }
 237 
 238     /**
 239      * Test .class file in unnamed package (top-level directory)
 240      */
 241     @Test(expectedExceptions = FindException.class)
 242     public void testClassInUnnamedPackage() throws IOException {
 243         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 244         createDummyJarFile(dir.resolve("m.jar"), "Mojo.class");
 245         ModuleFinder finder = ModuleFinder.of(dir);
 246         finder.findAll();
 247     }
 248 
 249     /**
 250      * Test JAR file with META-INF/services configuration file
 251      */
 252     public void testServicesConfiguration() throws IOException {
 253         String service = "p.S";
 254         String provider = "p.S1";
 255 
 256         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");







 257         Path services = tmpdir.resolve("META-INF").resolve("services");
 258         Files.createDirectories(services);
 259         Files.write(services.resolve(service), Set.of(provider));

 260         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 261         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 262 
 263         ModuleFinder finder = ModuleFinder.of(dir);
 264 
 265         Optional<ModuleReference> mref = finder.find("m");
 266         assertTrue(mref.isPresent(), "m not found");
 267 
 268         ModuleDescriptor descriptor = mref.get().descriptor();
 269         assertTrue(descriptor.provides().size() == 1);
 270         ModuleDescriptor.Provides provides = descriptor.provides().iterator().next();
 271         assertEquals(provides.service(), service);
 272         assertTrue(provides.providers().size() == 1);
 273         assertTrue(provides.providers().contains((provider)));
 274     }
 275 
 276 
 277     // META-INF/services files that don't map to legal service names
 278     @DataProvider(name = "badservices")
 279     public Object[][] createBadServices() {


 297         Path services = tmpdir.resolve("META-INF").resolve("services");
 298         Files.createDirectories(services);
 299         Files.write(services.resolve(service), Set.of(provider));
 300         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 301         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 302 
 303         Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
 304         assertTrue(omref.isPresent());
 305         ModuleDescriptor descriptor = omref.get().descriptor();
 306         assertTrue(descriptor.provides().isEmpty());
 307     }
 308 
 309 
 310     // META-INF/services configuration file entries that are not legal
 311     @DataProvider(name = "badproviders")
 312     public Object[][] createBadProviders() {
 313         return new Object[][] {
 314 
 315                 // service type         provider type
 316                 { "p.S",                "-" },
 317                 { "p.S",                ".S1" },
 318                 { "p.S",                "S1." },
 319         };
 320     }
 321 
 322     /**
 323      * Test JAR file with META-INF/services configuration file with bad
 324      * values or names.
 325      */
 326     @Test(dataProvider = "badproviders", expectedExceptions = FindException.class)
 327     public void testBadProvideNames(String service, String provider)
 328         throws IOException
 329     {
 330         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");







 331         Path services = tmpdir.resolve("META-INF").resolve("services");
 332         Files.createDirectories(services);
 333         Files.write(services.resolve(service), Set.of(provider));





















 334         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 335         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 336 
 337         // should throw FindException
 338         ModuleFinder.of(dir).findAll();
 339     }
 340 
 341 
 342     /**
 343      * Test that a JAR file with a Main-Class attribute results
 344      * in a module with a main class.
 345      */
 346     public void testMainClass() throws IOException {
 347         String mainClass = "p.Main";
 348 
 349         Manifest man = new Manifest();
 350         Attributes attrs = man.getMainAttributes();
 351         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 352         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 353 
 354         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 355         createDummyJarFile(dir.resolve("m.jar"), man);

 356 
 357         ModuleFinder finder = ModuleFinder.of(dir);
 358 
 359         Configuration parent = Layer.boot().configuration();
 360         Configuration cf = resolve(parent, finder, "m");
 361 
 362         ModuleDescriptor descriptor = findDescriptor(cf, "m");
 363 
 364         assertTrue(descriptor.mainClass().isPresent());
 365         assertEquals(descriptor.mainClass().get(), mainClass);
 366     }
 367 
 368 
 369     // Main-Class files that do not map to a legal Java identifier
 370     @DataProvider(name = "badmainclass")
 371     public Object[][] createBadMainClass() {
 372         return new Object[][]{
 373 


 374             { "p-.Main",     null },
 375             { ".Main",       null }
 376 
 377         };
 378     }
 379 
 380     /**
 381      * Test that a JAR file with a Main-Class attribute that is not a valid
 382      * Java identifier
 383      */
 384     @Test(dataProvider = "badmainclass", expectedExceptions = FindException.class)
 385     public void testBadMainClass(String mainClass, String ignore) throws IOException {
 386         Manifest man = new Manifest();
 387         Attributes attrs = man.getMainAttributes();
 388         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 389         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 390 
 391         Path dir = Files.createTempDirectory(USER_DIR, "mods");


















 392         createDummyJarFile(dir.resolve("m.jar"), man);
 393 
 394         // should throw FindException
 395         ModuleFinder.of(dir).findAll();
 396     }
 397 
 398 
 399     /**
 400      * Basic test of a configuration created with automatic modules.
 401      *   a requires b*
 402      *   a requires c*
 403      *   b*
 404      *   c*
 405      */
 406     public void testConfiguration1() throws Exception {
 407         ModuleDescriptor descriptor1
 408             = ModuleDescriptor.module("a")
 409                 .requires("b")
 410                 .requires("c")
 411                 .requires("java.base")
 412                 .build();
 413 
 414         // b and c are automatic modules
 415         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 416         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 417         createDummyJarFile(dir.resolve("c.jar"), "q/T.class");
 418 
 419         // module finder locates a and the modules in the directory
 420         ModuleFinder finder
 421             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1),
 422                 ModuleFinder.of(dir));
 423 
 424         Configuration parent = Layer.boot().configuration();
 425         Configuration cf = resolve(parent, finder, "a");
 426 
 427         assertTrue(cf.modules().size() == 3);
 428         assertTrue(cf.findModule("a").isPresent());


 448 
 449         assertTrue(b.reads().contains(a));
 450         assertTrue(b.reads().contains(c));
 451         testReadAllBootModules(cf, "b");  // b reads all modules in boot layer
 452 
 453         assertTrue(c.reads().contains(a));
 454         assertTrue(c.reads().contains(b));
 455         testReadAllBootModules(cf, "c");  // c reads all modules in boot layer
 456 
 457     }
 458 
 459     /**
 460      * Basic test of a configuration created with automatic modules
 461      *   a requires b
 462      *   b requires c*
 463      *   c*
 464      *   d*
 465      */
 466     public void testInConfiguration2() throws IOException {
 467         ModuleDescriptor descriptor1
 468             = ModuleDescriptor.module("a")
 469                 .requires("b")
 470                 .requires("java.base")
 471                 .build();
 472 
 473         ModuleDescriptor descriptor2
 474             = ModuleDescriptor.module("b")
 475                 .requires("c")
 476                 .requires("java.base")
 477                 .build();
 478 
 479         // c and d are automatic modules
 480         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 481         createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
 482         createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 483 
 484         // module finder locates a and the modules in the directory
 485         ModuleFinder finder
 486             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
 487                                    ModuleFinder.of(dir));
 488 
 489         Configuration parent = Layer.boot().configuration();
 490         Configuration cf = resolve(parent, finder, "a", "d");
 491 
 492         assertTrue(cf.modules().size() == 4);
 493         assertTrue(cf.findModule("a").isPresent());
 494         assertTrue(cf.findModule("b").isPresent());


 521         assertTrue(c.reads().contains(b));
 522         assertTrue(c.reads().contains(d));
 523         testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 524 
 525         assertTrue(d.reads().contains(a));
 526         assertTrue(d.reads().contains(b));
 527         assertTrue(d.reads().contains(c));
 528         testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
 529     }
 530 
 531 
 532     /**
 533      * Basic test of a configuration created with automatic modules
 534      *   a requires b
 535      *   b requires transitive c*
 536      *   c*
 537      *   d*
 538      */
 539     public void testInConfiguration3() throws IOException {
 540         ModuleDescriptor descriptor1
 541             = ModuleDescriptor.module("a")
 542                 .requires("b")
 543                 .requires("java.base")
 544                 .build();
 545 
 546         ModuleDescriptor descriptor2
 547             = ModuleDescriptor.module("b")
 548                 .requires(Set.of(Modifier.TRANSITIVE), "c")
 549                 .requires("java.base")
 550                 .build();
 551 
 552         // c and d are automatic modules
 553         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 554         createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
 555         createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 556 
 557         // module finder locates a and the modules in the directory
 558         ModuleFinder finder
 559             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
 560                 ModuleFinder.of(dir));
 561 
 562         Configuration parent = Layer.boot().configuration();
 563         Configuration cf = resolve(parent, finder, "a", "d");
 564 
 565         assertTrue(cf.modules().size() == 4);
 566         assertTrue(cf.findModule("a").isPresent());
 567         assertTrue(cf.findModule("b").isPresent());


 592         assertTrue(b.reads().contains(d));
 593         assertTrue(b.reads().contains(base));
 594 
 595         assertTrue(reads(cf, "b", "c"));
 596         assertTrue(reads(cf, "b", "d"));
 597         assertTrue(reads(cf, "b", "java.base"));
 598 
 599         assertTrue(c.reads().contains(a));
 600         assertTrue(c.reads().contains(b));
 601         assertTrue(c.reads().contains(d));
 602         testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 603 
 604         assertTrue(d.reads().contains(a));
 605         assertTrue(d.reads().contains(b));
 606         assertTrue(d.reads().contains(c));
 607         testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
 608     }
 609 
 610 
 611     /**
























































 612      * Basic test of Layer containing automatic modules
 613      */
 614     public void testInLayer() throws IOException {
 615         ModuleDescriptor descriptor
 616             = ModuleDescriptor.module("a")
 617                 .requires("b")
 618                 .requires("c")
 619                 .build();
 620 
 621         // b and c are simple JAR files
 622         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 623         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 624         createDummyJarFile(dir.resolve("c.jar"), "q/T2.class");
 625 
 626         // module finder locates a and the modules in the directory
 627         ModuleFinder finder
 628             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
 629                 ModuleFinder.of(dir));
 630 
 631         Configuration parent = Layer.boot().configuration();
 632         Configuration cf = resolve(parent, finder, "a");
 633         assertTrue(cf.modules().size() == 3);
 634 
 635         // each module gets its own loader
 636         Layer layer = Layer.boot().defineModules(cf, mn -> new ClassLoader() { });


 647         assertTrue(c.isNamed());
 648         assertTrue(b.canRead(unnamed));
 649         testsReadsAll(c, layer);
 650     }
 651 
 652 
 653     /**
 654      * Test miscellaneous methods.
 655      */
 656     public void testMisc() throws IOException {
 657         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 658         Path m_jar = createDummyJarFile(dir.resolve("m.jar"), "p/T.class");
 659 
 660         ModuleFinder finder = ModuleFinder.of(m_jar);
 661 
 662         assertTrue(finder.find("m").isPresent());
 663         ModuleDescriptor m = finder.find("m").get().descriptor();
 664 
 665         // test miscellaneous methods
 666         assertTrue(m.isAutomatic());
 667         assertFalse(m.isSynthetic());
 668         assertFalse(m.osName().isPresent());
 669         assertFalse(m.osArch().isPresent());
 670         assertFalse(m.osVersion().isPresent());
 671     }
 672 
 673 
 674     /**
 675      * Invokes parent.resolveRequires to resolve the given root modules.
 676      */
 677     static Configuration resolve(Configuration parent,
 678                                  ModuleFinder finder,
 679                                  String... roots) {
 680         return parent.resolveRequires(finder, ModuleFinder.of(), Set.of(roots));
 681     }
 682 
 683     /**
 684      * Finds a module in the given configuration or its parents, returning
 685      * the module descriptor (or null if not found)
 686      */
 687     static ModuleDescriptor findDescriptor(Configuration cf, String name) {
 688         Optional<ResolvedModule> om = cf.findModule(name);
 689         if (om.isPresent()) {
 690             return om.get().reference().descriptor();
 691         } else {
 692             return null;
 693         }
 694     }
 695 
 696     /**
 697      * Test that a module in a configuration reads all modules in the boot
 698      * configuration.
 699      */
 700     static void testReadAllBootModules(Configuration cf, String mn) {


   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
  27  * @build AutomaticModulesTest ModuleUtils JarUtils
  28  * @run testng AutomaticModulesTest
  29  * @summary Basic tests for automatic modules
  30  */
  31 
  32 import java.io.IOException;
  33 import java.lang.module.Configuration;
  34 import java.lang.module.FindException;
  35 import java.lang.module.ModuleDescriptor;

  36 import java.lang.module.ModuleDescriptor.Requires.Modifier;
  37 import java.lang.module.ModuleFinder;
  38 import java.lang.module.ModuleReference;
  39 import java.lang.module.ResolutionException;
  40 import java.lang.module.ResolvedModule;
  41 import java.lang.reflect.Layer;
  42 import java.lang.reflect.Module;
  43 import java.nio.file.Files;
  44 import java.nio.file.Path;
  45 import java.nio.file.Paths;
  46 import java.util.Optional;
  47 import java.util.Set;
  48 import java.util.jar.Attributes;
  49 import java.util.jar.Manifest;
  50 import java.util.stream.Collectors;
  51 import java.util.stream.Stream;
  52 
  53 import org.testng.annotations.DataProvider;
  54 import org.testng.annotations.Test;
  55 import static org.testng.Assert.*;
  56 
  57 @Test
  58 public class AutomaticModulesTest {
  59 


 120     @Test(dataProvider = "names")
 121     public void testNames(String fn, String mid) throws IOException {
 122         String[] s = mid.split("/");
 123         String mn = s[0];
 124         String vs = (s.length == 2) ? s[1] : null;
 125 
 126         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 127         Path jf = dir.resolve(fn);
 128 
 129         // create empty JAR file
 130         createDummyJarFile(jf);
 131 
 132         // create a ModuleFinder to find modules in the directory
 133         ModuleFinder finder = ModuleFinder.of(dir);
 134 
 135         // a module with the expected name should be found
 136         Optional<ModuleReference> mref = finder.find(mn);
 137         assertTrue(mref.isPresent(), mn + " not found");
 138 
 139         ModuleDescriptor descriptor = mref.get().descriptor();
 140         assertTrue(descriptor.isAutomatic());
 141         assertEquals(descriptor.name(), mn);
 142         if (vs == null) {
 143             assertFalse(descriptor.version().isPresent());
 144         } else {
 145             assertEquals(descriptor.version().get().toString(), vs);
 146         }
 147     }
 148 
 149 
 150     /**
 151      * Test impossible mapping of JAR files to modules names
 152      */
 153     @Test(dataProvider = "badnames", expectedExceptions = FindException.class)
 154     public void testBadNames(String fn, String ignore) throws IOException {
 155         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 156         Path jf = dir.resolve(fn);
 157 
 158         // create empty JAR file
 159         createDummyJarFile(jf);
 160 
 161         // should throw FindException
 162         ModuleFinder.of(dir).findAll();
 163     }
 164 
 165 
 166     /**
 167      * Test all packages are exported
 168      */
 169     public void testPackages() throws IOException {
 170         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 171         createDummyJarFile(dir.resolve("m.jar"),
 172                            "p/C1.class", "p/C2.class", "q/C1.class");
 173 
 174         ModuleFinder finder = ModuleFinder.of(dir);
 175         Optional<ModuleReference> mref = finder.find("m");
 176         assertTrue(mref.isPresent(), "m not found");
 177 
 178         ModuleDescriptor descriptor = mref.get().descriptor();
 179         assertTrue(descriptor.isAutomatic());
 180 
 181         assertTrue(descriptor.packages().size() == 2);
 182         assertTrue(descriptor.packages().contains("p"));
 183         assertTrue(descriptor.packages().contains("q"));
 184 
 185         assertTrue(descriptor.exports().isEmpty());
 186         assertTrue(descriptor.opens().isEmpty());




 187     }
 188 
 189     /**
 190      * Test class files in JAR file where the entry does not correspond to a
 191      * legal package name.
 192      */
 193     public void testBadPackage() throws IOException {
 194         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 195         createDummyJarFile(dir.resolve("m.jar"), "p/C1.class", "p-/C2.class");
 196 
 197         ModuleFinder finder = ModuleFinder.of(dir);
 198         Optional<ModuleReference> mref = finder.find("m");
 199         assertTrue(mref.isPresent(), "m not found");
 200 
 201         ModuleDescriptor descriptor = mref.get().descriptor();
 202         assertTrue(descriptor.isAutomatic());
 203 
 204         assertTrue(descriptor.packages().size() == 1);
 205         assertTrue(descriptor.packages().contains("p"));
 206 
 207         assertTrue(descriptor.exports().isEmpty());
 208         assertTrue(descriptor.opens().isEmpty());



 209     }
 210 
 211     /**
 212      * Test non-class resources in a JAR file.
 213      */
 214     public void testNonClassResources() throws IOException {
 215         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 216         createDummyJarFile(dir.resolve("m.jar"),
 217                 "LICENSE",
 218                 "README",
 219                 "WEB-INF/tags",
 220                 "p/Type.class",
 221                 "p/resources/m.properties");
 222 
 223         ModuleFinder finder = ModuleFinder.of(dir);
 224         Optional<ModuleReference> mref = finder.find("m");
 225         assertTrue(mref.isPresent(), "m not found");
 226 
 227         ModuleDescriptor descriptor = mref.get().descriptor();
 228         assertTrue(descriptor.isAutomatic());
 229 
 230         assertTrue(descriptor.packages().size() == 1);
 231         assertTrue(descriptor.packages().contains("p"));

 232     }
 233 
 234     /**
 235      * Test .class file in unnamed package (top-level directory)
 236      */
 237     @Test(expectedExceptions = FindException.class)
 238     public void testClassInUnnamedPackage() throws IOException {
 239         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 240         createDummyJarFile(dir.resolve("m.jar"), "Mojo.class");
 241         ModuleFinder finder = ModuleFinder.of(dir);
 242         finder.findAll();
 243     }
 244 
 245     /**
 246      * Test JAR file with META-INF/services configuration file
 247      */
 248     public void testServicesConfiguration() throws IOException {
 249         String service = "p.S";
 250         String provider = "p.S1";
 251 
 252         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
 253 
 254         // provider class
 255         Path providerClass = tmpdir.resolve(provider.replace('.', '/') + ".class");
 256         Files.createDirectories(providerClass.getParent());
 257         Files.createFile(providerClass);
 258 
 259         // services configuration file
 260         Path services = tmpdir.resolve("META-INF").resolve("services");
 261         Files.createDirectories(services);
 262         Files.write(services.resolve(service), Set.of(provider));
 263 
 264         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 265         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 266 
 267         ModuleFinder finder = ModuleFinder.of(dir);
 268 
 269         Optional<ModuleReference> mref = finder.find("m");
 270         assertTrue(mref.isPresent(), "m not found");
 271 
 272         ModuleDescriptor descriptor = mref.get().descriptor();
 273         assertTrue(descriptor.provides().size() == 1);
 274         ModuleDescriptor.Provides provides = descriptor.provides().iterator().next();
 275         assertEquals(provides.service(), service);
 276         assertTrue(provides.providers().size() == 1);
 277         assertTrue(provides.providers().contains((provider)));
 278     }
 279 
 280 
 281     // META-INF/services files that don't map to legal service names
 282     @DataProvider(name = "badservices")
 283     public Object[][] createBadServices() {


 301         Path services = tmpdir.resolve("META-INF").resolve("services");
 302         Files.createDirectories(services);
 303         Files.write(services.resolve(service), Set.of(provider));
 304         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 305         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 306 
 307         Optional<ModuleReference> omref = ModuleFinder.of(dir).find("m");
 308         assertTrue(omref.isPresent());
 309         ModuleDescriptor descriptor = omref.get().descriptor();
 310         assertTrue(descriptor.provides().isEmpty());
 311     }
 312 
 313 
 314     // META-INF/services configuration file entries that are not legal
 315     @DataProvider(name = "badproviders")
 316     public Object[][] createBadProviders() {
 317         return new Object[][] {
 318 
 319                 // service type         provider type
 320                 { "p.S",                "-" },
 321                 { "p.S",                "p..S1" },
 322                 { "p.S",                "S1." },
 323         };
 324     }
 325 
 326     /**
 327      * Test JAR file with META-INF/services configuration file with bad
 328      * values or names.
 329      */
 330     @Test(dataProvider = "badproviders", expectedExceptions = FindException.class)
 331     public void testBadProviderNames(String service, String provider)
 332         throws IOException
 333     {
 334         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
 335 
 336         // provider class
 337         Path providerClass = tmpdir.resolve(provider.replace('.', '/') + ".class");
 338         Files.createDirectories(providerClass.getParent());
 339         Files.createFile(providerClass);
 340 
 341         // services configuration file
 342         Path services = tmpdir.resolve("META-INF").resolve("services");
 343         Files.createDirectories(services);
 344         Files.write(services.resolve(service), Set.of(provider));
 345 
 346         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 347         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 348 
 349         // should throw FindException
 350         ModuleFinder.of(dir).findAll();
 351     }
 352 
 353     /**
 354      * Test JAR file with META-INF/services configuration file listing a
 355      * provider that is not in the module.
 356      */
 357     @Test(expectedExceptions = FindException.class)
 358     public void testMissingProviderPackage() throws IOException {
 359         Path tmpdir = Files.createTempDirectory(USER_DIR, "tmp");
 360 
 361         // services configuration file
 362         Path services = tmpdir.resolve("META-INF").resolve("services");
 363         Files.createDirectories(services);
 364         Files.write(services.resolve("p.S"), Set.of("q.P"));
 365 
 366         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 367         JarUtils.createJarFile(dir.resolve("m.jar"), tmpdir);
 368 
 369         // should throw FindException
 370         ModuleFinder.of(dir).findAll();
 371     }
 372 
 373 
 374     /**
 375      * Test that a JAR file with a Main-Class attribute results
 376      * in a module with a main class.
 377      */
 378     public void testMainClass() throws IOException {
 379         String mainClass = "p.Main";
 380 
 381         Manifest man = new Manifest();
 382         Attributes attrs = man.getMainAttributes();
 383         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 384         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 385 
 386         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 387         String entry = mainClass.replace('.', '/') + ".class";
 388         createDummyJarFile(dir.resolve("m.jar"), man, entry);
 389 
 390         ModuleFinder finder = ModuleFinder.of(dir);
 391 
 392         Configuration parent = Layer.boot().configuration();
 393         Configuration cf = resolve(parent, finder, "m");
 394 
 395         ModuleDescriptor descriptor = findDescriptor(cf, "m");
 396 
 397         assertTrue(descriptor.mainClass().isPresent());
 398         assertEquals(descriptor.mainClass().get(), mainClass);
 399     }
 400 
 401 
 402     // Main-Class files that do not map to a legal qualified type name
 403     @DataProvider(name = "badmainclass")
 404     public Object[][] createBadMainClass() {
 405         return new Object[][]{
 406 
 407             { "Main",        null },
 408             { "p..Main",     null },
 409             { "p-.Main",     null },

 410 
 411         };
 412     }
 413 
 414     /**
 415      * Test that a JAR file with a Main-Class attribute that is not a qualified
 416      * type name.
 417      */
 418     @Test(dataProvider = "badmainclass", expectedExceptions = FindException.class)
 419     public void testBadMainClass(String mainClass, String ignore) throws IOException {
 420         Manifest man = new Manifest();
 421         Attributes attrs = man.getMainAttributes();
 422         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 423         attrs.put(Attributes.Name.MAIN_CLASS, mainClass);
 424 
 425         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 426         String entry = mainClass.replace('.', '/') + ".class";
 427         createDummyJarFile(dir.resolve("m.jar"), man, entry);
 428 
 429         // should throw FindException
 430         ModuleFinder.of(dir).findAll();
 431     }
 432 
 433     /**
 434      * Test that a JAR file with a Main-Class attribute that is not in the module
 435      */
 436     @Test(expectedExceptions = FindException.class)
 437     public void testMissingMainClassPackage() throws IOException {
 438         Manifest man = new Manifest();
 439         Attributes attrs = man.getMainAttributes();
 440         attrs.put(Attributes.Name.MANIFEST_VERSION, "1.0.0");
 441         attrs.put(Attributes.Name.MAIN_CLASS, "p.Main");
 442 
 443         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 444         createDummyJarFile(dir.resolve("m.jar"), man);
 445 
 446         // should throw FindException
 447         ModuleFinder.of(dir).findAll();
 448     }
 449 
 450 
 451     /**
 452      * Basic test of a configuration created with automatic modules.
 453      *   a requires b*
 454      *   a requires c*
 455      *   b*
 456      *   c*
 457      */
 458     public void testConfiguration1() throws Exception {
 459         ModuleDescriptor descriptor1
 460             = ModuleDescriptor.newModule("a")
 461                 .requires("b")
 462                 .requires("c")
 463                 .requires("java.base")
 464                 .build();
 465 
 466         // b and c are automatic modules
 467         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 468         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 469         createDummyJarFile(dir.resolve("c.jar"), "q/T.class");
 470 
 471         // module finder locates a and the modules in the directory
 472         ModuleFinder finder
 473             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1),
 474                 ModuleFinder.of(dir));
 475 
 476         Configuration parent = Layer.boot().configuration();
 477         Configuration cf = resolve(parent, finder, "a");
 478 
 479         assertTrue(cf.modules().size() == 3);
 480         assertTrue(cf.findModule("a").isPresent());


 500 
 501         assertTrue(b.reads().contains(a));
 502         assertTrue(b.reads().contains(c));
 503         testReadAllBootModules(cf, "b");  // b reads all modules in boot layer
 504 
 505         assertTrue(c.reads().contains(a));
 506         assertTrue(c.reads().contains(b));
 507         testReadAllBootModules(cf, "c");  // c reads all modules in boot layer
 508 
 509     }
 510 
 511     /**
 512      * Basic test of a configuration created with automatic modules
 513      *   a requires b
 514      *   b requires c*
 515      *   c*
 516      *   d*
 517      */
 518     public void testInConfiguration2() throws IOException {
 519         ModuleDescriptor descriptor1
 520             = ModuleDescriptor.newModule("a")
 521                 .requires("b")
 522                 .requires("java.base")
 523                 .build();
 524 
 525         ModuleDescriptor descriptor2
 526             = ModuleDescriptor.newModule("b")
 527                 .requires("c")
 528                 .requires("java.base")
 529                 .build();
 530 
 531         // c and d are automatic modules
 532         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 533         createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
 534         createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 535 
 536         // module finder locates a and the modules in the directory
 537         ModuleFinder finder
 538             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
 539                                    ModuleFinder.of(dir));
 540 
 541         Configuration parent = Layer.boot().configuration();
 542         Configuration cf = resolve(parent, finder, "a", "d");
 543 
 544         assertTrue(cf.modules().size() == 4);
 545         assertTrue(cf.findModule("a").isPresent());
 546         assertTrue(cf.findModule("b").isPresent());


 573         assertTrue(c.reads().contains(b));
 574         assertTrue(c.reads().contains(d));
 575         testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 576 
 577         assertTrue(d.reads().contains(a));
 578         assertTrue(d.reads().contains(b));
 579         assertTrue(d.reads().contains(c));
 580         testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
 581     }
 582 
 583 
 584     /**
 585      * Basic test of a configuration created with automatic modules
 586      *   a requires b
 587      *   b requires transitive c*
 588      *   c*
 589      *   d*
 590      */
 591     public void testInConfiguration3() throws IOException {
 592         ModuleDescriptor descriptor1
 593             = ModuleDescriptor.newModule("a")
 594                 .requires("b")
 595                 .requires("java.base")
 596                 .build();
 597 
 598         ModuleDescriptor descriptor2
 599             = ModuleDescriptor.newModule("b")
 600                 .requires(Set.of(Modifier.TRANSITIVE), "c")
 601                 .requires("java.base")
 602                 .build();
 603 
 604         // c and d are automatic modules
 605         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 606         createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
 607         createDummyJarFile(dir.resolve("d.jar"), "q/T.class");
 608 
 609         // module finder locates a and the modules in the directory
 610         ModuleFinder finder
 611             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor1, descriptor2),
 612                 ModuleFinder.of(dir));
 613 
 614         Configuration parent = Layer.boot().configuration();
 615         Configuration cf = resolve(parent, finder, "a", "d");
 616 
 617         assertTrue(cf.modules().size() == 4);
 618         assertTrue(cf.findModule("a").isPresent());
 619         assertTrue(cf.findModule("b").isPresent());


 644         assertTrue(b.reads().contains(d));
 645         assertTrue(b.reads().contains(base));
 646 
 647         assertTrue(reads(cf, "b", "c"));
 648         assertTrue(reads(cf, "b", "d"));
 649         assertTrue(reads(cf, "b", "java.base"));
 650 
 651         assertTrue(c.reads().contains(a));
 652         assertTrue(c.reads().contains(b));
 653         assertTrue(c.reads().contains(d));
 654         testReadAllBootModules(cf, "c");   // c reads all modules in boot layer
 655 
 656         assertTrue(d.reads().contains(a));
 657         assertTrue(d.reads().contains(b));
 658         assertTrue(d.reads().contains(c));
 659         testReadAllBootModules(cf, "d");    // d reads all modules in boot layer
 660     }
 661 
 662 
 663     /**
 664      * Basic test of a configuration created with automatic modules
 665      *   a requires b* and c*
 666      *   b* contains p
 667      *   c* contains p
 668      */
 669     @Test(expectedExceptions = { ResolutionException.class })
 670     public void testDuplicateSuppliers1() throws IOException {
 671         ModuleDescriptor descriptor
 672             = ModuleDescriptor.newModule("a")
 673                 .requires("b")
 674                 .requires("c")
 675                 .build();
 676 
 677         // c and d are automatic modules with the same package
 678         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 679         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 680         createDummyJarFile(dir.resolve("c.jar"), "p/T.class");
 681 
 682         // module finder locates 'a' and the modules in the directory
 683         ModuleFinder finder
 684             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
 685                                    ModuleFinder.of(dir));
 686 
 687         Configuration parent = Layer.boot().configuration();
 688         resolve(parent, finder, "a");
 689     }
 690 
 691 
 692     /**
 693      * Basic test of a configuration created with automatic modules
 694      *   a contains p, requires b*
 695      *   b* contains p
 696      */
 697     @Test(expectedExceptions = { ResolutionException.class })
 698     public void testDuplicateSuppliers2() throws IOException {
 699         ModuleDescriptor descriptor
 700             = ModuleDescriptor.newModule("a")
 701                 .packages(Set.of("p"))
 702                 .requires("b")
 703                 .build();
 704 
 705         // c and d are automatic modules with the same package
 706         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 707         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 708 
 709         // module finder locates 'a' and the modules in the directory
 710         ModuleFinder finder
 711             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
 712                                    ModuleFinder.of(dir));
 713 
 714         Configuration parent = Layer.boot().configuration();
 715         resolve(parent, finder, "a");
 716     }
 717 
 718 
 719     /**
 720      * Basic test of Layer containing automatic modules
 721      */
 722     public void testInLayer() throws IOException {
 723         ModuleDescriptor descriptor
 724             = ModuleDescriptor.newModule("a")
 725                 .requires("b")
 726                 .requires("c")
 727                 .build();
 728 
 729         // b and c are simple JAR files
 730         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 731         createDummyJarFile(dir.resolve("b.jar"), "p/T.class");
 732         createDummyJarFile(dir.resolve("c.jar"), "q/T2.class");
 733 
 734         // module finder locates a and the modules in the directory
 735         ModuleFinder finder
 736             = ModuleFinder.compose(ModuleUtils.finderOf(descriptor),
 737                 ModuleFinder.of(dir));
 738 
 739         Configuration parent = Layer.boot().configuration();
 740         Configuration cf = resolve(parent, finder, "a");
 741         assertTrue(cf.modules().size() == 3);
 742 
 743         // each module gets its own loader
 744         Layer layer = Layer.boot().defineModules(cf, mn -> new ClassLoader() { });


 755         assertTrue(c.isNamed());
 756         assertTrue(b.canRead(unnamed));
 757         testsReadsAll(c, layer);
 758     }
 759 
 760 
 761     /**
 762      * Test miscellaneous methods.
 763      */
 764     public void testMisc() throws IOException {
 765         Path dir = Files.createTempDirectory(USER_DIR, "mods");
 766         Path m_jar = createDummyJarFile(dir.resolve("m.jar"), "p/T.class");
 767 
 768         ModuleFinder finder = ModuleFinder.of(m_jar);
 769 
 770         assertTrue(finder.find("m").isPresent());
 771         ModuleDescriptor m = finder.find("m").get().descriptor();
 772 
 773         // test miscellaneous methods
 774         assertTrue(m.isAutomatic());
 775         assertFalse(m.modifiers().contains(ModuleDescriptor.Modifier.SYNTHETIC));
 776         assertFalse(m.osName().isPresent());
 777         assertFalse(m.osArch().isPresent());
 778         assertFalse(m.osVersion().isPresent());
 779     }
 780 
 781 
 782     /**
 783      * Invokes parent.resolve to resolve the given root modules.
 784      */
 785     static Configuration resolve(Configuration parent,
 786                                  ModuleFinder finder,
 787                                  String... roots) {
 788         return parent.resolve(finder, ModuleFinder.of(), Set.of(roots));
 789     }
 790 
 791     /**
 792      * Finds a module in the given configuration or its parents, returning
 793      * the module descriptor (or null if not found)
 794      */
 795     static ModuleDescriptor findDescriptor(Configuration cf, String name) {
 796         Optional<ResolvedModule> om = cf.findModule(name);
 797         if (om.isPresent()) {
 798             return om.get().reference().descriptor();
 799         } else {
 800             return null;
 801         }
 802     }
 803 
 804     /**
 805      * Test that a module in a configuration reads all modules in the boot
 806      * configuration.
 807      */
 808     static void testReadAllBootModules(Configuration cf, String mn) {


< prev index next >