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