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