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