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