/* * 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 = 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 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 = 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(); } }