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