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