2b00ac0d02
Reviewed-by: ihse, mchung, vromero
266 lines
10 KiB
Java
266 lines
10 KiB
Java
/*
|
|
* Copyright (c) 2016, 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
|
|
* @enablePreview
|
|
* @modules java.base/jdk.internal.access
|
|
* java.base/jdk.internal.module
|
|
* @library /test/lib
|
|
* @build jdk.test.lib.util.ModuleInfoWriter
|
|
* @run testng ModuleNamesTest
|
|
* @summary Basic test of reading a module-info.class with module names that
|
|
* are legal in class files but not legal in the Java Language
|
|
*/
|
|
|
|
import java.io.ByteArrayOutputStream;
|
|
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.nio.ByteBuffer;
|
|
import java.util.Optional;
|
|
import java.util.Set;
|
|
|
|
import jdk.internal.access.SharedSecrets;
|
|
|
|
import jdk.test.lib.util.ModuleInfoWriter;
|
|
|
|
import org.testng.annotations.DataProvider;
|
|
import org.testng.annotations.Test;
|
|
import static org.testng.Assert.*;
|
|
|
|
@Test
|
|
public class ModuleNamesTest {
|
|
|
|
@DataProvider(name = "legalModuleNames")
|
|
public Object[][] legalModuleNames() {
|
|
return new Object[][] {
|
|
|
|
{ ".", "." },
|
|
{ ".foo", ".foo" },
|
|
{ "foo.", "foo." },
|
|
{ "foo.bar", "foo.bar" },
|
|
|
|
{ "..", ".." },
|
|
{ "..foo", "..foo" },
|
|
{ "foo..", "foo.." },
|
|
{ "foo..bar", "foo..bar" },
|
|
|
|
{ "[", "[" },
|
|
{ "[foo", "[foo" },
|
|
{ "foo[", "foo[" },
|
|
{ "foo[bar", "foo[bar" },
|
|
|
|
{ ";", ";" },
|
|
{ ";foo", ";foo" },
|
|
{ "foo;", "foo;" },
|
|
{ "foo;bar", "foo;bar" },
|
|
|
|
{ "\\\\", "\\" },
|
|
{ "\\\\foo", "\\foo" },
|
|
{ "foo\\\\", "foo\\" },
|
|
{ "foo\\\\bar", "foo\\bar" },
|
|
|
|
{ "\\\\\\\\", "\\\\" },
|
|
{ "\\\\\\\\foo", "\\\\foo" },
|
|
{ "foo\\\\\\\\", "foo\\\\" },
|
|
{ "foo\\\\\\\\bar", "foo\\\\bar" },
|
|
|
|
{ "\\:", ":" },
|
|
{ "\\:foo", ":foo" },
|
|
{ "foo\\:", "foo:" },
|
|
{ "foo\\:bar", "foo:bar" },
|
|
|
|
{ "\\:\\:", "::" },
|
|
{ "\\:\\:foo", "::foo" },
|
|
{ "foo\\:\\:", "foo::" },
|
|
{ "foo\\:\\:bar", "foo::bar" },
|
|
|
|
{ "\\@", "@" },
|
|
{ "\\@foo", "@foo" },
|
|
{ "foo\\@", "foo@" },
|
|
{ "foo\\@bar", "foo@bar" },
|
|
|
|
{ "\\@\\@", "@@" },
|
|
{ "\\@\\@foo", "@@foo" },
|
|
{ "foo\\@\\@", "foo@@" },
|
|
{ "foo\\@\\@bar", "foo@@bar" },
|
|
|
|
{ makeString("", 0x20, ""), " " },
|
|
{ makeString("foo", 0x20, ""), "foo " },
|
|
{ makeString("", 0x20, "foo"), " foo" },
|
|
{ makeString("foo", 0x20, "bar"), "foo bar" },
|
|
};
|
|
}
|
|
|
|
@DataProvider(name = "illegalModuleNames")
|
|
public Object[][] illegalModuleNames() {
|
|
return new Object[][] {
|
|
|
|
{ "", null },
|
|
|
|
{ ":", null },
|
|
{ ":foo", null },
|
|
{ "foo:", null },
|
|
{ "foo:bar", null },
|
|
|
|
{ "@", null },
|
|
{ "@foo", null },
|
|
{ "foo@", null },
|
|
{ "foo@bar", null },
|
|
|
|
{ "\\", null },
|
|
{ "\\foo", null },
|
|
{ "foo\\", null },
|
|
{ "foo\\bar", null },
|
|
|
|
{ makeString("", 0x00, ""), null },
|
|
{ makeString("", 0x00, "foo"), null },
|
|
{ makeString("foo", 0x00, ""), null },
|
|
{ makeString("foo", 0x00, "bar"), null },
|
|
|
|
{ makeString("", 0x1f, ""), null },
|
|
{ makeString("", 0x1f, "foo"), null },
|
|
{ makeString("foo", 0x1f, ""), null },
|
|
{ makeString("foo", 0x1f, "bar"), null },
|
|
|
|
};
|
|
}
|
|
|
|
@Test(dataProvider = "legalModuleNames")
|
|
public void testLegalModuleName(String mn, String expected) throws Exception {
|
|
ModuleDescriptor md = newBuilder(mn).requires("java.base").build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
String name = ModuleDescriptor.read(bb).name();
|
|
assertEquals(name, expected);
|
|
}
|
|
|
|
@Test(dataProvider = "illegalModuleNames",
|
|
expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testIllegalModuleName(String mn, String ignore) throws Exception {
|
|
ModuleDescriptor md = newBuilder(mn).requires("java.base").build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException
|
|
}
|
|
|
|
@Test(dataProvider = "legalModuleNames")
|
|
public void testLegalRequires(String mn, String expected) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m").requires("java.base").requires(mn).build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
|
|
Optional<Requires> requires = descriptor.requires().stream()
|
|
.filter(r -> !r.name().equals("java.base"))
|
|
.findAny();
|
|
assertTrue(requires.isPresent());
|
|
assertEquals(requires.get().name(), expected);
|
|
}
|
|
|
|
@Test(dataProvider = "illegalModuleNames",
|
|
expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testIllegalRequires(String mn, String ignore) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m").requires("java.base").requires(mn).build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException
|
|
}
|
|
|
|
@Test(dataProvider = "legalModuleNames")
|
|
public void testLegalExports(String mn, String expected) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m")
|
|
.requires("java.base")
|
|
.exports("p", Set.of(mn))
|
|
.build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
|
|
Optional<Exports> export = descriptor.exports().stream().findAny();
|
|
assertTrue(export.isPresent());
|
|
assertTrue(export.get().targets().contains(expected));
|
|
}
|
|
|
|
@Test(dataProvider = "illegalModuleNames",
|
|
expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testIllegalExports(String mn, String ignore) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m")
|
|
.requires("java.base")
|
|
.exports("p", Set.of(mn))
|
|
.build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException
|
|
}
|
|
|
|
@Test(dataProvider = "legalModuleNames")
|
|
public void testLegalOpens(String mn, String expected) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m")
|
|
.requires("java.base")
|
|
.opens("p", Set.of(mn))
|
|
.build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor descriptor = ModuleDescriptor.read(bb);
|
|
Optional<Opens> opens = descriptor.opens().stream().findAny();
|
|
assertTrue(opens.isPresent());
|
|
assertTrue(opens.get().targets().contains(expected));
|
|
}
|
|
|
|
@Test(dataProvider = "illegalModuleNames",
|
|
expectedExceptions = InvalidModuleDescriptorException.class)
|
|
public void testIllegalOpens(String mn, String ignore) throws Exception {
|
|
ModuleDescriptor md = newBuilder("m")
|
|
.requires("java.base")
|
|
.opens("p", Set.of(mn))
|
|
.build();
|
|
ByteBuffer bb = toBuffer(md);
|
|
ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException
|
|
}
|
|
|
|
/**
|
|
* Returns a Builder that does not validate module names.
|
|
*/
|
|
private Builder newBuilder(String mn) {
|
|
return SharedSecrets.getJavaLangModuleAccess()
|
|
.newModuleBuilder(mn, false, Set.of());
|
|
}
|
|
|
|
/**
|
|
* Returns a {@code ByteBuffer} containing the given module descriptor
|
|
* in module-info.class format.
|
|
*/
|
|
private ByteBuffer toBuffer(ModuleDescriptor descriptor) throws Exception {
|
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
ModuleInfoWriter.write(descriptor, baos);
|
|
return ByteBuffer.wrap(baos.toByteArray());
|
|
}
|
|
|
|
/**
|
|
* Returns a string containing a given code point.
|
|
*/
|
|
private String makeString(String prefix, int codePoint, String suffix) {
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.append(prefix);
|
|
sb.appendCodePoint(codePoint);
|
|
sb.append(suffix);
|
|
return sb.toString();
|
|
}
|
|
}
|