ConfigurationTest.java revision 16177:89ef4b822745
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
32import java.lang.module.Configuration;
33import java.lang.module.ModuleDescriptor;
34import java.lang.module.ModuleDescriptor.Requires;
35import java.lang.module.ModuleFinder;
36import java.lang.module.ResolutionException;
37import java.lang.module.ResolvedModule;
38import java.lang.reflect.Layer;
39import java.util.HashSet;
40import java.util.List;
41import java.util.Optional;
42import java.util.Set;
43
44import org.testng.annotations.DataProvider;
45import org.testng.annotations.Test;
46import static org.testng.Assert.*;
47
48@Test
49public 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}
2239