ModuleReaderTest.java revision 16909:085c764a3e5b
1215976Sjmallett/*
2232812Sjmallett * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3215976Sjmallett * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4215976Sjmallett *
5215976Sjmallett * This code is free software; you can redistribute it and/or modify it
6215976Sjmallett * under the terms of the GNU General Public License version 2 only, as
7215976Sjmallett * published by the Free Software Foundation.
8215976Sjmallett *
9215976Sjmallett * This code is distributed in the hope that it will be useful, but WITHOUT
10215976Sjmallett * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11215976Sjmallett * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12215976Sjmallett * version 2 for more details (a copy is included in the LICENSE file that
13215976Sjmallett * accompanied this code).
14215976Sjmallett *
15215976Sjmallett * You should have received a copy of the GNU General Public License version
16215976Sjmallett * 2 along with this work; if not, write to the Free Software Foundation,
17215976Sjmallett * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18232812Sjmallett *
19215976Sjmallett * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20215976Sjmallett * or visit www.oracle.com if you need additional information or have any
21215976Sjmallett * questions.
22215976Sjmallett */
23215976Sjmallett
24215976Sjmallett/**
25215976Sjmallett * @test
26215976Sjmallett * @library /lib/testlibrary
27215976Sjmallett * @modules java.base/jdk.internal.module
28215976Sjmallett *          jdk.compiler
29232812Sjmallett * @build ModuleReaderTest CompilerUtils JarUtils
30215976Sjmallett * @run testng ModuleReaderTest
31215976Sjmallett * @summary Basic tests for java.lang.module.ModuleReader
32215976Sjmallett */
33215976Sjmallett
34215976Sjmallettimport java.io.File;
35215976Sjmallettimport java.io.IOException;
36215976Sjmallettimport java.io.InputStream;
37215976Sjmallettimport java.lang.module.ModuleFinder;
38215976Sjmallettimport java.lang.module.ModuleReader;
39215976Sjmallettimport java.lang.module.ModuleReference;
40215976Sjmallettimport java.lang.reflect.Module;
41215976Sjmallettimport java.net.URI;
42215976Sjmallettimport java.net.URL;
43215976Sjmallettimport java.net.URLConnection;
44215976Sjmallettimport java.nio.ByteBuffer;
45215976Sjmallettimport java.nio.file.Files;
46232812Sjmallettimport java.nio.file.Path;
47215976Sjmallettimport java.nio.file.Paths;
48215976Sjmallettimport java.util.Arrays;
49215976Sjmallettimport java.util.HashSet;
50215976Sjmallettimport java.util.List;
51215976Sjmallettimport java.util.Optional;
52215976Sjmallettimport java.util.Set;
53215976Sjmallettimport java.util.stream.Collectors;
54215976Sjmallettimport java.util.spi.ToolProvider;
55215976Sjmallett
56232812Sjmallettimport jdk.internal.module.ModulePath;
57232812Sjmallett
58232812Sjmallettimport org.testng.annotations.BeforeTest;
59232812Sjmallettimport org.testng.annotations.Test;
60232812Sjmallettimport static org.testng.Assert.*;
61232812Sjmallett
62232812Sjmallett@Test
63232812Sjmallettpublic class ModuleReaderTest {
64232812Sjmallett
65232812Sjmallett    private static final String TEST_SRC = System.getProperty("test.src");
66232812Sjmallett
67232812Sjmallett    private static final Path USER_DIR   = Paths.get(System.getProperty("user.dir"));
68232812Sjmallett    private static final Path SRC_DIR    = Paths.get(TEST_SRC, "src");
69232812Sjmallett    private static final Path MODS_DIR   = Paths.get("mods");
70232812Sjmallett
71232812Sjmallett    // the module name of the base module
72215976Sjmallett    private static final String BASE_MODULE = "java.base";
73232812Sjmallett
74232812Sjmallett    // the module name of the test module
75232812Sjmallett    private static final String TEST_MODULE = "m";
76232812Sjmallett
77215976Sjmallett    // resources in the base module
78232812Sjmallett    private static final String[] BASE_RESOURCES = {
79215976Sjmallett        "java/lang/Object.class"
80232812Sjmallett    };
81232812Sjmallett
82232812Sjmallett    // (directory) resources that may be in the base module
83232812Sjmallett    private static final String[] MAYBE_BASE_RESOURCES = {
84232812Sjmallett        "java",
85232812Sjmallett        "java/",
86232812Sjmallett        "java/lang",
87232812Sjmallett        "java/lang/",
88232812Sjmallett    };
89215976Sjmallett
90215976Sjmallett    // resource names that should not be found in the base module
91232812Sjmallett    private static final String[] NOT_BASE_RESOURCES = {
92232812Sjmallett        "NotFound",
93215976Sjmallett        "/java",
94232812Sjmallett        "//java",
95232812Sjmallett        "/java/lang",
96215976Sjmallett        "//java/lang",
97215976Sjmallett        "java//lang",
98232812Sjmallett        "/java/lang/Object.class",
99232812Sjmallett        "//java/lang/Object.class",
100232812Sjmallett        "java/lang/Object.class/",
101232812Sjmallett        "java//lang//Object.class",
102232812Sjmallett        "./java/lang/Object.class",
103232812Sjmallett        "java/./lang/Object.class",
104215976Sjmallett        "java/lang/./Object.class",
105232812Sjmallett        "../java/lang/Object.class",
106232812Sjmallett        "java/../lang/Object.class",
107215976Sjmallett        "java/lang/../Object.class",
108215976Sjmallett    };
109232812Sjmallett
110232812Sjmallett    // resources in test module (can't use module-info.class as a test
111232812Sjmallett    // resource as it will be modified by the jmod tool)
112232812Sjmallett    private static final String[] TEST_RESOURCES = {
113232812Sjmallett        "p/Main.class"
114215976Sjmallett    };
115232812Sjmallett
116215976Sjmallett    // (directory) resources that may be in the test module
117215976Sjmallett    private static final String[] MAYBE_TEST_RESOURCES = {
118215976Sjmallett        "p",
119215976Sjmallett        "p/"
120215976Sjmallett    };
121
122    // resource names that should not be found in the test module
123    private static final String[] NOT_TEST_RESOURCES = {
124        "NotFound",
125        "/p",
126        "//p",
127        "/p/Main.class",
128        "//p/Main.class",
129        "p/Main.class/",
130        "p//Main.class",
131        "./p/Main.class",
132        "p/./Main.class",
133        "../p/Main.class",
134        "p/../p/Main.class"
135    };
136
137
138    @BeforeTest
139    public void compileTestModule() throws Exception {
140
141        // javac -d mods/$TESTMODULE src/$TESTMODULE/**
142        boolean compiled
143            = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
144                                    MODS_DIR.resolve(TEST_MODULE));
145        assertTrue(compiled, "test module did not compile");
146    }
147
148
149    /**
150     * Test ModuleReader to module in runtime image
151     */
152    public void testImage() throws IOException {
153
154        ModuleFinder finder = ModuleFinder.ofSystem();
155        ModuleReference mref = finder.find(BASE_MODULE).get();
156        ModuleReader reader = mref.open();
157
158        try (reader) {
159
160            for (String name : BASE_RESOURCES) {
161                byte[] expectedBytes;
162                Module baseModule = Object.class.getModule();
163                try (InputStream in = baseModule.getResourceAsStream(name)) {
164                    expectedBytes = in.readAllBytes();
165                }
166
167                testFind(reader, name, expectedBytes);
168                testOpen(reader, name, expectedBytes);
169                testRead(reader, name, expectedBytes);
170                testList(reader, name);
171            }
172
173            // test resources that may be in the base module
174            for (String name : MAYBE_BASE_RESOURCES) {
175                Optional<URI> ouri = reader.find(name);
176                ouri.ifPresent(uri -> {
177                    if (name.endsWith("/"))
178                        assertTrue(uri.toString().endsWith("/"));
179                });
180            }
181
182            // test "not found" in java.base module
183            for (String name : NOT_BASE_RESOURCES) {
184                assertFalse(reader.find(name).isPresent());
185                assertFalse(reader.open(name).isPresent());
186                assertFalse(reader.read(name).isPresent());
187            }
188
189            // test nulls
190            try {
191                reader.find(null);
192                assertTrue(false);
193            } catch (NullPointerException expected) { }
194
195            try {
196                reader.open(null);
197                assertTrue(false);
198            } catch (NullPointerException expected) { }
199
200            try {
201                reader.read(null);
202                assertTrue(false);
203            } catch (NullPointerException expected) { }
204
205            try {
206                reader.release(null);
207                assertTrue(false);
208            } catch (NullPointerException expected) { }
209
210        }
211
212        // test closed ModuleReader
213        try {
214            reader.open(BASE_RESOURCES[0]);
215            assertTrue(false);
216        } catch (IOException expected) { }
217
218
219        try {
220            reader.read(BASE_RESOURCES[0]);
221            assertTrue(false);
222        } catch (IOException expected) { }
223    }
224
225
226    /**
227     * Test ModuleReader to exploded module
228     */
229    public void testExplodedModule() throws IOException {
230        test(MODS_DIR);
231    }
232
233
234    /**
235     * Test ModuleReader to modular JAR
236     */
237    public void testModularJar() throws IOException {
238        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
239
240        // jar cf mlib/${TESTMODULE}.jar -C mods .
241        JarUtils.createJarFile(dir.resolve("m.jar"),
242                               MODS_DIR.resolve(TEST_MODULE));
243
244        test(dir);
245    }
246
247
248    /**
249     * Test ModuleReader to JMOD
250     */
251    public void testJMod() throws IOException {
252        Path dir = Files.createTempDirectory(USER_DIR, "mlib");
253
254        // jmod create --class-path mods/${TESTMODULE}  mlib/${TESTMODULE}.jmod
255        String cp = MODS_DIR.resolve(TEST_MODULE).toString();
256        String jmod = dir.resolve("m.jmod").toString();
257        String[] args = { "create", "--class-path", cp, jmod };
258        ToolProvider jmodTool = ToolProvider.findFirst("jmod")
259            .orElseThrow(() ->
260                new RuntimeException("jmod tool not found")
261            );
262        assertEquals(jmodTool.run(System.out, System.out, args), 0);
263
264        test(dir);
265    }
266
267
268    /**
269     * The test module is found on the given module path. Open a ModuleReader
270     * to the test module and test the reader.
271     */
272    void test(Path mp) throws IOException {
273
274        ModuleFinder finder = ModulePath.of(Runtime.version(), true, mp);
275        ModuleReference mref = finder.find(TEST_MODULE).get();
276        ModuleReader reader = mref.open();
277
278        try (reader) {
279
280            // test resources in test module
281            for (String name : TEST_RESOURCES) {
282                byte[] expectedBytes
283                    = Files.readAllBytes(MODS_DIR
284                        .resolve(TEST_MODULE)
285                        .resolve(name.replace('/', File.separatorChar)));
286
287                testFind(reader, name, expectedBytes);
288                testOpen(reader, name, expectedBytes);
289                testRead(reader, name, expectedBytes);
290                testList(reader, name);
291            }
292
293            // test resources that may be in the test module
294            for (String name : MAYBE_TEST_RESOURCES) {
295                System.out.println(name);
296                Optional<URI> ouri = reader.find(name);
297                ouri.ifPresent(uri -> {
298                    if (name.endsWith("/"))
299                        assertTrue(uri.toString().endsWith("/"));
300                });
301            }
302
303            // test "not found" in test module
304            for (String name : NOT_TEST_RESOURCES) {
305                assertFalse(reader.find(name).isPresent());
306                assertFalse(reader.open(name).isPresent());
307                assertFalse(reader.read(name).isPresent());
308            }
309
310            // test nulls
311            try {
312                reader.find(null);
313                assertTrue(false);
314            } catch (NullPointerException expected) { }
315
316            try {
317                reader.open(null);
318                assertTrue(false);
319            } catch (NullPointerException expected) { }
320
321            try {
322                reader.read(null);
323                assertTrue(false);
324            } catch (NullPointerException expected) { }
325
326            try {
327                reader.release(null);
328                throw new RuntimeException();
329            } catch (NullPointerException expected) { }
330
331        }
332
333        // test closed ModuleReader
334        try {
335            reader.open(TEST_RESOURCES[0]);
336            assertTrue(false);
337        } catch (IOException expected) { }
338
339
340        try {
341            reader.read(TEST_RESOURCES[0]);
342            assertTrue(false);
343        } catch (IOException expected) { }
344
345        try {
346            reader.list();
347            assertTrue(false);
348        } catch (IOException expected) { }
349    }
350
351    /**
352     * Test ModuleReader#find
353     */
354    void testFind(ModuleReader reader, String name, byte[] expectedBytes)
355        throws IOException
356    {
357        Optional<URI> ouri = reader.find(name);
358        assertTrue(ouri.isPresent());
359
360        URL url = ouri.get().toURL();
361        if (!url.getProtocol().equalsIgnoreCase("jmod")) {
362            URLConnection uc = url.openConnection();
363            uc.setUseCaches(false);
364            try (InputStream in = uc.getInputStream()) {
365                byte[] bytes = in.readAllBytes();
366                assertTrue(Arrays.equals(bytes, expectedBytes));
367            }
368        }
369    }
370
371    /**
372     * Test ModuleReader#open
373     */
374    void testOpen(ModuleReader reader, String name, byte[] expectedBytes)
375        throws IOException
376    {
377        Optional<InputStream> oin = reader.open(name);
378        assertTrue(oin.isPresent());
379
380        InputStream in = oin.get();
381        try (in) {
382            byte[] bytes = in.readAllBytes();
383            assertTrue(Arrays.equals(bytes, expectedBytes));
384        }
385    }
386
387    /**
388     * Test ModuleReader#read
389     */
390    void testRead(ModuleReader reader, String name, byte[] expectedBytes)
391        throws IOException
392    {
393        Optional<ByteBuffer> obb = reader.read(name);
394        assertTrue(obb.isPresent());
395
396        ByteBuffer bb = obb.get();
397        try {
398            int rem = bb.remaining();
399            assertTrue(rem == expectedBytes.length);
400            byte[] bytes = new byte[rem];
401            bb.get(bytes);
402            assertTrue(Arrays.equals(bytes, expectedBytes));
403        } finally {
404            reader.release(bb);
405        }
406    }
407
408    /**
409     * Test ModuleReader#list
410     */
411    void testList(ModuleReader reader, String name) throws IOException {
412        List<String> list = reader.list().collect(Collectors.toList());
413        Set<String> names = new HashSet<>(list);
414        assertTrue(names.size() == list.size()); // no duplicates
415
416        assertTrue(names.contains("module-info.class"));
417        assertTrue(names.contains(name));
418
419        // all resources should be locatable via find
420        for (String e : names) {
421            assertTrue(reader.find(e).isPresent());
422        }
423    }
424
425}
426