ModuleFinderTest.java revision 13901:b2a69d66dc65
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 * @modules java.base/jdk.internal.module 27 * @build ModuleFinderTest 28 * @run testng ModuleFinderTest 29 * @summary Basic tests for java.lang.module.ModuleFinder 30 */ 31 32import java.io.OutputStream; 33import java.lang.module.FindException; 34import java.lang.module.InvalidModuleDescriptorException; 35import java.lang.module.ModuleDescriptor; 36import java.lang.module.ModuleFinder; 37import java.lang.module.ModuleReference; 38import java.nio.file.Files; 39import java.nio.file.Path; 40import java.nio.file.Paths; 41import java.util.Set; 42import java.util.jar.JarEntry; 43import java.util.jar.JarOutputStream; 44import java.util.stream.Collectors; 45 46import jdk.internal.module.ModuleInfoWriter; 47 48import org.testng.annotations.Test; 49import static org.testng.Assert.*; 50 51@Test 52public class ModuleFinderTest { 53 54 private static final Path USER_DIR 55 = Paths.get(System.getProperty("user.dir")); 56 57 58 /** 59 * Test ModuleFinder.ofSystem 60 */ 61 public void testOfSystem() { 62 ModuleFinder finder = ModuleFinder.ofSystem(); 63 64 assertTrue(finder.find("java.se").isPresent()); 65 assertTrue(finder.find("java.base").isPresent()); 66 assertFalse(finder.find("java.rhubarb").isPresent()); 67 68 Set<String> names = finder.findAll().stream() 69 .map(ModuleReference::descriptor) 70 .map(ModuleDescriptor::name) 71 .collect(Collectors.toSet()); 72 assertTrue(names.contains("java.se")); 73 assertTrue(names.contains("java.base")); 74 assertFalse(names.contains("java.rhubarb")); 75 } 76 77 78 /** 79 * Test ModuleFinder.of with zero entries 80 */ 81 public void testOfZeroEntries() { 82 ModuleFinder finder = ModuleFinder.of(); 83 assertTrue(finder.findAll().isEmpty()); 84 assertFalse(finder.find("java.rhubarb").isPresent()); 85 } 86 87 88 /** 89 * Test ModuleFinder.of with one directory of modules 90 */ 91 public void testOfOneDirectory() throws Exception { 92 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 93 createExplodedModule(dir.resolve("m1"), "m1"); 94 createModularJar(dir.resolve("m2.jar"), "m2"); 95 96 ModuleFinder finder = ModuleFinder.of(dir); 97 assertTrue(finder.findAll().size() == 2); 98 assertTrue(finder.find("m1").isPresent()); 99 assertTrue(finder.find("m2").isPresent()); 100 assertFalse(finder.find("java.rhubarb").isPresent()); 101 } 102 103 104 /** 105 * Test ModuleFinder.of with two directories 106 */ 107 public void testOfTwoDirectories() throws Exception { 108 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 109 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 110 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 111 112 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 113 createExplodedModule(dir2.resolve("m1"), "m1@2.0"); 114 createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 115 createExplodedModule(dir2.resolve("m3"), "m3"); 116 createModularJar(dir2.resolve("m4.jar"), "m4"); 117 118 ModuleFinder finder = ModuleFinder.of(dir1, dir2); 119 assertTrue(finder.findAll().size() == 4); 120 assertTrue(finder.find("m1").isPresent()); 121 assertTrue(finder.find("m2").isPresent()); 122 assertTrue(finder.find("m3").isPresent()); 123 assertTrue(finder.find("m4").isPresent()); 124 assertFalse(finder.find("java.rhubarb").isPresent()); 125 126 // check that m1@1.0 (and not m1@2.0) is found 127 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 128 assertEquals(m1.version().get().toString(), "1.0"); 129 130 // check that m2@1.0 (and not m2@2.0) is found 131 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 132 assertEquals(m2.version().get().toString(), "1.0"); 133 } 134 135 136 /** 137 * Test ModuleFinder.of with one JAR file 138 */ 139 public void testOfOneJarFile() throws Exception { 140 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 141 Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1"); 142 143 ModuleFinder finder = ModuleFinder.of(jar1); 144 assertTrue(finder.findAll().size() == 1); 145 assertTrue(finder.find("m1").isPresent()); 146 assertFalse(finder.find("java.rhubarb").isPresent()); 147 } 148 149 150 /** 151 * Test ModuleFinder.of with two JAR files 152 */ 153 public void testOfTwoJarFiles() throws Exception { 154 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 155 156 Path jar1 = createModularJar(dir.resolve("m1.jar"), "m1"); 157 Path jar2 = createModularJar(dir.resolve("m2.jar"), "m2"); 158 159 ModuleFinder finder = ModuleFinder.of(jar1, jar2); 160 assertTrue(finder.findAll().size() == 2); 161 assertTrue(finder.find("m1").isPresent()); 162 assertTrue(finder.find("m2").isPresent()); 163 assertFalse(finder.find("java.rhubarb").isPresent()); 164 } 165 166 167 /** 168 * Test ModuleFinder.of with many JAR files 169 */ 170 public void testOfManyJarFiles() throws Exception { 171 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 172 173 Path jar1 = createModularJar(dir.resolve("m1@1.0.jar"), "m1@1.0"); 174 Path jar2 = createModularJar(dir.resolve("m2@1.0.jar"), "m2"); 175 Path jar3 = createModularJar(dir.resolve("m1@2.0.jar"), "m1@2.0"); // shadowed 176 Path jar4 = createModularJar(dir.resolve("m3@1.0.jar"), "m3"); 177 178 ModuleFinder finder = ModuleFinder.of(jar1, jar2, jar3, jar4); 179 assertTrue(finder.findAll().size() == 3); 180 assertTrue(finder.find("m1").isPresent()); 181 assertTrue(finder.find("m2").isPresent()); 182 assertTrue(finder.find("m3").isPresent()); 183 assertFalse(finder.find("java.rhubarb").isPresent()); 184 185 // check that m1@1.0 (and not m1@2.0) is found 186 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 187 assertEquals(m1.version().get().toString(), "1.0"); 188 } 189 190 191 /** 192 * Test ModuleFinder.of with one exploded module. 193 */ 194 public void testOfOneExplodedModule() throws Exception { 195 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 196 Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1"); 197 198 ModuleFinder finder = ModuleFinder.of(m1_dir); 199 assertTrue(finder.findAll().size() == 1); 200 assertTrue(finder.find("m1").isPresent()); 201 assertFalse(finder.find("java.rhubarb").isPresent()); 202 } 203 204 205 /** 206 * Test ModuleFinder.of with two exploded modules. 207 */ 208 public void testOfTwoExplodedModules() throws Exception { 209 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 210 Path m1_dir = createExplodedModule(dir.resolve("m1"), "m1"); 211 Path m2_dir = createExplodedModule(dir.resolve("m2"), "m2"); 212 213 ModuleFinder finder = ModuleFinder.of(m1_dir, m2_dir); 214 assertTrue(finder.findAll().size() == 2); 215 assertTrue(finder.find("m1").isPresent()); 216 assertTrue(finder.find("m2").isPresent()); 217 assertFalse(finder.find("java.rhubarb").isPresent()); 218 } 219 220 221 /** 222 * Test ModuleFinder.of with a mix of module directories and JAR files. 223 */ 224 public void testOfMixDirectoriesAndJars() throws Exception { 225 226 // directory with m1@1.0 and m2@1.0 227 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 228 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 229 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 230 231 // JAR files: m1@2.0, m2@2.0, m3@2.0, m4@2.0 232 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 233 Path jar1 = createModularJar(dir2.resolve("m1.jar"), "m1@2.0"); 234 Path jar2 = createModularJar(dir2.resolve("m2.jar"), "m2@2.0"); 235 Path jar3 = createModularJar(dir2.resolve("m3.jar"), "m3@2.0"); 236 Path jar4 = createModularJar(dir2.resolve("m4.jar"), "m4@2.0"); 237 238 // directory with m3@3.0 and m4@3.0 239 Path dir3 = Files.createTempDirectory(USER_DIR, "mods3"); 240 createExplodedModule(dir3.resolve("m3"), "m3@3.0"); 241 createModularJar(dir3.resolve("m4.jar"), "m4@3.0"); 242 243 // JAR files: m5 and m6 244 Path dir4 = Files.createTempDirectory(USER_DIR, "mods4"); 245 Path jar5 = createModularJar(dir4.resolve("m5.jar"), "m5@4.0"); 246 Path jar6 = createModularJar(dir4.resolve("m6.jar"), "m6@4.0"); 247 248 249 ModuleFinder finder 250 = ModuleFinder.of(dir1, jar1, jar2, jar3, jar4, dir3, jar5, jar6); 251 assertTrue(finder.findAll().size() == 6); 252 assertTrue(finder.find("m1").isPresent()); 253 assertTrue(finder.find("m2").isPresent()); 254 assertTrue(finder.find("m3").isPresent()); 255 assertTrue(finder.find("m4").isPresent()); 256 assertTrue(finder.find("m5").isPresent()); 257 assertTrue(finder.find("m6").isPresent()); 258 assertFalse(finder.find("java.rhubarb").isPresent()); 259 260 // m1 and m2 should be located in dir1 261 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 262 assertEquals(m1.version().get().toString(), "1.0"); 263 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 264 assertEquals(m2.version().get().toString(), "1.0"); 265 266 // m3 and m4 should be located in JAR files 267 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 268 assertEquals(m3.version().get().toString(), "2.0"); 269 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 270 assertEquals(m4.version().get().toString(), "2.0"); 271 272 // m5 and m6 should be located in JAR files 273 ModuleDescriptor m5 = finder.find("m5").get().descriptor(); 274 assertEquals(m5.version().get().toString(), "4.0"); 275 ModuleDescriptor m6 = finder.find("m6").get().descriptor(); 276 assertEquals(m6.version().get().toString(), "4.0"); 277 } 278 279 280 /** 281 * Test ModuleFinder.of with a mix of module directories and exploded 282 * modules. 283 */ 284 public void testOfMixDirectoriesAndExplodedModules() throws Exception { 285 // directory with m1@1.0 and m2@1.0 286 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 287 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 288 createModularJar(dir1.resolve("m2.jar"), "m2@1.0"); 289 290 // exploded modules: m1@2.0, m2@2.0, m3@2.0, m4@2.0 291 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 292 Path m1_dir = createExplodedModule(dir2.resolve("m1"), "m1@2.0"); 293 Path m2_dir = createExplodedModule(dir2.resolve("m2"), "m2@2.0"); 294 Path m3_dir = createExplodedModule(dir2.resolve("m3"), "m3@2.0"); 295 Path m4_dir = createExplodedModule(dir2.resolve("m4"), "m4@2.0"); 296 297 ModuleFinder finder = ModuleFinder.of(dir1, m1_dir, m2_dir, m3_dir, m4_dir); 298 assertTrue(finder.findAll().size() == 4); 299 assertTrue(finder.find("m1").isPresent()); 300 assertTrue(finder.find("m2").isPresent()); 301 assertTrue(finder.find("m3").isPresent()); 302 assertTrue(finder.find("m4").isPresent()); 303 assertFalse(finder.find("java.rhubarb").isPresent()); 304 305 // m1 and m2 should be located in dir1 306 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 307 assertEquals(m1.version().get().toString(), "1.0"); 308 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 309 assertEquals(m2.version().get().toString(), "1.0"); 310 311 // m3 and m4 should be located in dir2 312 ModuleDescriptor m3 = finder.find("m3").get().descriptor(); 313 assertEquals(m3.version().get().toString(), "2.0"); 314 ModuleDescriptor m4 = finder.find("m4").get().descriptor(); 315 assertEquals(m4.version().get().toString(), "2.0"); 316 } 317 318 319 /** 320 * Test ModuleFinder.of with a path to a file that does not exist. 321 */ 322 public void testOfWithDoesNotExistEntry() throws Exception { 323 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 324 325 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 326 createModularJar(dir2.resolve("m2.jar"), "m2@1.0"); 327 328 Files.delete(dir1); 329 330 ModuleFinder finder = ModuleFinder.of(dir1, dir2); 331 332 assertTrue(finder.find("m2").isPresent()); 333 assertTrue(finder.findAll().size() == 1); 334 assertFalse(finder.find("java.rhubarb").isPresent()); 335 } 336 337 338 /** 339 * Test ModuleFinder.of with a file path to an unrecognized file type. 340 */ 341 public void testOfWithUnrecognizedEntry() throws Exception { 342 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 343 Path mod = Files.createTempFile(dir, "m", "mod"); 344 345 ModuleFinder finder = ModuleFinder.of(mod); 346 try { 347 finder.find("java.rhubarb"); 348 assertTrue(false); 349 } catch (FindException e) { 350 // expected 351 } 352 353 finder = ModuleFinder.of(mod); 354 try { 355 finder.findAll(); 356 assertTrue(false); 357 } catch (FindException e) { 358 // expected 359 } 360 } 361 362 363 /** 364 * Test ModuleFinder.of with a directory that contains two 365 * versions of the same module 366 */ 367 public void testOfDuplicateModulesInDirectory() throws Exception { 368 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 369 createModularJar(dir.resolve("m1@1.0.jar"), "m1"); 370 createModularJar(dir.resolve("m1@2.0.jar"), "m1"); 371 372 ModuleFinder finder = ModuleFinder.of(dir); 373 try { 374 finder.find("m1"); 375 assertTrue(false); 376 } catch (FindException expected) { } 377 378 finder = ModuleFinder.of(dir); 379 try { 380 finder.findAll(); 381 assertTrue(false); 382 } catch (FindException expected) { } 383 } 384 385 386 /** 387 * Test ModuleFinder.of with a truncated module-info.class 388 */ 389 public void testOfWithTruncatedModuleInfo() throws Exception { 390 Path dir = Files.createTempDirectory(USER_DIR, "mods"); 391 392 // create an empty <dir>/rhubarb/module-info.class 393 Path subdir = Files.createDirectory(dir.resolve("rhubarb")); 394 Files.createFile(subdir.resolve("module-info.class")); 395 396 ModuleFinder finder = ModuleFinder.of(dir); 397 try { 398 finder.find("rhubarb"); 399 assertTrue(false); 400 } catch (FindException e) { 401 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 402 } 403 404 finder = ModuleFinder.of(dir); 405 try { 406 finder.findAll(); 407 assertTrue(false); 408 } catch (FindException e) { 409 assertTrue(e.getCause() instanceof InvalidModuleDescriptorException); 410 } 411 } 412 413 414 /** 415 * Test ModuleFinder.compose 416 */ 417 public void testCompose() throws Exception { 418 Path dir1 = Files.createTempDirectory(USER_DIR, "mods1"); 419 createExplodedModule(dir1.resolve("m1"), "m1@1.0"); 420 createExplodedModule(dir1.resolve("m2"), "m2@1.0"); 421 422 Path dir2 = Files.createTempDirectory(USER_DIR, "mods2"); 423 createExplodedModule(dir2.resolve("m1"), "m1@2.0"); 424 createExplodedModule(dir2.resolve("m2"), "m2@2.0"); 425 createExplodedModule(dir2.resolve("m3"), "m3"); 426 createExplodedModule(dir2.resolve("m4"), "m4"); 427 428 ModuleFinder finder1 = ModuleFinder.of(dir1); 429 ModuleFinder finder2 = ModuleFinder.of(dir2); 430 431 ModuleFinder finder = ModuleFinder.compose(finder1, finder2); 432 assertTrue(finder.findAll().size() == 4); 433 assertTrue(finder.find("m1").isPresent()); 434 assertTrue(finder.find("m2").isPresent()); 435 assertTrue(finder.find("m3").isPresent()); 436 assertTrue(finder.find("m4").isPresent()); 437 assertFalse(finder.find("java.rhubarb").isPresent()); 438 439 // check that m1@1.0 (and not m1@2.0) is found 440 ModuleDescriptor m1 = finder.find("m1").get().descriptor(); 441 assertEquals(m1.version().get().toString(), "1.0"); 442 443 // check that m2@1.0 (and not m2@2.0) is found 444 ModuleDescriptor m2 = finder.find("m2").get().descriptor(); 445 assertEquals(m2.version().get().toString(), "1.0"); 446 } 447 448 449 /** 450 * Test ModuleFinder.empty 451 */ 452 public void testEmpty() { 453 ModuleFinder finder = ModuleFinder.empty(); 454 assertTrue(finder.findAll().isEmpty()); 455 assertFalse(finder.find("java.rhubarb").isPresent()); 456 } 457 458 459 /** 460 * Test null handling 461 */ 462 public void testNulls() { 463 464 try { 465 ModuleFinder.ofSystem().find(null); 466 assertTrue(false); 467 } catch (NullPointerException expected) { } 468 469 try { 470 ModuleFinder.of().find(null); 471 assertTrue(false); 472 } catch (NullPointerException expected) { } 473 474 try { 475 ModuleFinder.empty().find(null); 476 assertTrue(false); 477 } catch (NullPointerException expected) { } 478 479 try { 480 ModuleFinder.of((Path[])null); 481 assertTrue(false); 482 } catch (NullPointerException expected) { } 483 484 try { 485 ModuleFinder.of((Path)null); 486 assertTrue(false); 487 } catch (NullPointerException expected) { } 488 489 // compose 490 ModuleFinder finder = ModuleFinder.of(); 491 try { 492 ModuleFinder.compose(finder, null); 493 assertTrue(false); 494 } catch (NullPointerException expected) { } 495 try { 496 ModuleFinder.compose(null, finder); 497 assertTrue(false); 498 } catch (NullPointerException expected) { } 499 500 } 501 502 503 /** 504 * Parses a string of the form {@code name[@version]} and returns a 505 * ModuleDescriptor with that name and version. The ModuleDescriptor 506 * will have a requires on java.base. 507 */ 508 static ModuleDescriptor newModuleDescriptor(String mid) { 509 String mn; 510 String vs; 511 int i = mid.indexOf("@"); 512 if (i == -1) { 513 mn = mid; 514 vs = null; 515 } else { 516 mn = mid.substring(0, i); 517 vs = mid.substring(i+1); 518 } 519 ModuleDescriptor.Builder builder 520 = new ModuleDescriptor.Builder(mn).requires("java.base"); 521 if (vs != null) 522 builder.version(vs); 523 return builder.build(); 524 } 525 526 /** 527 * Creates an exploded module in the given directory and containing a 528 * module descriptor with the given module name/version. 529 */ 530 static Path createExplodedModule(Path dir, String mid) throws Exception { 531 ModuleDescriptor descriptor = newModuleDescriptor(mid); 532 Files.createDirectories(dir); 533 Path mi = dir.resolve("module-info.class"); 534 try (OutputStream out = Files.newOutputStream(mi)) { 535 ModuleInfoWriter.write(descriptor, out); 536 } 537 return dir; 538 } 539 540 /** 541 * Creates a JAR file with the given file path and containing a module 542 * descriptor with the given module name/version. 543 */ 544 static Path createModularJar(Path file, String mid, String ... entries) 545 throws Exception 546 { 547 ModuleDescriptor descriptor = newModuleDescriptor(mid); 548 try (OutputStream out = Files.newOutputStream(file)) { 549 try (JarOutputStream jos = new JarOutputStream(out)) { 550 551 JarEntry je = new JarEntry("module-info.class"); 552 jos.putNextEntry(je); 553 ModuleInfoWriter.write(descriptor, jos); 554 jos.closeEntry(); 555 556 for (String entry : entries) { 557 je = new JarEntry(entry); 558 jos.putNextEntry(je); 559 jos.closeEntry(); 560 } 561 } 562 563 } 564 return file; 565 } 566 567} 568 569