Modules.java revision 3673:8bf23828bb2f
1/*
2 * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test
26 * @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        String log = new JavadocTask(tb)
226                .options("--module-source-path", src.toString(),
227                        "--module-path", modulePath.toString(),
228                        "--module", "m2")
229                .run(Expect.FAIL)
230                .writeAll()
231                .getOutput(OutputKind.DIRECT);
232        if (!log.contains("B.java:1: error: reference not found")) {
233            throw new Exception("Error not found");
234        }
235
236        new JavadocTask(tb)
237                .options("--module-source-path", src.toString(),
238                        "--module-path", modulePath.toString(),
239                        "--add-modules", "m1",
240                        "--module", "m2")
241                .run()
242                .writeAll();
243    }
244
245    @Test
246    public void testLimitModulesOption(Path base) throws Exception {
247        Path src = base.resolve("src");
248        Path modulePath = base.resolve("modules");
249
250        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
251        mb1.comment("Module on module path.")
252                .build(modulePath);
253
254        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
255        mb2.comment("The second module.")
256                .exports("pkg2")
257                .requires("m1")
258                .classes("package pkg2; /** Class B */ public class B { }")
259                .write(src);
260
261        execNegativeTask("--module-source-path", src.toString(),
262                "--module-path", modulePath.toString(),
263                "--limit-modules", "java.base",
264                "--module", "m2");
265        assertErrorPresent("error: module not found: m1");
266    }
267
268    @Test
269    public void testAddExportsOption(Path base) throws Exception {
270        Path src = base.resolve("src");
271        Path modulePath = base.resolve("modules");
272
273        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
274        mb1.comment("Module on module path.")
275                .classes("package pkg1; /** Class A */ public class A { }")
276                .build(modulePath);
277
278        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
279        mb2.comment("The second module.")
280                .exports("pkg2")
281                .requires("m1")
282                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f; }")
283                .write(src);
284        execTask("--module-source-path", src.toString(),
285                "--module-path", modulePath.toString(),
286                "--add-exports", "m1/pkg1=m2",
287                "--module", "m2");
288        checkModulesSpecified("m2");
289        checkPackagesIncluded("pkg2");
290        checkMembersSelected("pkg2.B.f");
291    }
292
293//    @Test @ignore JDK-8166379
294    public void testPatchModuleOption(Path base) throws Exception {
295        Path src = base.resolve("src");
296        Path modulePath = base.resolve("modules");
297        Path patchPath = base.resolve("patch");
298
299        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
300        mb1.comment("Module on module path.")
301                .exports("pkg1")
302                .classes("package pkg1; /** Class A */ public class A { }")
303                .build(modulePath);
304
305        tb.writeJavaFiles(patchPath, "package pkg1; /** Class A */ public class A { public static int k; }");
306        new JavacTask(tb)
307                .files(patchPath.resolve("pkg1/A.java"))
308                .run();
309
310        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
311        mb2.comment("The second module.")
312                .exports("pkg2")
313                .requires("m1")
314                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public int f = pkg1.A.k; }")
315                .write(src);
316        execTask("--module-source-path", src.toString(),
317                "--patch-module", "m1=" + patchPath.toString(),
318                "--module-path", modulePath.toString(),
319                "--module", "m2");
320        checkModulesSpecified("m2");
321        checkPackagesIncluded("pkg2");
322        checkMembersSelected("pkg2.B.f");
323    }
324
325    @Test
326    public void testAddReadsOption(Path base) throws Exception {
327        Path src = base.resolve("src");
328        Path modulePath = base.resolve("modules");
329
330        ModuleBuilder mb1 = new ModuleBuilder(tb, "m1");
331        mb1.comment("Module on module path.")
332                .exports("pkg1")
333                .classes("package pkg1; /** Class A */ public class A {}")
334                .build(modulePath);
335
336        ModuleBuilder mb2 = new ModuleBuilder(tb, "m2");
337        mb2.comment("The second module.")
338                .exports("pkg2")
339                .classes("package pkg2; /** Class B */ public class B { /** Field f */ public pkg1.A f;}")
340                .write(src);
341        execTask("--module-source-path", src.toString(),
342                "--module-path", modulePath.toString(),
343                "--add-modules", "m1",
344                "--add-reads", "m2=m1",
345                "--module", "m2");
346        checkModulesSpecified("m2");
347        checkPackagesIncluded("pkg2");
348        checkMembersSelected("pkg2.B.f");
349    }
350
351    @Test
352    public void testModuleOptionsWithLegacy(Path base) throws Exception {
353        Files.createDirectory(base);
354        Path src = base.resolve("src");
355        Path classpath = base.resolve("classpath");
356        Path modulePath = base.resolve("modules");
357
358        tb.writeJavaFiles(classpath, "package pkg1; /** Class C */ public class C { }");
359        new JavacTask(tb)
360                .files(classpath.resolve("pkg1/C.java"))
361                .run();
362
363        ModuleBuilder mb = new ModuleBuilder(tb, "m1");
364        mb.comment("The first module.")
365                .exports("pub")
366                .classes("package pub; /** Class M */ public class M { }")
367                .build(modulePath);
368
369        tb.writeJavaFiles(src, "package pkg; /** Class L */ public class L { public pkg1.C f1; public pub.M f2; }");
370
371        execTask("--source-path", src.toString(),
372                "--class-path", classpath.toString(),
373                "--module-path", modulePath.toString(),
374                "--add-modules", "m1",
375                "pkg");
376        checkPackagesIncluded("pkg");
377        checkTypesIncluded("pkg.L");
378        checkMembersSelected("pkg.L.f1");
379        checkMembersSelected("pkg.L.f2");
380        assertAbsent("error", OutputKind.DIRECT);
381    }
382
383    /**
384     * Tests diamond graph, inspired by javac diamond tests.
385     *
386     *
387     * Module M : test module, with variable requires
388     *
389     * Module N :
390     *     requires public O  --->   Module O:
391     *                                 requires J   ---->   Module J:
392     *                                 exports openO          exports openJ
393     *
394     *
395     * Module L :
396     *     requires public P  --->   Module P:
397     *                                 exports openP
398     *
399     *
400     */
401
402    @Test
403    public void testExpandRequiresNone(Path base) throws Exception {
404        Path src = base.resolve("src");
405
406        createAuxiliaryModules(src);
407
408        new ModuleBuilder(tb, "M")
409                .comment("The M module.")
410                .requires("N", src)
411                .requires("L", src)
412                .requires("O", src)
413                .exports("p")
414                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
415                .write(src);
416
417        execTask("--module-source-path", src.toString(),
418                "--module", "M");
419
420        checkModulesSpecified("M");
421        checkModulesIncluded("M");
422        checkPackagesIncluded("p");
423        checkTypesIncluded("p.Main");
424        checkPackagesNotIncluded(".*open.*");
425    }
426
427    @Test
428    public void testExpandRequiresPublic(Path base) throws Exception {
429        Path src = base.resolve("src");
430
431        createAuxiliaryModules(src);
432
433        new ModuleBuilder(tb, "M")
434                .comment("The M module.")
435                .requiresPublic("N", src)
436                .requires("L", src)
437                .exports("p")
438                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
439                .write(src);
440
441        execTask("--module-source-path", src.toString(),
442                "--module", "M",
443                "--expand-requires", "public");
444
445        checkModulesSpecified("M", "N", "O");
446        checkModulesIncluded("M", "N", "O");
447        checkPackagesIncluded("p", "openN", "openO");
448        checkTypesIncluded("p.Main", "openN.N", "openO.O");
449    }
450
451    @Test
452    public void testExpandRequiresAll(Path base) throws Exception {
453        Path src = base.resolve("src");
454
455        createAuxiliaryModules(src);
456
457        new ModuleBuilder(tb, "M")
458                .comment("The M module.")
459                .requiresPublic("N", src)
460                .requires("L", src)
461                .requires("O", src)
462                .exports("p")
463                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
464                .write(src);
465
466        execTask("--module-source-path", src.toString(),
467                "--module", "M",
468                "--expand-requires", "all");
469
470        checkModulesSpecified("M", "java.base", "N", "L", "O");
471        checkModulesIncluded("M", "java.base", "N", "L", "O");
472        checkModulesNotIncluded("P", "J", "Q");
473        checkPackagesIncluded("p", "openN", "openL", "openO");
474        checkPackagesNotIncluded(".*openP.*", ".*openJ.*");
475        checkTypesIncluded("p.Main", "openN.N", "openL.L", "openO.O");
476        checkTypesNotIncluded(".*openP.*", ".*openJ.*");
477    }
478
479    @Test
480    public void testMissingModule(Path base) throws Exception {
481        Path src = base.resolve("src");
482
483        createAuxiliaryModules(src);
484
485        new ModuleBuilder(tb, "M")
486                .comment("The M module.")
487                .requiresPublic("N", src)
488                .requires("L", src)
489                .requires("O", src)
490                .exports("p")
491                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
492                .write(src);
493
494        execNegativeTask("--module-source-path", src.toString(),
495                "--module", "MIA",
496                "--expand-requires", "all");
497
498        assertErrorPresent("javadoc: error - module MIA not found.");
499    }
500
501    @Test
502    public void testMissingModuleMultiModuleCmdline(Path base) throws Exception {
503        Path src = base.resolve("src");
504
505        createAuxiliaryModules(src);
506
507        new ModuleBuilder(tb, "M")
508                .comment("The M module.")
509                .requiresPublic("N", src)
510                .requires("L", src)
511                .requires("O", src)
512                .exports("p")
513                .classes("package p; public class Main { openO.O o; openN.N n; openL.L l; }")
514                .write(src);
515
516        execNegativeTask("--module-source-path", src.toString(),
517                "--module", "M,N,L,MIA,O,P",
518                "--expand-requires", "all");
519
520        assertErrorPresent("javadoc: error - module MIA not found");
521    }
522
523    void createAuxiliaryModules(Path src) throws IOException {
524
525        new ModuleBuilder(tb, "J")
526                .comment("The J module.")
527                .exports("openJ")
528                .classes("package openJ;  /** Class J open. */ public class J { }")
529                .classes("package closedJ; /** Class J closed. */ public class J  { }")
530                .write(src);
531
532        new ModuleBuilder(tb, "L")
533                .comment("The L module.")
534                .exports("openL")
535                .requiresPublic("P")
536                .classes("package openL; /** Class L open */ public class L { }")
537                .classes("package closedL;  /** Class L closed */ public class L { }")
538                .write(src);
539
540        new ModuleBuilder(tb, "N")
541                .comment("The N module.")
542                .exports("openN")
543                .requiresPublic("O")
544                .classes("package openN; /** Class N open */ public class N  { }")
545                .classes("package closedN; /** Class N closed */ public class N { }")
546                .write(src);
547
548        new ModuleBuilder(tb, "O")
549                .comment("The O module.")
550                .exports("openO")
551                .requires("J")
552                .classes("package openO; /** Class O open. */ public class O { openJ.J j; }")
553                .classes("package closedO;  /** Class O closed. */ public class O { }")
554                .write(src);
555
556        new ModuleBuilder(tb, "P")
557                .comment("The O module.")
558                .exports("openP")
559                .requires("J")
560                .classes("package openP; /** Class O open. */ public class O { openJ.J j; }")
561                .classes("package closedP;  /** Class O closed. */ public class O { }")
562                .write(src);
563
564        new ModuleBuilder(tb, "Q")
565                .comment("The Q module.")
566                .exports("openQ")
567                .requires("J")
568                .classes("package openQ; /** Class Q open. */ public class Q { openJ.J j; }")
569                .classes("package closedQ;  /** Class Q closed. */ public class Q { }")
570                .write(src);
571
572    }
573}
574