1 /* 2 * Copyright (c) 2015, 2016, 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/testlibrary 27 * @modules java.base/jdk.internal.module 28 * jdk.compiler 29 * @build ModuleReaderTest CompilerUtils JarUtils 30 * @run testng ModuleReaderTest 31 * @summary Basic tests for java.lang.module.ModuleReader 32 */ 33 34 import java.io.File; 35 import java.io.IOException; 36 import java.io.InputStream; 37 import java.lang.module.ModuleFinder; 38 import java.lang.module.ModuleReader; 39 import java.lang.module.ModuleReference; 40 import java.lang.reflect.Module; 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.HashSet; 50 import java.util.List; 51 import java.util.Optional; 52 import java.util.Set; 53 import java.util.stream.Collectors; 54 import java.util.spi.ToolProvider; 55 56 import jdk.internal.module.ModulePath; 57 58 import org.testng.annotations.BeforeTest; 59 import org.testng.annotations.Test; 60 import static org.testng.Assert.*; 61 62 @Test 63 public class ModuleReaderTest { 64 65 private static final String TEST_SRC = System.getProperty("test.src"); 66 67 private static final Path USER_DIR = Paths.get(System.getProperty("user.dir")); 68 private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 69 private static final Path MODS_DIR = Paths.get("mods"); 70 71 // the module name of the base module 72 private static final String BASE_MODULE = "java.base"; 73 74 // the module name of the test module 75 private static final String TEST_MODULE = "m"; 76 77 // resources in the base module 78 private static final String[] BASE_RESOURCES = { 79 "java/lang/Object.class" 80 }; 81 82 // resources in test module (can't use module-info.class as a test 83 // resource as it will be modified by the jmod tool) 84 private static final String[] TEST_RESOURCES = { 85 "p/Main.class" 86 }; 87 88 // a resource that is not in the base or test module 89 private static final String NOT_A_RESOURCE = "NotAResource"; 90 91 92 @BeforeTest 93 public void compileTestModule() throws Exception { 94 95 // javac -d mods/$TESTMODULE src/$TESTMODULE/** 96 boolean compiled 97 = CompilerUtils.compile(SRC_DIR.resolve(TEST_MODULE), 98 MODS_DIR.resolve(TEST_MODULE)); 99 assertTrue(compiled, "test module did not compile"); 100 } 101 102 103 /** 104 * Test ModuleReader to module in runtime image 105 */ 106 public void testImage() throws IOException { 107 108 ModuleFinder finder = ModuleFinder.ofSystem(); 109 ModuleReference mref = finder.find(BASE_MODULE).get(); 110 ModuleReader reader = mref.open(); 111 112 try (reader) { 113 114 for (String name : BASE_RESOURCES) { 115 byte[] expectedBytes; 116 Module baseModule = Object.class.getModule(); 117 try (InputStream in = baseModule.getResourceAsStream(name)) { 118 expectedBytes = in.readAllBytes(); 119 } 120 121 testFind(reader, name, expectedBytes); 122 testOpen(reader, name, expectedBytes); 123 testRead(reader, name, expectedBytes); 124 testList(reader, name); 125 126 } 127 128 // test "not found" 129 assertFalse(reader.find(NOT_A_RESOURCE).isPresent()); 130 assertFalse(reader.open(NOT_A_RESOURCE).isPresent()); 131 assertFalse(reader.read(NOT_A_RESOURCE).isPresent()); 132 133 134 // test nulls 135 try { 136 reader.find(null); 137 assertTrue(false); 138 } catch (NullPointerException expected) { } 139 140 try { 141 reader.open(null); 142 assertTrue(false); 143 } catch (NullPointerException expected) { } 144 145 try { 146 reader.read(null); 147 assertTrue(false); 148 } catch (NullPointerException expected) { } 149 150 try { 151 reader.release(null); 152 assertTrue(false); 153 } catch (NullPointerException expected) { } 154 155 } 156 157 // test closed ModuleReader 158 try { 159 reader.open(BASE_RESOURCES[0]); 160 assertTrue(false); 161 } catch (IOException expected) { } 162 163 164 try { 165 reader.read(BASE_RESOURCES[0]); 166 assertTrue(false); 167 } catch (IOException expected) { } 168 } 169 170 171 /** 172 * Test ModuleReader to exploded module 173 */ 174 public void testExplodedModule() throws IOException { 175 test(MODS_DIR); 176 } 177 178 179 /** 180 * Test ModuleReader to modular JAR 181 */ 182 public void testModularJar() throws IOException { 183 Path dir = Files.createTempDirectory(USER_DIR, "mlib"); 184 185 // jar cf mlib/${TESTMODULE}.jar -C mods . 186 JarUtils.createJarFile(dir.resolve("m.jar"), 187 MODS_DIR.resolve(TEST_MODULE)); 188 189 test(dir); 190 } 191 192 193 /** 194 * Test ModuleReader to JMOD 195 */ 196 public void testJMod() throws IOException { 197 Path dir = Files.createTempDirectory(USER_DIR, "mlib"); 198 199 // jmod create --class-path mods/${TESTMODULE} mlib/${TESTMODULE}.jmod 200 String cp = MODS_DIR.resolve(TEST_MODULE).toString(); 201 String jmod = dir.resolve("m.jmod").toString(); 202 String[] args = { "create", "--class-path", cp, jmod }; 203 ToolProvider jmodTool = ToolProvider.findFirst("jmod") 204 .orElseThrow(() -> 205 new RuntimeException("jmod tool not found") 206 ); 207 assertEquals(jmodTool.run(System.out, System.out, args), 0); 208 209 test(dir); 210 } 211 212 213 /** 214 * The test module is found on the given module path. Open a ModuleReader 215 * to the test module and test the reader. 216 */ 217 void test(Path mp) throws IOException { 218 219 ModuleFinder finder = new ModulePath(Runtime.version(), true, mp); 220 ModuleReference mref = finder.find(TEST_MODULE).get(); 221 ModuleReader reader = mref.open(); 222 223 try (reader) { 224 225 // test each of the known resources in the module 226 for (String name : TEST_RESOURCES) { 227 byte[] expectedBytes 228 = Files.readAllBytes(MODS_DIR 229 .resolve(TEST_MODULE) 230 .resolve(name.replace('/', File.separatorChar))); 231 232 testFind(reader, name, expectedBytes); 233 testOpen(reader, name, expectedBytes); 234 testRead(reader, name, expectedBytes); 235 testList(reader, name); 236 } 237 238 // test "not found" 239 assertFalse(reader.find(NOT_A_RESOURCE).isPresent()); 240 assertFalse(reader.open(NOT_A_RESOURCE).isPresent()); 241 assertFalse(reader.read(NOT_A_RESOURCE).isPresent()); 242 243 // test nulls 244 try { 245 reader.find(null); 246 assertTrue(false); 247 } catch (NullPointerException expected) { } 248 249 try { 250 reader.open(null); 251 assertTrue(false); 252 } catch (NullPointerException expected) { } 253 254 try { 255 reader.read(null); 256 assertTrue(false); 257 } catch (NullPointerException expected) { } 258 259 try { 260 reader.release(null); 261 throw new RuntimeException(); 262 } catch (NullPointerException expected) { } 263 264 } 265 266 // test closed ModuleReader 267 try { 268 reader.open(TEST_RESOURCES[0]); 269 assertTrue(false); 270 } catch (IOException expected) { } 271 272 273 try { 274 reader.read(TEST_RESOURCES[0]); 275 assertTrue(false); 276 } catch (IOException expected) { } 277 278 try { 279 reader.list(); 280 assertTrue(false); 281 } catch (IOException expected) { } 282 } 283 284 /** 285 * Test ModuleReader#find 286 */ 287 void testFind(ModuleReader reader, String name, byte[] expectedBytes) 288 throws IOException 289 { 290 Optional<URI> ouri = reader.find(name); 291 assertTrue(ouri.isPresent()); 292 293 URL url = ouri.get().toURL(); 294 if (!url.getProtocol().equalsIgnoreCase("jmod")) { 295 URLConnection uc = url.openConnection(); 296 uc.setUseCaches(false); 297 try (InputStream in = uc.getInputStream()) { 298 byte[] bytes = in.readAllBytes(); 299 assertTrue(Arrays.equals(bytes, expectedBytes)); 300 } 301 } 302 } 303 304 /** 305 * Test ModuleReader#open 306 */ 307 void testOpen(ModuleReader reader, String name, byte[] expectedBytes) 308 throws IOException 309 { 310 Optional<InputStream> oin = reader.open(name); 311 assertTrue(oin.isPresent()); 312 313 InputStream in = oin.get(); 314 try (in) { 315 byte[] bytes = in.readAllBytes(); 316 assertTrue(Arrays.equals(bytes, expectedBytes)); 317 } 318 } 319 320 /** 321 * Test ModuleReader#read 322 */ 323 void testRead(ModuleReader reader, String name, byte[] expectedBytes) 324 throws IOException 325 { 326 Optional<ByteBuffer> obb = reader.read(name); 327 assertTrue(obb.isPresent()); 328 329 ByteBuffer bb = obb.get(); 330 try { 331 int rem = bb.remaining(); 332 assertTrue(rem == expectedBytes.length); 333 byte[] bytes = new byte[rem]; 334 bb.get(bytes); 335 assertTrue(Arrays.equals(bytes, expectedBytes)); 336 } finally { 337 reader.release(bb); 338 } 339 } 340 341 /** 342 * Test ModuleReader#list 343 */ 344 void testList(ModuleReader reader, String name) throws IOException { 345 List<String> list = reader.list().collect(Collectors.toList()); 346 Set<String> names = new HashSet<>(list); 347 assertTrue(names.size() == list.size()); // no duplicates 348 349 assertTrue(names.contains("module-info.class")); 350 assertTrue(names.contains(name)); 351 352 // all resources should be locatable via find 353 for (String e : names) { 354 assertTrue(reader.find(e).isPresent()); 355 } 356 357 // should not contain directories 358 names.forEach(e -> assertFalse(e.endsWith("/"))); 359 } 360 361 }