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