1 /*
   2  * Copyright (c) 2013, 2024, 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  * @bug 8142968 8158456 8298875
  27  * @modules java.base/jdk.internal.access
  28  *          java.base/jdk.internal.module
  29  * @library /test/lib
  30  * @build jdk.test.lib.util.ModuleInfoWriter
  31  * @run testng ModuleDescriptorTest
  32  * @summary Basic test for java.lang.module.ModuleDescriptor and its builder
  33  */
  34 
  35 import java.io.ByteArrayOutputStream;
  36 import java.io.IOException;
  37 import java.io.InputStream;
  38 import java.lang.module.InvalidModuleDescriptorException;
  39 import java.lang.module.ModuleDescriptor;
  40 import java.lang.module.ModuleDescriptor.Builder;
  41 import java.lang.module.ModuleDescriptor.Exports;
  42 import java.lang.module.ModuleDescriptor.Opens;
  43 import java.lang.module.ModuleDescriptor.Requires;
  44 import java.lang.module.ModuleDescriptor.Provides;
  45 import java.lang.module.ModuleDescriptor.Requires.Modifier;
  46 import java.lang.module.ModuleDescriptor.Version;
  47 import java.nio.ByteBuffer;
  48 import java.util.ArrayList;
  49 import java.util.Collections;
  50 import java.util.EnumSet;
  51 import java.util.HashSet;
  52 import java.util.Iterator;
  53 import java.util.List;
  54 import java.util.Objects;
  55 import java.util.Set;
  56 import java.util.stream.Collectors;
  57 
  58 import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
  59 
  60 import jdk.internal.access.JavaLangModuleAccess;
  61 import jdk.internal.access.SharedSecrets;
  62 import java.lang.classfile.ClassFile;
  63 import java.lang.classfile.ClassFileVersion;
  64 import java.lang.classfile.ClassTransform;
  65 import java.lang.classfile.attribute.ModuleAttribute;
  66 import java.lang.constant.PackageDesc;
  67 import java.lang.constant.ModuleDesc;
  68 import jdk.test.lib.util.ModuleInfoWriter;
  69 import org.testng.annotations.DataProvider;
  70 import org.testng.annotations.Test;
  71 import static org.testng.Assert.*;
  72 
  73 @Test
  74 public class ModuleDescriptorTest {
  75     private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
  76 
  77     @DataProvider(name = "invalidNames")
  78     public Object[][] invalidNames() {
  79         return new Object[][]{
  80 
  81             { null,             null },
  82             { "1",              null },
  83             { "1foo",           null },
  84             { ".foo",           null },
  85             { "foo.",           null },
  86             { "[foo]",          null },
  87             { "foo.1",          null },
  88             { "1foo.bar",       null },
  89             { "foo.1bar",       null },
  90             { "foo.[bar]",      null },
  91             { "foo..bar",       null },
  92             { "foo.bar.1",      null },
  93             { "foo.bar.1gus",   null },
  94             { "foo.bar.[gus]",  null },
  95 
  96             { "class",          null },
  97             { "interface",      null },
  98             { "true",           null },
  99             { "false",          null },
 100             { "null",           null },
 101 
 102             { "x.class",        null },
 103             { "x.interface",    null },
 104             { "x.true",         null },
 105             { "x.false",        null },
 106             { "x.null",         null },
 107 
 108             { "class.x",        null },
 109             { "interface.x",    null },
 110             { "true.x",         null },
 111             { "false.x",        null },
 112             { "null.x",         null },
 113 
 114             { "x.class.x",      null },
 115             { "x.interface.x",  null },
 116             { "x.true.x",       null },
 117             { "x.false.x",      null },
 118             { "x.null.x",       null },
 119 
 120             { "_",              null },
 121 
 122         };
 123     }
 124 
 125 
 126     // requires
 127 
 128     private Requires requires(Set<Modifier> mods, String mn) {
 129         return requires(mods, mn, null);
 130     }
 131 
 132     private Requires requires(Set<Modifier> mods, String mn, Version v) {
 133         Builder builder = ModuleDescriptor.newModule("m");
 134         if (v == null) {
 135             builder.requires(mods, mn);
 136         } else {
 137             builder.requires(mods, mn, v);
 138         }
 139         Set<Requires> requires = builder.build().requires();
 140         assertTrue(requires.size() == 2);
 141         Iterator<Requires> iterator = requires.iterator();
 142         Requires r = iterator.next();
 143         if (r.name().equals("java.base")) {
 144             r = iterator.next();
 145         } else {
 146             Requires other = iterator.next();
 147             assertEquals(other.name(), "java.base");
 148         }
 149         return r;
 150     }
 151 
 152     private Requires requires(String mn) {
 153         return requires(Collections.emptySet(), mn);
 154     }
 155 
 156     public void testRequiresWithRequires() {
 157         Requires r1 = requires("foo");
 158         ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").requires(r1).build();
 159         assertEquals(descriptor.requires().size(), 2);
 160         var iterator = descriptor.requires().iterator();
 161         Requires r2 = iterator.next();
 162         if (r2.name().equals("java.base")) {
 163             r2 = iterator.next();
 164         }
 165         assertEquals(r1, r2);
 166     }
 167 
 168     public void testRequiresWithNoModifiers() {
 169         Requires r = requires(EnumSet.noneOf(Requires.Modifier.class), "foo");
 170         assertEquals(r, r);
 171         assertTrue(r.compareTo(r) == 0);
 172         assertTrue(r.modifiers().isEmpty());
 173         assertEquals(r.name(), "foo");
 174         assertFalse(r.compiledVersion().isPresent());
 175     }
 176 
 177     public void testRequiresWithOneModifier() {
 178         Requires r = requires(EnumSet.of(TRANSITIVE), "foo");
 179         assertEquals(r, r);
 180         assertTrue(r.compareTo(r) == 0);
 181         assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE));
 182         assertEquals(r.name(), "foo");
 183         assertFalse(r.compiledVersion().isPresent());
 184     }
 185 
 186     public void testRequiresWithTwoModifiers() {
 187         Requires r = requires(EnumSet.of(TRANSITIVE, SYNTHETIC), "foo");
 188         assertEquals(r, r);
 189         assertTrue(r.compareTo(r) == 0);
 190         assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, SYNTHETIC));
 191         assertEquals(r.name(), "foo");
 192         assertFalse(r.compiledVersion().isPresent());
 193     }
 194 
 195     public void testRequiresWithAllModifiers() {
 196         Requires r = requires(EnumSet.allOf(Modifier.class), "foo");
 197         assertEquals(r, r);
 198         assertTrue(r.compareTo(r) == 0);
 199         assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, STATIC, SYNTHETIC, MANDATED));
 200         assertEquals(r.name(), "foo");
 201         assertFalse(r.compiledVersion().isPresent());
 202     }
 203 
 204     public void testRequiresWithCompiledVersion() {
 205         Version v = Version.parse("1.0");
 206         Requires r = requires(Set.of(), "foo", v);
 207         assertEquals(r, r);
 208         assertTrue(r.compareTo(r) == 0);
 209         assertEquals(r.modifiers(), Set.of());
 210         assertEquals(r.name(), "foo");
 211         assertTrue(r.compiledVersion().isPresent());
 212         assertEquals(r.compiledVersion().get().toString(), "1.0");
 213     }
 214 
 215     @Test(expectedExceptions = IllegalStateException.class)
 216     public void testRequiresWithDuplicatesRequires() {
 217         Requires r = requires("foo");
 218         ModuleDescriptor.newModule("m").requires(r).requires(r);
 219     }
 220 
 221     @Test(expectedExceptions = IllegalArgumentException.class)
 222     public void testRequiresSelfWithRequires() {
 223         Requires r = requires("foo");
 224         ModuleDescriptor.newModule("foo").requires(r);
 225     }
 226 
 227     @Test(expectedExceptions = IllegalArgumentException.class)
 228     public void testRequiresSelfWithNoModifier() {
 229         ModuleDescriptor.newModule("m").requires("m");
 230     }
 231 
 232     @Test(expectedExceptions = IllegalArgumentException.class)
 233     public void testRequiresSelfWithOneModifier() {
 234         ModuleDescriptor.newModule("m").requires(Set.of(TRANSITIVE), "m");
 235     }
 236 
 237     @Test(expectedExceptions = IllegalArgumentException.class)
 238     public void testRequiresSelfWithAllModifiers() {
 239         ModuleDescriptor.newModule("m").requires(EnumSet.allOf(Modifier.class), "m");
 240     }
 241 
 242     @Test(dataProvider = "invalidNames",
 243           expectedExceptions = IllegalArgumentException.class )
 244     public void testRequiresWithBadModuleName(String mn, String ignore) {
 245         requires(EnumSet.noneOf(Modifier.class), mn);
 246     }
 247 
 248     @Test(expectedExceptions = NullPointerException.class)
 249     public void testRequiresWithNullRequires() {
 250         ModuleDescriptor.newModule("m").requires((Requires) null);
 251     }
 252 
 253     @Test(expectedExceptions = NullPointerException.class)
 254     public void testRequiresWithNullModifiers() {
 255         ModuleDescriptor.newModule("m").requires(null, "foo");
 256     }
 257 
 258     @Test(expectedExceptions = NullPointerException.class)
 259     public void testRequiresWithNullVersion() {
 260         ModuleDescriptor.newModule("m").requires(Set.of(), "foo", null);
 261     }
 262 
 263     public void testRequiresCompare() {
 264         Requires r1 = requires(EnumSet.noneOf(Modifier.class), "foo");
 265         Requires r2 = requires(EnumSet.noneOf(Modifier.class), "bar");
 266         int n = "foo".compareTo("bar");
 267         assertTrue(r1.compareTo(r2) == n);
 268         assertTrue(r2.compareTo(r1) == -n);
 269     }
 270 
 271     public void testRequiresCompareWithDifferentModifiers() {
 272         Requires r1 = requires(EnumSet.of(TRANSITIVE), "foo");
 273         Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo");
 274         int n = Integer.compare(1 << TRANSITIVE.ordinal(), 1 << SYNTHETIC.ordinal());
 275         assertTrue(r1.compareTo(r2) == n);
 276         assertTrue(r2.compareTo(r1) == -n);
 277     }
 278 
 279     public void testRequiresCompareWithSameModifiers() {
 280         Requires r1 = requires(EnumSet.of(SYNTHETIC), "foo");
 281         Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo");
 282         assertTrue(r1.compareTo(r2) == 0);
 283         assertTrue(r2.compareTo(r1) == 0);
 284     }
 285 
 286     public void testRequiresCompareWithSameCompiledVersion() {
 287         Requires r1 = requires(Set.of(), "foo", Version.parse("2.0"));
 288         Requires r2 = requires(Set.of(), "foo", Version.parse("2.0"));
 289         assertTrue(r1.compareTo(r2) == 0);
 290         assertTrue(r2.compareTo(r1) == 0);
 291     }
 292 
 293     public void testRequiresCompareWithDifferentCompiledVersion() {
 294         Requires r1 = requires(Set.of(), "foo", Version.parse("1.0"));
 295         Requires r2 = requires(Set.of(), "foo", Version.parse("2.0"));
 296         assertTrue(r1.compareTo(r2) < 0);
 297         assertTrue(r2.compareTo(r1) > 0);
 298     }
 299 
 300     public void testRequiresEqualsAndHashCode() {
 301         Requires r1 = requires("foo");
 302         Requires r2 = requires("foo");
 303         assertEquals(r1, r2);
 304         assertTrue(r1.hashCode() == r2.hashCode());
 305 
 306         r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
 307         r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
 308         assertEquals(r1, r2);
 309         assertTrue(r1.hashCode() == r2.hashCode());
 310 
 311         r1 = requires("foo");
 312         r2 = requires("bar");
 313         assertNotEquals(r1, r2);
 314 
 315         r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
 316         r2 = requires(Set.of(), "foo");
 317         assertNotEquals(r1, r2);
 318 
 319         Version v1 = Version.parse("1.0");
 320         r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
 321         r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
 322         assertEquals(r1, r2);
 323         assertTrue(r1.hashCode() == r2.hashCode());
 324 
 325         Version v2 = Version.parse("2.0");
 326         r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
 327         r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v2);
 328         assertNotEquals(r1, r2);
 329     }
 330 
 331     public void testRequiresToString() {
 332         Requires r = requires(EnumSet.noneOf(Modifier.class), "foo");
 333         assertTrue(r.toString().contains("foo"));
 334     }
 335 
 336 
 337     // exports
 338 
 339     private Exports exports(Set<Exports.Modifier> mods, String pn) {
 340         return ModuleDescriptor.newModule("foo")
 341             .exports(mods, pn)
 342             .build()
 343             .exports()
 344             .iterator()
 345             .next();
 346     }
 347 
 348     private Exports exports(String pn) {
 349         return exports(Set.of(), pn);
 350     }
 351 
 352     private Exports exports(Set<Exports.Modifier> mods, String pn, String target) {
 353         return ModuleDescriptor.newModule("foo")
 354             .exports(mods, pn, Set.of(target))
 355             .build()
 356             .exports()
 357             .iterator()
 358             .next();
 359     }
 360 
 361     private Exports exports(String pn, String target) {
 362         return exports(Set.of(), pn, target);
 363     }
 364 
 365 
 366     public void testExportsExports() {
 367         Exports e1 = exports("p");
 368         ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").exports(e1).build();
 369         Exports e2 = descriptor.exports().iterator().next();
 370         assertEquals(e1, e2);
 371     }
 372 
 373     public void testExportsToAll() {
 374         Exports e = exports("p");
 375         assertEquals(e, e);
 376         assertTrue(e.modifiers().isEmpty());
 377         assertEquals(e.source(), "p");
 378         assertFalse(e.isQualified());
 379         assertTrue(e.targets().isEmpty());
 380     }
 381 
 382     public void testExportsToTarget() {
 383         Exports e = exports("p", "bar");
 384         assertEquals(e, e);
 385         assertTrue(e.modifiers().isEmpty());
 386         assertEquals(e.source(), "p");
 387         assertTrue(e.isQualified());
 388         assertTrue(e.targets().size() == 1);
 389         assertTrue(e.targets().contains("bar"));
 390     }
 391 
 392     public void testExportsToTargets() {
 393         Set<String> targets = new HashSet<>();
 394         targets.add("bar");
 395         targets.add("gus");
 396         Exports e
 397             = ModuleDescriptor.newModule("foo")
 398                 .exports("p", targets)
 399                 .build()
 400                 .exports()
 401                 .iterator()
 402                 .next();
 403         assertEquals(e, e);
 404         assertTrue(e.modifiers().isEmpty());
 405         assertEquals(e.source(), "p");
 406         assertTrue(e.isQualified());
 407         assertTrue(e.targets().size() == 2);
 408         assertTrue(e.targets().contains("bar"));
 409         assertTrue(e.targets().contains("gus"));
 410     }
 411 
 412     public void testExportsToAllWithModifier() {
 413         Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
 414         assertEquals(e, e);
 415         assertTrue(e.modifiers().size() == 1);
 416         assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
 417         assertEquals(e.source(), "p");
 418         assertFalse(e.isQualified());
 419         assertTrue(e.targets().isEmpty());
 420     }
 421 
 422     public void testExportsToTargetWithModifier() {
 423         Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p", "bar");
 424         assertEquals(e, e);
 425         assertTrue(e.modifiers().size() == 1);
 426         assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
 427         assertEquals(e.source(), "p");
 428         assertTrue(e.isQualified());
 429         assertTrue(e.targets().size() == 1);
 430         assertTrue(e.targets().contains("bar"));
 431     }
 432 
 433     @Test(expectedExceptions = IllegalStateException.class)
 434     public void testExportsWithDuplicate1() {
 435         Exports e = exports("p");
 436         ModuleDescriptor.newModule("foo").exports(e).exports(e);
 437     }
 438 
 439     @Test(expectedExceptions = IllegalStateException.class)
 440     public void testExportsWithDuplicate2() {
 441         ModuleDescriptor.newModule("foo").exports("p").exports("p");
 442     }
 443 
 444     @Test(expectedExceptions = IllegalArgumentException.class )
 445     public void testExportsWithEmptySet() {
 446         ModuleDescriptor.newModule("foo").exports("p", Collections.emptySet());
 447     }
 448 
 449     @Test(dataProvider = "invalidNames",
 450           expectedExceptions = IllegalArgumentException.class )
 451     public void testExportsWithBadName(String pn, String ignore) {
 452         ModuleDescriptor.newModule("foo").exports(pn);
 453     }
 454 
 455     @Test(expectedExceptions = NullPointerException.class )
 456     public void testExportsWithNullExports() {
 457         ModuleDescriptor.newModule("foo").exports((Exports) null);
 458     }
 459 
 460     @Test(expectedExceptions = NullPointerException.class )
 461     public void testExportsWithNullTargets() {
 462         ModuleDescriptor.newModule("foo").exports("p", (Set<String>) null);
 463     }
 464 
 465     public void testExportsCompare() {
 466         Exports e1 = exports("p");
 467         Exports e2 = exports("p");
 468         assertEquals(e1, e2);
 469         assertTrue(e1.hashCode() == e2.hashCode());
 470         assertTrue(e1.compareTo(e2) == 0);
 471         assertTrue(e2.compareTo(e1) == 0);
 472     }
 473 
 474     public void testExportsCompareWithSameModifiers() {
 475         Exports e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
 476         Exports e2 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
 477         assertEquals(e1, e2);
 478         assertTrue(e1.hashCode() == e2.hashCode());
 479         assertTrue(e1.compareTo(e2) == 0);
 480         assertTrue(e2.compareTo(e1) == 0);
 481     }
 482 
 483     public void testExportsCompareWithDifferentModifiers() {
 484         Exports e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
 485         Exports e2 = exports("p");
 486         assertNotEquals(e1, e2);
 487         assertTrue(e1.compareTo(e2) == 1);
 488         assertTrue(e2.compareTo(e1) == -1);
 489     }
 490 
 491     public void testExportsCompareWithSameTargets() {
 492         Exports e1 = exports("p", "x");
 493         Exports e2 = exports("p", "x");
 494         assertEquals(e1, e2);
 495         assertTrue(e1.hashCode() == e2.hashCode());
 496         assertTrue(e1.compareTo(e2) == 0);
 497         assertTrue(e2.compareTo(e1) == 0);
 498     }
 499 
 500     public void testExportsCompareWithDifferentTargets() {
 501         Exports e1 = exports("p", "y");
 502         Exports e2 = exports("p", "x");
 503         assertNotEquals(e1, e2);
 504         assertTrue(e1.compareTo(e2) == 1);
 505         assertTrue(e2.compareTo(e1) == -1);
 506     }
 507 
 508     public void testExportsToString() {
 509         String s = ModuleDescriptor.newModule("foo")
 510             .exports("p1", Set.of("bar"))
 511             .build()
 512             .exports()
 513             .iterator()
 514             .next()
 515             .toString();
 516         assertTrue(s.contains("p1"));
 517         assertTrue(s.contains("bar"));
 518     }
 519 
 520 
 521     // opens
 522 
 523     private Opens opens(Set<Opens.Modifier> mods, String pn) {
 524         return ModuleDescriptor.newModule("foo")
 525                 .opens(mods, pn)
 526                 .build()
 527                 .opens()
 528                 .iterator()
 529                 .next();
 530     }
 531 
 532     private Opens opens(String pn) {
 533         return opens(Set.of(), pn);
 534     }
 535 
 536     private Opens opens(Set<Opens.Modifier> mods, String pn, String target) {
 537         return ModuleDescriptor.newModule("foo")
 538                 .opens(mods, pn, Set.of(target))
 539                 .build()
 540                 .opens()
 541                 .iterator()
 542                 .next();
 543     }
 544 
 545     private Opens opens(String pn, String target) {
 546         return opens(Set.of(), pn, target);
 547     }
 548 
 549     public void testOpensOpens() {
 550         Opens o1 = opens("p");
 551         ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").opens(o1).build();
 552         Opens o2 = descriptor.opens().iterator().next();
 553         assertEquals(o1, o2);
 554     }
 555 
 556     public void testOpensToAll() {
 557         Opens o = opens("p");
 558         assertEquals(o, o);
 559         assertTrue(o.modifiers().isEmpty());
 560         assertEquals(o.source(), "p");
 561         assertFalse(o.isQualified());
 562         assertTrue(o.targets().isEmpty());
 563     }
 564 
 565 
 566     public void testOpensToTarget() {
 567         Opens o = opens("p", "bar");
 568         assertEquals(o, o);
 569         assertTrue(o.modifiers().isEmpty());
 570         assertEquals(o.source(), "p");
 571         assertTrue(o.isQualified());
 572         assertTrue(o.targets().size() == 1);
 573         assertTrue(o.targets().contains("bar"));
 574     }
 575 
 576     public void testOpensToTargets() {
 577         Set<String> targets = new HashSet<>();
 578         targets.add("bar");
 579         targets.add("gus");
 580         Opens o = ModuleDescriptor.newModule("foo")
 581                 .opens("p", targets)
 582                 .build()
 583                 .opens()
 584                 .iterator()
 585                 .next();
 586         assertEquals(o, o);
 587         assertTrue(o.modifiers().isEmpty());
 588         assertEquals(o.source(), "p");
 589         assertTrue(o.isQualified());
 590         assertTrue(o.targets().size() == 2);
 591         assertTrue(o.targets().contains("bar"));
 592         assertTrue(o.targets().contains("gus"));
 593     }
 594 
 595     @Test(expectedExceptions = IllegalStateException.class)
 596     public void testOpensWithDuplicate1() {
 597         Opens o = opens("p");
 598         ModuleDescriptor.newModule("foo").opens(o).opens(o);
 599     }
 600 
 601     @Test(expectedExceptions = IllegalStateException.class)
 602     public void testOpensWithDuplicate2() {
 603         ModuleDescriptor.newModule("foo").opens("p").opens("p");
 604     }
 605 
 606     @Test(expectedExceptions = IllegalArgumentException.class )
 607     public void testOpensWithEmptySet() {
 608         ModuleDescriptor.newModule("foo").opens("p", Collections.emptySet());
 609     }
 610 
 611     @Test(dataProvider = "invalidNames",
 612             expectedExceptions = IllegalArgumentException.class )
 613     public void testOpensWithBadName(String pn, String ignore) {
 614         ModuleDescriptor.newModule("foo").opens(pn);
 615     }
 616 
 617     @Test(expectedExceptions = NullPointerException.class )
 618     public void testOpensWithNullExports() {
 619         ModuleDescriptor.newModule("foo").opens((Opens) null);
 620     }
 621 
 622     @Test(expectedExceptions = NullPointerException.class )
 623     public void testOpensWithNullTargets() {
 624         ModuleDescriptor.newModule("foo").opens("p", (Set<String>) null);
 625     }
 626 
 627     public void testOpensCompare() {
 628         Opens o1 = opens("p");
 629         Opens o2 = opens("p");
 630         assertEquals(o1, o2);
 631         assertTrue(o1.hashCode() == o2.hashCode());
 632         assertTrue(o1.compareTo(o2) == 0);
 633         assertTrue(o2.compareTo(o1) == 0);
 634     }
 635 
 636     public void testOpensCompareWithSameModifiers() {
 637         Opens o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
 638         Opens o2 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
 639         assertEquals(o1, o2);
 640         assertTrue(o1.hashCode() == o2.hashCode());
 641         assertTrue(o1.compareTo(o2) == 0);
 642         assertTrue(o2.compareTo(o1) == 0);
 643     }
 644 
 645     public void testOpensCompareWithDifferentModifiers() {
 646         Opens o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
 647         Opens o2 = opens("p");
 648         assertNotEquals(o1, o2);
 649         assertTrue(o1.compareTo(o2) == 1);
 650         assertTrue(o2.compareTo(o1) == -1);
 651     }
 652 
 653     public void testOpensCompareWithSameTargets() {
 654         Opens o1 = opens("p", "x");
 655         Opens o2 = opens("p", "x");
 656         assertEquals(o1, o2);
 657         assertTrue(o1.hashCode() == o2.hashCode());
 658         assertTrue(o1.compareTo(o2) == 0);
 659         assertTrue(o2.compareTo(o1) == 0);
 660     }
 661 
 662     public void testOpensCompareWithDifferentTargets() {
 663         Opens o1 = opens("p", "y");
 664         Opens o2 = opens("p", "x");
 665         assertNotEquals(o1, o2);
 666         assertTrue(o1.compareTo(o2) == 1);
 667         assertTrue(o2.compareTo(o1) == -1);
 668     }
 669 
 670     public void testOpensToString() {
 671         String s = ModuleDescriptor.newModule("foo")
 672                 .opens("p1", Set.of("bar"))
 673                 .build()
 674                 .opens()
 675                 .iterator()
 676                 .next()
 677                 .toString();
 678         assertTrue(s.contains("p1"));
 679         assertTrue(s.contains("bar"));
 680     }
 681 
 682 
 683     // uses
 684 
 685     public void testUses() {
 686         Set<String> uses
 687             = ModuleDescriptor.newModule("foo")
 688                 .uses("p.S")
 689                 .uses("q.S")
 690                 .build()
 691                 .uses();
 692         assertTrue(uses.size() == 2);
 693         assertTrue(uses.contains("p.S"));
 694         assertTrue(uses.contains("q.S"));
 695     }
 696 
 697     @Test(expectedExceptions = IllegalStateException.class)
 698     public void testUsesWithDuplicate() {
 699         ModuleDescriptor.newModule("foo").uses("p.S").uses("p.S");
 700     }
 701 
 702     @Test(expectedExceptions = IllegalArgumentException.class)
 703     public void testUsesWithSimpleIdentifier() {
 704         ModuleDescriptor.newModule("foo").uses("S");
 705     }
 706 
 707     @Test(dataProvider = "invalidNames",
 708           expectedExceptions = IllegalArgumentException.class )
 709     public void testUsesWithBadName(String service, String ignore) {
 710         ModuleDescriptor.newModule("foo").uses(service);
 711     }
 712 
 713 
 714     // provides
 715 
 716     private Provides provides(String st, String pc) {
 717         return ModuleDescriptor.newModule("foo")
 718             .provides(st, List.of(pc))
 719             .build()
 720             .provides()
 721             .iterator()
 722             .next();
 723     }
 724 
 725     private Provides provides(String st, List<String> pns) {
 726         return ModuleDescriptor.newModule("foo")
 727                 .provides(st, pns)
 728                 .build()
 729                 .provides()
 730                 .iterator()
 731                 .next();
 732     }
 733 
 734     public void testProvidesWithProvides() {
 735         Provides p1 = provides("p.S", "q.S1");
 736         ModuleDescriptor descriptor = ModuleDescriptor.newModule("m")
 737                 .provides(p1)
 738                 .build();
 739         Provides p2 = descriptor.provides().iterator().next();
 740         assertEquals(p1, p2);
 741     }
 742 
 743 
 744     public void testProvides() {
 745         Set<Provides> set = ModuleDescriptor.newModule("foo")
 746                 .provides("p.S", List.of("q.P1", "q.P2"))
 747                 .build()
 748                 .provides();
 749         assertTrue(set.size() == 1);
 750 
 751         Provides p = set.iterator().next();
 752         assertEquals(p, p);
 753         assertEquals(p.service(), "p.S");
 754         assertTrue(p.providers().size() == 2);
 755         assertEquals(p.providers().get(0), "q.P1");
 756         assertEquals(p.providers().get(1), "q.P2");
 757     }
 758 
 759     @Test(expectedExceptions = IllegalStateException.class )
 760     public void testProvidesWithDuplicateProvides() {
 761         Provides p = provides("p.S", "q.S2");
 762         ModuleDescriptor.newModule("m").provides("p.S", List.of("q.S1")).provides(p);
 763     }
 764 
 765     @Test(expectedExceptions = IllegalArgumentException.class )
 766     public void testProvidesWithEmptySet() {
 767         ModuleDescriptor.newModule("foo").provides("p.Service", Collections.emptyList());
 768     }
 769 
 770     @Test(expectedExceptions = IllegalArgumentException.class )
 771     public void testProvidesWithSimpleIdentifier1() {
 772         ModuleDescriptor.newModule("foo").provides("S", List.of("q.P"));
 773     }
 774 
 775     @Test(expectedExceptions = IllegalArgumentException.class )
 776     public void testProvidesWithSimpleIdentifier2() {
 777         ModuleDescriptor.newModule("foo").provides("p.S", List.of("P"));
 778     }
 779 
 780     @Test(dataProvider = "invalidNames",
 781           expectedExceptions = IllegalArgumentException.class )
 782     public void testProvidesWithBadService(String service, String ignore) {
 783         ModuleDescriptor.newModule("foo").provides(service, List.of("p.Provider"));
 784     }
 785 
 786     @Test(dataProvider = "invalidNames",
 787           expectedExceptions = IllegalArgumentException.class )
 788     public void testProvidesWithBadProvider(String provider, String ignore) {
 789         List<String> names = new ArrayList<>(); // allows nulls
 790         names.add(provider);
 791         ModuleDescriptor.newModule("foo").provides("p.Service", names);
 792     }
 793 
 794     @Test(expectedExceptions = NullPointerException.class )
 795     public void testProvidesWithNullProvides() {
 796         ModuleDescriptor.newModule("foo").provides((Provides) null);
 797     }
 798 
 799     @Test(expectedExceptions = NullPointerException.class )
 800     public void testProvidesWithNullProviders() {
 801         ModuleDescriptor.newModule("foo").provides("p.S", (List<String>) null);
 802     }
 803 
 804     public void testProvidesCompare() {
 805         Provides p1 = provides("p.S", "q.S1");
 806         Provides p2 = provides("p.S", "q.S1");
 807         assertEquals(p1, p2);
 808         assertTrue(p1.hashCode() == p2.hashCode());
 809         assertTrue(p1.compareTo(p2) == 0);
 810         assertTrue(p2.compareTo(p1) == 0);
 811     }
 812 
 813     public void testProvidesCompareWithDifferentService() {
 814         Provides p1 = provides("p.S2", "q.S1");
 815         Provides p2 = provides("p.S1", "q.S1");
 816         assertNotEquals(p1, p2);
 817         assertTrue(p1.compareTo(p2) == 1);
 818         assertTrue(p2.compareTo(p1) == -1);
 819     }
 820 
 821     public void testProvidesCompareWithDifferentProviders1() {
 822         Provides p1 = provides("p.S", "q.S2");
 823         Provides p2 = provides("p.S", "q.S1");
 824         assertNotEquals(p1, p2);
 825         assertTrue(p1.compareTo(p2) == 1);
 826         assertTrue(p2.compareTo(p1) == -1);
 827     }
 828 
 829     public void testProvidesCompareWithDifferentProviders2() {
 830         Provides p1 = provides("p.S", List.of("q.S1", "q.S2"));
 831         Provides p2 = provides("p.S", "q.S1");
 832         assertNotEquals(p1, p2);
 833         assertTrue(p1.compareTo(p2) == 1);
 834         assertTrue(p2.compareTo(p1) == -1);
 835     }
 836 
 837     // packages
 838 
 839     public void testPackages1() {
 840         Set<String> packages = ModuleDescriptor.newModule("foo")
 841                 .packages(Set.of("p", "q"))
 842                 .build()
 843                 .packages();
 844         assertTrue(packages.size() == 2);
 845         assertTrue(packages.contains("p"));
 846         assertTrue(packages.contains("q"));
 847     }
 848 
 849     public void testPackages2() {
 850         Set<String> packages = ModuleDescriptor.newModule("foo")
 851                 .packages(Set.of("p"))
 852                 .packages(Set.of("q"))
 853                 .build()
 854                 .packages();
 855         assertTrue(packages.size() == 2);
 856         assertTrue(packages.contains("p"));
 857         assertTrue(packages.contains("q"));
 858     }
 859 
 860 
 861     public void testPackagesWithEmptySet() {
 862         Set<String> packages = ModuleDescriptor.newModule("foo")
 863                 .packages(Collections.emptySet())
 864                 .build()
 865                 .packages();
 866         assertTrue(packages.size() == 0);
 867     }
 868 
 869     public void testPackagesDuplicate() {
 870         Set<String> packages = ModuleDescriptor.newModule("foo")
 871                 .packages(Set.of("p"))
 872                 .packages(Set.of("p"))
 873                 .build()
 874                 .packages();
 875         assertTrue(packages.size() == 1);
 876         assertTrue(packages.contains("p"));
 877     }
 878 
 879     public void testPackagesAndExportsPackage1() {
 880         Set<String> packages = ModuleDescriptor.newModule("foo")
 881                 .packages(Set.of("p"))
 882                 .exports("p")
 883                 .build()
 884                 .packages();
 885         assertTrue(packages.size() == 1);
 886         assertTrue(packages.contains("p"));
 887     }
 888 
 889     public void testPackagesAndExportsPackage2() {
 890         Set<String> packages = ModuleDescriptor.newModule("foo")
 891                 .exports("p")
 892                 .packages(Set.of("p"))
 893                 .build()
 894                 .packages();
 895         assertTrue(packages.size() == 1);
 896         assertTrue(packages.contains("p"));
 897     }
 898 
 899     public void testPackagesAndOpensPackage1() {
 900         Set<String> packages = ModuleDescriptor.newModule("foo")
 901                 .packages(Set.of("p"))
 902                 .opens("p")
 903                 .build()
 904                 .packages();
 905         assertTrue(packages.size() == 1);
 906         assertTrue(packages.contains("p"));
 907     }
 908 
 909     public void testPackagesAndOpensPackage2() {
 910         Set<String> packages = ModuleDescriptor.newModule("foo")
 911                 .opens("p")
 912                 .packages(Set.of("p"))
 913                 .build()
 914                 .packages();
 915         assertTrue(packages.size() == 1);
 916         assertTrue(packages.contains("p"));
 917     }
 918 
 919     public void testPackagesAndProvides1() {
 920         Set<String> packages = ModuleDescriptor.newModule("foo")
 921                 .packages(Set.of("p"))
 922                 .provides("q.S", List.of("p.T"))
 923                 .build()
 924                 .packages();
 925         assertTrue(packages.size() == 1);
 926         assertTrue(packages.contains("p"));
 927     }
 928 
 929     public void testPackagesAndProvides2() {
 930         Set<String> packages = ModuleDescriptor.newModule("foo")
 931                 .provides("q.S", List.of("p.T"))
 932                 .packages(Set.of("p"))
 933                 .build()
 934                 .packages();
 935         assertTrue(packages.size() == 1);
 936         assertTrue(packages.contains("p"));
 937     }
 938 
 939     public void testPackagesAndMainClass1() {
 940         Set<String> packages = ModuleDescriptor.newModule("foo")
 941                 .packages(Set.of("p"))
 942                 .mainClass("p.Main")
 943                 .build()
 944                 .packages();
 945         assertTrue(packages.size() == 1);
 946         assertTrue(packages.contains("p"));
 947     }
 948 
 949     public void testPackagesAndMainClass2() {
 950         Set<String> packages = ModuleDescriptor.newModule("foo")
 951                 .mainClass("p.Main")
 952                 .packages(Set.of("p"))
 953                 .build()
 954                 .packages();
 955         assertTrue(packages.size() == 1);
 956         assertTrue(packages.contains("p"));
 957     }
 958 
 959     public void testPackagesAndAll() {
 960         Set<String> packages = ModuleDescriptor.newModule("foo")
 961                 .exports("p1")
 962                 .opens("p2")
 963                 .packages(Set.of("p3"))
 964                 .provides("q.S", List.of("p4.T"))
 965                 .mainClass("p5.Main")
 966                 .build()
 967                 .packages();
 968         assertTrue(Objects.equals(packages, Set.of("p1", "p2", "p3", "p4", "p5")));
 969     }
 970 
 971     @Test(dataProvider = "invalidNames",
 972           expectedExceptions = IllegalArgumentException.class )
 973     public void testPackagesWithBadName(String pn, String ignore) {
 974         Set<String> pkgs = new HashSet<>();  // allows nulls
 975         pkgs.add(pn);
 976         ModuleDescriptor.newModule("foo").packages(pkgs);
 977     }
 978 
 979     // name
 980 
 981     public void testModuleName() {
 982         String mn = ModuleDescriptor.newModule("foo").build().name();
 983         assertEquals(mn, "foo");
 984     }
 985 
 986     @Test(dataProvider = "invalidNames",
 987           expectedExceptions = IllegalArgumentException.class )
 988     public void testBadModuleName(String mn, String ignore) {
 989         ModuleDescriptor.newModule(mn);
 990     }
 991 
 992 
 993     // version
 994 
 995     public void testVersion1() {
 996         Version v1 = Version.parse("1.0");
 997         Version v2 = ModuleDescriptor.newModule("foo")
 998                 .version(v1)
 999                 .build()
1000                 .version()
1001                 .get();
1002         assertEquals(v1, v2);
1003     }
1004 
1005     public void testVersion2() {
1006         String vs = "1.0";
1007         Version v1 = ModuleDescriptor.newModule("foo")
1008                 .version(vs)
1009                 .build()
1010                 .version()
1011                 .get();
1012         Version v2 = Version.parse(vs);
1013         assertEquals(v1, v2);
1014     }
1015 
1016     @Test(expectedExceptions = NullPointerException.class )
1017     public void testNullVersion1() {
1018         ModuleDescriptor.newModule("foo").version((Version) null);
1019     }
1020 
1021     @Test(expectedExceptions = IllegalArgumentException.class )
1022     public void testNullVersion2() {
1023         ModuleDescriptor.newModule("foo").version((String) null);
1024     }
1025 
1026     @Test(expectedExceptions = IllegalArgumentException.class )
1027     public void testEmptyVersion() {
1028         ModuleDescriptor.newModule("foo").version("");
1029     }
1030 
1031 
1032     @DataProvider(name = "unparseableVersions")
1033     public Object[][] unparseableVersions() {
1034         return new Object[][]{
1035 
1036                 { null,  "A1" },    // no version < unparseable
1037                 { "A1",  "A2" },    // unparseable < unparseable
1038                 { "A1",  "1.0" },   // unparseable < parseable
1039 
1040         };
1041     }
1042 
1043     /**
1044      * Basic test for unparseable module versions
1045      */
1046     @Test(dataProvider = "unparseableVersions")
1047     public void testUnparseableModuleVersion(String vs1, String vs2) {
1048         ModuleDescriptor descriptor1 = newModule("m", vs1);
1049         ModuleDescriptor descriptor2 = newModule("m", vs2);
1050 
1051         if (vs1 != null && !isParsableVersion(vs1)) {
1052             assertFalse(descriptor1.version().isPresent());
1053             assertTrue(descriptor1.rawVersion().isPresent());
1054             assertEquals(descriptor1.rawVersion().get(), vs1);
1055         }
1056 
1057         if (vs2 != null && !isParsableVersion(vs2)) {
1058             assertFalse(descriptor2.version().isPresent());
1059             assertTrue(descriptor2.rawVersion().isPresent());
1060             assertEquals(descriptor2.rawVersion().get(), vs2);
1061         }
1062 
1063         assertFalse(descriptor1.equals(descriptor2));
1064         assertFalse(descriptor2.equals(descriptor1));
1065         assertTrue(descriptor1.compareTo(descriptor2) == -1);
1066         assertTrue(descriptor2.compareTo(descriptor1) == 1);
1067     }
1068 
1069     /**
1070      * Basic test for requiring a module with an unparseable version recorded
1071      * at compile version.
1072      */
1073     @Test(dataProvider = "unparseableVersions")
1074     public void testUnparseableCompiledVersion(String vs1, String vs2) {
1075         Requires r1 = newRequires("m", vs1);
1076         Requires r2 = newRequires("m", vs2);
1077 
1078         if (vs1 != null && !isParsableVersion(vs1)) {
1079             assertFalse(r1.compiledVersion().isPresent());
1080             assertTrue(r1.rawCompiledVersion().isPresent());
1081             assertEquals(r1.rawCompiledVersion().get(), vs1);
1082         }
1083 
1084         if (vs2 != null && !isParsableVersion(vs2)) {
1085             assertFalse(r2.compiledVersion().isPresent());
1086             assertTrue(r2.rawCompiledVersion().isPresent());
1087             assertEquals(r2.rawCompiledVersion().get(), vs2);
1088         }
1089 
1090         assertFalse(r1.equals(r2));
1091         assertFalse(r2.equals(r1));
1092         assertTrue(r1.compareTo(r2) == -1);
1093         assertTrue(r2.compareTo(r1) == 1);
1094     }
1095 
1096     private ModuleDescriptor newModule(String name, String vs) {
1097         Builder builder = JLMA.newModuleBuilder(name, false, Set.of());
1098         if (vs != null)
1099             builder.version(vs);
1100         builder.requires("java.base");
1101         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(builder.build());
1102         return ModuleDescriptor.read(bb);
1103     }
1104 
1105     private Requires newRequires(String name, String vs) {
1106         Builder builder = JLMA.newModuleBuilder("foo", false, Set.of());
1107         if (vs == null) {
1108             builder.requires(name);
1109         } else {
1110             JLMA.requires(builder, Set.of(), name, vs);
1111         }
1112         Set<ModuleDescriptor.Requires> requires = builder.build().requires();
1113         Iterator<ModuleDescriptor.Requires> iterator = requires.iterator();
1114         ModuleDescriptor.Requires r = iterator.next();
1115         if (r.name().equals("java.base")) {
1116             r = iterator.next();
1117         }
1118         return r;
1119     }
1120 
1121     private boolean isParsableVersion(String vs) {
1122         try {
1123             Version.parse(vs);
1124             return true;
1125         } catch (IllegalArgumentException e) {
1126             return false;
1127         }
1128     }
1129 
1130 
1131     // toNameAndVersion
1132 
1133     public void testToNameAndVersion() {
1134         ModuleDescriptor md1 = ModuleDescriptor.newModule("foo").build();
1135         assertEquals(md1.toNameAndVersion(), "foo");
1136 
1137         ModuleDescriptor md2 = ModuleDescriptor.newModule("foo").version("1.0").build();
1138         assertEquals(md2.toNameAndVersion(), "foo@1.0");
1139     }
1140 
1141 
1142     // open modules
1143 
1144     public void testOpenModule() {
1145         ModuleDescriptor descriptor = ModuleDescriptor.newOpenModule("foo")
1146                 .requires("bar")
1147                 .exports("p")
1148                 .provides("p.Service", List.of("q.ServiceImpl"))
1149                 .build();
1150 
1151         // modifiers
1152         assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.OPEN));
1153         assertTrue(descriptor.isOpen());
1154 
1155         // requires
1156         assertTrue(descriptor.requires().size() == 2);
1157         Set<String> names = descriptor.requires()
1158                 .stream()
1159                 .map(Requires::name)
1160                 .collect(Collectors.toSet());
1161         assertEquals(names, Set.of("bar", "java.base"));
1162 
1163         // packages
1164         assertEquals(descriptor.packages(), Set.of("p", "q"));
1165 
1166         // exports
1167         assertTrue(descriptor.exports().size() == 1);
1168         names = descriptor.exports()
1169                 .stream()
1170                 .map(Exports::source)
1171                 .collect(Collectors.toSet());
1172         assertEquals(names, Set.of("p"));
1173 
1174         // opens
1175         assertTrue(descriptor.opens().isEmpty());
1176     }
1177 
1178     @Test(expectedExceptions = IllegalStateException.class)
1179     public void testOpensOnOpenModule1() {
1180         ModuleDescriptor.newOpenModule("foo").opens("p");
1181     }
1182 
1183     @Test(expectedExceptions = IllegalStateException.class)
1184     public void testOpensOnOpenModule2() {
1185         ModuleDescriptor.newOpenModule("foo").opens("p", Set.of("bar"));
1186     }
1187 
1188     public void testIsOpen() {
1189         assertFalse(ModuleDescriptor.newModule("m").build().isOpen());
1190         assertFalse(ModuleDescriptor.newAutomaticModule("m").build().isOpen());
1191         assertTrue(ModuleDescriptor.newOpenModule("m").build().isOpen());
1192     }
1193 
1194 
1195     // automatic modules
1196 
1197     public void testAutomaticModule() {
1198         ModuleDescriptor descriptor = ModuleDescriptor.newAutomaticModule("foo")
1199                 .packages(Set.of("p"))
1200                 .provides("p.Service", List.of("q.ServiceImpl"))
1201                 .build();
1202 
1203         // modifiers
1204         assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.AUTOMATIC));
1205         assertTrue(descriptor.isAutomatic());
1206 
1207         // requires
1208         assertTrue(descriptor.requires().size() == 1);
1209         Set<String> names = descriptor.requires()
1210                 .stream()
1211                 .map(Requires::name)
1212                 .collect(Collectors.toSet());
1213         assertEquals(names, Set.of("java.base"));
1214 
1215         // packages
1216         assertEquals(descriptor.packages(), Set.of("p", "q"));
1217         assertTrue(descriptor.exports().isEmpty());
1218         assertTrue(descriptor.opens().isEmpty());
1219     }
1220 
1221     @Test(expectedExceptions = IllegalStateException.class)
1222     public void testRequiresOnAutomaticModule() {
1223         ModuleDescriptor.newAutomaticModule("foo").requires("java.base");
1224     }
1225 
1226     @Test(expectedExceptions = IllegalStateException.class)
1227     public void testExportsOnAutomaticModule1() {
1228         ModuleDescriptor.newAutomaticModule("foo").exports("p");
1229     }
1230 
1231     @Test(expectedExceptions = IllegalStateException.class)
1232     public void testExportsOnAutomaticModule2() {
1233         ModuleDescriptor.newAutomaticModule("foo").exports("p", Set.of("bar"));
1234     }
1235 
1236     @Test(expectedExceptions = IllegalStateException.class)
1237     public void testOpensOnAutomaticModule1() {
1238         ModuleDescriptor.newAutomaticModule("foo").opens("p");
1239     }
1240 
1241     @Test(expectedExceptions = IllegalStateException.class)
1242     public void testOpensOnAutomaticModule2() {
1243         ModuleDescriptor.newAutomaticModule("foo").opens("p", Set.of("bar"));
1244     }
1245 
1246     @Test(expectedExceptions = IllegalStateException.class)
1247     public void testUsesOnAutomaticModule() {
1248         ModuleDescriptor.newAutomaticModule("foo").uses("p.Service");
1249     }
1250 
1251     public void testIsAutomatic() {
1252         ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("foo").build();
1253         assertFalse(descriptor1.isAutomatic());
1254 
1255         ModuleDescriptor descriptor2 = ModuleDescriptor.newOpenModule("foo").build();
1256         assertFalse(descriptor2.isAutomatic());
1257 
1258         ModuleDescriptor descriptor3 = ModuleDescriptor.newAutomaticModule("foo").build();
1259         assertTrue(descriptor3.isAutomatic());
1260     }
1261 
1262 
1263     // newModule with modifiers
1264 
1265     public void testNewModuleToBuildAutomaticModule() {
1266         Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.AUTOMATIC);
1267         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo", ms).build();
1268         assertTrue(descriptor.modifiers().equals(ms));
1269         assertTrue(descriptor.isAutomatic());
1270     }
1271 
1272     public void testNewModuleToBuildOpenModule() {
1273         Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.OPEN);
1274         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo", ms).build();
1275         assertTrue(descriptor.modifiers().equals(ms));
1276         assertTrue(descriptor.isOpen());
1277 
1278         ms = Set.of(ModuleDescriptor.Modifier.OPEN, ModuleDescriptor.Modifier.SYNTHETIC);
1279         descriptor = ModuleDescriptor.newModule("foo", ms).build();
1280         assertTrue(descriptor.modifiers().equals(ms));
1281         assertTrue(descriptor.isOpen());
1282     }
1283 
1284     @Test(expectedExceptions = IllegalArgumentException.class)
1285     public void testNewModuleToBuildAutomaticAndOpenModule() {
1286         Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.AUTOMATIC,
1287                                                    ModuleDescriptor.Modifier.OPEN);
1288         ModuleDescriptor.newModule("foo", ms);
1289     }
1290 
1291 
1292     // mainClass
1293 
1294     public void testMainClass() {
1295         String mainClass
1296             = ModuleDescriptor.newModule("foo").mainClass("p.Main").build().mainClass().get();
1297         assertEquals(mainClass, "p.Main");
1298     }
1299 
1300     @Test(expectedExceptions = IllegalArgumentException.class)
1301     public void testMainClassWithSimpleIdentifier() {
1302         ModuleDescriptor.newModule("foo").mainClass("Main");
1303     }
1304 
1305     @Test(dataProvider = "invalidNames",
1306           expectedExceptions = IllegalArgumentException.class )
1307     public void testMainClassWithBadName(String mainClass, String ignore) {
1308         Builder builder = ModuleDescriptor.newModule("foo");
1309         builder.mainClass(mainClass);
1310     }
1311 
1312 
1313     // reads
1314 
1315     private static InputStream EMPTY_INPUT_STREAM = new InputStream() {
1316         @Override
1317         public int read() {
1318             return -1;
1319         }
1320     };
1321 
1322     private static InputStream FAILING_INPUT_STREAM = new InputStream() {
1323         @Override
1324         public int read() throws IOException {
1325             throw new IOException();
1326         }
1327     };
1328 
1329     /**
1330      * Basic test reading module-info.class
1331      */
1332     public void testRead() throws Exception {
1333         Module base = Object.class.getModule();
1334 
1335         try (InputStream in = base.getResourceAsStream("module-info.class")) {
1336             ModuleDescriptor descriptor = ModuleDescriptor.read(in);
1337             assertTrue(in.read() == -1); // all bytes read
1338             assertEquals(descriptor.name(), "java.base");
1339         }
1340 
1341         try (InputStream in = base.getResourceAsStream("module-info.class")) {
1342             ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
1343             ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
1344             assertFalse(bb.hasRemaining()); // no more remaining bytes
1345             assertEquals(descriptor.name(), "java.base");
1346         }
1347     }
1348 
1349     /**
1350      * Test ModuleDescriptor with a packager finder
1351      */
1352     public void testReadsWithPackageFinder() throws Exception {
1353         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
1354                 .requires("java.base")
1355                 .build();
1356 
1357         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1358         ModuleInfoWriter.write(descriptor, baos);
1359         ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
1360 
1361         descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
1362 
1363         assertTrue(descriptor.packages().size() == 2);
1364         assertTrue(descriptor.packages().contains("p"));
1365         assertTrue(descriptor.packages().contains("q"));
1366     }
1367 
1368     /**
1369      * Test ModuleDescriptor with a packager finder that doesn't return the
1370      * complete set of packages.
1371      */
1372     public void testReadsWithBadPackageFinder() throws Exception {
1373         ByteBuffer bb = ByteBuffer.wrap(ClassFile.of().buildModule(
1374                 ModuleAttribute.of(
1375                         ModuleDesc.of("foo"),
1376                         mb -> mb.requires(ModuleDesc.of("java.base"), 0, null)
1377                                 .exports(PackageDesc.of("p"), 0))));
1378 
1379         // package finder returns a set that doesn't include p
1380         assertThrows(InvalidModuleDescriptorException.class,
1381                      () -> ModuleDescriptor.read(bb, () -> Set.of("q")));
1382     }
1383 
1384     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
1385     public void testReadFromEmptyInputStream() throws Exception {
1386         ModuleDescriptor.read(EMPTY_INPUT_STREAM);
1387     }
1388 
1389     @Test(expectedExceptions = IOException.class)
1390     public void testReadFromFailingInputStream() throws Exception {
1391         ModuleDescriptor.read(FAILING_INPUT_STREAM);
1392     }
1393 
1394     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
1395     public void testReadFromEmptyBuffer() {
1396         ByteBuffer bb = ByteBuffer.allocate(0);
1397         ModuleDescriptor.read(bb);
1398     }
1399 
1400     /**
1401      * Test ModuleDescriptor.read reading a module-info for java.base that has a non-0
1402      * length requires table.
1403      */
1404     public void testReadOfJavaBaseWithRequires() {
1405         ModuleDescriptor descriptor = ModuleDescriptor.newModule("java.base")
1406                 .requires("other")
1407                 .build();
1408         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
1409         assertThrows(InvalidModuleDescriptorException.class,
1410                      () -> ModuleDescriptor.read(bb));
1411     }
1412 
1413     /**
1414      * Test ModuleDescriptor.read reading a module-info with a zero length requires table
1415      * (no entry for java.base).
1416      */
1417     public void testReadWithEmptyRequires() {
1418         // use non-strict builder to create module that does not require java.base
1419         ModuleDescriptor descriptor = JLMA.newModuleBuilder("m", false, Set.of()).build();
1420         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
1421         assertThrows(InvalidModuleDescriptorException.class,
1422                      () -> ModuleDescriptor.read(bb));
1423     }
1424 
1425     /**
1426      * Test ModuleDescriptor.read reading a module-info with a non-zero length requires
1427      * table that does not have entry for java.base.
1428      */
1429     public void testReadWithNoRequiresBase() {
1430         // use non-strict builder to create module that does not require java.base
1431         ModuleDescriptor descriptor = JLMA.newModuleBuilder("m1", false, Set.of())
1432                 .requires("m2")
1433                 .build();
1434         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
1435         assertThrows(InvalidModuleDescriptorException.class,
1436                      () -> ModuleDescriptor.read(bb));
1437     }
1438 
1439     /**
1440      * Test ModuleDescriptor.read reading a module-info with a requires entry for
1441      * java.base with the ACC_SYNTHETIC flag set.
1442      */
1443     public void testReadWithSynethticRequiresBase() {
1444         ModuleDescriptor descriptor = ModuleDescriptor.newModule("m")
1445                 .requires(Set.of(SYNTHETIC), "java.base")
1446                 .build();
1447         ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
1448         assertThrows(InvalidModuleDescriptorException.class,
1449                      () -> ModuleDescriptor.read(bb));
1450     }
1451 
1452     /**
1453      * Test ModuleDescriptor.read with a null parameter.
1454      */
1455     public void testReadWithNull() throws Exception {
1456         Module base = Object.class.getModule();
1457 
1458         assertThrows(NullPointerException.class,
1459                      () -> ModuleDescriptor.read((InputStream) null));
1460         assertThrows(NullPointerException.class,
1461                      () -> ModuleDescriptor.read((ByteBuffer) null));
1462 
1463         try (InputStream in = base.getResourceAsStream("module-info.class")) {
1464             assertThrows(NullPointerException.class,
1465                         () -> ModuleDescriptor.read(in, null));
1466 
1467             ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
1468             assertThrows(NullPointerException.class,
1469                          () -> ModuleDescriptor.read(bb, null));
1470         }
1471     }
1472 
1473 
1474     // equals/hashCode/compareTo/toString
1475 
1476     public void testEqualsAndHashCode() {
1477         ModuleDescriptor md1 = ModuleDescriptor.newModule("m").build();
1478         ModuleDescriptor md2 = ModuleDescriptor.newModule("m").build();
1479         assertEquals(md1, md1);
1480         assertEquals(md1.hashCode(), md2.hashCode());
1481         assertTrue(md1.compareTo(md2) == 0);
1482         assertTrue(md2.compareTo(md1) == 0);
1483     }
1484 
1485     @DataProvider(name = "sortedModuleDescriptors")
1486     public Object[][] sortedModuleDescriptors() {
1487         return new Object[][]{
1488 
1489             { ModuleDescriptor.newModule("m2").build(),
1490               ModuleDescriptor.newModule("m1").build()
1491             },
1492 
1493             { ModuleDescriptor.newModule("m").version("2").build(),
1494               ModuleDescriptor.newModule("m").version("1").build()
1495             },
1496 
1497             { ModuleDescriptor.newModule("m").version("1").build(),
1498               ModuleDescriptor.newModule("m").build()
1499             },
1500 
1501             { ModuleDescriptor.newOpenModule("m").build(),
1502               ModuleDescriptor.newModule("m").build()
1503             },
1504 
1505         };
1506     }
1507 
1508     @Test(dataProvider = "sortedModuleDescriptors")
1509     public void testCompare(ModuleDescriptor md1, ModuleDescriptor md2) {
1510         assertNotEquals(md1, md2);
1511         assertTrue(md1.compareTo(md2) == 1);
1512         assertTrue(md2.compareTo(md1) == -1);
1513     }
1514 
1515     public void testToString() {
1516         String s = ModuleDescriptor.newModule("m1")
1517                 .requires("m2")
1518                 .exports("p1")
1519                 .build()
1520                 .toString();
1521         assertTrue(s.contains("m1"));
1522         assertTrue(s.contains("m2"));
1523         assertTrue(s.contains("p1"));
1524     }
1525 
1526     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
1527     public void testRequiresTransitiveJavaBaseNotPermitted1() throws Exception {
1528         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
1529                 .requires(Set.of(Modifier.TRANSITIVE), "java.base")
1530                 .build();
1531 
1532         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1533         ModuleInfoWriter.write(descriptor, baos);
1534         ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
1535 
1536         ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
1537     }
1538 
1539     @Test(expectedExceptions = InvalidModuleDescriptorException.class)
1540     public void testRequiresTransitiveJavaBaseNotPermitted2() throws Exception {
1541         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
1542                 .requires(Set.of(Modifier.TRANSITIVE), "java.base")
1543                 .build();
1544 
1545         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1546         ModuleInfoWriter.write(descriptor, baos);
1547         byte[] bytecode = baos.toByteArray();
1548         ByteBuffer bb = ByteBuffer.wrap(bytecode);
1549         setClassFileVersion(bb, ClassFile.JAVA_21_VERSION, -1);
1550 
1551         ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
1552     }
1553 
1554     public void testRequiresTransitiveJavaBasePermitted() throws Exception {
1555         ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
1556                 .requires(Set.of(Modifier.TRANSITIVE), "java.base")
1557                 .build();
1558 
1559         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1560         ModuleInfoWriter.write(descriptor, baos);
1561         byte[] bytecode = baos.toByteArray();
1562         ByteBuffer bb = ByteBuffer.wrap(bytecode);
1563         setClassFileVersion(bb, -1, ClassFile.PREVIEW_MINOR_VERSION);
1564 
1565         descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
1566 
1567         assertEquals(descriptor.requires().size(), 1);
1568         Requires javaBase = descriptor.requires().iterator().next();
1569         assertEquals(javaBase.name(), "java.base");
1570         assertEquals(javaBase.modifiers(), Set.of(Modifier.TRANSITIVE));
1571     }
1572 
1573     /**Change the classfile versions of the provided classfile to the provided
1574      * values.
1575      *
1576      * @param bytecode the classfile content to modify
1577      * @param major the major classfile version to set,
1578      *              -1 if the existing version should be kept
1579      * @param minor the minor classfile version to set,
1580      *              -1 if the existing version should be kept
1581      */
1582     private void setClassFileVersion(ByteBuffer bb, int major, int minor) {
1583         if (minor != (-1)) {
1584             bb.putShort(4, (short) minor);
1585         }
1586         if (major != (-1)) {
1587             bb.putShort(6, (short) major);
1588         }
1589     }
1590 }