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.misc 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.misc.SharedSecrets; 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 = SharedSecrets.getJavaLangModuleAccess() 220 .newModulePath(Runtime.version(), true, mp); 221 222 ModuleReference mref = finder.find(TEST_MODULE).get(); 223 ModuleReader reader = mref.open(); 224 225 try (reader) { 226 227 // test each of the known resources in the module 228 for (String name : TEST_RESOURCES) { 229 byte[] expectedBytes 230 = Files.readAllBytes(MODS_DIR 231 .resolve(TEST_MODULE) 232 .resolve(name.replace('/', File.separatorChar))); 233 234 testFind(reader, name, expectedBytes); 235 testOpen(reader, name, expectedBytes); 236 testRead(reader, name, expectedBytes); 237 testList(reader, name); 238 } 239 240 // test "not found" 241 assertFalse(reader.find(NOT_A_RESOURCE).isPresent()); 242 assertFalse(reader.open(NOT_A_RESOURCE).isPresent()); 243 assertFalse(reader.read(NOT_A_RESOURCE).isPresent()); 244 245 // test nulls 246 try { 247 reader.find(null); 248 assertTrue(false); 249 } catch (NullPointerException expected) { } 250 251 try { 252 reader.open(null); 253 assertTrue(false); 254 } catch (NullPointerException expected) { } 255 256 try { 257 reader.read(null); 258 assertTrue(false); 259 } catch (NullPointerException expected) { } 260 261 try { 262 reader.release(null); 263 throw new RuntimeException(); 264 } catch (NullPointerException expected) { } 265 266 } 267 268 // test closed ModuleReader 269 try { 270 reader.open(TEST_RESOURCES[0]); 271 assertTrue(false); 272 } catch (IOException expected) { } 273 274 275 try { 276 reader.read(TEST_RESOURCES[0]); 277 assertTrue(false); 278 } catch (IOException expected) { } 279 280 try { 281 reader.list(); 282 assertTrue(false); 283 } catch (IOException expected) { } 284 } 285 286 /** 287 * Test ModuleReader#find 288 */ 289 void testFind(ModuleReader reader, String name, byte[] expectedBytes) 290 throws IOException 291 { 292 Optional<URI> ouri = reader.find(name); 293 assertTrue(ouri.isPresent()); 294 295 URL url = ouri.get().toURL(); 296 if (!url.getProtocol().equalsIgnoreCase("jmod")) { 297 URLConnection uc = url.openConnection(); 298 uc.setUseCaches(false); 299 try (InputStream in = uc.getInputStream()) { 300 byte[] bytes = in.readAllBytes(); 301 assertTrue(Arrays.equals(bytes, expectedBytes)); 302 } 303 } 304 } 305 306 /** 307 * Test ModuleReader#open 308 */ 309 void testOpen(ModuleReader reader, String name, byte[] expectedBytes) 310 throws IOException 311 { 312 Optional<InputStream> oin = reader.open(name); 313 assertTrue(oin.isPresent()); 314 315 InputStream in = oin.get(); 316 try (in) { 317 byte[] bytes = in.readAllBytes(); 318 assertTrue(Arrays.equals(bytes, expectedBytes)); 319 } 320 } 321 322 /** 323 * Test ModuleReader#read 324 */ 325 void testRead(ModuleReader reader, String name, byte[] expectedBytes) 326 throws IOException 327 { 328 Optional<ByteBuffer> obb = reader.read(name); 329 assertTrue(obb.isPresent()); 330 331 ByteBuffer bb = obb.get(); 332 try { 333 int rem = bb.remaining(); 334 assertTrue(rem == expectedBytes.length); 335 byte[] bytes = new byte[rem]; 336 bb.get(bytes); 337 assertTrue(Arrays.equals(bytes, expectedBytes)); 338 } finally { 339 reader.release(bb); 340 } 341 } 342 343 /** 344 * Test ModuleReader#list 345 */ 346 void testList(ModuleReader reader, String name) throws IOException { 347 List<String> list = reader.list().collect(Collectors.toList()); 348 Set<String> names = new HashSet<>(list); 349 assertTrue(names.size() == list.size()); // no duplicates 350 351 assertTrue(names.contains("module-info.class")); 352 assertTrue(names.contains(name)); 353 354 // all resources should be locatable via find 355 for (String e : names) { 356 assertTrue(reader.find(e).isPresent()); 357 } 358 359 // should not contain directories 360 names.forEach(e -> assertFalse(e.endsWith("/"))); 361 } 362 363 }