1/*
2 * Copyright (c) 2017, 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 8178339
27 * @summary Tests indirect exports and opens in the module summary page
28 * @modules jdk.javadoc/jdk.javadoc.internal.api
29 *          jdk.javadoc/jdk.javadoc.internal.tool
30 *          jdk.compiler/com.sun.tools.javac.api
31 *          jdk.compiler/com.sun.tools.javac.main
32 * @library ../lib /tools/lib
33 * @build toolbox.ToolBox toolbox.ModuleBuilder JavadocTester
34 * @run main TestIndirectExportsOpens
35 */
36
37import java.nio.file.Path;
38import java.nio.file.Paths;
39
40import toolbox.*;
41
42public class TestIndirectExportsOpens extends JavadocTester {
43
44    public final ToolBox tb;
45    public static void main(String... args) throws Exception {
46        TestIndirectExportsOpens tester = new TestIndirectExportsOpens();
47        tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
48    }
49
50    public TestIndirectExportsOpens() {
51        tb = new ToolBox();
52    }
53
54    @Test
55    public void checkNoIndirects(Path base) throws Exception {
56
57        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
58                .classes("package pm; public class A {}");
59        Path p0 = mb0.write(base);
60
61        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
62                .requiresTransitive("m", p0)
63                .classes("package pa; public class NoOp {}")
64                .exports("pa");
65        mb1.write(base);
66
67        javadoc("-d", base.resolve("out-api").toString(),
68                "-quiet",
69                "--module-source-path", base.toString(),
70                "--expand-requires", "transitive",
71                "--module", "a");
72        checkExit(Exit.OK);
73        verifyIndirectExports(false);
74        verifyIndirectOpens(false);
75    }
76
77    @Test
78    public void checkExportsOpens(Path base) throws Exception {
79
80        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
81                .classes("package pm; public class A {}")
82                .exports("pm")
83                .opens("pm");
84
85        Path p0 = mb0.write(base);
86
87        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
88                .requiresTransitive("m", p0)
89                .classes("package pa ; public class NoOp {}")
90                .exports("pa");
91        mb1.write(base);
92
93        javadoc("-d", base.resolve("out-api").toString(),
94                "-quiet",
95                "--module-source-path", base.toString(),
96                "--expand-requires", "transitive",
97                "--module", "a");
98        checkExit(Exit.OK);
99        verifyIndirectExports(true);
100        verifyIndirectOpens(true);
101    }
102
103    @Test
104    public void checkExportsToOpensTo(Path base) throws Exception {
105
106        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
107                .classes("package pm; public class A {}")
108                .exportsTo("pm", "x")
109                .opensTo("pm", "x");
110
111        Path p0 = mb0.write(base);
112
113        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
114                .requiresTransitive("m", p0)
115                .classes("package pa ; public class NoOp {}")
116                .exports("pa");
117        mb1.write(base);
118
119        javadoc("-d", base.resolve("out-api").toString(),
120                "-quiet",
121                "--module-source-path", base.toString(),
122                "--expand-requires", "transitive",
123                "--module", "a");
124
125        checkExit(Exit.OK);
126        verifyIndirectExports(false);
127        verifyIndirectOpens(false);
128    }
129
130    @Test
131    public void checkExportsToOpensToDetailMode(Path base) throws Exception {
132
133        ModuleBuilder mb0 = new ModuleBuilder(tb, "m")
134                .classes("package exportsto; public class A {}")
135                .classes("package opensto; public class A {}")
136                .exportsTo("exportsto", "x")
137                .opensTo("opensto", "x");
138
139        Path p0 = mb0.write(base);
140
141        ModuleBuilder mb1 = new ModuleBuilder(tb, "a")
142                .requiresTransitive("m", p0)
143                .classes("package pa ; public class NoOp {}")
144                .exports("pa");
145        mb1.write(base);
146
147        javadoc("-d", base.resolve("out-detail").toString(),
148                "-quiet",
149                "--module-source-path", base.toString(),
150                "--expand-requires", "transitive",
151                "--show-module-contents", "all",
152                "--module", "a");
153
154        checkExit(Exit.OK);
155
156        // In details mode all kinds of packages from java.base,
157        // could be listed in the indirects section, so just
158        // check for minimal expected strings.
159        checkOutput("a-summary.html", true,
160                "Indirect Exports table",
161                "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
162                + "<td class=\"colLast\"><a href=\"exportsto/package-summary.html\">exportsto</a></td>\n"
163                + "</tr>\n");
164
165        checkOutput("a-summary.html", true,
166                "Indirect Opens table",
167                "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
168                + "<td class=\"colLast\">opensto</td>\n"
169                + "</tr>\n");
170    }
171
172    void verifyIndirectExports(boolean present) {
173        verifyIndirects(present, false);
174    }
175
176    void verifyIndirectOpens(boolean present) {
177        verifyIndirects(present, true);
178    }
179
180    void verifyIndirects(boolean present, boolean opens) {
181
182        String typeString = opens ? "Indirect Opens" : "Indirect Exports";
183
184        // Avoid false positives, just check for primary string absence.
185        if (!present) {
186            checkOutput("a-summary.html", false, typeString);
187            return;
188        }
189
190        checkOutput("a-summary.html", present,
191                "<table class=\"packagesSummary\" summary=\"" + typeString + " table, listing modules, and packages\">\n"
192                + "<caption><span>" + typeString + "</span><span class=\"tabEnd\">&nbsp;</span></caption>\n"
193                + "<tr>\n"
194                + "<th class=\"colFirst\" scope=\"col\">From</th>\n"
195                + "<th class=\"colLast\" scope=\"col\">Packages</th>\n"
196                + "</tr>\n"
197                + "<tbody>\n"
198                + "<tr class=\"altColor\">\n"
199                + "<th class=\"colFirst\" scope=\"row\"><a href=\"m-summary.html\">m</a></th>\n"
200                + "<td class=\"colLast\"><a href=\"pm/package-summary.html\">pm</a></td>\n"
201                + "</tr>\n"
202                + "</tbody>\n"
203                + "</table>\n");
204    }
205
206}
207
208