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 }
--- EOF ---