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