1 /*
   2  * Copyright (c) 2015, 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  * @library ../../lib
  27  * @modules java.base/jdk.internal.module
  28  *          jdk.jlink/jdk.tools.jmod
  29  *          jdk.compiler
  30  * @build ModuleReaderTest CompilerUtils JarUtils
  31  * @run testng ModuleReaderTest
  32  * @summary Basic tests for java.lang.module.ModuleReader
  33  */
  34 
  35 import java.io.File;
  36 import java.io.IOException;
  37 import java.io.InputStream;
  38 import java.lang.module.ModuleFinder;
  39 import java.lang.module.ModuleReader;
  40 import java.lang.module.ModuleReference;
  41 import java.net.URI;
  42 import java.net.URL;
  43 import java.net.URLConnection;
  44 import java.nio.ByteBuffer;
  45 import java.nio.file.Files;
  46 import java.nio.file.Path;
  47 import java.nio.file.Paths;
  48 import java.util.Arrays;
  49 import java.util.Optional;
  50 
  51 import jdk.internal.module.ConfigurableModuleFinder;
  52 import jdk.internal.module.ConfigurableModuleFinder.Phase;
  53 
  54 import org.testng.annotations.BeforeTest;
  55 import org.testng.annotations.Test;
  56 import static org.testng.Assert.*;
  57 
  58 @Test
  59 public class ModuleReaderTest {
  60 
  61     private static final String TEST_SRC = System.getProperty("test.src");
  62 
  63     private static final Path USER_DIR   = Paths.get(System.getProperty("user.dir"));
  64     private static final Path SRC_DIR    = Paths.get(TEST_SRC, "src");
  65     private static final Path MODS_DIR   = Paths.get("mods");
  66 
  67     // the module name of the test module
  68     private static final String TEST_MODULE = "m";
  69 
  70     // resources in test module (can't use module-info.class as a test
  71     // resource as it will be modified by the jmod tool)
  72     private static final String[] RESOURCES = {
  73         "p/Main.class"
  74     };
  75 
  76     // a resource that is not in the test module
  77     private static final String NOT_A_RESOURCE = "NotAResource";
  78 
  79 
  80     @BeforeTest
  81     public void compileTestModule() throws Exception {
  82 
  83         // javac -d mods/$TESTMODULE src/$TESTMODULE/**
  84         boolean compiled
  85             = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE),
  86                                     MODS_DIR.resolve(TEST_MODULE));
  87         assertTrue(compiled, "test module did not compile");
  88     }
  89 
  90 
  91     /**
  92      * Test exploded module
  93      */
  94     public void testExplodedModule() throws Exception {
  95         test(MODS_DIR);
  96     }
  97 
  98 
  99     /**
 100      * Test modular JAR
 101      */
 102     public void testModularJar() throws Exception {
 103         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 104 
 105         // jar cf mlib/${TESTMODULE}.jar -C mods .
 106         JarUtils.createJarFile(dir.resolve("m.jar"),
 107                                MODS_DIR.resolve(TEST_MODULE));
 108 
 109         test(dir);
 110     }
 111 
 112 
 113     /**
 114      * Test JMOD
 115      */
 116     public void testJMod() throws Exception {
 117         Path dir = Files.createTempDirectory(USER_DIR, "mlib");
 118 
 119         // jmod --create --class-path mods/${TESTMODULE}  mlib/${TESTMODULE}.jmod
 120         String cp = MODS_DIR.resolve(TEST_MODULE).toString();
 121         String jmod = dir.resolve("m.jmod").toString();
 122         String[] args = { "--create", "--class-path", cp, jmod };
 123         jdk.tools.jmod.JmodTask task = new jdk.tools.jmod.JmodTask();
 124         assertEquals(task.run(args), 0);
 125 
 126         test(dir);
 127     }
 128 
 129 
 130     /**
 131      * The test module is found on the given module path. Open a ModuleReader
 132      * to the test module and test the reader.
 133      */
 134     void test(Path mp) throws Exception {
 135 
 136         ModuleFinder finder = ModuleFinder.of(mp);
 137         if (finder instanceof ConfigurableModuleFinder) {
 138             // need ModuleFinder to be in the phase to find JMOD files
 139             ((ConfigurableModuleFinder)finder).configurePhase(Phase.LINK_TIME);
 140         }
 141 
 142         ModuleReference mref = finder.find(TEST_MODULE).get();
 143         ModuleReader reader = mref.open();
 144 
 145         try (reader) {
 146 
 147             // test each of the known resources in the module
 148             for (String name : RESOURCES) {
 149                 byte[] expectedBytes
 150                     = Files.readAllBytes(MODS_DIR
 151                         .resolve(TEST_MODULE)
 152                         .resolve(name.replace('/', File.separatorChar)));
 153 
 154                 testFind(reader, name, expectedBytes);
 155                 testOpen(reader, name, expectedBytes);
 156                 testRead(reader, name, expectedBytes);
 157             }
 158 
 159             // test "not found"
 160             assertFalse(reader.open(NOT_A_RESOURCE).isPresent());
 161             assertFalse(reader.read(NOT_A_RESOURCE).isPresent());
 162 
 163             // test nulls
 164             try {
 165                 reader.find(null);
 166                 assertTrue(false);
 167             } catch (NullPointerException expected) { }
 168 
 169             try {
 170                 reader.open(null);
 171                 assertTrue(false);
 172             } catch (NullPointerException expected) { }
 173 
 174             try {
 175                 reader.read(null);
 176                 assertTrue(false);
 177             } catch (NullPointerException expected) { }
 178 
 179             // should release(null) throw NPE?
 180 
 181         }
 182 
 183         // test closed ModuleReader
 184         try {
 185             reader.open(RESOURCES[0]);
 186             assertTrue(false);
 187         } catch (IOException expected) { }
 188 
 189 
 190         try {
 191             reader.read(RESOURCES[0]);
 192             assertTrue(false);
 193         } catch (IOException expected) { }
 194     }
 195 
 196     /**
 197      * Test ModuleReader#find
 198      */
 199     void testFind(ModuleReader reader, String name, byte[] expectedBytes)
 200         throws Exception
 201     {
 202         Optional<URI> ouri = reader.find(name);
 203         assertTrue(ouri.isPresent());
 204 
 205         URL url = ouri.get().toURL();
 206         if (!url.getProtocol().equalsIgnoreCase("jmod")) {
 207             URLConnection uc = url.openConnection();
 208             uc.setUseCaches(false);
 209             try (InputStream in = uc.getInputStream()) {
 210                 byte[] bytes = in.readAllBytes();
 211                 assertTrue(Arrays.equals(bytes, expectedBytes));
 212             }
 213         }
 214     }
 215 
 216     /**
 217      * Test ModuleReader#open
 218      */
 219     void testOpen(ModuleReader reader, String name, byte[] expectedBytes)
 220         throws Exception
 221     {
 222         Optional<InputStream> oin = reader.open(name);
 223         assertTrue(oin.isPresent());
 224 
 225         InputStream in = oin.get();
 226         try (in) {
 227             byte[] bytes = in.readAllBytes();
 228             assertTrue(Arrays.equals(bytes, expectedBytes));
 229         }
 230     }
 231 
 232     /**
 233      * Test ModuleReader#read
 234      */
 235     void testRead(ModuleReader reader, String name, byte[] expectedBytes)
 236         throws Exception
 237     {
 238         Optional<ByteBuffer> obb = reader.read(name);
 239         assertTrue(obb.isPresent());
 240 
 241         ByteBuffer bb = obb.get();
 242         try {
 243             int rem = bb.remaining();
 244             assertTrue(rem == expectedBytes.length);
 245             byte[] bytes = new byte[rem];
 246             bb.get(bytes);
 247             assertTrue(Arrays.equals(bytes, expectedBytes));
 248         } finally {
 249             reader.release(bb);
 250         }
 251     }
 252 
 253 }