1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.utils;
21  
22  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.util.List;
29  
30  import org.junit.Test;
31  
32  import com.puppycrawl.tools.checkstyle.api.Comment;
33  import com.puppycrawl.tools.checkstyle.api.DetailAST;
34  import com.puppycrawl.tools.checkstyle.api.DetailNode;
35  import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
36  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
37  import com.puppycrawl.tools.checkstyle.checks.javadoc.InvalidJavadocTag;
38  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocNodeImpl;
39  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag;
40  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTagInfo;
41  import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTags;
42  
43  public class JavadocUtilTest {
44  
45      @Test
46      public void testTags() {
47          final String[] text = {
48              "/** @see elsewhere ",
49              " * {@link List }, {@link List link text }",
50              "   {@link List#add(Object) link text}",
51              " * {@link Class link text}",
52          };
53          final Comment comment = new Comment(text, 1, 4, text[3].length());
54          final JavadocTags allTags =
55              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
56          assertEquals("Invalid valid tags size", 5, allTags.getValidTags().size());
57      }
58  
59      @Test
60      public void testBlockTag() {
61          final String[] text = {
62              "/** @see elsewhere ",
63              " */",
64          };
65          final Comment comment = new Comment(text, 1, 4, text[1].length());
66          final JavadocTags allTags =
67              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
68          assertEquals("Invalid valid tags size", 1, allTags.getValidTags().size());
69      }
70  
71      @Test
72      public void testTagType() {
73          final String[] text = {
74              "/** @see block",
75              " * {@link List inline}, {@link List#add(Object)}",
76          };
77          final Comment comment = new Comment(text, 1, 2, text[1].length());
78          final JavadocTags blockTags =
79              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.BLOCK);
80          final JavadocTags inlineTags =
81              JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.INLINE);
82          assertEquals("Invalid valid tags size", 1, blockTags.getValidTags().size());
83          assertEquals("Invalid valid tags size", 2, inlineTags.getValidTags().size());
84      }
85  
86      @Test
87      public void testInlineTagLinkText() {
88          final String[] text = {
89              "/** {@link List link text }",
90          };
91          final Comment comment = new Comment(text, 1, 1, text[0].length());
92          final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
93              comment, JavadocUtil.JavadocTagType.ALL).getValidTags();
94          assertEquals("Invalid first arg", "List link text", tags.get(0).getFirstArg());
95      }
96  
97      @Test
98      public void testInlineTagMethodRef() {
99          final String[] text = {
100             "/** {@link List#add(Object)}",
101         };
102         final Comment comment = new Comment(text, 1, 1, text[0].length());
103         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
104             comment, JavadocUtil.JavadocTagType.ALL).getValidTags();
105         assertEquals("Invalid first arg", "List#add(Object)", tags.get(0).getFirstArg());
106     }
107 
108     @Test
109     public void testTagPositions() {
110         final String[] text = {
111             "/** @see elsewhere",
112             "    also {@link Name value} */",
113         };
114         final Comment comment = new Comment(text, 1, 2, text[1].length());
115 
116         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
117             comment, JavadocUtil.JavadocTagType.ALL).getValidTags();
118 
119         assertEquals("Invalid tags size", 2, tags.size());
120 
121         final JavadocTag seeTag = tags.get(0);
122         assertEquals("Invalid tag name", JavadocTagInfo.SEE.getName(), seeTag.getTagName());
123         assertEquals("Invalid line number", 1, seeTag.getLineNo());
124         assertEquals("Invalid column number", 4, seeTag.getColumnNo());
125 
126         final JavadocTag linkTag = tags.get(1);
127         assertEquals("Invalid tag name", JavadocTagInfo.LINK.getName(), linkTag.getTagName());
128         assertEquals("Invalid line number", 2, linkTag.getLineNo());
129         assertEquals("Invalid column number", 10, linkTag.getColumnNo());
130     }
131 
132     @Test
133     public void testInlineTagPositions() {
134         final String[] text = {"/** Also {@link Name value} */"};
135         final Comment comment = new Comment(text, 1, 0, text[0].length());
136 
137         final List<JavadocTag> tags = JavadocUtil.getJavadocTags(
138             comment, JavadocUtil.JavadocTagType.INLINE).getValidTags();
139 
140         assertEquals("Invalid tags size", 1, tags.size());
141 
142         assertEquals("Unexpected line number", 0, tags.get(0).getLineNo());
143         assertEquals("Unexpected column number", 10, tags.get(0).getColumnNo());
144     }
145 
146     @Test
147     public void testInvalidTags() {
148         final String[] text = {
149             "/** @fake block",
150             " * {@bogus inline}",
151             " * {@link List valid}",
152         };
153         final Comment comment = new Comment(text, 1, 3, text[2].length());
154         final JavadocTags allTags =
155             JavadocUtil.getJavadocTags(comment, JavadocUtil.JavadocTagType.ALL);
156         assertEquals("Unexpected invalid tags size", 2, allTags.getInvalidTags().size());
157         assertTag("Unexpected invalid tag", new InvalidJavadocTag(1, 4, "fake"),
158                 allTags.getInvalidTags().get(0));
159         assertTag("Unexpected invalid tag", new InvalidJavadocTag(2, 4, "bogus"),
160                 allTags.getInvalidTags().get(1));
161         assertEquals("Unexpected valid tags size", 1, allTags.getValidTags().size());
162         assertTag("Unexpected valid tag", new JavadocTag(3, 4, "link", "List valid"),
163                 allTags.getValidTags().get(0));
164     }
165 
166     @Test
167     public void testEmptyBlockComment() {
168         final String emptyComment = "";
169         assertFalse("Should return false when empty string is passed",
170                 JavadocUtil.isJavadocComment(emptyComment));
171     }
172 
173     @Test
174     public void testEmptyBlockCommentAst() {
175         final DetailAST commentBegin = new DetailAST();
176         commentBegin.setType(TokenTypes.BLOCK_COMMENT_BEGIN);
177         commentBegin.setText("/*");
178 
179         final DetailAST commentContent = new DetailAST();
180         commentContent.setType(TokenTypes.COMMENT_CONTENT);
181         commentContent.setText("");
182 
183         final DetailAST commentEnd = new DetailAST();
184         commentEnd.setType(TokenTypes.BLOCK_COMMENT_END);
185         commentEnd.setText("*/");
186 
187         commentBegin.setFirstChild(commentContent);
188         commentContent.setNextSibling(commentEnd);
189 
190         assertFalse("Should return false when empty block comment is passed",
191                 JavadocUtil.isJavadocComment(commentBegin));
192     }
193 
194     @Test
195     public void testEmptyJavadocComment() {
196         final String emptyJavadocComment = "*";
197         assertTrue("Should return true when empty javadoc comment is passed",
198                 JavadocUtil.isJavadocComment(emptyJavadocComment));
199     }
200 
201     @Test
202     public void testEmptyJavadocCommentAst() {
203         final DetailAST commentBegin = new DetailAST();
204         commentBegin.setType(TokenTypes.BLOCK_COMMENT_BEGIN);
205         commentBegin.setText("/*");
206 
207         final DetailAST javadocCommentContent = new DetailAST();
208         javadocCommentContent.setType(TokenTypes.COMMENT_CONTENT);
209         javadocCommentContent.setText("*");
210 
211         final DetailAST commentEnd = new DetailAST();
212         commentEnd.setType(TokenTypes.BLOCK_COMMENT_END);
213         commentEnd.setText("*/");
214 
215         commentBegin.setFirstChild(javadocCommentContent);
216         javadocCommentContent.setNextSibling(commentEnd);
217 
218         final DetailAST commentBeginParent = new DetailAST();
219         commentBeginParent.setType(TokenTypes.MODIFIERS);
220         commentBeginParent.setFirstChild(commentBegin);
221 
222         final DetailAST aJavadocPosition = new DetailAST();
223         aJavadocPosition.setType(TokenTypes.METHOD_DEF);
224         aJavadocPosition.setFirstChild(commentBeginParent);
225         assertTrue("Should return true when empty javadoc comment ast is passed",
226                 JavadocUtil.isJavadocComment(commentBegin));
227     }
228 
229     @Test
230     public void testIsProperUtilsClass() throws ReflectiveOperationException {
231         assertTrue("Constructor is not private",
232                 isUtilsClassHasPrivateConstructor(JavadocUtil.class, true));
233     }
234 
235     @Test
236     public void testBranchContains() {
237         final JavadocNodeImpl node = new JavadocNodeImpl();
238         final JavadocNodeImpl firstChild = new JavadocNodeImpl();
239         final JavadocNodeImpl secondChild = new JavadocNodeImpl();
240 
241         node.setType(JavadocTokenTypes.JAVADOC);
242         firstChild.setType(JavadocTokenTypes.BODY_TAG_START);
243         secondChild.setType(JavadocTokenTypes.CODE_LITERAL);
244 
245         node.setChildren(firstChild, secondChild);
246         assertFalse("Should return true when branch contains node passed",
247                 JavadocUtil.containsInBranch(node, JavadocTokenTypes.AUTHOR_LITERAL));
248 
249         firstChild.setParent(node);
250         secondChild.setParent(node);
251         assertFalse("Should return false when branch does not contain node passed",
252                 JavadocUtil.containsInBranch(node, JavadocTokenTypes.AUTHOR_LITERAL));
253 
254         secondChild.setType(JavadocTokenTypes.AUTHOR_LITERAL);
255         assertTrue("Should return true when branch contains node passed",
256                 JavadocUtil.containsInBranch(node, JavadocTokenTypes.AUTHOR_LITERAL));
257     }
258 
259     @Test
260     public void testGetTokenNameForId() {
261         assertEquals("Invalid token name",
262                 "EOF", JavadocUtil.getTokenName(JavadocTokenTypes.EOF));
263     }
264 
265     @Test
266     public void testGetTokenNameForLargeId() {
267         try {
268             JavadocUtil.getTokenName(30073);
269             fail("exception expected");
270         }
271         catch (IllegalArgumentException ex) {
272             assertEquals("Invalid exception message",
273                     "Unknown javadoc token id. Given id: 30073", ex.getMessage());
274         }
275     }
276 
277     @Test
278     public void testGetTokenNameForInvalidId() {
279         try {
280             JavadocUtil.getTokenName(110);
281             fail("exception expected");
282         }
283         catch (IllegalArgumentException ex) {
284             assertEquals("Invalid exception message",
285                     "Unknown javadoc token id. Given id: 110", ex.getMessage());
286         }
287     }
288 
289     @Test
290     public void testGetTokenNameForLowerBoundInvalidId() {
291         try {
292             JavadocUtil.getTokenName(10095);
293             fail("exception expected");
294         }
295         catch (IllegalArgumentException ex) {
296             assertEquals("Invalid exception message",
297                     "Unknown javadoc token id. Given id: 10095", ex.getMessage());
298         }
299     }
300 
301     @Test
302     public void testGetTokenIdThatIsUnknown() {
303         try {
304             JavadocUtil.getTokenId("");
305             fail("exception expected");
306         }
307         catch (IllegalArgumentException ex) {
308             assertEquals("Invalid exception message",
309                     "Unknown javadoc token name. Given name ", ex.getMessage());
310         }
311     }
312 
313     @Test
314     public void testGetTokenId() {
315         final int tokenId = JavadocUtil.getTokenId("JAVADOC");
316 
317         assertEquals("Invalid token id", JavadocTokenTypes.JAVADOC, tokenId);
318     }
319 
320     @Test
321     public void testGetJavadocCommentContent() {
322         final DetailAST detailAST = new DetailAST();
323         final DetailAST javadoc = new DetailAST();
324 
325         javadoc.setText("1javadoc");
326         detailAST.setFirstChild(javadoc);
327         final String commentContent = JavadocUtil.getJavadocCommentContent(detailAST);
328 
329         assertEquals("Invalid comment content", "javadoc", commentContent);
330     }
331 
332     @Test
333     public void testGetFirstToken() {
334         final JavadocNodeImpl javadocNode = new JavadocNodeImpl();
335         final JavadocNodeImpl basetag = new JavadocNodeImpl();
336         basetag.setType(JavadocTokenTypes.BASE_TAG);
337         final JavadocNodeImpl body = new JavadocNodeImpl();
338         body.setType(JavadocTokenTypes.BODY);
339 
340         body.setParent(javadocNode);
341         basetag.setParent(javadocNode);
342         javadocNode.setChildren(basetag, body);
343 
344         final DetailNode result = JavadocUtil.findFirstToken(javadocNode, JavadocTokenTypes.BODY);
345 
346         assertEquals("Invalid first token", body, result);
347     }
348 
349     @Test
350     public void testGetPreviousSibling() {
351         final JavadocNodeImpl root = new JavadocNodeImpl();
352 
353         final JavadocNodeImpl node = new JavadocNodeImpl();
354         node.setIndex(1);
355         node.setParent(root);
356 
357         final JavadocNodeImpl previousNode = new JavadocNodeImpl();
358         previousNode.setIndex(0);
359         node.setParent(root);
360 
361         root.setChildren(previousNode, node);
362 
363         assertEquals("Unexpected node", previousNode, JavadocUtil.getPreviousSibling(node));
364     }
365 
366     @Test
367     public void testGetLastTokenName() {
368         assertEquals("Unexpected token name",
369                 "RP", JavadocUtil.getTokenName(10094));
370     }
371 
372     @Test
373     public void testEscapeAllControlChars() {
374         assertEquals("invalid result", "abc", JavadocUtil.escapeAllControlChars("abc"));
375         assertEquals("invalid result", "1\\r2\\n3\\t",
376                 JavadocUtil.escapeAllControlChars("1\\r2\\n3\\t"));
377     }
378 
379     private static void assertTag(String message, InvalidJavadocTag expected,
380             InvalidJavadocTag actual) {
381         assertEquals(message + " line", expected.getLine(), actual.getLine());
382         assertEquals(message + " column", expected.getCol(), actual.getCol());
383         assertEquals(message + " name", expected.getName(), actual.getName());
384     }
385 
386     private static void assertTag(String message, JavadocTag expected,
387             JavadocTag actual) {
388         assertEquals(message + " line", expected.getLineNo(), actual.getLineNo());
389         assertEquals(message + " column", expected.getColumnNo(), actual.getColumnNo());
390         assertEquals(message + " first arg", expected.getFirstArg(), actual.getFirstArg());
391         assertEquals(message + " tag name", expected.getTagName(), actual.getTagName());
392     }
393 
394 }