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