1 /*
2  * Copyright (c) 2016, 2018, 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")
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")
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")
testLegalModuleName(String mn, String expected)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)
testIllegalModuleName(String mn, String ignore)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")
testLegalRequires(String mn, String expected)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)
testIllegalRequires(String mn, String ignore)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")
testLegalExports(String mn, String expected)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)
testIllegalExports(String mn, String ignore)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")
testLegalOpens(String mn, String expected)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)
testIllegalOpens(String mn, String ignore)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      */
newBuilder(String mn)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      */
toBuffer(ModuleDescriptor descriptor)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      */
makeString(String prefix, int codePoint, String suffix)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 }
262