1 /* 2 * Copyright (c) 2014, 2025, 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 * @bug 8142968 8299504 27 * @modules java.base/jdk.internal.access 28 * java.base/jdk.internal.module 29 * @library /test/lib 30 * @build ConfigurationTest 31 * jdk.test.lib.util.ModuleUtils 32 * @run junit ConfigurationTest 33 * @summary Basic tests for java.lang.module.Configuration 34 */ 35 36 import java.io.IOException; 37 import java.io.OutputStream; 38 import java.lang.module.Configuration; 39 import java.lang.module.FindException; 40 import java.lang.module.ModuleDescriptor; 41 import java.lang.module.ModuleDescriptor.Requires; 42 import java.lang.module.ModuleFinder; 43 import java.lang.module.ResolutionException; 44 import java.lang.module.ResolvedModule; 45 import java.nio.file.Files; 46 import java.nio.file.Path; 47 import java.nio.file.Paths; 48 import java.util.List; 49 import java.util.Set; 50 import java.util.stream.Stream; 51 import jdk.internal.access.SharedSecrets; 52 import jdk.internal.module.ModuleTarget; 53 54 import jdk.test.lib.util.ModuleInfoWriter; 55 import jdk.test.lib.util.ModuleUtils; 56 57 import org.junit.jupiter.api.Test; 58 import org.junit.jupiter.params.ParameterizedTest; 59 import org.junit.jupiter.params.provider.MethodSource; 60 import org.junit.jupiter.params.provider.CsvSource; 61 import static org.junit.jupiter.api.Assertions.*; 62 63 class ConfigurationTest { 64 65 /** 66 * Creates a "non-strict" builder for building a module. This allows the 67 * test the create ModuleDescriptor objects that do not require java.base. 68 */ 69 private static ModuleDescriptor.Builder newBuilder(String mn) { 70 return SharedSecrets.getJavaLangModuleAccess() 71 .newModuleBuilder(mn, false, Set.of()); 72 } 73 74 /** 75 * Basic test of resolver 76 * m1 requires m2, m2 requires m3 77 */ 78 @Test 79 void testBasic() { 80 ModuleDescriptor descriptor1 = newBuilder("m1") 81 .requires("m2") 82 .build(); 83 84 ModuleDescriptor descriptor2 = newBuilder("m2") 85 .requires("m3") 86 .build(); 87 88 ModuleDescriptor descriptor3 = newBuilder("m3") 89 .build(); 90 91 ModuleFinder finder 92 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 93 94 Configuration cf = resolve(finder, "m1"); 95 96 assertTrue(cf.modules().size() == 3); 97 98 assertTrue(cf.findModule("m1").isPresent()); 99 assertTrue(cf.findModule("m2").isPresent()); 100 assertTrue(cf.findModule("m3").isPresent()); 101 102 assertTrue(cf.parents().size() == 1); 103 assertTrue(cf.parents().get(0) == Configuration.empty()); 104 105 ResolvedModule m1 = cf.findModule("m1").get(); 106 ResolvedModule m2 = cf.findModule("m2").get(); 107 ResolvedModule m3 = cf.findModule("m3").get(); 108 109 // m1 reads m2 110 assertTrue(m1.reads().size() == 1); 111 assertTrue(m1.reads().contains(m2)); 112 113 // m2 reads m3 114 assertTrue(m2.reads().size() == 1); 115 assertTrue(m2.reads().contains(m3)); 116 117 // m3 reads nothing 118 assertTrue(m3.reads().size() == 0); 119 120 // toString 121 assertTrue(cf.toString().contains("m1")); 122 assertTrue(cf.toString().contains("m2")); 123 assertTrue(cf.toString().contains("m3")); 124 } 125 126 127 /** 128 * Basic test of "requires transitive": 129 * m1 requires m2, m2 requires transitive m3 130 */ 131 @Test 132 void testRequiresTransitive1() { 133 // m1 requires m2, m2 requires transitive m3 134 ModuleDescriptor descriptor1 = newBuilder("m1") 135 .requires("m2") 136 .build(); 137 138 ModuleDescriptor descriptor2 = newBuilder("m2") 139 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m3") 140 .build(); 141 142 ModuleDescriptor descriptor3 = newBuilder("m3") 143 .build(); 144 145 ModuleFinder finder 146 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 147 148 Configuration cf = resolve(finder, "m1"); 149 150 assertTrue(cf.modules().size() == 3); 151 152 assertTrue(cf.findModule("m1").isPresent()); 153 assertTrue(cf.findModule("m2").isPresent()); 154 assertTrue(cf.findModule("m3").isPresent()); 155 156 assertTrue(cf.parents().size() == 1); 157 assertTrue(cf.parents().get(0) == Configuration.empty()); 158 159 ResolvedModule m1 = cf.findModule("m1").get(); 160 ResolvedModule m2 = cf.findModule("m2").get(); 161 ResolvedModule m3 = cf.findModule("m3").get(); 162 163 // m1 reads m2 and m3 164 assertTrue(m1.reads().size() == 2); 165 assertTrue(m1.reads().contains(m2)); 166 assertTrue(m1.reads().contains(m3)); 167 168 // m2 reads m3 169 assertTrue(m2.reads().size() == 1); 170 assertTrue(m2.reads().contains(m3)); 171 172 // m3 reads nothing 173 assertTrue(m3.reads().size() == 0); 174 } 175 176 177 /** 178 * Basic test of "requires transitive" with configurations. 179 * 180 * The test consists of three configurations: 181 * - Configuration cf1: m1, m2 requires transitive m1 182 * - Configuration cf2: m3 requires m2 183 */ 184 @Test 185 void testRequiresTransitive2() { 186 187 // cf1: m1 and m2, m2 requires transitive m1 188 189 ModuleDescriptor descriptor1 = newBuilder("m1") 190 .build(); 191 192 ModuleDescriptor descriptor2 = newBuilder("m2") 193 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 194 .build(); 195 196 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 197 198 Configuration cf1 = resolve(finder1, "m2"); 199 200 assertTrue(cf1.modules().size() == 2); 201 assertTrue(cf1.findModule("m1").isPresent()); 202 assertTrue(cf1.findModule("m2").isPresent()); 203 assertTrue(cf1.parents().size() == 1); 204 assertTrue(cf1.parents().get(0) == Configuration.empty()); 205 206 ResolvedModule m1 = cf1.findModule("m1").get(); 207 ResolvedModule m2 = cf1.findModule("m2").get(); 208 209 assertTrue(m1.reads().size() == 0); 210 assertTrue(m2.reads().size() == 1); 211 assertTrue(m2.reads().contains(m1)); 212 213 214 // cf2: m3, m3 requires m2 215 216 ModuleDescriptor descriptor3 = newBuilder("m3") 217 .requires("m2") 218 .build(); 219 220 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); 221 222 Configuration cf2 = resolve(cf1, finder2, "m3"); 223 224 assertTrue(cf2.modules().size() == 1); 225 assertTrue(cf2.findModule("m1").isPresent()); // in parent 226 assertTrue(cf2.findModule("m2").isPresent()); // in parent 227 assertTrue(cf2.findModule("m3").isPresent()); 228 assertTrue(cf2.parents().size() == 1); 229 assertTrue(cf2.parents().get(0) == cf1); 230 231 ResolvedModule m3 = cf2.findModule("m3").get(); 232 assertTrue(m3.configuration() == cf2); 233 assertTrue(m3.reads().size() == 2); 234 assertTrue(m3.reads().contains(m1)); 235 assertTrue(m3.reads().contains(m2)); 236 } 237 238 239 /** 240 * Basic test of "requires transitive" with configurations. 241 * 242 * The test consists of three configurations: 243 * - Configuration cf1: m1 244 * - Configuration cf2: m2 requires transitive m1, m3 requires m2 245 */ 246 @Test 247 void testRequiresTransitive3() { 248 249 // cf1: m1 250 251 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 252 253 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 254 255 Configuration cf1 = resolve(finder1, "m1"); 256 257 assertTrue(cf1.modules().size() == 1); 258 assertTrue(cf1.findModule("m1").isPresent()); 259 assertTrue(cf1.parents().size() == 1); 260 assertTrue(cf1.parents().get(0) == Configuration.empty()); 261 262 ResolvedModule m1 = cf1.findModule("m1").get(); 263 assertTrue(m1.reads().size() == 0); 264 265 266 // cf2: m2, m3: m2 requires transitive m1, m3 requires m2 267 268 ModuleDescriptor descriptor2 = newBuilder("m2") 269 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 270 .build(); 271 272 ModuleDescriptor descriptor3 = newBuilder("m3") 273 .requires("m2") 274 .build(); 275 276 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2, descriptor3); 277 278 Configuration cf2 = resolve(cf1, finder2, "m3"); 279 280 assertTrue(cf2.modules().size() == 2); 281 assertTrue(cf2.findModule("m1").isPresent()); // in parent 282 assertTrue(cf2.findModule("m2").isPresent()); 283 assertTrue(cf2.findModule("m3").isPresent()); 284 assertTrue(cf2.parents().size() == 1); 285 assertTrue(cf2.parents().get(0) == cf1); 286 287 ResolvedModule m2 = cf2.findModule("m2").get(); 288 ResolvedModule m3 = cf2.findModule("m3").get(); 289 290 assertTrue(m2.configuration() == cf2); 291 assertTrue(m2.reads().size() == 1); 292 assertTrue(m2.reads().contains(m1)); 293 294 assertTrue(m3.configuration() == cf2); 295 assertTrue(m3.reads().size() == 2); 296 assertTrue(m3.reads().contains(m1)); 297 assertTrue(m3.reads().contains(m2)); 298 } 299 300 301 /** 302 * Basic test of "requires transitive" with configurations. 303 * 304 * The test consists of three configurations: 305 * - Configuration cf1: m1 306 * - Configuration cf2: m2 requires transitive m1 307 * - Configuraiton cf3: m3 requires m2 308 */ 309 @Test 310 void testRequiresTransitive4() { 311 312 // cf1: m1 313 314 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 315 316 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 317 318 Configuration cf1 = resolve(finder1, "m1"); 319 320 assertTrue(cf1.modules().size() == 1); 321 assertTrue(cf1.findModule("m1").isPresent()); 322 assertTrue(cf1.parents().size() == 1); 323 assertTrue(cf1.parents().get(0) == Configuration.empty()); 324 325 ResolvedModule m1 = cf1.findModule("m1").get(); 326 assertTrue(m1.reads().size() == 0); 327 328 329 // cf2: m2 requires transitive m1 330 331 ModuleDescriptor descriptor2 = newBuilder("m2") 332 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 333 .build(); 334 335 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 336 337 Configuration cf2 = resolve(cf1, finder2, "m2"); 338 339 assertTrue(cf2.modules().size() == 1); 340 assertTrue(cf2.findModule("m1").isPresent()); // in parent 341 assertTrue(cf2.findModule("m2").isPresent()); 342 assertTrue(cf2.parents().size() == 1); 343 assertTrue(cf2.parents().get(0) == cf1); 344 345 ResolvedModule m2 = cf2.findModule("m2").get(); 346 347 assertTrue(m2.configuration() == cf2); 348 assertTrue(m2.reads().size() == 1); 349 assertTrue(m2.reads().contains(m1)); 350 351 352 // cf3: m3 requires m2 353 354 ModuleDescriptor descriptor3 = newBuilder("m3") 355 .requires("m2") 356 .build(); 357 358 ModuleFinder finder3 = ModuleUtils.finderOf(descriptor3); 359 360 Configuration cf3 = resolve(cf2, finder3, "m3"); 361 362 assertTrue(cf3.modules().size() == 1); 363 assertTrue(cf3.findModule("m1").isPresent()); // in parent 364 assertTrue(cf3.findModule("m2").isPresent()); // in parent 365 assertTrue(cf3.findModule("m3").isPresent()); 366 assertTrue(cf3.parents().size() == 1); 367 assertTrue(cf3.parents().get(0) == cf2); 368 369 ResolvedModule m3 = cf3.findModule("m3").get(); 370 371 assertTrue(m3.configuration() == cf3); 372 assertTrue(m3.reads().size() == 2); 373 assertTrue(m3.reads().contains(m1)); 374 assertTrue(m3.reads().contains(m2)); 375 } 376 377 378 /** 379 * Basic test of "requires transitive" with configurations. 380 * 381 * The test consists of two configurations: 382 * - Configuration cf1: m1, m2 requires transitive m1 383 * - Configuration cf2: m3 requires transitive m2, m4 requires m3 384 */ 385 @Test 386 void testRequiresTransitive5() { 387 388 // cf1: m1, m2 requires transitive m1 389 390 ModuleDescriptor descriptor1 = newBuilder("m1") 391 .build(); 392 393 ModuleDescriptor descriptor2 = newBuilder("m2") 394 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 395 .build(); 396 397 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 398 399 Configuration cf1 = resolve(finder1, "m2"); 400 401 assertTrue(cf1.modules().size() == 2); 402 assertTrue(cf1.findModule("m1").isPresent()); 403 assertTrue(cf1.findModule("m2").isPresent()); 404 assertTrue(cf1.parents().size() == 1); 405 assertTrue(cf1.parents().get(0) == Configuration.empty()); 406 407 ResolvedModule m1 = cf1.findModule("m1").get(); 408 ResolvedModule m2 = cf1.findModule("m2").get(); 409 410 assertTrue(m1.configuration() == cf1); 411 assertTrue(m1.reads().size() == 0); 412 413 assertTrue(m2.configuration() == cf1); 414 assertTrue(m2.reads().size() == 1); 415 assertTrue(m2.reads().contains(m1)); 416 417 418 // cf2: m3 requires transitive m2, m4 requires m3 419 420 ModuleDescriptor descriptor3 = newBuilder("m3") 421 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m2") 422 .build(); 423 424 ModuleDescriptor descriptor4 = newBuilder("m4") 425 .requires("m3") 426 .build(); 427 428 429 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 430 431 Configuration cf2 = resolve(cf1, finder2, "m3", "m4"); 432 433 assertTrue(cf2.modules().size() == 2); 434 assertTrue(cf2.findModule("m1").isPresent()); // in parent 435 assertTrue(cf2.findModule("m2").isPresent()); // in parent 436 assertTrue(cf2.findModule("m3").isPresent()); 437 assertTrue(cf2.findModule("m4").isPresent()); 438 assertTrue(cf2.parents().size() == 1); 439 assertTrue(cf2.parents().get(0) == cf1); 440 441 ResolvedModule m3 = cf2.findModule("m3").get(); 442 ResolvedModule m4 = cf2.findModule("m4").get(); 443 444 assertTrue(m3.configuration() == cf2); 445 assertTrue(m3.reads().size() == 2); 446 assertTrue(m3.reads().contains(m1)); 447 assertTrue(m3.reads().contains(m2)); 448 449 assertTrue(m4.configuration() == cf2); 450 assertTrue(m4.reads().size() == 3); 451 assertTrue(m4.reads().contains(m1)); 452 assertTrue(m4.reads().contains(m2)); 453 assertTrue(m4.reads().contains(m3)); 454 } 455 456 457 /** 458 * Basic test of "requires static": 459 * m1 requires static m2 460 * m2 is not observable 461 * resolve m1 462 */ 463 @Test 464 void testRequiresStatic1() { 465 ModuleDescriptor descriptor1 = newBuilder("m1") 466 .requires(Set.of(Requires.Modifier.STATIC), "m2") 467 .build(); 468 469 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 470 471 Configuration cf = resolve(finder, "m1"); 472 473 assertTrue(cf.modules().size() == 1); 474 475 ResolvedModule m1 = cf.findModule("m1").get(); 476 assertTrue(m1.reads().size() == 0); 477 } 478 479 480 /** 481 * Basic test of "requires static": 482 * m1 requires static m2 483 * m2 484 * resolve m1 485 */ 486 @Test 487 void testRequiresStatic2() { 488 ModuleDescriptor descriptor1 = newBuilder("m1") 489 .requires(Set.of(Requires.Modifier.STATIC), "m2") 490 .build(); 491 492 ModuleDescriptor descriptor2 = newBuilder("m2") 493 .build(); 494 495 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 496 497 Configuration cf = resolve(finder, "m1"); 498 499 assertTrue(cf.modules().size() == 1); 500 501 ResolvedModule m1 = cf.findModule("m1").get(); 502 assertTrue(m1.reads().size() == 0); 503 } 504 505 506 /** 507 * Basic test of "requires static": 508 * m1 requires static m2 509 * m2 510 * resolve m1, m2 511 */ 512 @Test 513 void testRequiresStatic3() { 514 ModuleDescriptor descriptor1 = newBuilder("m1") 515 .requires(Set.of(Requires.Modifier.STATIC), "m2") 516 .build(); 517 518 ModuleDescriptor descriptor2 = newBuilder("m2") 519 .build(); 520 521 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 522 523 Configuration cf = resolve(finder, "m1", "m2"); 524 525 assertTrue(cf.modules().size() == 2); 526 527 ResolvedModule m1 = cf.findModule("m1").get(); 528 ResolvedModule m2 = cf.findModule("m2").get(); 529 530 assertTrue(m1.reads().size() == 1); 531 assertTrue(m1.reads().contains(m2)); 532 533 assertTrue(m2.reads().size() == 0); 534 } 535 536 537 /** 538 * Basic test of "requires static": 539 * m1 requires m2, m3 540 * m2 requires static m2 541 * m3 542 */ 543 @Test 544 void testRequiresStatic4() { 545 ModuleDescriptor descriptor1 = newBuilder("m1") 546 .requires("m2") 547 .requires("m3") 548 .build(); 549 550 ModuleDescriptor descriptor2 = newBuilder("m2") 551 .requires(Set.of(Requires.Modifier.STATIC), "m3") 552 .build(); 553 554 ModuleDescriptor descriptor3 = newBuilder("m3") 555 .build(); 556 557 ModuleFinder finder 558 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 559 560 Configuration cf = resolve(finder, "m1"); 561 562 assertTrue(cf.modules().size() == 3); 563 564 ResolvedModule m1 = cf.findModule("m1").get(); 565 ResolvedModule m2 = cf.findModule("m2").get(); 566 ResolvedModule m3 = cf.findModule("m3").get(); 567 568 assertTrue(m1.reads().size() == 2); 569 assertTrue(m1.reads().contains(m2)); 570 assertTrue(m1.reads().contains(m3)); 571 572 assertTrue(m2.reads().size() == 1); 573 assertTrue(m2.reads().contains(m3)); 574 575 assertTrue(m3.reads().size() == 0); 576 } 577 578 579 /** 580 * Basic test of "requires static": 581 * The test consists of three configurations: 582 * - Configuration cf1: m1, m2 583 * - Configuration cf2: m3 requires m1, requires static m2 584 */ 585 @Test 586 void testRequiresStatic5() { 587 ModuleDescriptor descriptor1 = newBuilder("m1") 588 .build(); 589 590 ModuleDescriptor descriptor2 = newBuilder("m2") 591 .build(); 592 593 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 594 595 Configuration cf1 = resolve(finder1, "m1", "m2"); 596 597 assertTrue(cf1.modules().size() == 2); 598 assertTrue(cf1.findModule("m1").isPresent()); 599 assertTrue(cf1.findModule("m2").isPresent()); 600 601 ModuleDescriptor descriptor3 = newBuilder("m3") 602 .requires("m1") 603 .requires(Set.of(Requires.Modifier.STATIC), "m2") 604 .build(); 605 606 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); 607 608 Configuration cf2 = resolve(cf1, finder2, "m3"); 609 610 assertTrue(cf2.modules().size() == 1); 611 assertTrue(cf2.findModule("m3").isPresent()); 612 613 ResolvedModule m1 = cf1.findModule("m1").get(); 614 ResolvedModule m2 = cf1.findModule("m2").get(); 615 ResolvedModule m3 = cf2.findModule("m3").get(); 616 617 assertTrue(m3.reads().size() == 2); 618 assertTrue(m3.reads().contains(m1)); 619 assertTrue(m3.reads().contains(m2)); 620 } 621 622 623 /** 624 * Basic test of "requires static": 625 * The test consists of three configurations: 626 * - Configuration cf1: m1 627 * - Configuration cf2: m3 requires m1, requires static m2 628 */ 629 @Test 630 void testRequiresStatic6() { 631 ModuleDescriptor descriptor1 = newBuilder("m1") 632 .build(); 633 634 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 635 636 Configuration cf1 = resolve(finder1, "m1"); 637 638 assertTrue(cf1.modules().size() == 1); 639 assertTrue(cf1.findModule("m1").isPresent()); 640 641 ModuleDescriptor descriptor3 = newBuilder("m3") 642 .requires("m1") 643 .requires(Set.of(Requires.Modifier.STATIC), "m2") 644 .build(); 645 646 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); 647 648 Configuration cf2 = resolve(cf1, finder2, "m3"); 649 650 assertTrue(cf2.modules().size() == 1); 651 assertTrue(cf2.findModule("m3").isPresent()); 652 653 ResolvedModule m1 = cf1.findModule("m1").get(); 654 ResolvedModule m3 = cf2.findModule("m3").get(); 655 656 assertTrue(m3.reads().size() == 1); 657 assertTrue(m3.reads().contains(m1)); 658 } 659 660 661 /** 662 * Basic test of "requires static": 663 * (m1 not observable) 664 * m2 requires transitive static m1 665 * m3 requires m2 666 */ 667 @Test 668 void testRequiresStatic7() { 669 ModuleDescriptor descriptor1 = null; // not observable 670 671 ModuleDescriptor descriptor2 = newBuilder("m2") 672 .requires(Set.of(Requires.Modifier.TRANSITIVE, 673 Requires.Modifier.STATIC), 674 "m1") 675 .build(); 676 677 ModuleDescriptor descriptor3 = newBuilder("m3") 678 .requires("m2") 679 .build(); 680 681 ModuleFinder finder = ModuleUtils.finderOf(descriptor2, descriptor3); 682 683 Configuration cf = resolve(finder, "m3"); 684 685 assertTrue(cf.modules().size() == 2); 686 assertTrue(cf.findModule("m2").isPresent()); 687 assertTrue(cf.findModule("m3").isPresent()); 688 ResolvedModule m2 = cf.findModule("m2").get(); 689 ResolvedModule m3 = cf.findModule("m3").get(); 690 assertTrue(m2.reads().isEmpty()); 691 assertTrue(m3.reads().size() == 1); 692 assertTrue(m3.reads().contains(m2)); 693 } 694 695 696 /** 697 * Basic test of "requires static": 698 * - Configuration cf1: m2 requires transitive static m1 699 * - Configuration cf2: m3 requires m2 700 */ 701 @Test 702 void testRequiresStatic8() { 703 ModuleDescriptor descriptor1 = null; // not observable 704 705 ModuleDescriptor descriptor2 = newBuilder("m2") 706 .requires(Set.of(Requires.Modifier.TRANSITIVE, 707 Requires.Modifier.STATIC), 708 "m1") 709 .build(); 710 711 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor2); 712 713 Configuration cf1 = resolve(finder1, "m2"); 714 715 assertTrue(cf1.modules().size() == 1); 716 assertTrue(cf1.findModule("m2").isPresent()); 717 ResolvedModule m2 = cf1.findModule("m2").get(); 718 assertTrue(m2.reads().isEmpty()); 719 720 ModuleDescriptor descriptor3 = newBuilder("m3") 721 .requires("m2") 722 .build(); 723 724 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3); 725 726 Configuration cf2 = resolve(cf1, finder2, "m3"); 727 728 assertTrue(cf2.modules().size() == 1); 729 assertTrue(cf2.findModule("m3").isPresent()); 730 ResolvedModule m3 = cf2.findModule("m3").get(); 731 assertTrue(m3.reads().size() == 1); 732 assertTrue(m3.reads().contains(m2)); 733 } 734 735 736 /** 737 * Basic test of binding services 738 * m1 uses p.S 739 * m2 provides p.S 740 */ 741 @Test 742 void testServiceBinding1() { 743 ModuleDescriptor descriptor1 = newBuilder("m1") 744 .exports("p") 745 .uses("p.S") 746 .build(); 747 748 ModuleDescriptor descriptor2 = newBuilder("m2") 749 .requires("m1") 750 .provides("p.S", List.of("q.T")) 751 .build(); 752 753 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 754 755 Configuration cf = resolveAndBind(finder, "m1"); 756 757 assertTrue(cf.modules().size() == 2); 758 assertTrue(cf.findModule("m1").isPresent()); 759 assertTrue(cf.findModule("m2").isPresent()); 760 assertTrue(cf.parents().size() == 1); 761 assertTrue(cf.parents().get(0) == Configuration.empty()); 762 763 ResolvedModule m1 = cf.findModule("m1").get(); 764 ResolvedModule m2 = cf.findModule("m2").get(); 765 766 assertTrue(m1.configuration() == cf); 767 assertTrue(m1.reads().size() == 0); 768 769 assertTrue(m2.configuration() == cf); 770 assertTrue(m2.reads().size() == 1); 771 assertTrue(m2.reads().contains(m1)); 772 } 773 774 775 /** 776 * Basic test of binding services 777 * m1 uses p.S1 778 * m2 provides p.S1, m2 uses p.S2 779 * m3 provides p.S2 780 */ 781 @Test 782 void testServiceBinding2() { 783 ModuleDescriptor descriptor1 = newBuilder("m1") 784 .exports("p") 785 .uses("p.S1") 786 .build(); 787 788 ModuleDescriptor descriptor2 = newBuilder("m2") 789 .requires("m1") 790 .uses("p.S2") 791 .provides("p.S1", List.of("q.Service1Impl")) 792 .build(); 793 794 ModuleDescriptor descriptor3 = newBuilder("m3") 795 .requires("m1") 796 .provides("p.S2", List.of("q.Service2Impl")) 797 .build(); 798 799 ModuleFinder finder 800 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 801 802 Configuration cf = resolveAndBind(finder, "m1"); 803 804 assertTrue(cf.modules().size() == 3); 805 assertTrue(cf.findModule("m1").isPresent()); 806 assertTrue(cf.findModule("m2").isPresent()); 807 assertTrue(cf.findModule("m3").isPresent()); 808 assertTrue(cf.parents().size() == 1); 809 assertTrue(cf.parents().get(0) == Configuration.empty()); 810 811 ResolvedModule m1 = cf.findModule("m1").get(); 812 ResolvedModule m2 = cf.findModule("m2").get(); 813 ResolvedModule m3 = cf.findModule("m3").get(); 814 815 assertTrue(m1.configuration() == cf); 816 assertTrue(m1.reads().size() == 0); 817 818 assertTrue(m2.configuration() == cf); 819 assertTrue(m2.reads().size() == 1); 820 assertTrue(m2.reads().contains(m1)); 821 822 assertTrue(m3.configuration() == cf); 823 assertTrue(m3.reads().size() == 1); 824 assertTrue(m3.reads().contains(m1)); 825 } 826 827 828 /** 829 * Basic test of binding services with configurations. 830 * 831 * The test consists of two configurations: 832 * - Configuration cf1: m1 uses p.S 833 * - Configuration cf2: m2 provides p.S 834 */ 835 @Test 836 void testServiceBindingWithConfigurations1() { 837 ModuleDescriptor descriptor1 = newBuilder("m1") 838 .exports("p") 839 .uses("p.S") 840 .build(); 841 842 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 843 844 Configuration cf1 = resolve(finder1, "m1"); 845 846 assertTrue(cf1.modules().size() == 1); 847 assertTrue(cf1.findModule("m1").isPresent()); 848 849 ModuleDescriptor descriptor2 = newBuilder("m2") 850 .requires("m1") 851 .provides("p.S", List.of("q.T")) 852 .build(); 853 854 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 855 856 Configuration cf2 = resolveAndBind(cf1, finder2); // no roots 857 858 assertTrue(cf2.parents().size() == 1); 859 assertTrue(cf2.parents().get(0) == cf1); 860 861 assertTrue(cf2.modules().size() == 1); 862 assertTrue(cf2.findModule("m2").isPresent()); 863 864 ResolvedModule m1 = cf1.findModule("m1").get(); 865 ResolvedModule m2 = cf2.findModule("m2").get(); 866 867 assertTrue(m2.reads().size() == 1); 868 assertTrue(m2.reads().contains(m1)); 869 } 870 871 872 /** 873 * Basic test of binding services with configurations. 874 * 875 * The test consists of two configurations: 876 * - Configuration cf1: m1 uses p.S && provides p.S, 877 * m2 provides p.S 878 * - Configuration cf2: m3 provides p.S 879 * m4 provides p.S 880 */ 881 @Test 882 void testServiceBindingWithConfigurations2() { 883 ModuleDescriptor descriptor1 = newBuilder("m1") 884 .exports("p") 885 .uses("p.S") 886 .provides("p.S", List.of("p1.ServiceImpl")) 887 .build(); 888 889 ModuleDescriptor descriptor2 = newBuilder("m2") 890 .requires("m1") 891 .provides("p.S", List.of("p2.ServiceImpl")) 892 .build(); 893 894 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 895 896 Configuration cf1 = resolveAndBind(finder1, "m1"); 897 898 assertTrue(cf1.modules().size() == 2); 899 assertTrue(cf1.findModule("m1").isPresent()); 900 assertTrue(cf1.findModule("m2").isPresent()); 901 902 903 ModuleDescriptor descriptor3 = newBuilder("m3") 904 .requires("m1") 905 .provides("p.S", List.of("p3.ServiceImpl")) 906 .build(); 907 908 ModuleDescriptor descriptor4 = newBuilder("m4") 909 .requires("m1") 910 .provides("p.S", List.of("p4.ServiceImpl")) 911 .build(); 912 913 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor3, descriptor4); 914 915 Configuration cf2 = resolveAndBind(cf1, finder2); // no roots 916 917 assertTrue(cf2.parents().size() == 1); 918 assertTrue(cf2.parents().get(0) == cf1); 919 920 assertTrue(cf2.modules().size() == 2); 921 assertTrue(cf2.findModule("m3").isPresent()); 922 assertTrue(cf2.findModule("m4").isPresent()); 923 924 ResolvedModule m1 = cf2.findModule("m1").get(); // should find in parent 925 ResolvedModule m2 = cf2.findModule("m2").get(); 926 ResolvedModule m3 = cf2.findModule("m3").get(); 927 ResolvedModule m4 = cf2.findModule("m4").get(); 928 929 assertTrue(m1.reads().size() == 0); 930 931 assertTrue(m2.reads().size() == 1); 932 assertTrue(m2.reads().contains(m1)); 933 934 assertTrue(m3.reads().size() == 1); 935 assertTrue(m3.reads().contains(m1)); 936 937 assertTrue(m4.reads().size() == 1); 938 assertTrue(m4.reads().contains(m1)); 939 } 940 941 942 /** 943 * Basic test of binding services with configurations. 944 * 945 * Configuration cf1: p@1.0 provides p.S 946 * Test configuration cf2: m1 uses p.S, p@2.0 provides p.S 947 * Test configuration cf2: m1 uses p.S 948 */ 949 @Test 950 void testServiceBindingWithConfigurations3() { 951 ModuleDescriptor service = newBuilder("s") 952 .exports("p") 953 .build(); 954 955 ModuleDescriptor provider_v1 = newBuilder("p") 956 .version("1.0") 957 .requires("s") 958 .provides("p.S", List.of("q.T")) 959 .build(); 960 961 ModuleFinder finder1 = ModuleUtils.finderOf(service, provider_v1); 962 963 Configuration cf1 = resolve(finder1, "p"); 964 965 assertTrue(cf1.modules().size() == 2); 966 assertTrue(cf1.findModule("s").isPresent()); 967 assertTrue(cf1.findModule("p").isPresent()); 968 969 // p@1.0 in cf1 970 ResolvedModule p = cf1.findModule("p").get(); 971 assertEquals(provider_v1, p.reference().descriptor()); 972 973 974 ModuleDescriptor descriptor1 = newBuilder("m1") 975 .requires("s") 976 .uses("p.S") 977 .build(); 978 979 ModuleDescriptor provider_v2 = newBuilder("p") 980 .version("2.0") 981 .requires("s") 982 .provides("p.S", List.of("q.T")) 983 .build(); 984 985 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, provider_v2); 986 987 988 // finder2 is the before ModuleFinder and so p@2.0 should be located 989 990 Configuration cf2 = resolveAndBind(cf1, finder2, "m1"); 991 992 assertTrue(cf2.parents().size() == 1); 993 assertTrue(cf2.parents().get(0) == cf1); 994 assertTrue(cf2.modules().size() == 2); 995 996 // p should be found in cf2 997 p = cf2.findModule("p").get(); 998 assertTrue(p.configuration() == cf2); 999 assertEquals(provider_v2, p.reference().descriptor()); 1000 1001 1002 // finder2 is the after ModuleFinder and so p@2.0 should not be located 1003 // as module p is in parent configuration. 1004 1005 cf2 = resolveAndBind(cf1, ModuleFinder.of(), finder2, "m1"); 1006 1007 assertTrue(cf2.parents().size() == 1); 1008 assertTrue(cf2.parents().get(0) == cf1); 1009 assertTrue(cf2.modules().size() == 1); 1010 1011 // p should be found in cf1 1012 p = cf2.findModule("p").get(); 1013 assertTrue(p.configuration() == cf1); 1014 assertEquals(provider_v1, p.reference().descriptor()); 1015 } 1016 1017 1018 /** 1019 * Basic test with two module finders. 1020 * 1021 * Module m2 can be found by both the before and after finders. 1022 */ 1023 @Test 1024 void testWithTwoFinders1() { 1025 ModuleDescriptor descriptor1 = newBuilder("m1") 1026 .requires("m2") 1027 .build(); 1028 1029 ModuleDescriptor descriptor2_v1 = newBuilder("m2") 1030 .version("1.0") 1031 .build(); 1032 1033 ModuleDescriptor descriptor2_v2 = newBuilder("m2") 1034 .version("2.0") 1035 .build(); 1036 1037 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor2_v1); 1038 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor2_v2); 1039 1040 Configuration cf = resolve(finder1, finder2, "m1"); 1041 1042 assertTrue(cf.modules().size() == 2); 1043 assertTrue(cf.findModule("m1").isPresent()); 1044 assertTrue(cf.findModule("m2").isPresent()); 1045 1046 ResolvedModule m1 = cf.findModule("m1").get(); 1047 ResolvedModule m2 = cf.findModule("m2").get(); 1048 1049 assertEquals(descriptor1, m1.reference().descriptor()); 1050 assertEquals(descriptor2_v1, m2.reference().descriptor()); 1051 } 1052 1053 1054 /** 1055 * Basic test with two modules finders and service binding. 1056 * 1057 * The before and after ModuleFinders both locate a service provider module 1058 * named "m2" that provide implementations of the same service type. 1059 */ 1060 @Test 1061 void testWithTwoFinders2() { 1062 ModuleDescriptor descriptor1 = newBuilder("m1") 1063 .exports("p") 1064 .uses("p.S") 1065 .build(); 1066 1067 ModuleDescriptor descriptor2_v1 = newBuilder("m2") 1068 .requires("m1") 1069 .provides("p.S", List.of("q.T")) 1070 .build(); 1071 1072 ModuleDescriptor descriptor2_v2 = newBuilder("m2") 1073 .requires("m1") 1074 .provides("p.S", List.of("q.T")) 1075 .build(); 1076 1077 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2_v1); 1078 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2_v2); 1079 1080 Configuration cf = resolveAndBind(finder1, finder2, "m1"); 1081 1082 assertTrue(cf.modules().size() == 2); 1083 assertTrue(cf.findModule("m1").isPresent()); 1084 assertTrue(cf.findModule("m2").isPresent()); 1085 1086 ResolvedModule m1 = cf.findModule("m1").get(); 1087 ResolvedModule m2 = cf.findModule("m2").get(); 1088 1089 assertEquals(descriptor1, m1.reference().descriptor()); 1090 assertEquals(descriptor2_v1, m2.reference().descriptor()); 1091 } 1092 1093 1094 /** 1095 * Basic test for resolving a module that is located in the parent 1096 * configuration. 1097 */ 1098 @Test 1099 void testResolvedInParent1() { 1100 ModuleDescriptor descriptor1 = newBuilder("m1") 1101 .build(); 1102 1103 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1104 1105 Configuration cf1 = resolve(finder, "m1"); 1106 1107 assertTrue(cf1.modules().size() == 1); 1108 assertTrue(cf1.findModule("m1").isPresent()); 1109 1110 Configuration cf2 = resolve(cf1, finder, "m1"); 1111 1112 assertTrue(cf2.modules().size() == 1); 1113 } 1114 1115 1116 /** 1117 * Basic test for resolving a module that has a dependency on a module 1118 * in the parent configuration. 1119 */ 1120 @Test 1121 void testResolvedInParent2() { 1122 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1123 1124 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1); 1125 1126 Configuration cf1 = resolve(finder1, "m1"); 1127 1128 assertTrue(cf1.modules().size() == 1); 1129 assertTrue(cf1.findModule("m1").isPresent()); 1130 1131 1132 ModuleDescriptor descriptor2 = newBuilder("m2") 1133 .requires("m1") 1134 .build(); 1135 1136 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor2); 1137 1138 Configuration cf2 = resolve(cf1, ModuleFinder.of(), finder2, "m2"); 1139 1140 assertTrue(cf2.modules().size() == 1); 1141 assertTrue(cf2.findModule("m2").isPresent()); 1142 1143 ResolvedModule m1 = cf2.findModule("m1").get(); // find in parent 1144 ResolvedModule m2 = cf2.findModule("m2").get(); 1145 1146 assertTrue(m1.reads().size() == 0); 1147 assertTrue(m2.reads().size() == 1); 1148 assertTrue(m2.reads().contains(m1)); 1149 } 1150 1151 1152 /** 1153 * Basic test of resolving a module that depends on modules in two parent 1154 * configurations. 1155 * 1156 * The test consists of three configurations: 1157 * - Configuration cf1: m1 1158 * - Configuration cf2: m2 1159 * - Configuration cf3(cf1,cf2): m3 requires m1, m2 1160 */ 1161 @Test 1162 void testResolvedInMultipleParents1() { 1163 // Configuration cf1: m1 1164 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1165 Configuration cf1 = resolve(ModuleUtils.finderOf(descriptor1), "m1"); 1166 assertEquals(List.of(Configuration.empty()), cf1.parents()); 1167 assertTrue(cf1.findModule("m1").isPresent()); 1168 ResolvedModule m1 = cf1.findModule("m1").get(); 1169 assertTrue(m1.configuration() == cf1); 1170 1171 // Configuration cf2: m2 1172 ModuleDescriptor descriptor2 = newBuilder("m2").build(); 1173 Configuration cf2 = resolve(ModuleUtils.finderOf(descriptor2), "m2"); 1174 assertEquals(List.of(Configuration.empty()), cf2.parents()); 1175 assertTrue(cf2.findModule("m2").isPresent()); 1176 ResolvedModule m2 = cf2.findModule("m2").get(); 1177 assertTrue(m2.configuration() == cf2); 1178 1179 // Configuration cf3(cf1,cf2): m3 requires m1 and m2 1180 ModuleDescriptor descriptor3 = newBuilder("m3") 1181 .requires("m1") 1182 .requires("m2") 1183 .build(); 1184 ModuleFinder finder = ModuleUtils.finderOf(descriptor3); 1185 Configuration cf3 = Configuration.resolve( 1186 finder, 1187 List.of(cf1, cf2), // parents 1188 ModuleFinder.of(), 1189 Set.of("m3")); 1190 assertEquals(List.of(cf1, cf2), cf3.parents()); 1191 assertTrue(cf3.findModule("m3").isPresent()); 1192 ResolvedModule m3 = cf3.findModule("m3").get(); 1193 assertTrue(m3.configuration() == cf3); 1194 1195 // check readability 1196 assertTrue(m1.reads().isEmpty()); 1197 assertTrue(m2.reads().isEmpty()); 1198 assertEquals(Set.of(m1, m2), m3.reads()); 1199 } 1200 1201 1202 /** 1203 * Basic test of resolving a module that depends on modules in three parent 1204 * configurations arranged in a diamond (two direct parents). 1205 * 1206 * The test consists of four configurations: 1207 * - Configuration cf1: m1 1208 * - Configuration cf2(cf1): m2 requires m1 1209 * - Configuration cf3(cf3): m3 requires m1 1210 * - Configuration cf4(cf2,cf3): m4 requires m1,m2,m3 1211 */ 1212 @Test 1213 void testResolvedInMultipleParents2() { 1214 // Configuration cf1: m1 1215 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1216 Configuration cf1 = resolve(ModuleUtils.finderOf(descriptor1), "m1"); 1217 assertEquals( List.of(Configuration.empty()), cf1.parents()); 1218 assertTrue(cf1.findModule("m1").isPresent()); 1219 ResolvedModule m1 = cf1.findModule("m1").get(); 1220 assertTrue(m1.configuration() == cf1); 1221 1222 // Configuration cf2(cf1): m2 requires m1 1223 ModuleDescriptor descriptor2 = newBuilder("m2") 1224 .requires("m1") 1225 .build(); 1226 Configuration cf2 = Configuration.resolve( 1227 ModuleUtils.finderOf(descriptor2), 1228 List.of(cf1), // parents 1229 ModuleFinder.of(), 1230 Set.of("m2")); 1231 assertEquals(List.of(cf1), cf2.parents()); 1232 assertTrue(cf2.findModule("m2").isPresent()); 1233 ResolvedModule m2 = cf2.findModule("m2").get(); 1234 assertTrue(m2.configuration() == cf2); 1235 1236 // Configuration cf3(cf1): m3 requires m1 1237 ModuleDescriptor descriptor3 = newBuilder("m3") 1238 .requires("m1") 1239 .build(); 1240 Configuration cf3 = Configuration.resolve( 1241 ModuleUtils.finderOf(descriptor3), 1242 List.of(cf1), // parents 1243 ModuleFinder.of(), 1244 Set.of("m3")); 1245 assertEquals(List.of(cf1), cf3.parents()); 1246 assertTrue(cf3.findModule("m3").isPresent()); 1247 ResolvedModule m3 = cf3.findModule("m3").get(); 1248 assertTrue(m3.configuration() == cf3); 1249 1250 // Configuration cf4(cf2,cf3): m4 requires m1,m2,m3 1251 ModuleDescriptor descriptor4 = newBuilder("m4") 1252 .requires("m1") 1253 .requires("m2") 1254 .requires("m3") 1255 .build(); 1256 Configuration cf4 = Configuration.resolve( 1257 ModuleUtils.finderOf(descriptor4), 1258 List.of(cf2, cf3), // parents 1259 ModuleFinder.of(), 1260 Set.of("m4")); 1261 assertEquals(List.of(cf2, cf3), cf4.parents()); 1262 assertTrue(cf4.findModule("m4").isPresent()); 1263 ResolvedModule m4 = cf4.findModule("m4").get(); 1264 assertTrue(m4.configuration() == cf4); 1265 1266 // check readability 1267 assertTrue(m1.reads().isEmpty()); 1268 assertEquals(Set.of(m1), m2.reads()); 1269 assertEquals(Set.of(m1), m3.reads()); 1270 assertEquals(Set.of(m1, m2, m3), m4.reads()); 1271 } 1272 1273 1274 /** 1275 * Basic test of resolving a module that depends on modules in three parent 1276 * configurations arranged in a diamond (two direct parents). 1277 * 1278 * The test consists of four configurations: 1279 * - Configuration cf1: m1@1 1280 * - Configuration cf2: m1@2, m2@2 1281 * - Configuration cf3: m1@3, m2@3, m3@3 1282 * - Configuration cf4(cf1,cf2,cf3): m4 requires m1,m2,m3 1283 */ 1284 @Test 1285 void testResolvedInMultipleParents3() { 1286 ModuleDescriptor descriptor1, descriptor2, descriptor3; 1287 1288 // Configuration cf1: m1@1 1289 descriptor1 = newBuilder("m1").version("1").build(); 1290 Configuration cf1 = resolve(ModuleUtils.finderOf(descriptor1), "m1"); 1291 assertEquals(List.of(Configuration.empty()), cf1.parents()); 1292 1293 // Configuration cf2: m1@2, m2@2 1294 descriptor1 = newBuilder("m1").version("2").build(); 1295 descriptor2 = newBuilder("m2").version("2").build(); 1296 Configuration cf2 = resolve( 1297 ModuleUtils.finderOf(descriptor1, descriptor2), 1298 "m1", "m2"); 1299 assertEquals(List.of(Configuration.empty()), cf2.parents()); 1300 1301 // Configuration cf3: m1@3, m2@3, m3@3 1302 descriptor1 = newBuilder("m1").version("3").build(); 1303 descriptor2 = newBuilder("m2").version("3").build(); 1304 descriptor3 = newBuilder("m3").version("3").build(); 1305 Configuration cf3 = resolve( 1306 ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3), 1307 "m1", "m2", "m3"); 1308 assertEquals(List.of(Configuration.empty()), cf3.parents()); 1309 1310 // Configuration cf4(cf1,cf2,cf3): m4 requires m1,m2,m3 1311 ModuleDescriptor descriptor4 = newBuilder("m4") 1312 .requires("m1") 1313 .requires("m2") 1314 .requires("m3") 1315 .build(); 1316 Configuration cf4 = Configuration.resolve( 1317 ModuleUtils.finderOf(descriptor4), 1318 List.of(cf1, cf2, cf3), // parents 1319 ModuleFinder.of(), 1320 Set.of("m4")); 1321 assertEquals(List.of(cf1, cf2, cf3), cf4.parents()); 1322 1323 assertTrue(cf1.findModule("m1").isPresent()); 1324 assertTrue(cf2.findModule("m1").isPresent()); 1325 assertTrue(cf2.findModule("m2").isPresent()); 1326 assertTrue(cf3.findModule("m1").isPresent()); 1327 assertTrue(cf3.findModule("m2").isPresent()); 1328 assertTrue(cf3.findModule("m3").isPresent()); 1329 assertTrue(cf4.findModule("m4").isPresent()); 1330 1331 ResolvedModule m1_1 = cf1.findModule("m1").get(); 1332 ResolvedModule m1_2 = cf2.findModule("m1").get(); 1333 ResolvedModule m2_2 = cf2.findModule("m2").get(); 1334 ResolvedModule m1_3 = cf3.findModule("m1").get(); 1335 ResolvedModule m2_3 = cf3.findModule("m2").get(); 1336 ResolvedModule m3_3 = cf3.findModule("m3").get(); 1337 ResolvedModule m4 = cf4.findModule("m4").get(); 1338 1339 assertTrue(m1_1.configuration() == cf1); 1340 assertTrue(m1_2.configuration() == cf2); 1341 assertTrue(m2_2.configuration() == cf2); 1342 assertTrue(m1_3.configuration() == cf3); 1343 assertTrue(m2_3.configuration() == cf3); 1344 assertTrue(m3_3.configuration() == cf3); 1345 assertTrue(m4.configuration() == cf4); 1346 1347 // check readability 1348 assertTrue(m1_1.reads().isEmpty()); 1349 assertTrue(m1_2.reads().isEmpty()); 1350 assertTrue(m2_2.reads().isEmpty()); 1351 assertTrue(m1_3.reads().isEmpty()); 1352 assertTrue(m2_3.reads().isEmpty()); 1353 assertTrue(m3_3.reads().isEmpty()); 1354 assertEquals(Set.of(m1_1, m2_2, m3_3), m4.reads()); 1355 } 1356 1357 1358 /** 1359 * Basic test of using the beforeFinder to override a module in a parent 1360 * configuration. 1361 */ 1362 @Test 1363 void testOverriding1() { 1364 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1365 1366 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1367 1368 Configuration cf1 = resolve(finder, "m1"); 1369 assertTrue(cf1.modules().size() == 1); 1370 assertTrue(cf1.findModule("m1").isPresent()); 1371 1372 Configuration cf2 = resolve(cf1, finder, "m1"); 1373 assertTrue(cf2.modules().size() == 1); 1374 assertTrue(cf2.findModule("m1").isPresent()); 1375 } 1376 1377 /** 1378 * Basic test of using the beforeFinder to override a module in a parent 1379 * configuration. 1380 */ 1381 @Test 1382 void testOverriding2() { 1383 ModuleDescriptor descriptor1 = newBuilder("m1").build(); 1384 Configuration cf1 = resolve(ModuleUtils.finderOf(descriptor1), "m1"); 1385 assertTrue(cf1.modules().size() == 1); 1386 assertTrue(cf1.findModule("m1").isPresent()); 1387 1388 ModuleDescriptor descriptor2 = newBuilder("m2").build(); 1389 Configuration cf2 = resolve(ModuleUtils.finderOf(descriptor2), "m2"); 1390 assertTrue(cf2.modules().size() == 1); 1391 assertTrue(cf2.findModule("m2").isPresent()); 1392 1393 ModuleDescriptor descriptor3 = newBuilder("m3").build(); 1394 Configuration cf3 = resolve(ModuleUtils.finderOf(descriptor3), "m3"); 1395 assertTrue(cf3.modules().size() == 1); 1396 assertTrue(cf3.findModule("m3").isPresent()); 1397 1398 // override m2, m1 and m3 should be found in parent configurations 1399 ModuleFinder finder = ModuleUtils.finderOf(descriptor2); 1400 Configuration cf4 = Configuration.resolve( 1401 finder, 1402 List.of(cf1, cf2, cf3), 1403 ModuleFinder.of(), 1404 Set.of("m1", "m2", "m3")); 1405 assertTrue(cf4.modules().size() == 1); 1406 assertTrue(cf4.findModule("m2").isPresent()); 1407 ResolvedModule m2 = cf4.findModule("m2").get(); 1408 assertTrue(m2.configuration() == cf4); 1409 } 1410 1411 1412 /** 1413 * Basic test of using the beforeFinder to override a module in the parent 1414 * configuration but where implied readability in the picture so that the 1415 * module in the parent is read. 1416 * 1417 * The test consists of two configurations: 1418 * - Configuration cf1: m1, m2 requires transitive m1 1419 * - Configuration cf2: m1, m3 requires m2 1420 */ 1421 @Test 1422 void testOverriding3() { 1423 ModuleDescriptor descriptor1 = newBuilder("m1") 1424 .build(); 1425 1426 ModuleDescriptor descriptor2 = newBuilder("m2") 1427 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 1428 .build(); 1429 1430 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 1431 1432 Configuration cf1 = resolve(finder1, "m2"); 1433 1434 assertTrue(cf1.modules().size() == 2); 1435 assertTrue(cf1.findModule("m1").isPresent()); 1436 assertTrue(cf1.findModule("m2").isPresent()); 1437 1438 // cf2: m3 requires m2, m1 1439 1440 ModuleDescriptor descriptor3 = newBuilder("m3") 1441 .requires("m2") 1442 .build(); 1443 1444 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3); 1445 1446 Configuration cf2 = resolve(cf1, finder2, "m1", "m3"); 1447 1448 assertTrue(cf2.parents().size() == 1); 1449 assertTrue(cf2.parents().get(0) == cf1); 1450 1451 assertTrue(cf2.modules().size() == 2); 1452 assertTrue(cf2.findModule("m1").isPresent()); 1453 assertTrue(cf2.findModule("m3").isPresent()); 1454 1455 ResolvedModule m1_1 = cf1.findModule("m1").get(); 1456 ResolvedModule m1_2 = cf2.findModule("m1").get(); 1457 ResolvedModule m2 = cf1.findModule("m2").get(); 1458 ResolvedModule m3 = cf2.findModule("m3").get(); 1459 1460 assertTrue(m1_1.configuration() == cf1); 1461 assertTrue(m1_2.configuration() == cf2); 1462 assertTrue(m3.configuration() == cf2); 1463 1464 1465 // check that m3 reads cf1/m1 and cf2/m2 1466 assertTrue(m3.reads().size() == 2); 1467 assertTrue(m3.reads().contains(m1_1)); 1468 assertTrue(m3.reads().contains(m2)); 1469 } 1470 1471 1472 /** 1473 * Root module not found 1474 */ 1475 @Test 1476 void testRootNotFound() { 1477 assertThrows(FindException.class, () -> resolve(ModuleFinder.of(), "m1")); 1478 } 1479 1480 1481 /** 1482 * Direct dependency not found 1483 */ 1484 @Test 1485 void testDirectDependencyNotFound() { 1486 ModuleDescriptor descriptor1 = newBuilder("m1").requires("m2").build(); 1487 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1488 assertThrows(FindException.class, () -> resolve(finder, "m1")); 1489 } 1490 1491 1492 /** 1493 * Transitive dependency not found 1494 */ 1495 @Test 1496 void testTransitiveDependencyNotFound() { 1497 ModuleDescriptor descriptor1 = newBuilder("m1").requires("m2").build(); 1498 ModuleDescriptor descriptor2 = newBuilder("m2").requires("m3").build(); 1499 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1500 assertThrows(FindException.class, () -> resolve(finder, "m1")); 1501 } 1502 1503 1504 /** 1505 * Service provider dependency not found 1506 */ 1507 @Test 1508 void testServiceProviderDependencyNotFound() { 1509 1510 // service provider dependency (on m3) not found 1511 1512 ModuleDescriptor descriptor1 = newBuilder("m1") 1513 .exports("p") 1514 .uses("p.S") 1515 .build(); 1516 1517 ModuleDescriptor descriptor2 = newBuilder("m2") 1518 .requires("m1") 1519 .requires("m3") 1520 .provides("p.S", List.of("q.T")) 1521 .build(); 1522 1523 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1524 1525 // should throw ResolutionException because m3 is not found 1526 assertThrows(FindException.class, () -> resolveAndBind(finder, "m1")); 1527 } 1528 1529 1530 /** 1531 * Simple cycle. 1532 */ 1533 @Test 1534 void testSimpleCycle() { 1535 ModuleDescriptor descriptor1 = newBuilder("m1").requires("m2").build(); 1536 ModuleDescriptor descriptor2 = newBuilder("m2").requires("m3").build(); 1537 ModuleDescriptor descriptor3 = newBuilder("m3").requires("m1").build(); 1538 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 1539 assertThrows(ResolutionException.class, () -> resolve(finder, "m1")); 1540 } 1541 1542 /** 1543 * Basic test for detecting cycles involving a service provider module 1544 */ 1545 @Test 1546 void testCycleInProvider() { 1547 ModuleDescriptor descriptor1 = newBuilder("m1") 1548 .exports("p") 1549 .uses("p.S") 1550 .build(); 1551 ModuleDescriptor descriptor2 = newBuilder("m2") 1552 .requires("m1") 1553 .requires("m3") 1554 .provides("p.S", List.of("q.T")) 1555 .build(); 1556 ModuleDescriptor descriptor3 = newBuilder("m3") 1557 .requires("m2") 1558 .build(); 1559 1560 ModuleFinder finder 1561 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 1562 1563 // should throw ResolutionException because of the m2 <--> m3 cycle 1564 assertThrows(ResolutionException.class, () -> resolveAndBind(finder, "m1")); 1565 } 1566 1567 1568 /** 1569 * Basic test to detect reading a module with the same name as itself 1570 * 1571 * The test consists of three configurations: 1572 * - Configuration cf1: m1, m2 requires transitive m1 1573 * - Configuration cf2: m1 requires m2 1574 */ 1575 @Test 1576 void testReadModuleWithSameNameAsSelf() { 1577 ModuleDescriptor descriptor1_v1 = newBuilder("m1") 1578 .build(); 1579 1580 ModuleDescriptor descriptor2 = newBuilder("m2") 1581 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 1582 .build(); 1583 1584 ModuleDescriptor descriptor1_v2 = newBuilder("m1") 1585 .requires("m2") 1586 .build(); 1587 1588 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1_v1, descriptor2); 1589 Configuration cf1 = resolve(finder1, "m2"); 1590 assertTrue(cf1.modules().size() == 2); 1591 1592 // resolve should throw ResolutionException 1593 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1_v2); 1594 assertThrows(ResolutionException.class, () -> resolve(cf1, finder2, "m1")); 1595 } 1596 1597 1598 /** 1599 * Basic test to detect reading two modules with the same name 1600 * 1601 * The test consists of three configurations: 1602 * - Configuration cf1: m1, m2 requires transitive m1 1603 * - Configuration cf2: m1, m3 requires transitive m1 1604 * - Configuration cf3(cf1,cf2): m4 requires m2, m3 1605 */ 1606 @Test 1607 void testReadTwoModuleWithSameName() { 1608 ModuleDescriptor descriptor1 = newBuilder("m1") 1609 .build(); 1610 1611 ModuleDescriptor descriptor2 = newBuilder("m2") 1612 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 1613 .build(); 1614 1615 ModuleDescriptor descriptor3 = newBuilder("m3") 1616 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m1") 1617 .build(); 1618 1619 ModuleDescriptor descriptor4 = newBuilder("m4") 1620 .requires("m2") 1621 .requires("m3") 1622 .build(); 1623 1624 ModuleFinder finder1 = ModuleUtils.finderOf(descriptor1, descriptor2); 1625 Configuration cf1 = resolve(finder1, "m2"); 1626 assertTrue(cf1.modules().size() == 2); 1627 1628 ModuleFinder finder2 = ModuleUtils.finderOf(descriptor1, descriptor3); 1629 Configuration cf2 = resolve(finder2, "m3"); 1630 assertTrue(cf2.modules().size() == 2); 1631 1632 // should throw ResolutionException as m4 will read modules named "m1". 1633 ModuleFinder finder3 = ModuleUtils.finderOf(descriptor4); 1634 assertThrows(ResolutionException.class, 1635 () -> Configuration.resolve(finder3, 1636 List.of(cf1, cf2), 1637 ModuleFinder.of(), 1638 Set.of("m4"))); 1639 } 1640 1641 1642 /** 1643 * Test two modules exporting package p to a module that reads both. 1644 */ 1645 @Test 1646 void testPackageSuppliedByTwoOthers() { 1647 ModuleDescriptor descriptor1 = newBuilder("m1") 1648 .requires("m2") 1649 .requires("m3") 1650 .build(); 1651 1652 ModuleDescriptor descriptor2 = newBuilder("m2") 1653 .exports("p") 1654 .build(); 1655 1656 ModuleDescriptor descriptor3 = newBuilder("m3") 1657 .exports("p", Set.of("m1")) 1658 .build(); 1659 1660 ModuleFinder finder 1661 = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 1662 1663 // m2 and m3 export package p to module m1 1664 assertThrows(ResolutionException.class, () -> resolve(finder, "m1")); 1665 } 1666 1667 1668 /** 1669 * Test the scenario where a module contains a package p and reads 1670 * a module that exports package p. 1671 */ 1672 @Test 1673 void testPackageSuppliedBySelfAndOther() { 1674 ModuleDescriptor descriptor1 = newBuilder("m1") 1675 .requires("m2") 1676 .packages(Set.of("p")) 1677 .build(); 1678 1679 ModuleDescriptor descriptor2 = newBuilder("m2") 1680 .exports("p") 1681 .build(); 1682 1683 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1684 1685 // m1 contains package p, module m2 exports package p to m1 1686 assertThrows(ResolutionException.class, () -> resolve(finder, "m1")); 1687 } 1688 1689 1690 /** 1691 * Test the scenario where a module contains a package p and reads 1692 * a module that also contains a package p. 1693 */ 1694 @Test 1695 void testContainsPackageInSelfAndOther() { 1696 ModuleDescriptor descriptor1 = newBuilder("m1") 1697 .requires("m2") 1698 .packages(Set.of("p")) 1699 .build(); 1700 1701 ModuleDescriptor descriptor2 = newBuilder("m2") 1702 .packages(Set.of("p")) 1703 .build(); 1704 1705 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1706 1707 Configuration cf = resolve(finder, "m1"); 1708 1709 assertTrue(cf.modules().size() == 2); 1710 assertTrue(cf.findModule("m1").isPresent()); 1711 assertTrue(cf.findModule("m2").isPresent()); 1712 1713 // m1 reads m2, m2 reads nothing 1714 ResolvedModule m1 = cf.findModule("m1").get(); 1715 ResolvedModule m2 = cf.findModule("m2").get(); 1716 assertTrue(m1.reads().size() == 1); 1717 assertTrue(m1.reads().contains(m2)); 1718 assertTrue(m2.reads().size() == 0); 1719 } 1720 1721 1722 /** 1723 * Test the scenario where a module that exports a package that is also 1724 * exported by a module that it reads in a parent layer. 1725 */ 1726 @Test 1727 void testExportSamePackageAsBootLayer() { 1728 ModuleDescriptor descriptor = newBuilder("m1") 1729 .requires("java.base") 1730 .exports("java.lang") 1731 .build(); 1732 1733 ModuleFinder finder = ModuleUtils.finderOf(descriptor); 1734 1735 Configuration bootConfiguration = ModuleLayer.boot().configuration(); 1736 1737 // m1 contains package java.lang, java.base exports package java.lang to m1 1738 assertThrows(ResolutionException.class, () -> resolve(bootConfiguration, finder, "m1")); 1739 } 1740 1741 1742 /** 1743 * Test "uses p.S" where p is contained in the same module. 1744 */ 1745 @Test 1746 void testContainsService1() { 1747 ModuleDescriptor descriptor1 = newBuilder("m1") 1748 .packages(Set.of("p")) 1749 .uses("p.S") 1750 .build(); 1751 1752 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1753 1754 Configuration cf = resolve(finder, "m1"); 1755 1756 assertTrue(cf.modules().size() == 1); 1757 assertTrue(cf.findModule("m1").isPresent()); 1758 } 1759 1760 1761 /** 1762 * Test "uses p.S" where p is contained in a different module. 1763 */ 1764 @Test 1765 void testContainsService2() { 1766 ModuleDescriptor descriptor1 = newBuilder("m1") 1767 .packages(Set.of("p")) 1768 .build(); 1769 1770 ModuleDescriptor descriptor2 = newBuilder("m2") 1771 .requires("m1") 1772 .uses("p.S") 1773 .build(); 1774 1775 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1776 1777 // m2 does not read a module that exports p 1778 assertThrows(ResolutionException.class, () -> resolve(finder, "m2")); 1779 } 1780 1781 1782 /** 1783 * Test "provides p.S" where p is contained in the same module. 1784 */ 1785 @Test 1786 void testContainsService3() { 1787 ModuleDescriptor descriptor1 = newBuilder("m1") 1788 .packages(Set.of("p", "q")) 1789 .provides("p.S", List.of("q.S1")) 1790 .build(); 1791 1792 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1793 1794 Configuration cf = resolve(finder, "m1"); 1795 1796 assertTrue(cf.modules().size() == 1); 1797 assertTrue(cf.findModule("m1").isPresent()); 1798 } 1799 1800 1801 /** 1802 * Test "provides p.S" where p is contained in a different module. 1803 */ 1804 @Test 1805 void testContainsService4() { 1806 ModuleDescriptor descriptor1 = newBuilder("m1") 1807 .packages(Set.of("p")) 1808 .build(); 1809 1810 ModuleDescriptor descriptor2 = newBuilder("m2") 1811 .requires("m1") 1812 .provides("p.S", List.of("q.S1")) 1813 .build(); 1814 1815 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1816 1817 // m2 does not read a module that exports p 1818 assertThrows(ResolutionException.class, () -> resolve(finder, "m2")); 1819 } 1820 1821 /** 1822 * Test uses optional service. 1823 * 1824 * module m1 { requires static m2; uses p.S; } 1825 */ 1826 @Test 1827 void testUsesOptionalService1() { 1828 ModuleDescriptor descriptor1 = newBuilder("m1") 1829 .requires(Set.of(Requires.Modifier.STATIC), "m2") 1830 .uses("p.S") 1831 .build(); 1832 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1833 Configuration cf = resolve(finder, "m1"); 1834 assertTrue(cf.modules().size() == 1); 1835 assertTrue(cf.findModule("m1").isPresent()); 1836 } 1837 1838 /** 1839 * Test uses optional service. 1840 * 1841 * module m1 { requires m2; uses p.S; } 1842 * module m2 { requires static transitive m3; } 1843 */ 1844 @Test 1845 void testUsesOptionalService2() { 1846 ModuleDescriptor descriptor1 = newBuilder("m1") 1847 .requires("m2") 1848 .uses("p.S") 1849 .build(); 1850 ModuleDescriptor descriptor2 = newBuilder("m2") 1851 .requires(Set.of(Requires.Modifier.STATIC, Requires.Modifier.TRANSITIVE), "m3") 1852 .build(); 1853 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1854 Configuration cf = resolve(finder, "m1"); 1855 assertTrue(cf.modules().size() == 2); 1856 assertTrue(cf.findModule("m1").isPresent()); 1857 assertTrue(cf.findModule("m2").isPresent()); 1858 } 1859 1860 /** 1861 * Test uses optional service. 1862 * 1863 * module m1 { requires m2; uses p.S; } 1864 * module m2 { requires transitive m3; } 1865 * module m3 { requires static transitive m4; } 1866 */ 1867 @Test 1868 void testUsesOptionalService3() { 1869 ModuleDescriptor descriptor1 = newBuilder("m1") 1870 .requires("m2") 1871 .uses("p.S") 1872 .build(); 1873 ModuleDescriptor descriptor2 = newBuilder("m2") 1874 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m3") 1875 .build(); 1876 ModuleDescriptor descriptor3 = newBuilder("m3") 1877 .requires(Set.of(Requires.Modifier.STATIC, Requires.Modifier.TRANSITIVE), "m4") 1878 .build(); 1879 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 1880 Configuration cf = resolve(finder, "m1"); 1881 assertTrue(cf.modules().size() == 3); 1882 assertTrue(cf.findModule("m1").isPresent()); 1883 assertTrue(cf.findModule("m2").isPresent()); 1884 assertTrue(cf.findModule("m3").isPresent()); 1885 } 1886 1887 /** 1888 * Test provides optional service. 1889 * 1890 * module m1 { requires static m2; provides p.S with q.P; } 1891 */ 1892 @Test 1893 void testProvidesOptionalService1() { 1894 ModuleDescriptor descriptor1 = newBuilder("m1") 1895 .requires(Set.of(Requires.Modifier.STATIC), "m2") 1896 .provides("p.S", List.of("q.P")) 1897 .build(); 1898 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1899 Configuration cf = resolve(finder, "m1"); 1900 assertTrue(cf.modules().size() == 1); 1901 assertTrue(cf.findModule("m1").isPresent()); 1902 } 1903 1904 /** 1905 * Test provides optional service. 1906 * 1907 * module m1 { requires m2; provides p.S with q.P; } 1908 * module m2 { requires static transitive m3; } 1909 */ 1910 @Test 1911 void testProvidesOptionalService2() { 1912 ModuleDescriptor descriptor1 = newBuilder("m1") 1913 .requires("m2") 1914 .provides("p.S", List.of("q.P")) 1915 .build(); 1916 ModuleDescriptor descriptor2 = newBuilder("m2") 1917 .requires(Set.of(Requires.Modifier.STATIC, Requires.Modifier.TRANSITIVE), "m3") 1918 .build(); 1919 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1920 Configuration cf = resolve(finder, "m1"); 1921 assertTrue(cf.modules().size() == 2); 1922 assertTrue(cf.findModule("m1").isPresent()); 1923 assertTrue(cf.findModule("m2").isPresent()); 1924 } 1925 1926 /** 1927 * Test provides optional service. 1928 * 1929 * module m1 { requires m2; provides p.S with q.P; } 1930 * module m2 { requires transitive m3; } 1931 * module m3 { requires static transitive m4; } 1932 */ 1933 @Test 1934 void testProvidesOptionalService3() { 1935 ModuleDescriptor descriptor1 = newBuilder("m1") 1936 .requires("m2") 1937 .provides("p.S", List.of("q.P")) 1938 .build(); 1939 ModuleDescriptor descriptor2 = newBuilder("m2") 1940 .requires(Set.of(Requires.Modifier.TRANSITIVE), "m3") 1941 .build(); 1942 ModuleDescriptor descriptor3 = newBuilder("m3") 1943 .requires(Set.of(Requires.Modifier.STATIC, Requires.Modifier.TRANSITIVE), "m4") 1944 .build(); 1945 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2, descriptor3); 1946 Configuration cf = resolve(finder, "m1"); 1947 assertTrue(cf.modules().size() == 3); 1948 assertTrue(cf.findModule("m1").isPresent()); 1949 assertTrue(cf.findModule("m2").isPresent()); 1950 assertTrue(cf.findModule("m3").isPresent()); 1951 } 1952 1953 /** 1954 * Test "uses p.S" where p is not exported to the module. 1955 */ 1956 @Test 1957 void testServiceTypePackageNotExported1() { 1958 ModuleDescriptor descriptor1 = newBuilder("m1") 1959 .uses("p.S") 1960 .build(); 1961 ModuleFinder finder = ModuleUtils.finderOf(descriptor1); 1962 1963 // m1 does not read a module that exports p to m1 1964 assertThrows(ResolutionException.class, () -> resolve(finder, "m1")); 1965 } 1966 1967 /** 1968 * Test "uses p.S" where p is not exported to the module. 1969 * 1970 * module m1 { requires m2; uses p.S; } 1971 * module m2 { contains p; } 1972 */ 1973 @Test 1974 void testServiceTypePackageNotExported2() { 1975 ModuleDescriptor descriptor1 = newBuilder("m1") 1976 .requires("m2") 1977 .uses("p.S") 1978 .build(); 1979 ModuleDescriptor descriptor2 = newBuilder("m2") 1980 .packages(Set.of("p")) 1981 .build(); 1982 ModuleFinder finder = ModuleUtils.finderOf(descriptor1, descriptor2); 1983 1984 // m1 does not read a module that exports p to m1 1985 assertThrows(ResolutionException.class, () -> resolve(finder, "m1")); 1986 } 1987 1988 1989 /** 1990 * Test the empty configuration. 1991 */ 1992 @Test 1993 void testEmptyConfiguration() { 1994 Configuration cf = Configuration.empty(); 1995 1996 assertTrue(cf.parents().isEmpty()); 1997 1998 assertTrue(cf.modules().isEmpty()); 1999 assertFalse(cf.findModule("java.base").isPresent()); 2000 } 2001 2002 /** 2003 * Test creating a configuration containing platform specific modules. 2004 */ 2005 @ParameterizedTest 2006 @CsvSource({",", "linux-aarch64,", "linux-aarch64,linux-aarch64"}) 2007 void testPlatformMatch(String targetPlatform1, String targetPlatform2) throws IOException { 2008 ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build(); 2009 Path system = writeModule(base, null); 2010 2011 ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1") 2012 .requires("m2") 2013 .build(); 2014 Path dir1 = writeModule(descriptor1, targetPlatform1); 2015 2016 ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2").build(); 2017 Path dir2 = writeModule(descriptor2, targetPlatform2); 2018 2019 ModuleFinder finder = ModuleFinder.of(system, dir1, dir2); 2020 2021 Configuration cf = resolve(finder, "m1"); 2022 2023 assertTrue(cf.modules().size() == 3); 2024 assertTrue(cf.findModule("java.base").isPresent()); 2025 assertTrue(cf.findModule("m1").isPresent()); 2026 assertTrue(cf.findModule("m2").isPresent()); 2027 } 2028 2029 /** 2030 * Test attempting to create a configuration with modules for different platforms. 2031 */ 2032 @ParameterizedTest 2033 @CsvSource({"linux-x64,linux-aarch64", "linux-x64,windows-x64"}) 2034 void testPlatformMisMatch(String targetPlatform1, String targetPlatform2) throws IOException { 2035 assertThrows(FindException.class, 2036 () -> testPlatformMatch(targetPlatform1, targetPlatform2)); 2037 } 2038 2039 // no parents 2040 2041 @Test 2042 void testResolveRequiresWithNoParents() { 2043 ModuleFinder empty = ModuleFinder.of(); 2044 assertThrows(IllegalArgumentException.class, 2045 () -> Configuration.resolve(empty, List.of(), empty, Set.of())); 2046 } 2047 2048 @Test 2049 void testResolveRequiresAndUsesWithNoParents() { 2050 ModuleFinder empty = ModuleFinder.of(); 2051 assertThrows(IllegalArgumentException.class, 2052 () -> Configuration.resolveAndBind(empty, List.of(), empty, Set.of())); 2053 } 2054 2055 2056 // parents with modules for specific platforms 2057 @ParameterizedTest 2058 @CsvSource({",", "linux-aarch64,", "linux-aarch64,linux-aarch64"}) 2059 void testResolveRequiresWithCompatibleParents(String targetPlatform1, 2060 String targetPlatform2) throws IOException { 2061 ModuleDescriptor base = ModuleDescriptor.newModule("java.base").build(); 2062 Path system = writeModule(base, null); 2063 2064 ModuleDescriptor descriptor1 = ModuleDescriptor.newModule("m1").build(); 2065 Path dir1 = writeModule(descriptor1, targetPlatform1); 2066 2067 ModuleDescriptor descriptor2 = ModuleDescriptor.newModule("m2").build(); 2068 Path dir2 = writeModule(descriptor2, targetPlatform2); 2069 2070 ModuleFinder finder1 = ModuleFinder.of(system, dir1); 2071 Configuration cf1 = resolve(finder1, "m1"); 2072 2073 ModuleFinder finder2 = ModuleFinder.of(system, dir2); 2074 Configuration cf2 = resolve(finder2, "m2"); 2075 2076 Configuration cf3 = Configuration.resolve(ModuleFinder.of(), 2077 List.of(cf1, cf2), 2078 ModuleFinder.of(), 2079 Set.of()); 2080 assertTrue(cf3.parents().size() == 2); 2081 } 2082 2083 2084 @ParameterizedTest 2085 @CsvSource({"linux-x64,linux-aarch64", "linux-x64,windows-x64"}) 2086 void testResolveRequiresWithConflictingParents(String targetPlatform1, 2087 String targetPlatform2) throws IOException { 2088 assertThrows(IllegalArgumentException.class, 2089 () -> testResolveRequiresWithCompatibleParents(targetPlatform1, targetPlatform2)); 2090 } 2091 2092 2093 // null handling 2094 2095 @Test 2096 void testResolveRequiresWithNull1() { 2097 assertThrows(NullPointerException.class, 2098 () -> resolve((ModuleFinder) null, ModuleFinder.of())); 2099 } 2100 2101 @Test 2102 void testResolveRequiresWithNull2() { 2103 assertThrows(NullPointerException.class, 2104 () -> resolve(ModuleFinder.of(), (ModuleFinder) null)); 2105 } 2106 2107 @Test 2108 void testResolveRequiresWithNull3() { 2109 Configuration empty = Configuration.empty(); 2110 assertThrows(NullPointerException.class, 2111 () -> Configuration.resolve(null, List.of(empty), ModuleFinder.of(), Set.of())); 2112 } 2113 2114 @Test 2115 void testResolveRequiresWithNull4() { 2116 ModuleFinder empty = ModuleFinder.of(); 2117 assertThrows(NullPointerException.class, 2118 () -> Configuration.resolve(empty, null, empty, Set.of())); 2119 } 2120 2121 @Test 2122 void testResolveRequiresWithNull5() { 2123 Configuration cf = ModuleLayer.boot().configuration(); 2124 assertThrows(NullPointerException.class, 2125 () -> Configuration.resolve(ModuleFinder.of(), List.of(cf), null, Set.of())); 2126 } 2127 2128 @Test 2129 void testResolveRequiresWithNull6() { 2130 ModuleFinder empty = ModuleFinder.of(); 2131 Configuration cf = ModuleLayer.boot().configuration(); 2132 assertThrows(NullPointerException.class, 2133 () -> Configuration.resolve(empty, List.of(cf), empty, null)); 2134 } 2135 2136 @Test 2137 void testResolveRequiresAndUsesWithNull1() { 2138 assertThrows(NullPointerException.class, 2139 () -> resolveAndBind((ModuleFinder) null, ModuleFinder.of())); 2140 } 2141 2142 @Test 2143 void testResolveRequiresAndUsesWithNull2() { 2144 assertThrows(NullPointerException.class, 2145 () -> resolveAndBind(ModuleFinder.of(), (ModuleFinder) null)); 2146 } 2147 2148 @Test 2149 void testResolveRequiresAndUsesWithNull3() { 2150 Configuration empty = Configuration.empty(); 2151 assertThrows(NullPointerException.class, 2152 () -> Configuration.resolveAndBind(null, List.of(empty), ModuleFinder.of(), Set.of())); 2153 } 2154 2155 @Test 2156 void testResolveRequiresAndUsesWithNull4() { 2157 ModuleFinder empty = ModuleFinder.of(); 2158 assertThrows(NullPointerException.class, 2159 () -> Configuration.resolveAndBind(empty, null, empty, Set.of())); 2160 } 2161 2162 @Test 2163 void testResolveRequiresAndUsesWithNull5() { 2164 Configuration cf = ModuleLayer.boot().configuration(); 2165 assertThrows(NullPointerException.class, 2166 () -> Configuration.resolveAndBind(ModuleFinder.of(), List.of(cf), null, Set.of())); 2167 } 2168 2169 @Test 2170 void testResolveRequiresAndUsesWithNull6() { 2171 ModuleFinder empty = ModuleFinder.of(); 2172 Configuration cf = ModuleLayer.boot().configuration(); 2173 assertThrows(NullPointerException.class, 2174 () -> Configuration.resolveAndBind(empty, List.of(cf), empty, null)); 2175 } 2176 2177 @Test 2178 void testFindModuleWithNull() { 2179 assertThrows(NullPointerException.class, () -> Configuration.empty().findModule(null)); 2180 } 2181 2182 // unmodifiable collections 2183 2184 static Stream<Configuration> configurations() { 2185 return Stream.of( 2186 Configuration.empty(), 2187 ModuleLayer.boot().configuration(), 2188 resolve(ModuleFinder.of()) 2189 ); 2190 } 2191 2192 @ParameterizedTest 2193 @MethodSource("configurations") 2194 void testUnmodifiableParents(Configuration cf) { 2195 assertThrows(UnsupportedOperationException.class, 2196 () -> cf.parents().add(Configuration.empty())); 2197 assertThrows(UnsupportedOperationException.class, 2198 () -> cf.parents().remove(Configuration.empty())); 2199 } 2200 2201 @ParameterizedTest 2202 @MethodSource("configurations") 2203 void testUnmodifiableModules(Configuration cf) { 2204 ResolvedModule module = ModuleLayer.boot() 2205 .configuration() 2206 .findModule("java.base") 2207 .orElseThrow(); 2208 assertThrows(UnsupportedOperationException.class, 2209 () -> cf.modules().add(module)); 2210 assertThrows(UnsupportedOperationException.class, 2211 () -> cf.modules().remove(module)); 2212 } 2213 2214 /** 2215 * Invokes parent.resolve(...) 2216 */ 2217 private static Configuration resolve(Configuration parent, 2218 ModuleFinder before, 2219 ModuleFinder after, 2220 String... roots) { 2221 return parent.resolve(before, after, Set.of(roots)); 2222 } 2223 2224 private static Configuration resolve(Configuration parent, 2225 ModuleFinder before, 2226 String... roots) { 2227 return resolve(parent, before, ModuleFinder.of(), roots); 2228 } 2229 2230 private static Configuration resolve(ModuleFinder before, 2231 ModuleFinder after, 2232 String... roots) { 2233 return resolve(Configuration.empty(), before, after, roots); 2234 } 2235 2236 private static Configuration resolve(ModuleFinder before, 2237 String... roots) { 2238 return resolve(Configuration.empty(), before, roots); 2239 } 2240 2241 2242 /** 2243 * Invokes parent.resolveAndBind(...) 2244 */ 2245 private static Configuration resolveAndBind(Configuration parent, 2246 ModuleFinder before, 2247 ModuleFinder after, 2248 String... roots) { 2249 return parent.resolveAndBind(before, after, Set.of(roots)); 2250 } 2251 2252 private static Configuration resolveAndBind(Configuration parent, 2253 ModuleFinder before, 2254 String... roots) { 2255 return resolveAndBind(parent, before, ModuleFinder.of(), roots); 2256 } 2257 2258 private static Configuration resolveAndBind(ModuleFinder before, 2259 ModuleFinder after, 2260 String... roots) { 2261 return resolveAndBind(Configuration.empty(), before, after, roots); 2262 } 2263 2264 private static Configuration resolveAndBind(ModuleFinder before, 2265 String... roots) { 2266 return resolveAndBind(Configuration.empty(), before, roots); 2267 } 2268 2269 2270 /** 2271 * Writes a module-info.class. If {@code targetPlatform} is not null then 2272 * it includes the ModuleTarget class file attribute with the target platform. 2273 */ 2274 private static Path writeModule(ModuleDescriptor descriptor, String targetPlatform) 2275 throws IOException 2276 { 2277 ModuleTarget target; 2278 if (targetPlatform != null) { 2279 target = new ModuleTarget(targetPlatform); 2280 } else { 2281 target = null; 2282 } 2283 String name = descriptor.name(); 2284 Path dir = Files.createTempDirectory(Paths.get(""), name); 2285 Path mi = dir.resolve("module-info.class"); 2286 try (OutputStream out = Files.newOutputStream(mi)) { 2287 ModuleInfoWriter.write(descriptor, target, out); 2288 } 2289 return dir; 2290 } 2291 }