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 * @build jdk.test.lib.util.ModuleInfoWriter
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 }
--- EOF ---