1 /* 2 * Copyright (c) 2016, 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 * @modules java.base/jdk.internal.access 27 * java.base/jdk.internal.module 28 * @library /test/lib 29 * @run testng ModuleNamesTest 30 * @summary Basic test of reading a module-info.class with module names that 31 * are legal in class files but not legal in the Java Language 32 */ 33 34 import java.io.ByteArrayOutputStream; 35 import java.lang.module.InvalidModuleDescriptorException; 36 import java.lang.module.ModuleDescriptor; 37 import java.lang.module.ModuleDescriptor.Builder; 38 import java.lang.module.ModuleDescriptor.Exports; 39 import java.lang.module.ModuleDescriptor.Opens; 40 import java.lang.module.ModuleDescriptor.Requires; 41 import java.nio.ByteBuffer; 42 import java.util.Optional; 43 import java.util.Set; 44 45 import jdk.internal.access.SharedSecrets; 46 47 import jdk.test.lib.util.ModuleInfoWriter; 48 49 import org.testng.annotations.DataProvider; 50 import org.testng.annotations.Test; 51 import static org.testng.Assert.*; 52 53 @Test 54 public class ModuleNamesTest { 55 56 @DataProvider(name = "legalModuleNames") 57 public Object[][] legalModuleNames() { 58 return new Object[][] { 59 60 { ".", "." }, 61 { ".foo", ".foo" }, 62 { "foo.", "foo." }, 63 { "foo.bar", "foo.bar" }, 64 65 { "..", ".." }, 66 { "..foo", "..foo" }, 67 { "foo..", "foo.." }, 68 { "foo..bar", "foo..bar" }, 69 70 { "[", "[" }, 71 { "[foo", "[foo" }, 72 { "foo[", "foo[" }, 73 { "foo[bar", "foo[bar" }, 74 75 { ";", ";" }, 76 { ";foo", ";foo" }, 77 { "foo;", "foo;" }, 78 { "foo;bar", "foo;bar" }, 79 80 { "\\\\", "\\" }, 81 { "\\\\foo", "\\foo" }, 82 { "foo\\\\", "foo\\" }, 83 { "foo\\\\bar", "foo\\bar" }, 84 85 { "\\\\\\\\", "\\\\" }, 86 { "\\\\\\\\foo", "\\\\foo" }, 87 { "foo\\\\\\\\", "foo\\\\" }, 88 { "foo\\\\\\\\bar", "foo\\\\bar" }, 89 90 { "\\:", ":" }, 91 { "\\:foo", ":foo" }, 92 { "foo\\:", "foo:" }, 93 { "foo\\:bar", "foo:bar" }, 94 95 { "\\:\\:", "::" }, 96 { "\\:\\:foo", "::foo" }, 97 { "foo\\:\\:", "foo::" }, 98 { "foo\\:\\:bar", "foo::bar" }, 99 100 { "\\@", "@" }, 101 { "\\@foo", "@foo" }, 102 { "foo\\@", "foo@" }, 103 { "foo\\@bar", "foo@bar" }, 104 105 { "\\@\\@", "@@" }, 106 { "\\@\\@foo", "@@foo" }, 107 { "foo\\@\\@", "foo@@" }, 108 { "foo\\@\\@bar", "foo@@bar" }, 109 110 { makeString("", 0x20, ""), " " }, 111 { makeString("foo", 0x20, ""), "foo " }, 112 { makeString("", 0x20, "foo"), " foo" }, 113 { makeString("foo", 0x20, "bar"), "foo bar" }, 114 }; 115 } 116 117 @DataProvider(name = "illegalModuleNames") 118 public Object[][] illegalModuleNames() { 119 return new Object[][] { 120 121 { "", null }, 122 123 { ":", null }, 124 { ":foo", null }, 125 { "foo:", null }, 126 { "foo:bar", null }, 127 128 { "@", null }, 129 { "@foo", null }, 130 { "foo@", null }, 131 { "foo@bar", null }, 132 133 { "\\", null }, 134 { "\\foo", null }, 135 { "foo\\", null }, 136 { "foo\\bar", null }, 137 138 { makeString("", 0x00, ""), null }, 139 { makeString("", 0x00, "foo"), null }, 140 { makeString("foo", 0x00, ""), null }, 141 { makeString("foo", 0x00, "bar"), null }, 142 143 { makeString("", 0x1f, ""), null }, 144 { makeString("", 0x1f, "foo"), null }, 145 { makeString("foo", 0x1f, ""), null }, 146 { makeString("foo", 0x1f, "bar"), null }, 147 148 }; 149 } 150 151 @Test(dataProvider = "legalModuleNames") 152 public void testLegalModuleName(String mn, String expected) throws Exception { 153 ModuleDescriptor md = newBuilder(mn).requires("java.base").build(); 154 ByteBuffer bb = toBuffer(md); 155 String name = ModuleDescriptor.read(bb).name(); 156 assertEquals(name, expected); 157 } 158 159 @Test(dataProvider = "illegalModuleNames", 160 expectedExceptions = InvalidModuleDescriptorException.class) 161 public void testIllegalModuleName(String mn, String ignore) throws Exception { 162 ModuleDescriptor md = newBuilder(mn).requires("java.base").build(); 163 ByteBuffer bb = toBuffer(md); 164 ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException 165 } 166 167 @Test(dataProvider = "legalModuleNames") 168 public void testLegalRequires(String mn, String expected) throws Exception { 169 ModuleDescriptor md = newBuilder("m").requires("java.base").requires(mn).build(); 170 ByteBuffer bb = toBuffer(md); 171 ModuleDescriptor descriptor = ModuleDescriptor.read(bb); 172 Optional<Requires> requires = descriptor.requires().stream() 173 .filter(r -> !r.name().equals("java.base")) 174 .findAny(); 175 assertTrue(requires.isPresent()); 176 assertEquals(requires.get().name(), expected); 177 } 178 179 @Test(dataProvider = "illegalModuleNames", 180 expectedExceptions = InvalidModuleDescriptorException.class) 181 public void testIllegalRequires(String mn, String ignore) throws Exception { 182 ModuleDescriptor md = newBuilder("m").requires("java.base").requires(mn).build(); 183 ByteBuffer bb = toBuffer(md); 184 ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException 185 } 186 187 @Test(dataProvider = "legalModuleNames") 188 public void testLegalExports(String mn, String expected) throws Exception { 189 ModuleDescriptor md = newBuilder("m") 190 .requires("java.base") 191 .exports("p", Set.of(mn)) 192 .build(); 193 ByteBuffer bb = toBuffer(md); 194 ModuleDescriptor descriptor = ModuleDescriptor.read(bb); 195 Optional<Exports> export = descriptor.exports().stream().findAny(); 196 assertTrue(export.isPresent()); 197 assertTrue(export.get().targets().contains(expected)); 198 } 199 200 @Test(dataProvider = "illegalModuleNames", 201 expectedExceptions = InvalidModuleDescriptorException.class) 202 public void testIllegalExports(String mn, String ignore) throws Exception { 203 ModuleDescriptor md = newBuilder("m") 204 .requires("java.base") 205 .exports("p", Set.of(mn)) 206 .build(); 207 ByteBuffer bb = toBuffer(md); 208 ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException 209 } 210 211 @Test(dataProvider = "legalModuleNames") 212 public void testLegalOpens(String mn, String expected) throws Exception { 213 ModuleDescriptor md = newBuilder("m") 214 .requires("java.base") 215 .opens("p", Set.of(mn)) 216 .build(); 217 ByteBuffer bb = toBuffer(md); 218 ModuleDescriptor descriptor = ModuleDescriptor.read(bb); 219 Optional<Opens> opens = descriptor.opens().stream().findAny(); 220 assertTrue(opens.isPresent()); 221 assertTrue(opens.get().targets().contains(expected)); 222 } 223 224 @Test(dataProvider = "illegalModuleNames", 225 expectedExceptions = InvalidModuleDescriptorException.class) 226 public void testIllegalOpens(String mn, String ignore) throws Exception { 227 ModuleDescriptor md = newBuilder("m") 228 .requires("java.base") 229 .opens("p", Set.of(mn)) 230 .build(); 231 ByteBuffer bb = toBuffer(md); 232 ModuleDescriptor.read(bb); // throws InvalidModuleDescriptorException 233 } 234 235 /** 236 * Returns a Builder that does not validate module names. 237 */ 238 private Builder newBuilder(String mn) { 239 return SharedSecrets.getJavaLangModuleAccess() 240 .newModuleBuilder(mn, false, Set.of()); 241 } 242 243 /** 244 * Returns a {@code ByteBuffer} containing the given module descriptor 245 * in module-info.class format. 246 */ 247 private ByteBuffer toBuffer(ModuleDescriptor descriptor) throws Exception { 248 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 249 ModuleInfoWriter.write(descriptor, baos); 250 return ByteBuffer.wrap(baos.toByteArray()); 251 } 252 253 /** 254 * Returns a string containing a given code point. 255 */ 256 private String makeString(String prefix, int codePoint, String suffix) { 257 StringBuilder sb = new StringBuilder(); 258 sb.append(prefix); 259 sb.appendCodePoint(codePoint); 260 sb.append(suffix); 261 return sb.toString(); 262 } 263 }