1e97c1c913
Reviewed-by: vromero, abimpoudis, mcimadamore, alanb
1592 lines
55 KiB
Java
1592 lines
55 KiB
Java
/*
|
|
* Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved.
|
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
*
|
|
* This code is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 only, as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* version 2 for more details (a copy is included in the LICENSE file that
|
|
* accompanied this code).
|
|
*
|
|
* You should have received a copy of the GNU General Public License version
|
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*
|
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
* or visit www.oracle.com if you need additional information or have any
|
|
* questions.
|
|
*/
|
|
|
|
/**
|
|
* @test
|
|
* @bug 8142968 8158456 8298875
|
|
* @enablePreview
|
|
* @modules java.base/jdk.internal.access
|
|
* java.base/jdk.internal.module
|
|
* @library /test/lib
|
|
* @build jdk.test.lib.util.ModuleInfoWriter
|
|
* @run testng ModuleDescriptorTest
|
|
* @summary Basic test for java.lang.module.ModuleDescriptor and its builder
|
|
*/
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.lang.module.InvalidModuleDescriptorException;
|
|
import java.lang.module.ModuleDescriptor;
|
|
import java.lang.module.ModuleDescriptor.Builder;
|
|
import java.lang.module.ModuleDescriptor.Exports;
|
|
import java.lang.module.ModuleDescriptor.Opens;
|
|
import java.lang.module.ModuleDescriptor.Requires;
|
|
import java.lang.module.ModuleDescriptor.Provides;
|
|
import java.lang.module.ModuleDescriptor.Requires.Modifier;
|
|
import java.lang.module.ModuleDescriptor.Version;
|
|
import java.nio.ByteBuffer;
|
|
import java.util.ArrayList;
|
|
import java.util.Collections;
|
|
import java.util.EnumSet;
|
|
import java.util.HashSet;
|
|
import java.util.Iterator;
|
|
import java.util.List;
|
|
import java.util.Objects;
|
|
import java.util.Set;
|
|
import java.util.stream.Collectors;
|
|
|
|
import static java.lang.module.ModuleDescriptor.Requires.Modifier.*;
|
|
|
|
import jdk.internal.access.JavaLangModuleAccess;
|
|
import jdk.internal.access.SharedSecrets;
|
|
import java.lang.classfile.ClassFile;
|
|
import java.lang.classfile.ClassFileVersion;
|
|
import java.lang.classfile.ClassTransform;
|
|
import java.lang.classfile.attribute.ModuleAttribute;
|
|
import java.lang.constant.PackageDesc;
|
|
import java.lang.constant.ModuleDesc;
|
|
import jdk.test.lib.util.ModuleInfoWriter;
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
import static org.testng.Assert.*;
|
|
|
|
@Test
|
|
public class ModuleDescriptorTest {
|
|
private static final JavaLangModuleAccess JLMA = SharedSecrets.getJavaLangModuleAccess();
|
|
|
|
@DataProvider(name = "invalidNames")
|
|
public Object[][] invalidNames() {
|
|
return new Object[][]{
|
|
|
|
{ null, null },
|
|
{ "1", null },
|
|
{ "1foo", null },
|
|
{ ".foo", null },
|
|
{ "foo.", null },
|
|
{ "[foo]", null },
|
|
{ "foo.1", null },
|
|
{ "1foo.bar", null },
|
|
{ "foo.1bar", null },
|
|
{ "foo.[bar]", null },
|
|
{ "foo..bar", null },
|
|
{ "foo.bar.1", null },
|
|
{ "foo.bar.1gus", null },
|
|
{ "foo.bar.[gus]", null },
|
|
|
|
{ "class", null },
|
|
{ "interface", null },
|
|
{ "true", null },
|
|
{ "false", null },
|
|
{ "null", null },
|
|
|
|
{ "x.class", null },
|
|
{ "x.interface", null },
|
|
{ "x.true", null },
|
|
{ "x.false", null },
|
|
{ "x.null", null },
|
|
|
|
{ "class.x", null },
|
|
{ "interface.x", null },
|
|
{ "true.x", null },
|
|
{ "false.x", null },
|
|
{ "null.x", null },
|
|
|
|
{ "x.class.x", null },
|
|
{ "x.interface.x", null },
|
|
{ "x.true.x", null },
|
|
{ "x.false.x", null },
|
|
{ "x.null.x", null },
|
|
|
|
{ "_", null },
|
|
|
|
};
|
|
}
|
|
|
|
|
|
// requires
|
|
|
|
private Requires requires(Set<Modifier> mods, String mn) {
|
|
return requires(mods, mn, null);
|
|
}
|
|
|
|
private Requires requires(Set<Modifier> mods, String mn, Version v) {
|
|
Builder builder = ModuleDescriptor.newModule("m");
|
|
if (v == null) {
|
|
builder.requires(mods, mn);
|
|
} else {
|
|
builder.requires(mods, mn, v);
|
|
}
|
|
Set<Requires> requires = builder.build().requires();
|
|
assertTrue(requires.size() == 2);
|
|
Iterator<Requires> iterator = requires.iterator();
|
|
Requires r = iterator.next();
|
|
if (r.name().equals("java.base")) {
|
|
r = iterator.next();
|
|
} else {
|
|
Requires other = iterator.next();
|
|
assertEquals(other.name(), "java.base");
|
|
}
|
|
return r;
|
|
}
|
|
|
|
private Requires requires(String mn) {
|
|
return requires(Collections.emptySet(), mn);
|
|
}
|
|
|
|
public void testRequiresWithRequires() {
|
|
Requires r1 = requires("foo");
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").requires(r1).build();
|
|
assertEquals(descriptor.requires().size(), 2);
|
|
var iterator = descriptor.requires().iterator();
|
|
Requires r2 = iterator.next();
|
|
if (r2.name().equals("java.base")) {
|
|
r2 = iterator.next();
|
|
}
|
|
assertEquals(r1, r2);
|
|
}
|
|
|
|
public void testRequiresWithNoModifiers() {
|
|
Requires r = requires(EnumSet.noneOf(Requires.Modifier.class), "foo");
|
|
assertEquals(r, r);
|
|
assertTrue(r.compareTo(r) == 0);
|
|
assertTrue(r.modifiers().isEmpty());
|
|
assertEquals(r.name(), "foo");
|
|
assertFalse(r.compiledVersion().isPresent());
|
|
}
|
|
|
|
public void testRequiresWithOneModifier() {
|
|
Requires r = requires(EnumSet.of(TRANSITIVE), "foo");
|
|
assertEquals(r, r);
|
|
assertTrue(r.compareTo(r) == 0);
|
|
assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE));
|
|
assertEquals(r.name(), "foo");
|
|
assertFalse(r.compiledVersion().isPresent());
|
|
}
|
|
|
|
public void testRequiresWithTwoModifiers() {
|
|
Requires r = requires(EnumSet.of(TRANSITIVE, SYNTHETIC), "foo");
|
|
assertEquals(r, r);
|
|
assertTrue(r.compareTo(r) == 0);
|
|
assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, SYNTHETIC));
|
|
assertEquals(r.name(), "foo");
|
|
assertFalse(r.compiledVersion().isPresent());
|
|
}
|
|
|
|
public void testRequiresWithAllModifiers() {
|
|
Requires r = requires(EnumSet.allOf(Modifier.class), "foo");
|
|
assertEquals(r, r);
|
|
assertTrue(r.compareTo(r) == 0);
|
|
assertEquals(r.modifiers(), EnumSet.of(TRANSITIVE, STATIC, SYNTHETIC, MANDATED));
|
|
assertEquals(r.name(), "foo");
|
|
assertFalse(r.compiledVersion().isPresent());
|
|
}
|
|
|
|
public void testRequiresWithCompiledVersion() {
|
|
Version v = Version.parse("1.0");
|
|
Requires r = requires(Set.of(), "foo", v);
|
|
assertEquals(r, r);
|
|
assertTrue(r.compareTo(r) == 0);
|
|
assertEquals(r.modifiers(), Set.of());
|
|
assertEquals(r.name(), "foo");
|
|
assertTrue(r.compiledVersion().isPresent());
|
|
assertEquals(r.compiledVersion().get().toString(), "1.0");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testRequiresWithDuplicatesRequires() {
|
|
Requires r = requires("foo");
|
|
ModuleDescriptor.newModule("m").requires(r).requires(r);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testRequiresSelfWithRequires() {
|
|
Requires r = requires("foo");
|
|
ModuleDescriptor.newModule("foo").requires(r);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testRequiresSelfWithNoModifier() {
|
|
ModuleDescriptor.newModule("m").requires("m");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testRequiresSelfWithOneModifier() {
|
|
ModuleDescriptor.newModule("m").requires(Set.of(TRANSITIVE), "m");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testRequiresSelfWithAllModifiers() {
|
|
ModuleDescriptor.newModule("m").requires(EnumSet.allOf(Modifier.class), "m");
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testRequiresWithBadModuleName(String mn, String ignore) {
|
|
requires(EnumSet.noneOf(Modifier.class), mn);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class)
|
|
public void testRequiresWithNullRequires() {
|
|
ModuleDescriptor.newModule("m").requires((Requires) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class)
|
|
public void testRequiresWithNullModifiers() {
|
|
ModuleDescriptor.newModule("m").requires(null, "foo");
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class)
|
|
public void testRequiresWithNullVersion() {
|
|
ModuleDescriptor.newModule("m").requires(Set.of(), "foo", null);
|
|
}
|
|
|
|
public void testRequiresCompare() {
|
|
Requires r1 = requires(EnumSet.noneOf(Modifier.class), "foo");
|
|
Requires r2 = requires(EnumSet.noneOf(Modifier.class), "bar");
|
|
int n = "foo".compareTo("bar");
|
|
assertTrue(r1.compareTo(r2) == n);
|
|
assertTrue(r2.compareTo(r1) == -n);
|
|
}
|
|
|
|
public void testRequiresCompareWithDifferentModifiers() {
|
|
Requires r1 = requires(EnumSet.of(TRANSITIVE), "foo");
|
|
Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo");
|
|
int n = Integer.compare(1 << TRANSITIVE.ordinal(), 1 << SYNTHETIC.ordinal());
|
|
assertTrue(r1.compareTo(r2) == n);
|
|
assertTrue(r2.compareTo(r1) == -n);
|
|
}
|
|
|
|
public void testRequiresCompareWithSameModifiers() {
|
|
Requires r1 = requires(EnumSet.of(SYNTHETIC), "foo");
|
|
Requires r2 = requires(EnumSet.of(SYNTHETIC), "foo");
|
|
assertTrue(r1.compareTo(r2) == 0);
|
|
assertTrue(r2.compareTo(r1) == 0);
|
|
}
|
|
|
|
public void testRequiresCompareWithSameCompiledVersion() {
|
|
Requires r1 = requires(Set.of(), "foo", Version.parse("2.0"));
|
|
Requires r2 = requires(Set.of(), "foo", Version.parse("2.0"));
|
|
assertTrue(r1.compareTo(r2) == 0);
|
|
assertTrue(r2.compareTo(r1) == 0);
|
|
}
|
|
|
|
public void testRequiresCompareWithDifferentCompiledVersion() {
|
|
Requires r1 = requires(Set.of(), "foo", Version.parse("1.0"));
|
|
Requires r2 = requires(Set.of(), "foo", Version.parse("2.0"));
|
|
assertTrue(r1.compareTo(r2) < 0);
|
|
assertTrue(r2.compareTo(r1) > 0);
|
|
}
|
|
|
|
public void testRequiresEqualsAndHashCode() {
|
|
Requires r1 = requires("foo");
|
|
Requires r2 = requires("foo");
|
|
assertEquals(r1, r2);
|
|
assertTrue(r1.hashCode() == r2.hashCode());
|
|
|
|
r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
|
|
r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
|
|
assertEquals(r1, r2);
|
|
assertTrue(r1.hashCode() == r2.hashCode());
|
|
|
|
r1 = requires("foo");
|
|
r2 = requires("bar");
|
|
assertNotEquals(r1, r2);
|
|
|
|
r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo");
|
|
r2 = requires(Set.of(), "foo");
|
|
assertNotEquals(r1, r2);
|
|
|
|
Version v1 = Version.parse("1.0");
|
|
r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
|
|
r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
|
|
assertEquals(r1, r2);
|
|
assertTrue(r1.hashCode() == r2.hashCode());
|
|
|
|
Version v2 = Version.parse("2.0");
|
|
r1 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v1);
|
|
r2 = requires(EnumSet.allOf(Requires.Modifier.class), "foo", v2);
|
|
assertNotEquals(r1, r2);
|
|
}
|
|
|
|
public void testRequiresToString() {
|
|
Requires r = requires(EnumSet.noneOf(Modifier.class), "foo");
|
|
assertTrue(r.toString().contains("foo"));
|
|
}
|
|
|
|
|
|
// exports
|
|
|
|
private Exports exports(Set<Exports.Modifier> mods, String pn) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.exports(mods, pn)
|
|
.build()
|
|
.exports()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
private Exports exports(String pn) {
|
|
return exports(Set.of(), pn);
|
|
}
|
|
|
|
private Exports exports(Set<Exports.Modifier> mods, String pn, String target) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.exports(mods, pn, Set.of(target))
|
|
.build()
|
|
.exports()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
private Exports exports(String pn, String target) {
|
|
return exports(Set.of(), pn, target);
|
|
}
|
|
|
|
|
|
public void testExportsExports() {
|
|
Exports e1 = exports("p");
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").exports(e1).build();
|
|
Exports e2 = descriptor.exports().iterator().next();
|
|
assertEquals(e1, e2);
|
|
}
|
|
|
|
public void testExportsToAll() {
|
|
Exports e = exports("p");
|
|
assertEquals(e, e);
|
|
assertTrue(e.modifiers().isEmpty());
|
|
assertEquals(e.source(), "p");
|
|
assertFalse(e.isQualified());
|
|
assertTrue(e.targets().isEmpty());
|
|
}
|
|
|
|
public void testExportsToTarget() {
|
|
Exports e = exports("p", "bar");
|
|
assertEquals(e, e);
|
|
assertTrue(e.modifiers().isEmpty());
|
|
assertEquals(e.source(), "p");
|
|
assertTrue(e.isQualified());
|
|
assertTrue(e.targets().size() == 1);
|
|
assertTrue(e.targets().contains("bar"));
|
|
}
|
|
|
|
public void testExportsToTargets() {
|
|
Set<String> targets = new HashSet<>();
|
|
targets.add("bar");
|
|
targets.add("gus");
|
|
Exports e
|
|
= ModuleDescriptor.newModule("foo")
|
|
.exports("p", targets)
|
|
.build()
|
|
.exports()
|
|
.iterator()
|
|
.next();
|
|
assertEquals(e, e);
|
|
assertTrue(e.modifiers().isEmpty());
|
|
assertEquals(e.source(), "p");
|
|
assertTrue(e.isQualified());
|
|
assertTrue(e.targets().size() == 2);
|
|
assertTrue(e.targets().contains("bar"));
|
|
assertTrue(e.targets().contains("gus"));
|
|
}
|
|
|
|
public void testExportsToAllWithModifier() {
|
|
Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
|
|
assertEquals(e, e);
|
|
assertTrue(e.modifiers().size() == 1);
|
|
assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
|
|
assertEquals(e.source(), "p");
|
|
assertFalse(e.isQualified());
|
|
assertTrue(e.targets().isEmpty());
|
|
}
|
|
|
|
public void testExportsToTargetWithModifier() {
|
|
Exports e = exports(Set.of(Exports.Modifier.SYNTHETIC), "p", "bar");
|
|
assertEquals(e, e);
|
|
assertTrue(e.modifiers().size() == 1);
|
|
assertTrue(e.modifiers().contains(Exports.Modifier.SYNTHETIC));
|
|
assertEquals(e.source(), "p");
|
|
assertTrue(e.isQualified());
|
|
assertTrue(e.targets().size() == 1);
|
|
assertTrue(e.targets().contains("bar"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testExportsWithDuplicate1() {
|
|
Exports e = exports("p");
|
|
ModuleDescriptor.newModule("foo").exports(e).exports(e);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testExportsWithDuplicate2() {
|
|
ModuleDescriptor.newModule("foo").exports("p").exports("p");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testExportsWithEmptySet() {
|
|
ModuleDescriptor.newModule("foo").exports("p", Collections.emptySet());
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testExportsWithBadName(String pn, String ignore) {
|
|
ModuleDescriptor.newModule("foo").exports(pn);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testExportsWithNullExports() {
|
|
ModuleDescriptor.newModule("foo").exports((Exports) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testExportsWithNullTargets() {
|
|
ModuleDescriptor.newModule("foo").exports("p", (Set<String>) null);
|
|
}
|
|
|
|
public void testExportsCompare() {
|
|
Exports e1 = exports("p");
|
|
Exports e2 = exports("p");
|
|
assertEquals(e1, e2);
|
|
assertTrue(e1.hashCode() == e2.hashCode());
|
|
assertTrue(e1.compareTo(e2) == 0);
|
|
assertTrue(e2.compareTo(e1) == 0);
|
|
}
|
|
|
|
public void testExportsCompareWithSameModifiers() {
|
|
Exports e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
|
|
Exports e2 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
|
|
assertEquals(e1, e2);
|
|
assertTrue(e1.hashCode() == e2.hashCode());
|
|
assertTrue(e1.compareTo(e2) == 0);
|
|
assertTrue(e2.compareTo(e1) == 0);
|
|
}
|
|
|
|
public void testExportsCompareWithDifferentModifiers() {
|
|
Exports e1 = exports(Set.of(Exports.Modifier.SYNTHETIC), "p");
|
|
Exports e2 = exports("p");
|
|
assertNotEquals(e1, e2);
|
|
assertTrue(e1.compareTo(e2) == 1);
|
|
assertTrue(e2.compareTo(e1) == -1);
|
|
}
|
|
|
|
public void testExportsCompareWithSameTargets() {
|
|
Exports e1 = exports("p", "x");
|
|
Exports e2 = exports("p", "x");
|
|
assertEquals(e1, e2);
|
|
assertTrue(e1.hashCode() == e2.hashCode());
|
|
assertTrue(e1.compareTo(e2) == 0);
|
|
assertTrue(e2.compareTo(e1) == 0);
|
|
}
|
|
|
|
public void testExportsCompareWithDifferentTargets() {
|
|
Exports e1 = exports("p", "y");
|
|
Exports e2 = exports("p", "x");
|
|
assertNotEquals(e1, e2);
|
|
assertTrue(e1.compareTo(e2) == 1);
|
|
assertTrue(e2.compareTo(e1) == -1);
|
|
}
|
|
|
|
public void testExportsToString() {
|
|
String s = ModuleDescriptor.newModule("foo")
|
|
.exports("p1", Set.of("bar"))
|
|
.build()
|
|
.exports()
|
|
.iterator()
|
|
.next()
|
|
.toString();
|
|
assertTrue(s.contains("p1"));
|
|
assertTrue(s.contains("bar"));
|
|
}
|
|
|
|
|
|
// opens
|
|
|
|
private Opens opens(Set<Opens.Modifier> mods, String pn) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.opens(mods, pn)
|
|
.build()
|
|
.opens()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
private Opens opens(String pn) {
|
|
return opens(Set.of(), pn);
|
|
}
|
|
|
|
private Opens opens(Set<Opens.Modifier> mods, String pn, String target) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.opens(mods, pn, Set.of(target))
|
|
.build()
|
|
.opens()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
private Opens opens(String pn, String target) {
|
|
return opens(Set.of(), pn, target);
|
|
}
|
|
|
|
public void testOpensOpens() {
|
|
Opens o1 = opens("p");
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m").opens(o1).build();
|
|
Opens o2 = descriptor.opens().iterator().next();
|
|
assertEquals(o1, o2);
|
|
}
|
|
|
|
public void testOpensToAll() {
|
|
Opens o = opens("p");
|
|
assertEquals(o, o);
|
|
assertTrue(o.modifiers().isEmpty());
|
|
assertEquals(o.source(), "p");
|
|
assertFalse(o.isQualified());
|
|
assertTrue(o.targets().isEmpty());
|
|
}
|
|
|
|
|
|
public void testOpensToTarget() {
|
|
Opens o = opens("p", "bar");
|
|
assertEquals(o, o);
|
|
assertTrue(o.modifiers().isEmpty());
|
|
assertEquals(o.source(), "p");
|
|
assertTrue(o.isQualified());
|
|
assertTrue(o.targets().size() == 1);
|
|
assertTrue(o.targets().contains("bar"));
|
|
}
|
|
|
|
public void testOpensToTargets() {
|
|
Set<String> targets = new HashSet<>();
|
|
targets.add("bar");
|
|
targets.add("gus");
|
|
Opens o = ModuleDescriptor.newModule("foo")
|
|
.opens("p", targets)
|
|
.build()
|
|
.opens()
|
|
.iterator()
|
|
.next();
|
|
assertEquals(o, o);
|
|
assertTrue(o.modifiers().isEmpty());
|
|
assertEquals(o.source(), "p");
|
|
assertTrue(o.isQualified());
|
|
assertTrue(o.targets().size() == 2);
|
|
assertTrue(o.targets().contains("bar"));
|
|
assertTrue(o.targets().contains("gus"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensWithDuplicate1() {
|
|
Opens o = opens("p");
|
|
ModuleDescriptor.newModule("foo").opens(o).opens(o);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensWithDuplicate2() {
|
|
ModuleDescriptor.newModule("foo").opens("p").opens("p");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testOpensWithEmptySet() {
|
|
ModuleDescriptor.newModule("foo").opens("p", Collections.emptySet());
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testOpensWithBadName(String pn, String ignore) {
|
|
ModuleDescriptor.newModule("foo").opens(pn);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testOpensWithNullExports() {
|
|
ModuleDescriptor.newModule("foo").opens((Opens) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testOpensWithNullTargets() {
|
|
ModuleDescriptor.newModule("foo").opens("p", (Set<String>) null);
|
|
}
|
|
|
|
public void testOpensCompare() {
|
|
Opens o1 = opens("p");
|
|
Opens o2 = opens("p");
|
|
assertEquals(o1, o2);
|
|
assertTrue(o1.hashCode() == o2.hashCode());
|
|
assertTrue(o1.compareTo(o2) == 0);
|
|
assertTrue(o2.compareTo(o1) == 0);
|
|
}
|
|
|
|
public void testOpensCompareWithSameModifiers() {
|
|
Opens o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
|
|
Opens o2 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
|
|
assertEquals(o1, o2);
|
|
assertTrue(o1.hashCode() == o2.hashCode());
|
|
assertTrue(o1.compareTo(o2) == 0);
|
|
assertTrue(o2.compareTo(o1) == 0);
|
|
}
|
|
|
|
public void testOpensCompareWithDifferentModifiers() {
|
|
Opens o1 = opens(Set.of(Opens.Modifier.SYNTHETIC), "p");
|
|
Opens o2 = opens("p");
|
|
assertNotEquals(o1, o2);
|
|
assertTrue(o1.compareTo(o2) == 1);
|
|
assertTrue(o2.compareTo(o1) == -1);
|
|
}
|
|
|
|
public void testOpensCompareWithSameTargets() {
|
|
Opens o1 = opens("p", "x");
|
|
Opens o2 = opens("p", "x");
|
|
assertEquals(o1, o2);
|
|
assertTrue(o1.hashCode() == o2.hashCode());
|
|
assertTrue(o1.compareTo(o2) == 0);
|
|
assertTrue(o2.compareTo(o1) == 0);
|
|
}
|
|
|
|
public void testOpensCompareWithDifferentTargets() {
|
|
Opens o1 = opens("p", "y");
|
|
Opens o2 = opens("p", "x");
|
|
assertNotEquals(o1, o2);
|
|
assertTrue(o1.compareTo(o2) == 1);
|
|
assertTrue(o2.compareTo(o1) == -1);
|
|
}
|
|
|
|
public void testOpensToString() {
|
|
String s = ModuleDescriptor.newModule("foo")
|
|
.opens("p1", Set.of("bar"))
|
|
.build()
|
|
.opens()
|
|
.iterator()
|
|
.next()
|
|
.toString();
|
|
assertTrue(s.contains("p1"));
|
|
assertTrue(s.contains("bar"));
|
|
}
|
|
|
|
|
|
// uses
|
|
|
|
public void testUses() {
|
|
Set<String> uses
|
|
= ModuleDescriptor.newModule("foo")
|
|
.uses("p.S")
|
|
.uses("q.S")
|
|
.build()
|
|
.uses();
|
|
assertTrue(uses.size() == 2);
|
|
assertTrue(uses.contains("p.S"));
|
|
assertTrue(uses.contains("q.S"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testUsesWithDuplicate() {
|
|
ModuleDescriptor.newModule("foo").uses("p.S").uses("p.S");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testUsesWithSimpleIdentifier() {
|
|
ModuleDescriptor.newModule("foo").uses("S");
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testUsesWithBadName(String service, String ignore) {
|
|
ModuleDescriptor.newModule("foo").uses(service);
|
|
}
|
|
|
|
|
|
// provides
|
|
|
|
private Provides provides(String st, String pc) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.provides(st, List.of(pc))
|
|
.build()
|
|
.provides()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
private Provides provides(String st, List<String> pns) {
|
|
return ModuleDescriptor.newModule("foo")
|
|
.provides(st, pns)
|
|
.build()
|
|
.provides()
|
|
.iterator()
|
|
.next();
|
|
}
|
|
|
|
public void testProvidesWithProvides() {
|
|
Provides p1 = provides("p.S", "q.S1");
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m")
|
|
.provides(p1)
|
|
.build();
|
|
Provides p2 = descriptor.provides().iterator().next();
|
|
assertEquals(p1, p2);
|
|
}
|
|
|
|
|
|
public void testProvides() {
|
|
Set<Provides> set = ModuleDescriptor.newModule("foo")
|
|
.provides("p.S", List.of("q.P1", "q.P2"))
|
|
.build()
|
|
.provides();
|
|
assertTrue(set.size() == 1);
|
|
|
|
Provides p = set.iterator().next();
|
|
assertEquals(p, p);
|
|
assertEquals(p.service(), "p.S");
|
|
assertTrue(p.providers().size() == 2);
|
|
assertEquals(p.providers().get(0), "q.P1");
|
|
assertEquals(p.providers().get(1), "q.P2");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class )
|
|
public void testProvidesWithDuplicateProvides() {
|
|
Provides p = provides("p.S", "q.S2");
|
|
ModuleDescriptor.newModule("m").provides("p.S", List.of("q.S1")).provides(p);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testProvidesWithEmptySet() {
|
|
ModuleDescriptor.newModule("foo").provides("p.Service", Collections.emptyList());
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testProvidesWithSimpleIdentifier1() {
|
|
ModuleDescriptor.newModule("foo").provides("S", List.of("q.P"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testProvidesWithSimpleIdentifier2() {
|
|
ModuleDescriptor.newModule("foo").provides("p.S", List.of("P"));
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testProvidesWithBadService(String service, String ignore) {
|
|
ModuleDescriptor.newModule("foo").provides(service, List.of("p.Provider"));
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testProvidesWithBadProvider(String provider, String ignore) {
|
|
List<String> names = new ArrayList<>(); // allows nulls
|
|
names.add(provider);
|
|
ModuleDescriptor.newModule("foo").provides("p.Service", names);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testProvidesWithNullProvides() {
|
|
ModuleDescriptor.newModule("foo").provides((Provides) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testProvidesWithNullProviders() {
|
|
ModuleDescriptor.newModule("foo").provides("p.S", (List<String>) null);
|
|
}
|
|
|
|
public void testProvidesCompare() {
|
|
Provides p1 = provides("p.S", "q.S1");
|
|
Provides p2 = provides("p.S", "q.S1");
|
|
assertEquals(p1, p2);
|
|
assertTrue(p1.hashCode() == p2.hashCode());
|
|
assertTrue(p1.compareTo(p2) == 0);
|
|
assertTrue(p2.compareTo(p1) == 0);
|
|
}
|
|
|
|
public void testProvidesCompareWithDifferentService() {
|
|
Provides p1 = provides("p.S2", "q.S1");
|
|
Provides p2 = provides("p.S1", "q.S1");
|
|
assertNotEquals(p1, p2);
|
|
assertTrue(p1.compareTo(p2) == 1);
|
|
assertTrue(p2.compareTo(p1) == -1);
|
|
}
|
|
|
|
public void testProvidesCompareWithDifferentProviders1() {
|
|
Provides p1 = provides("p.S", "q.S2");
|
|
Provides p2 = provides("p.S", "q.S1");
|
|
assertNotEquals(p1, p2);
|
|
assertTrue(p1.compareTo(p2) == 1);
|
|
assertTrue(p2.compareTo(p1) == -1);
|
|
}
|
|
|
|
public void testProvidesCompareWithDifferentProviders2() {
|
|
Provides p1 = provides("p.S", List.of("q.S1", "q.S2"));
|
|
Provides p2 = provides("p.S", "q.S1");
|
|
assertNotEquals(p1, p2);
|
|
assertTrue(p1.compareTo(p2) == 1);
|
|
assertTrue(p2.compareTo(p1) == -1);
|
|
}
|
|
|
|
// packages
|
|
|
|
public void testPackages1() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p", "q"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 2);
|
|
assertTrue(packages.contains("p"));
|
|
assertTrue(packages.contains("q"));
|
|
}
|
|
|
|
public void testPackages2() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.packages(Set.of("q"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 2);
|
|
assertTrue(packages.contains("p"));
|
|
assertTrue(packages.contains("q"));
|
|
}
|
|
|
|
|
|
public void testPackagesWithEmptySet() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Collections.emptySet())
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 0);
|
|
}
|
|
|
|
public void testPackagesDuplicate() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.packages(Set.of("p"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndExportsPackage1() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.exports("p")
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndExportsPackage2() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.exports("p")
|
|
.packages(Set.of("p"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndOpensPackage1() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.opens("p")
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndOpensPackage2() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.opens("p")
|
|
.packages(Set.of("p"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndProvides1() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.provides("q.S", List.of("p.T"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndProvides2() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.provides("q.S", List.of("p.T"))
|
|
.packages(Set.of("p"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndMainClass1() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.packages(Set.of("p"))
|
|
.mainClass("p.Main")
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndMainClass2() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.mainClass("p.Main")
|
|
.packages(Set.of("p"))
|
|
.build()
|
|
.packages();
|
|
assertTrue(packages.size() == 1);
|
|
assertTrue(packages.contains("p"));
|
|
}
|
|
|
|
public void testPackagesAndAll() {
|
|
Set<String> packages = ModuleDescriptor.newModule("foo")
|
|
.exports("p1")
|
|
.opens("p2")
|
|
.packages(Set.of("p3"))
|
|
.provides("q.S", List.of("p4.T"))
|
|
.mainClass("p5.Main")
|
|
.build()
|
|
.packages();
|
|
assertTrue(Objects.equals(packages, Set.of("p1", "p2", "p3", "p4", "p5")));
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testPackagesWithBadName(String pn, String ignore) {
|
|
Set<String> pkgs = new HashSet<>(); // allows nulls
|
|
pkgs.add(pn);
|
|
ModuleDescriptor.newModule("foo").packages(pkgs);
|
|
}
|
|
|
|
// name
|
|
|
|
public void testModuleName() {
|
|
String mn = ModuleDescriptor.newModule("foo").build().name();
|
|
assertEquals(mn, "foo");
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testBadModuleName(String mn, String ignore) {
|
|
ModuleDescriptor.newModule(mn);
|
|
}
|
|
|
|
|
|
// version
|
|
|
|
public void testVersion1() {
|
|
Version v1 = Version.parse("1.0");
|
|
Version v2 = ModuleDescriptor.newModule("foo")
|
|
.version(v1)
|
|
.build()
|
|
.version()
|
|
.get();
|
|
assertEquals(v1, v2);
|
|
}
|
|
|
|
public void testVersion2() {
|
|
String vs = "1.0";
|
|
Version v1 = ModuleDescriptor.newModule("foo")
|
|
.version(vs)
|
|
.build()
|
|
.version()
|
|
.get();
|
|
Version v2 = Version.parse(vs);
|
|
assertEquals(v1, v2);
|
|
}
|
|
|
|
@Test(expectedExceptions = NullPointerException.class )
|
|
public void testNullVersion1() {
|
|
ModuleDescriptor.newModule("foo").version((Version) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testNullVersion2() {
|
|
ModuleDescriptor.newModule("foo").version((String) null);
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class )
|
|
public void testEmptyVersion() {
|
|
ModuleDescriptor.newModule("foo").version("");
|
|
}
|
|
|
|
|
|
@DataProvider(name = "unparseableVersions")
|
|
public Object[][] unparseableVersions() {
|
|
return new Object[][]{
|
|
|
|
{ null, "A1" }, // no version < unparseable
|
|
{ "A1", "A2" }, // unparseable < unparseable
|
|
{ "A1", "1.0" }, // unparseable < parseable
|
|
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Basic test for unparseable module versions
|
|
*/
|
|
@Test(dataProvider = "unparseableVersions")
|
|
public void testUnparseableModuleVersion(String vs1, String vs2) {
|
|
ModuleDescriptor descriptor1 = newModule("m", vs1);
|
|
ModuleDescriptor descriptor2 = newModule("m", vs2);
|
|
|
|
if (vs1 != null && !isParsableVersion(vs1)) {
|
|
assertFalse(descriptor1.version().isPresent());
|
|
assertTrue(descriptor1.rawVersion().isPresent());
|
|
assertEquals(descriptor1.rawVersion().get(), vs1);
|
|
}
|
|
|
|
if (vs2 != null && !isParsableVersion(vs2)) {
|
|
assertFalse(descriptor2.version().isPresent());
|
|
assertTrue(descriptor2.rawVersion().isPresent());
|
|
assertEquals(descriptor2.rawVersion().get(), vs2);
|
|
}
|
|
|
|
assertFalse(descriptor1.equals(descriptor2));
|
|
assertFalse(descriptor2.equals(descriptor1));
|
|
assertTrue(descriptor1.compareTo(descriptor2) == -1);
|
|
assertTrue(descriptor2.compareTo(descriptor1) == 1);
|
|
}
|
|
|
|
/**
|
|
* Basic test for requiring a module with an unparseable version recorded
|
|
* at compile version.
|
|
*/
|
|
@Test(dataProvider = "unparseableVersions")
|
|
public void testUnparseableCompiledVersion(String vs1, String vs2) {
|
|
Requires r1 = newRequires("m", vs1);
|
|
Requires r2 = newRequires("m", vs2);
|
|
|
|
if (vs1 != null && !isParsableVersion(vs1)) {
|
|
assertFalse(r1.compiledVersion().isPresent());
|
|
assertTrue(r1.rawCompiledVersion().isPresent());
|
|
assertEquals(r1.rawCompiledVersion().get(), vs1);
|
|
}
|
|
|
|
if (vs2 != null && !isParsableVersion(vs2)) {
|
|
assertFalse(r2.compiledVersion().isPresent());
|
|
assertTrue(r2.rawCompiledVersion().isPresent());
|
|
assertEquals(r2.rawCompiledVersion().get(), vs2);
|
|
}
|
|
|
|
assertFalse(r1.equals(r2));
|
|
assertFalse(r2.equals(r1));
|
|
assertTrue(r1.compareTo(r2) == -1);
|
|
assertTrue(r2.compareTo(r1) == 1);
|
|
}
|
|
|
|
private ModuleDescriptor newModule(String name, String vs) {
|
|
Builder builder = JLMA.newModuleBuilder(name, false, Set.of());
|
|
if (vs != null)
|
|
builder.version(vs);
|
|
builder.requires("java.base");
|
|
ByteBuffer bb = ModuleInfoWriter.toByteBuffer(builder.build());
|
|
return ModuleDescriptor.read(bb);
|
|
}
|
|
|
|
private Requires newRequires(String name, String vs) {
|
|
Builder builder = JLMA.newModuleBuilder("foo", false, Set.of());
|
|
if (vs == null) {
|
|
builder.requires(name);
|
|
} else {
|
|
JLMA.requires(builder, Set.of(), name, vs);
|
|
}
|
|
Set<ModuleDescriptor.Requires> requires = builder.build().requires();
|
|
Iterator<ModuleDescriptor.Requires> iterator = requires.iterator();
|
|
ModuleDescriptor.Requires r = iterator.next();
|
|
if (r.name().equals("java.base")) {
|
|
r = iterator.next();
|
|
}
|
|
return r;
|
|
}
|
|
|
|
private boolean isParsableVersion(String vs) {
|
|
try {
|
|
Version.parse(vs);
|
|
return true;
|
|
} catch (IllegalArgumentException e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
// toNameAndVersion
|
|
|
|
public void testToNameAndVersion() {
|
|
ModuleDescriptor md1 = ModuleDescriptor.newModule("foo").build();
|
|
assertEquals(md1.toNameAndVersion(), "foo");
|
|
|
|
ModuleDescriptor md2 = ModuleDescriptor.newModule("foo").version("1.0").build();
|
|
assertEquals(md2.toNameAndVersion(), "foo@1.0");
|
|
}
|
|
|
|
|
|
// open modules
|
|
|
|
public void testOpenModule() {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newOpenModule("foo")
|
|
.requires("bar")
|
|
.exports("p")
|
|
.provides("p.Service", List.of("q.ServiceImpl"))
|
|
.build();
|
|
|
|
// modifiers
|
|
assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.OPEN));
|
|
assertTrue(descriptor.isOpen());
|
|
|
|
// requires
|
|
assertTrue(descriptor.requires().size() == 2);
|
|
Set<String> names = descriptor.requires()
|
|
.stream()
|
|
.map(Requires::name)
|
|
.collect(Collectors.toSet());
|
|
assertEquals(names, Set.of("bar", "java.base"));
|
|
|
|
// packages
|
|
assertEquals(descriptor.packages(), Set.of("p", "q"));
|
|
|
|
// exports
|
|
assertTrue(descriptor.exports().size() == 1);
|
|
names = descriptor.exports()
|
|
.stream()
|
|
.map(Exports::source)
|
|
.collect(Collectors.toSet());
|
|
assertEquals(names, Set.of("p"));
|
|
|
|
// opens
|
|
assertTrue(descriptor.opens().isEmpty());
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensOnOpenModule1() {
|
|
ModuleDescriptor.newOpenModule("foo").opens("p");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensOnOpenModule2() {
|
|
ModuleDescriptor.newOpenModule("foo").opens("p", Set.of("bar"));
|
|
}
|
|
|
|
public void testIsOpen() {
|
|
assertFalse(ModuleDescriptor.newModule("m").build().isOpen());
|
|
assertFalse(ModuleDescriptor.newAutomaticModule("m").build().isOpen());
|
|
assertTrue(ModuleDescriptor.newOpenModule("m").build().isOpen());
|
|
}
|
|
|
|
|
|
// automatic modules
|
|
|
|
public void testAutomaticModule() {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newAutomaticModule("foo")
|
|
.packages(Set.of("p"))
|
|
.provides("p.Service", List.of("q.ServiceImpl"))
|
|
.build();
|
|
|
|
// modifiers
|
|
assertTrue(descriptor.modifiers().contains(ModuleDescriptor.Modifier.AUTOMATIC));
|
|
assertTrue(descriptor.isAutomatic());
|
|
|
|
// requires
|
|
assertTrue(descriptor.requires().size() == 1);
|
|
Set<String> names = descriptor.requires()
|
|
.stream()
|
|
.map(Requires::name)
|
|
.collect(Collectors.toSet());
|
|
assertEquals(names, Set.of("java.base"));
|
|
|
|
// packages
|
|
assertEquals(descriptor.packages(), Set.of("p", "q"));
|
|
assertTrue(descriptor.exports().isEmpty());
|
|
assertTrue(descriptor.opens().isEmpty());
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testRequiresOnAutomaticModule() {
|
|
ModuleDescriptor.newAutomaticModule("foo").requires("java.base");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testExportsOnAutomaticModule1() {
|
|
ModuleDescriptor.newAutomaticModule("foo").exports("p");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testExportsOnAutomaticModule2() {
|
|
ModuleDescriptor.newAutomaticModule("foo").exports("p", Set.of("bar"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensOnAutomaticModule1() {
|
|
ModuleDescriptor.newAutomaticModule("foo").opens("p");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testOpensOnAutomaticModule2() {
|
|
ModuleDescriptor.newAutomaticModule("foo").opens("p", Set.of("bar"));
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalStateException.class)
|
|
public void testUsesOnAutomaticModule() {
|
|
ModuleDescriptor.newAutomaticModule("foo").uses("p.Service");
|
|
}
|
|
|
|
public void testIsAutomatic() {
|
|
ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("foo").build();
|
|
assertFalse(descriptor1.isAutomatic());
|
|
|
|
ModuleDescriptor descriptor2 = ModuleDescriptor.newOpenModule("foo").build();
|
|
assertFalse(descriptor2.isAutomatic());
|
|
|
|
ModuleDescriptor descriptor3 = ModuleDescriptor.newAutomaticModule("foo").build();
|
|
assertTrue(descriptor3.isAutomatic());
|
|
}
|
|
|
|
|
|
// newModule with modifiers
|
|
|
|
public void testNewModuleToBuildAutomaticModule() {
|
|
Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.AUTOMATIC);
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo", ms).build();
|
|
assertTrue(descriptor.modifiers().equals(ms));
|
|
assertTrue(descriptor.isAutomatic());
|
|
}
|
|
|
|
public void testNewModuleToBuildOpenModule() {
|
|
Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.OPEN);
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo", ms).build();
|
|
assertTrue(descriptor.modifiers().equals(ms));
|
|
assertTrue(descriptor.isOpen());
|
|
|
|
ms = Set.of(ModuleDescriptor.Modifier.OPEN, ModuleDescriptor.Modifier.SYNTHETIC);
|
|
descriptor = ModuleDescriptor.newModule("foo", ms).build();
|
|
assertTrue(descriptor.modifiers().equals(ms));
|
|
assertTrue(descriptor.isOpen());
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testNewModuleToBuildAutomaticAndOpenModule() {
|
|
Set<ModuleDescriptor.Modifier> ms = Set.of(ModuleDescriptor.Modifier.AUTOMATIC,
|
|
ModuleDescriptor.Modifier.OPEN);
|
|
ModuleDescriptor.newModule("foo", ms);
|
|
}
|
|
|
|
|
|
// mainClass
|
|
|
|
public void testMainClass() {
|
|
String mainClass
|
|
= ModuleDescriptor.newModule("foo").mainClass("p.Main").build().mainClass().get();
|
|
assertEquals(mainClass, "p.Main");
|
|
}
|
|
|
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
|
public void testMainClassWithSimpleIdentifier() {
|
|
ModuleDescriptor.newModule("foo").mainClass("Main");
|
|
}
|
|
|
|
@Test(dataProvider = "invalidNames",
|
|
expectedExceptions = IllegalArgumentException.class )
|
|
public void testMainClassWithBadName(String mainClass, String ignore) {
|
|
Builder builder = ModuleDescriptor.newModule("foo");
|
|
builder.mainClass(mainClass);
|
|
}
|
|
|
|
|
|
// reads
|
|
|
|
private static InputStream EMPTY_INPUT_STREAM = new InputStream() {
|
|
@Override
|
|
public int read() {
|
|
return -1;
|
|
}
|
|
};
|
|
|
|
private static InputStream FAILING_INPUT_STREAM = new InputStream() {
|
|
@Override
|
|
public int read() throws IOException {
|
|
throw new IOException();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Basic test reading module-info.class
|
|
*/
|
|
public void testRead() throws Exception {
|
|
Module base = Object.class.getModule();
|
|
|
|
try (InputStream in = base.getResourceAsStream("module-info.class")) {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.read(in);
|
|
assertTrue(in.read() == -1); // all bytes read
|
|
assertEquals(descriptor.name(), "java.base");
|
|
}
|
|
|
|
try (InputStream in = base.getResourceAsStream("module-info.class")) {
|
|
ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
|
|
ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
|
|
assertFalse(bb.hasRemaining()); // no more remaining bytes
|
|
assertEquals(descriptor.name(), "java.base");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor with a packager finder
|
|
*/
|
|
public void testReadsWithPackageFinder() throws Exception {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
|
.requires("java.base")
|
|
.build();
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
ModuleInfoWriter.write(descriptor, baos);
|
|
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
|
|
|
|
descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
|
|
|
assertTrue(descriptor.packages().size() == 2);
|
|
assertTrue(descriptor.packages().contains("p"));
|
|
assertTrue(descriptor.packages().contains("q"));
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor with a packager finder that doesn't return the
|
|
* complete set of packages.
|
|
*/
|
|
public void testReadsWithBadPackageFinder() throws Exception {
|
|
ByteBuffer bb = ByteBuffer.wrap(ClassFile.of().buildModule(
|
|
ModuleAttribute.of(
|
|
ModuleDesc.of("foo"),
|
|
mb -> mb.requires(ModuleDesc.of("java.base"), 0, null)
|
|
.exports(PackageDesc.of("p"), 0))));
|
|
|
|
// package finder returns a set that doesn't include p
|
|
assertThrows(InvalidModuleDescriptorException.class,
|
|
() -> ModuleDescriptor.read(bb, () -> Set.of("q")));
|
|
}
|
|
|
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testReadFromEmptyInputStream() throws Exception {
|
|
ModuleDescriptor.read(EMPTY_INPUT_STREAM);
|
|
}
|
|
|
|
@Test(expectedExceptions = IOException.class)
|
|
public void testReadFromFailingInputStream() throws Exception {
|
|
ModuleDescriptor.read(FAILING_INPUT_STREAM);
|
|
}
|
|
|
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testReadFromEmptyBuffer() {
|
|
ByteBuffer bb = ByteBuffer.allocate(0);
|
|
ModuleDescriptor.read(bb);
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor.read reading a module-info for java.base that has a non-0
|
|
* length requires table.
|
|
*/
|
|
public void testReadOfJavaBaseWithRequires() {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("java.base")
|
|
.requires("other")
|
|
.build();
|
|
ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
|
|
assertThrows(InvalidModuleDescriptorException.class,
|
|
() -> ModuleDescriptor.read(bb));
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor.read reading a module-info with a zero length requires table
|
|
* (no entry for java.base).
|
|
*/
|
|
public void testReadWithEmptyRequires() {
|
|
// use non-strict builder to create module that does not require java.base
|
|
ModuleDescriptor descriptor = JLMA.newModuleBuilder("m", false, Set.of()).build();
|
|
ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
|
|
assertThrows(InvalidModuleDescriptorException.class,
|
|
() -> ModuleDescriptor.read(bb));
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor.read reading a module-info with a non-zero length requires
|
|
* table that does not have entry for java.base.
|
|
*/
|
|
public void testReadWithNoRequiresBase() {
|
|
// use non-strict builder to create module that does not require java.base
|
|
ModuleDescriptor descriptor = JLMA.newModuleBuilder("m1", false, Set.of())
|
|
.requires("m2")
|
|
.build();
|
|
ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
|
|
assertThrows(InvalidModuleDescriptorException.class,
|
|
() -> ModuleDescriptor.read(bb));
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor.read reading a module-info with a requires entry for
|
|
* java.base with the ACC_SYNTHETIC flag set.
|
|
*/
|
|
public void testReadWithSynethticRequiresBase() {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("m")
|
|
.requires(Set.of(SYNTHETIC), "java.base")
|
|
.build();
|
|
ByteBuffer bb = ModuleInfoWriter.toByteBuffer(descriptor);
|
|
assertThrows(InvalidModuleDescriptorException.class,
|
|
() -> ModuleDescriptor.read(bb));
|
|
}
|
|
|
|
/**
|
|
* Test ModuleDescriptor.read with a null parameter.
|
|
*/
|
|
public void testReadWithNull() throws Exception {
|
|
Module base = Object.class.getModule();
|
|
|
|
assertThrows(NullPointerException.class,
|
|
() -> ModuleDescriptor.read((InputStream) null));
|
|
assertThrows(NullPointerException.class,
|
|
() -> ModuleDescriptor.read((ByteBuffer) null));
|
|
|
|
try (InputStream in = base.getResourceAsStream("module-info.class")) {
|
|
assertThrows(NullPointerException.class,
|
|
() -> ModuleDescriptor.read(in, null));
|
|
|
|
ByteBuffer bb = ByteBuffer.wrap(in.readAllBytes());
|
|
assertThrows(NullPointerException.class,
|
|
() -> ModuleDescriptor.read(bb, null));
|
|
}
|
|
}
|
|
|
|
|
|
// equals/hashCode/compareTo/toString
|
|
|
|
public void testEqualsAndHashCode() {
|
|
ModuleDescriptor md1 = ModuleDescriptor.newModule("m").build();
|
|
ModuleDescriptor md2 = ModuleDescriptor.newModule("m").build();
|
|
assertEquals(md1, md1);
|
|
assertEquals(md1.hashCode(), md2.hashCode());
|
|
assertTrue(md1.compareTo(md2) == 0);
|
|
assertTrue(md2.compareTo(md1) == 0);
|
|
}
|
|
|
|
@DataProvider(name = "sortedModuleDescriptors")
|
|
public Object[][] sortedModuleDescriptors() {
|
|
return new Object[][]{
|
|
|
|
{ ModuleDescriptor.newModule("m2").build(),
|
|
ModuleDescriptor.newModule("m1").build()
|
|
},
|
|
|
|
{ ModuleDescriptor.newModule("m").version("2").build(),
|
|
ModuleDescriptor.newModule("m").version("1").build()
|
|
},
|
|
|
|
{ ModuleDescriptor.newModule("m").version("1").build(),
|
|
ModuleDescriptor.newModule("m").build()
|
|
},
|
|
|
|
{ ModuleDescriptor.newOpenModule("m").build(),
|
|
ModuleDescriptor.newModule("m").build()
|
|
},
|
|
|
|
};
|
|
}
|
|
|
|
@Test(dataProvider = "sortedModuleDescriptors")
|
|
public void testCompare(ModuleDescriptor md1, ModuleDescriptor md2) {
|
|
assertNotEquals(md1, md2);
|
|
assertTrue(md1.compareTo(md2) == 1);
|
|
assertTrue(md2.compareTo(md1) == -1);
|
|
}
|
|
|
|
public void testToString() {
|
|
String s = ModuleDescriptor.newModule("m1")
|
|
.requires("m2")
|
|
.exports("p1")
|
|
.build()
|
|
.toString();
|
|
assertTrue(s.contains("m1"));
|
|
assertTrue(s.contains("m2"));
|
|
assertTrue(s.contains("p1"));
|
|
}
|
|
|
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testRequiresTransitiveJavaBaseNotPermitted1() throws Exception {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
|
.build();
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
ModuleInfoWriter.write(descriptor, baos);
|
|
ByteBuffer bb = ByteBuffer.wrap(baos.toByteArray());
|
|
|
|
ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
|
}
|
|
|
|
@Test(expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testRequiresTransitiveJavaBaseNotPermitted2() throws Exception {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
|
.build();
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
ModuleInfoWriter.write(descriptor, baos);
|
|
byte[] bytecode = baos.toByteArray();
|
|
ByteBuffer bb = ByteBuffer.wrap(bytecode);
|
|
setClassFileVersion(bb, ClassFile.JAVA_21_VERSION, -1);
|
|
|
|
ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
|
}
|
|
|
|
public void testRequiresTransitiveJavaBasePermitted() throws Exception {
|
|
ModuleDescriptor descriptor = ModuleDescriptor.newModule("foo")
|
|
.requires(Set.of(Modifier.TRANSITIVE), "java.base")
|
|
.build();
|
|
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
ModuleInfoWriter.write(descriptor, baos);
|
|
byte[] bytecode = baos.toByteArray();
|
|
ByteBuffer bb = ByteBuffer.wrap(bytecode);
|
|
setClassFileVersion(bb, -1, ClassFile.PREVIEW_MINOR_VERSION);
|
|
|
|
descriptor = ModuleDescriptor.read(bb, () -> Set.of("p", "q"));
|
|
|
|
assertEquals(descriptor.requires().size(), 1);
|
|
Requires javaBase = descriptor.requires().iterator().next();
|
|
assertEquals(javaBase.name(), "java.base");
|
|
assertEquals(javaBase.modifiers(), Set.of(Modifier.TRANSITIVE));
|
|
}
|
|
|
|
/**Change the classfile versions of the provided classfile to the provided
|
|
* values.
|
|
*
|
|
* @param bytecode the classfile content to modify
|
|
* @param major the major classfile version to set,
|
|
* -1 if the existing version should be kept
|
|
* @param minor the minor classfile version to set,
|
|
* -1 if the existing version should be kept
|
|
*/
|
|
private void setClassFileVersion(ByteBuffer bb, int major, int minor) {
|
|
if (minor != (-1)) {
|
|
bb.putShort(4, (short) minor);
|
|
}
|
|
if (major != (-1)) {
|
|
bb.putShort(6, (short) major);
|
|
}
|
|
}
|
|
}
|