Modules.java revision 3792:d516975e8110
1290000Sglebius/*
2132451Sroberto * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3290000Sglebius * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4290000Sglebius *
5290000Sglebius * 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 8159305 8166127
27 * @summary Tests primarily the module graph computations.
28 * @modules
29 *      jdk.javadoc/jdk.javadoc.internal.api
30 *      jdk.javadoc/jdk.javadoc.internal.tool
31 *      jdk.compiler/com.sun.tools.javac.api
32 *      jdk.compiler/com.sun.tools.javac.main
33 * @library /tools/lib
34 * @build toolbox.ToolBox toolbox.TestRunner
35 * @run main Modules
36 */
37
38import java.io.IOException;
39import java.nio.file.Files;
40import java.nio.file.Path;
41
42import toolbox.*;
43import toolbox.Task.Expect;
44import toolbox.Task.OutputKind;
45
46public class Modules extends ModuleTestBase {
47
48    public static void main(String... args) throws Exception {
49        new Modules().runTests();
50    }
51
52    @Test
53    public void testBasicMoption(Path base) throws Exception {
54        Files.createDirectory(base);
55        Path src = base.resolve("src");
56        ModuleBuilder mb = new ModuleBuilder(tb, "m1");
57        mb.comment("The first module.")
58                .exports("pub")
59                .classes("package pub; /** Class A */ public class A {}")
60                .classes("package pro; /** Class B */ public class B {}")
61                .write(src);
62        execTask("--module-source-path", src.toString(),
63                 "--module", "m1");
64        checkModulesSpecified("m1");
65        checkPackagesIncluded("pub");
66        checkTypesIncluded("pub.A");
67    }
68
69    @Test
70    public void testMultipleModulesOption1(Path base) throws Exception {
71        Path src = base.resolve("src");
72
73        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
74        mb1.comment("The first module.")
75                .exports("m1pub")
76                .requires("m2")
77                .classes("package m1pub; /** Class A */ public class A {}")
78                .classes("package m1pro; /** Class B */ public class B {}")
79                .write(src);
80
81        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
82        mb2.comment("The second module.")
83                .exports("m2pub")
84                .classes("package m2pub; /** Class A */ public class A {}")
85                .classes("package m2pro; /** Class B */ public class B {}")
86                .write(src);
87        execTask("--module-source-path", src.toString(),
88            "--module", "m1,m2");
89        checkModulesSpecified("m1", "m2");
90        checkPackagesIncluded("m1pub", "m2pub");
91        checkTypesIncluded("m1pub.A", "m2pub.A");
92
93    }
94
95    @Test
96    public void testMultipleModulesAggregatedModuleOption(Path base) throws Exception {
97        Path src = base.resolve("src");
98
99        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
100        mb1.comment("The first module.")
101                .exports("m1pub")
102                .requires("m2")
103                .classes("package m1pub; /** Class A */ public class A {}")
104                .classes("package m1pro; /** Class B */ public class B {}")
105                .write(src);
106
107        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
108        mb2.comment("The second module.")
109                .exports("m2pub")
110                .classes("package m2pub; /** Class A */ public class A {}")
111                .classes("package m2pro; /** Class B */ public class B {}")
112                .write(src);
113        execTask("--module-source-path", src.toString(),
114            "--module", "m1",
115            "--module", "m2");
116        checkModulesSpecified("m1", "m2");
117        checkPackagesIncluded("m1pub", "m2pub");
118        checkTypesIncluded("m1pub.A", "m2pub.A");
119
120    }
121
122    @Test
123    public void testModulePathOption(Path base) throws Exception {
124        Path src = base.resolve("src");
125        Path modulePath = base.resolve("modules");
126
127        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
128        mb1.comment("Module on module path.")
129                .exports("pkg1")
130                .classes("package pkg1; /** Class A */ public class A { }")
131                .build(modulePath);
132
133        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
134        mb2.comment("The second module.")
135                .exports("pkg2")
136                .requires("m1")
137                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }")
138                .write(src);
139        execTask("--module-source-path", src.toString(),
140                "--module-path", modulePath.toString(),
141                "--module", "m2");
142        checkModulesSpecified("m2");
143        checkPackagesIncluded("pkg2");
144        checkMembersSelected("pkg2.B.f");
145
146        // module path option "-p"
147        execTask("--module-source-path", src.toString(),
148                "-p", modulePath.toString(),
149                "--module", "m2");
150        // no module path
151        execNegativeTask("--module-source-path", src.toString(),
152                "--module", "m2");
153        assertErrorPresent("error: module not found: m1");
154    }
155
156    @Test
157    public void testUpgradeModulePathOption(Path base) throws Exception {
158        Path src = base.resolve("src");
159        Path modulePath = base.resolve("modules");
160        Path upgradePath = base.resolve("upgrades");
161
162        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
163        mb1.comment("Module on module path.")
164                .exports("pkg1")
165                .classes("package pkg1; /** Class A */ public class A { }")
166                .build(modulePath);
167
168        ModuleBuilder mbUpgrade = new ModuleBuilder(tb, "m1");
169        mbUpgrade.comment("Module on upgrade module path.")
170                .exports("pkg1")
171                .classes("package pkg1; /** Class C */ public class C { }")
172                .build(upgradePath);
173
174        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
175        mb2.comment("The second module.")
176                .exports("pkg2")
177                .requires("m1")
178                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.C f; }")
179                .write(src);
180        execTask("--module-source-path", src.toString(),
181                "--module-path", modulePath.toString(),
182                "--upgrade-module-path", upgradePath.toString(),
183                "--module", "m2");
184        checkModulesSpecified("m2");
185        checkPackagesIncluded("pkg2");
186        checkMembersSelected("pkg2.B.f");
187
188        // no upgrade module path
189        execNegativeTask("--module-source-path", src.toString(),
190                "--module-path", modulePath.toString(),
191                "--module", "m2");
192        assertErrorPresent("error: cannot find symbol");
193
194        // dependency from module path
195        ModuleBuilder mb3 = new ModuleBuilder(tb, "m3");
196        mb3.comment("The third module.")
197                .exports("pkg3")
198                .requires("m1")
199                .classes("package pkg3; /** Class Z */ public class Z { /** Field f */ public pkg1.A f; }")
200                .write(src);
201        execNegativeTask("--module-source-path", src.toString(),
202                "--module-path", modulePath.toString(),
203                "--upgrade-module-path", upgradePath.toString(),
204                "--module", "m3");
205        assertErrorPresent("Z.java:1: error: cannot find symbol");
206    }
207
208    @Test
209    public void testAddModulesOption(Path base) throws Exception {
210        Path src = base.resolve("src");
211        Path modulePath = base.resolve("modules");
212
213        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
214        mb1.comment("Module on module path.")
215                .exports("pkg1")
216                .classes("package pkg1; /** Class A */ public class A { }")
217                .build(modulePath);
218
219        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
220        mb2.comment("The second module.")
221                .exports("pkg2")
222                .classes("package pkg2; /** @see pkg1.A */ public class B { }")
223                .write(src);
224
225        Path out = base.resolve("out-1");
226        Files.createDirectories(out);
227        String log = new JavadocTask(tb)
228                .outdir(out)
229                .options("--module-source-path", src.toString(),
230                        "--module-path", modulePath.toString(),
231                        "--module", "m2")
232                .run(Expect.FAIL)
233                .writeAll()
234                .getOutput(OutputKind.DIRECT);
235        if (!log.contains("B.java:1: error: reference not found")) {
236            throw new Exception("Error not found");
237        }
238
239        out = base.resolve("out-2");
240        Files.createDirectories(out);
241        new JavadocTask(tb)
242                .outdir(out)
243                .options("--module-source-path", src.toString(),
244                        "--module-path", modulePath.toString(),
245                        "--add-modules", "m1",
246                        "--module", "m2")
247                .run()
248                .writeAll();
249    }
250
251    @Test
252    public void testLimitModulesOption(Path base) throws Exception {
253        Path src = base.resolve("src");
254        Path modulePath = base.resolve("modules");
255
256        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
257        mb1.comment("Module on module path.")
258                .build(modulePath);
259
260        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
261        mb2.comment("The second module.")
262                .exports("pkg2")
263                .requires("m1")
264                .classes("package pkg2; /** Class B */ public class B { }")
265                .write(src);
266
267        execNegativeTask("--module-source-path", src.toString(),
268                "--module-path", modulePath.toString(),
269                "--limit-modules", "java.base",
270                "--module", "m2");
271        assertErrorPresent("error: module not found: m1");
272    }
273
274    @Test
275    public void testAddExportsOption(Path base) throws Exception {
276        Path src = base.resolve("src");
277        Path modulePath = base.resolve("modules");
278
279        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
280        mb1.comment("Module on module path.")
281                .classes("package pkg1; /** Class A */ public class A { }")
282                .build(modulePath);
283
284        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
285        mb2.comment("The second module.")
286                .exports("pkg2")
287                .requires("m1")
288                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }")
289                .write(src);
290        execTask("--module-source-path", src.toString(),
291                "--module-path", modulePath.toString(),
292                "--add-exports", "m1/pkg1=m2",
293                "--module", "m2");
294        checkModulesSpecified("m2");
295        checkPackagesIncluded("pkg2");
296        checkMembersSelected("pkg2.B.f");
297    }
298
299    @Test
300    public void testPatchModuleOption(Path base) throws Exception {
301        Path src = base.resolve("src");
302        Path modulePath = base.resolve("modules");
303        Path patchPath = base.resolve("patch");
304
305        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
306        mb1.comment("Module on module path.")
307                .exports("pkg1")
308                .classes("package pkg1; /** Class A */ public class A { }")
309                .build(modulePath);
310
311        tb.writeJavaFiles(patchPath, "package pkg1; /** Class A */ public class A { public static int k; }");
312        new JavacTask(tb)
313                .files(patchPath.resolve("pkg1/A.java"))
314                .run();
315
316        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
317        mb2.comment("The second module.")
318                .exports("pkg2")
319                .requires("m1")
320                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public int f = pkg1.A.k; }")
321                .write(src);
322        execTask("--module-source-path", src.toString(),
323                "--patch-module", "m1=" + patchPath.toString(),
324                "--module-path", modulePath.toString(),
325                "--module", "m2");
326        checkModulesSpecified("m2");
327        checkPackagesIncluded("pkg2");
328        checkMembersSelected("pkg2.B.f");
329    }
330
331    @Test
332    public void testAddReadsOption(Path base) throws Exception {
333        Path src = base.resolve("src");
334        Path modulePath = base.resolve("modules");
335
336        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
337        mb1.comment("Module on module path.")
338                .exports("pkg1")
339                .classes("package pkg1; /** Class A */ public class A {}")
340                .build(modulePath);
341
342        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
343        mb2.comment("The second module.")
344                .exports("pkg2")
345                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f;}")
346                .write(src);
347        execTask("--module-source-path", src.toString(),
348                "--module-path", modulePath.toString(),
349                "--add-modules", "m1",
350                "--add-reads", "m2=m1",
351                "--module", "m2");
352        checkModulesSpecified("m2");
353        checkPackagesIncluded("pkg2");
354        checkMembersSelected("pkg2.B.f");
355    }
356
357    @Test
358    public void testModuleOptionsWithLegacy(Path base) throws Exception {
359        Files.createDirectory(base);
360        Path src = base.resolve("src");
361        Path classpath = base.resolve("classpath");
362        Path modulePath = base.resolve("modules");
363
364        tb.writeJavaFiles(classpath, "package pkg1; /** Class C */ public class C { }");
365        new JavacTask(tb)
366                .files(classpath.resolve("pkg1/C.java"))
367                .run();
368
369        ModuleBuilder mb = new ModuleBuilder(tb, "m1");
370        mb.comment("The first module.")
371                .exports("pub")
372                .classes("package pub; /** Class M */ public class M { }")
373                .build(modulePath);
374
375        tb.writeJavaFiles(src, "package pkg; /** Class L */ public class L { public pkg1.C f1; public pub.M f2; }");
376
377        execTask("--source-path", src.toString(),
378                "--class-path", classpath.toString(),
379                "--module-path", modulePath.toString(),
380                "--add-modules", "m1",
381                "pkg");
382        checkPackagesIncluded("pkg");
383        checkTypesIncluded("pkg.L");
384        checkMembersSelected("pkg.L.f1");
385        checkMembersSelected("pkg.L.f2");
386        assertAbsent("error", OutputKind.DIRECT);
387    }
388
389    /**
390     * Tests diamond graph, inspired by javac diamond tests.
391     *
392     *
393     * Module M : test module, with variable requires
394     *
395     * Module N :
396     *     requires transitive O  --->   Module O:
397     *                                   requires J   ---->   Module J:
398     *                                   exports openO          exports openJ
399     *
400     *
401     * Module L :
402     *     requires transitive P  --->   Module P:
403     *                                   exports openP
404     *
405     *
406     */
407
408    @Test
409    public void testExpandRequiresNone(Path base) throws Exception {
410        Path src = base.resolve("src");
411
412        createAuxiliaryModules(src);
413
414        new ModuleBuilder(tb, "M")
415                .comment("The M module.")
416                .requires("N", src)
417                .requires("L", src)
418                .requires("O", src)
419                .exports("p")
420                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
421                .write(src);
422
423        execTask("--module-source-path", src.toString(),
424                "--module", "M");
425
426        checkModulesSpecified("M");
427        checkModulesIncluded("M");
428        checkPackagesIncluded("p");
429        checkTypesIncluded("p.Main");
430        checkPackagesNotIncluded(".*open.*");
431    }
432
433    @Test
434    public void testExpandRequiresTransitive(Path base) throws Exception {
435        Path src = base.resolve("src");
436
437        createAuxiliaryModules(src);
438
439        new ModuleBuilder(tb, "M")
440                .comment("The M module.")
441                .requiresTransitive("N", src)
442                .requires("L", src)
443                .exports("p")
444                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
445                .write(src);
446
447        execTask("--module-source-path", src.toString(),
448                "--module", "M",
449                "--expand-requires", "transitive");
450
451        checkModulesSpecified("M", "N", "O");
452        checkModulesIncluded("M", "N", "O");
453        checkPackagesIncluded("p", "openN", "openO");
454        checkTypesIncluded("p.Main", "openN.N", "openO.O");
455    }
456
457    @Test
458    public void testExpandRequiresAll(Path base) throws Exception {
459        Path src = base.resolve("src");
460
461        createAuxiliaryModules(src);
462
463        new ModuleBuilder(tb, "M")
464                .comment("The M module.")
465                .requiresTransitive("N", src)
466                .requires("L", src)
467                .requires("O", src)
468                .exports("p")
469                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
470                .write(src);
471
472        execTask("--module-source-path", src.toString(),
473                "--module", "M",
474                "--expand-requires", "all");
475
476        checkModulesSpecified("M", "java.base", "N", "L", "O");
477        checkModulesIncluded("M", "java.base", "N", "L", "O");
478        checkModulesNotIncluded("P", "J", "Q");
479        checkPackagesIncluded("p", "openN", "openL", "openO");
480        checkPackagesNotIncluded(".*openP.*", ".*openJ.*");
481        checkTypesIncluded("p.Main", "openN.N", "openL.L", "openO.O");
482        checkTypesNotIncluded(".*openP.*", ".*openJ.*");
483    }
484
485    @Test
486    public void testMissingModule(Path base) throws Exception {
487        Path src = base.resolve("src");
488
489        createAuxiliaryModules(src);
490
491        new ModuleBuilder(tb, "M")
492                .comment("The M module.")
493                .requiresTransitive("N", src)
494                .requires("L", src)
495                .requires("O", src)
496                .exports("p")
497                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
498                .write(src);
499
500        execNegativeTask("--module-source-path", src.toString(),
501                "--module", "MIA",
502                "--expand-requires", "all");
503
504        assertErrorPresent("javadoc: error - module MIA not found.");
505    }
506
507    @Test
508    public void testMissingModuleMultiModuleCmdline(Path base) throws Exception {
509        Path src = base.resolve("src");
510
511        createAuxiliaryModules(src);
512
513        new ModuleBuilder(tb, "M")
514                .comment("The M module.")
515                .requiresTransitive("N", src)
516                .requires("L", src)
517                .requires("O", src)
518                .exports("p")
519                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
520                .write(src);
521
522        execNegativeTask("--module-source-path", src.toString(),
523                "--module", "M,N,L,MIA,O,P",
524                "--expand-requires", "all");
525
526        assertErrorPresent("javadoc: error - module MIA not found");
527    }
528
529    void createAuxiliaryModules(Path src) throws IOException {
530
531        new ModuleBuilder(tb, "J")
532                .comment("The J module.")
533                .exports("openJ")
534                .classes("package openJ;  /** Class J open. */ public class J { }")
535                .classes("package closedJ; /** Class J closed. */ public class J  { }")
536                .write(src);
537
538        new ModuleBuilder(tb, "L")
539                .comment("The L module.")
540                .exports("openL")
541                . requiresTransitive("P")
542                .classes("package openL; /** Class L open */ public class L { }")
543                .classes("package closedL;  /** Class L closed */ public class L { }")
544                .write(src);
545
546        new ModuleBuilder(tb, "N")
547                .comment("The N module.")
548                .exports("openN")
549                .requiresTransitive("O")
550                .classes("package openN; /** Class N open */ public class N  { }")
551                .classes("package closedN; /** Class N closed */ public class N { }")
552                .write(src);
553
554        new ModuleBuilder(tb, "O")
555                .comment("The O module.")
556                .exports("openO")
557                .requires("J")
558                .classes("package openO; /** Class O open. */ public class O { openJ.J j; }")
559                .classes("package closedO;  /** Class O closed. */ public class O { }")
560                .write(src);
561
562        new ModuleBuilder(tb, "P")
563                .comment("The O module.")
564                .exports("openP")
565                .requires("J")
566                .classes("package openP; /** Class O open. */ public class O { openJ.J j; }")
567                .classes("package closedP;  /** Class O closed. */ public class O { }")
568                .write(src);
569
570        new ModuleBuilder(tb, "Q")
571                .comment("The Q module.")
572                .exports("openQ")
573                .requires("J")
574                .classes("package openQ; /** Class Q open. */ public class Q { openJ.J j; }")
575                .classes("package closedQ;  /** Class Q closed. */ public class Q { }")
576                .write(src);
577
578    }
579}
580