| /* |
| * Copyright (c) 2016, 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 |
| * @modules java.base/jdk.internal.misc |
| * java.base/jdk.internal.module |
| * @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.misc.SharedSecrets; |
| import jdk.internal.module.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(); |
| } |
| } |