1 /*
2  * Copyright (c) 2013, 2018, 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 8025633 8025524 8081854 8187521 8182765
27  * @summary Test for valid name attribute in HTML anchors.
28  * @author Bhavesh Patel
29  * @library /tools/lib ../lib
30  * @modules jdk.javadoc/jdk.javadoc.internal.tool
31  * @build toolbox.ToolBox JavadocTester
32  * @run main TestAnchorNames
33  */
34 
35 import java.io.IOException;
36 import java.nio.file.Path;
37 import java.nio.file.Paths;
38 
39 import toolbox.*;
40 
41 public class TestAnchorNames extends JavadocTester {
42 
43     public final ToolBox tb;
main(String... args)44     public static void main(String... args) throws Exception {
45         TestAnchorNames tester = new TestAnchorNames();
46         tester.runTests(m -> new Object[] { Paths.get(m.getName()) });
47     }
48 
TestAnchorNames()49     public TestAnchorNames() {
50         tb = new ToolBox();
51     }
52 
53     @Test
testHtml4(Path ignore)54     void testHtml4(Path ignore) {
55         setAutomaticCheckLinks(false); // @ignore JDK-8202622
56         javadoc("-d", "out-html4",
57                 "-html4",
58                 "-sourcepath", testSrc,
59                 "-source", "8", //so that '_' can be used as an identifier
60                 "-use",
61                 "pkg1");
62         setAutomaticCheckLinks(true); // @ignore JDK-8202622
63         checkExit(Exit.OK);
64 
65         // Test some section markers and links to these markers
66         checkOutput("pkg1/RegClass.html", true,
67                 "<a name=\"skip.navbar.top\">",
68                 "<a href=\"#skip.navbar.top\" title=\"Skip navigation links\">",
69                 "<a name=\"nested.class.summary\">",
70                 "<a href=\"#nested.class.summary\">",
71                 "<a name=\"method.summary\">",
72                 "<a href=\"#method.summary\">",
73                 "<a name=\"field.detail\">",
74                 "<a href=\"#field.detail\">",
75                 "<a name=\"constructor.detail\">",
76                 "<a href=\"#constructor.detail\">");
77 
78         // Test some members and link to these members
79         checkOutput("pkg1/RegClass.html", true,
80                 //The marker for this appears in the serialized-form.html which we will
81                 //test below
82                 "<a href=\"../serialized-form.html#pkg1.RegClass\">");
83 
84         // Test some fields
85         checkOutput("pkg1/RegClass.html", true,
86                 "<a name=\"Z:Z_\">",
87                 "<a href=\"#Z:Z_\">",
88                 "<a name=\"Z:Z_:D\">",
89                 "<a href=\"#Z:Z_:D\">",
90                 "<a name=\"Z:Z:D_\">",
91                 "<a href=\"#Z:Z:D_\">",
92                 "<a name=\"Z:Z:Dfield\">",
93                 "<a href=\"#Z:Z:Dfield\">",
94                 "<a name=\"fieldInCla:D:D\">",
95                 "<a href=\"#fieldInCla:D:D\">",
96                 "<a name=\"S_:D:D:D:D:DINT\">",
97                 "<a href=\"#S_:D:D:D:D:DINT\">",
98                 "<a name=\"method:D:D\">",
99                 "<a href=\"#method:D:D\">");
100 
101         checkOutput("pkg1/DeprMemClass.html", true,
102                 "<a name=\"Z:Z_field_In_Class\">",
103                 "<a href=\"#Z:Z_field_In_Class\">");
104 
105         // Test constructor
106         checkOutput("pkg1/RegClass.html", true,
107                 "<a name=\"RegClass-java.lang.String-int-\">",
108                 "<a href=\"#RegClass-java.lang.String-int-\">");
109 
110         // Test some methods
111         checkOutput("pkg1/RegClass.html", true,
112                 "<a name=\"Z:Z_methodInClass-java.lang.String-\">",
113                 "<a href=\"#Z:Z_methodInClass-java.lang.String-\">",
114                 "<a name=\"method--\">",
115                 "<a href=\"#method--\">",
116                 "<a name=\"foo-java.util.Map-\">",
117                 "<a href=\"#foo-java.util.Map-\">",
118                 "<a name=\"methodInCla:Ds-java.lang.String:A-\">",
119                 "<a href=\"#methodInCla:Ds-java.lang.String:A-\">",
120                 "<a name=\"Z:Z_methodInClas:D-java.lang.String-int-\">",
121                 "<a href=\"#Z:Z_methodInClas:D-java.lang.String-int-\">",
122                 "<a name=\"methodD-pkg1.RegClass.:DA-\">",
123                 "<a href=\"#methodD-pkg1.RegClass.:DA-\">",
124                 "<a name=\"methodD-pkg1.RegClass.D:A-\">",
125                 "<a href=\"#methodD-pkg1.RegClass.D:A-\">");
126 
127         checkOutput("pkg1/DeprMemClass.html", true,
128                 "<a name=\"Z:Z:Dmethod_In_Class--\">",
129                 "<a href=\"#Z:Z:Dmethod_In_Class--\">");
130 
131         // Test enum
132         checkOutput("pkg1/RegClass.Te$t_Enum.html", true,
133                 "<a name=\"Z:Z:DFLD2\">",
134                 "<a href=\"#Z:Z:DFLD2\">");
135 
136         // Test nested class
137         checkOutput("pkg1/RegClass._NestedClas$.html", true,
138                 "<a name=\"Z:Z_NestedClas:D--\">",
139                 "<a href=\"#Z:Z_NestedClas:D--\">");
140 
141         // Test class use page
142         checkOutput("pkg1/class-use/DeprMemClass.html", true,
143                 "<a href=\"../RegClass.html#d____mc\">");
144 
145         // Test deprecated list page
146         checkOutput("deprecated-list.html", true,
147                 "<a href=\"pkg1/DeprMemClass.html#Z:Z_field_In_Class\">",
148                 "<a href=\"pkg1/DeprMemClass.html#Z:Z:Dmethod_In_Class--\">");
149 
150         // Test constant values page
151         checkOutput("constant-values.html", true,
152                 "<a href=\"pkg1/RegClass.html#S_:D:D:D:D:DINT\">");
153 
154         // Test serialized form page
155         checkOutput("serialized-form.html", true,
156                 //This is the marker for the link that appears in the pkg1.RegClass.html page
157                 "<a name=\"pkg1.RegClass\">");
158 
159         // Test member name index page
160         checkOutput("index-all.html", true,
161                 "<a name=\"I:Z:Z:D\">",
162                 "<a href=\"#I:Z:Z:D\">$",
163                 "<a href=\"#I:Z:Z_\">_");
164 
165         // The marker name conversion should only affect HTML anchors. It should not
166         // affect the labels.
167         checkOutput("pkg1/RegClass.html", false,
168                 " Z:Z_",
169                 " Z:Z:Dfield",
170                 " Z:Z_field_In_Class",
171                 " S_:D:D:D:D:DINT");
172     }
173 
174     @Test
testHtml5(Path ignore)175     void testHtml5(Path ignore) {
176         javadoc("-d", "out-html5",
177                 "-sourcepath", testSrc,
178                 "-source", "8", //so that '_' can be used as an identifier
179                 "-use",
180                 "pkg1");
181         checkExit(Exit.OK);
182 
183         // Test some section markers and links to these markers
184         checkOutput("pkg1/RegClass.html", true,
185                 "<a id=\"skip.navbar.top\">",
186                 "<a href=\"#skip.navbar.top\" title=\"Skip navigation links\">",
187                 "<a id=\"nested.class.summary\">",
188                 "<a href=\"#nested.class.summary\">",
189                 "<a id=\"method.summary\">",
190                 "<a href=\"#method.summary\">",
191                 "<a id=\"field.detail\">",
192                 "<a href=\"#field.detail\">",
193                 "<a id=\"constructor.detail\">",
194                 "<a href=\"#constructor.detail\">");
195 
196         // Test some members and link to these members
197         checkOutput("pkg1/RegClass.html", true,
198                 //The marker for this appears in the serialized-form.html which we will
199                 //test below
200                 "<a href=\"../serialized-form.html#pkg1.RegClass\">");
201 
202         // Test some fields
203         checkOutput("pkg1/RegClass.html", true,
204                 "<a id=\"_\">",
205                 "<a href=\"#_\">",
206                 "<a id=\"_$\">",
207                 "<a href=\"#_$\">",
208                 "<a id=\"$_\">",
209                 "<a href=\"#$_\">",
210                 "<a id=\"$field\">",
211                 "<a href=\"#$field\">",
212                 "<a id=\"fieldInCla$$\">",
213                 "<a href=\"#fieldInCla$$\">",
214                 "<a id=\"S_$$$$$INT\">",
215                 "<a href=\"#S_$$$$$INT\">",
216                 "<a id=\"method$$\">",
217                 "<a href=\"#method$$\">");
218 
219         checkOutput("pkg1/DeprMemClass.html", true,
220                 "<a id=\"_field_In_Class\">",
221                 "<a href=\"#_field_In_Class\">");
222 
223         // Test constructor
224         checkOutput("pkg1/RegClass.html", true,
225                 "<a id=\"&lt;init&gt;(java.lang.String,int)\">",
226                 "<a href=\"#%3Cinit%3E(java.lang.String,int)\">");
227 
228         // Test some methods
229         checkOutput("pkg1/RegClass.html", true,
230                 "<a id=\"_methodInClass(java.lang.String)\">",
231                 "<a href=\"#_methodInClass(java.lang.String)\">",
232                 "<a id=\"method()\">",
233                 "<a href=\"#method()\">",
234                 "<a id=\"foo(java.util.Map)\">",
235                 "<a href=\"#foo(java.util.Map)\">",
236                 "<a id=\"methodInCla$s(java.lang.String[])\">",
237                 "<a href=\"#methodInCla$s(java.lang.String%5B%5D)\">",
238                 "<a id=\"_methodInClas$(java.lang.String,int)\">",
239                 "<a href=\"#_methodInClas$(java.lang.String,int)\">",
240                 "<a id=\"methodD(pkg1.RegClass.$A)\">",
241                 "<a href=\"#methodD(pkg1.RegClass.$A)\">",
242                 "<a id=\"methodD(pkg1.RegClass.D[])\">",
243                 "<a href=\"#methodD(pkg1.RegClass.D%5B%5D)\">");
244 
245         checkOutput("pkg1/DeprMemClass.html", true,
246                 "<a id=\"$method_In_Class()\">",
247                 "<a href=\"#$method_In_Class()\">");
248 
249         // Test enum
250         checkOutput("pkg1/RegClass.Te$t_Enum.html", true,
251                 "<a id=\"$FLD2\">",
252                 "<a href=\"#$FLD2\">");
253 
254         // Test nested class
255         checkOutput("pkg1/RegClass._NestedClas$.html", true,
256                 "<a id=\"&lt;init&gt;()\">",
257                 "<a href=\"#%3Cinit%3E()\">");
258 
259         // Test class use page
260         checkOutput("pkg1/class-use/DeprMemClass.html", true,
261                 "<a href=\"../RegClass.html#d____mc\">");
262 
263         // Test deprecated list page
264         checkOutput("deprecated-list.html", true,
265                 "<a href=\"pkg1/DeprMemClass.html#_field_In_Class\">",
266                 "<a href=\"pkg1/DeprMemClass.html#$method_In_Class()\">");
267 
268         // Test constant values page
269         checkOutput("constant-values.html", true,
270                 "<a href=\"pkg1/RegClass.html#S_$$$$$INT\">");
271 
272         // Test serialized form page
273         checkOutput("serialized-form.html", true,
274                 //This is the marker for the link that appears in the pkg1.RegClass.html page
275                 "<a id=\"pkg1.RegClass\">");
276 
277         // Test member name index page
278         checkOutput("index-all.html", true,
279                 "<a id=\"I:$\">",
280                 "<a href=\"#I:$\">$",
281                 "<a href=\"#I:_\">_");
282     }
283 
284     /**
285      * The following test is somewhat simplistic, but it is useful
286      * in conjunction with the W3C Validation Service at https://validator.w3.org/nu/#file
287      * @param base A working directory for this method, in which some UTF-8 source files
288      *      will be generated
289      * @throws IOException if there is a problem generating the source files
290      */
291     @Test
testNonAscii(Path base)292     void testNonAscii(Path base) throws IOException {
293         Path src = base.resolve("src");
294         tb.writeJavaFiles(src,
295                 "package p; public class Def {\n"
296                 + "    public int \u00e0\u00e9;\n"              // a`e'
297                 + "    public void \u00c0\u00c9() { }\n"        // A`E'
298                 + "    public int \u03b1\u03b2\u03b3;\n"        // alpha beta gamma
299                 + "    public void \u0391\u0392\u0393() { }\n"  // ALPHA BETA GAMMA
300                 + "}",
301                 "package p; \n"
302                 + "/**\n"
303                 + " * {@link Def#\u00e0\u00e9 &agrave;&eacute;}<br>\n"
304                 + " * {@link Def#\u00c0\u00c9() &Agrave;&Eacute;}<br>\n"
305                 + " * {@link Def#\u03b1\u03b2\u03b3 &alpha;&beta;&gamma;}<br>\n"
306                 + " * {@link Def#\u0391\u0392\u0393() &Alpha;&Beta;&Gamma;}<br>\n"
307                 + " */\n"
308                 + "public class Ref { }");
309 
310         javadoc("-d", "out-nonAscii",
311                 "-sourcepath", src.toString(),
312                 "-html5",
313                 "-encoding", "utf-8",
314                 "p");
315         checkExit(Exit.OK);
316 
317         checkOutput("p/Def.html", true,
318                 "<a id=\"\u00e0\u00e9\">",
319                 "<a id=\"\u00c0\u00c9()\">",
320                 "<a id=\"\u03b1\u03b2\u03b3\">",
321                 "<a id=\"\u0391\u0392\u0393()\">");
322 
323         checkOutput("p/Ref.html", true,
324                 "<a href=\"Def.html#%C3%A0%C3%A9\"><code>&agrave;&eacute;</code></a>",
325                 "<a href=\"Def.html#%C3%80%C3%89()\"><code>&Agrave;&Eacute;</code></a>",
326                 "<a href=\"Def.html#%CE%B1%CE%B2%CE%B3\"><code>&alpha;&beta;&gamma;</code></a>",
327                 "<a href=\"Def.html#%CE%91%CE%92%CE%93()\"><code>&Alpha;&Beta;&Gamma;</code></a>");
328 
329     }
330 }
331