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