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;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.File;
27  import java.io.FileNotFoundException;
28  import java.io.IOException;
29  import java.nio.charset.StandardCharsets;
30  import java.util.Locale;
31  
32  import org.apache.commons.io.FileUtils;
33  import org.junit.Rule;
34  import org.junit.Test;
35  import org.junit.contrib.java.lang.system.SystemErrRule;
36  import org.junit.contrib.java.lang.system.SystemOutRule;
37  
38  import antlr.MismatchedTokenException;
39  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
40  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
41  
42  public class JavadocPropertiesGeneratorTest extends AbstractPathTestSupport {
43  
44      private static final String EOL = System.lineSeparator();
45      private static final String USAGE = String.format(Locale.ROOT,
46            "Usage: java com.puppycrawl.tools.checkstyle.JavadocPropertiesGenerator [-hV]%n"
47            + "                                                                       "
48            + "--destfile=<outputFile>%n"
49            + "                                                                       "
50            + "<inputFile>%n"
51            + "      <inputFile>   The input file.%n"
52            + "      --destfile=<outputFile>%n"
53            + "                    The output file.%n"
54            + "  -h, --help        Show this help message and exit.%n"
55            + "  -V, --version     Print version information and exit.%n");
56      private static final File DESTFILE = new File("target/tokentypes.properties");
57  
58      @Rule
59      public final SystemErrRule systemErr = new SystemErrRule().enableLog().mute();
60      @Rule
61      public final SystemOutRule systemOut = new SystemOutRule().enableLog().mute();
62  
63      @Override
64      protected String getPackageLocation() {
65          return "com/puppycrawl/tools/checkstyle/javadocpropertiesgenerator";
66      }
67  
68      /**
69       * Returns canonical path for the file with the given file name.
70       * The path is formed base on the non-compilable resources location.
71       * This implementation uses 'src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/'
72       * as a non-compilable resource location.
73       * @param filename file name.
74       * @return canonical path for the file with the given file name.
75       * @throws IOException if I/O exception occurs while forming the path.
76       */
77      protected final String getNonCompilablePath(String filename) throws IOException {
78          return new File("src/test/resources-noncompilable/" + getPackageLocation() + "/"
79                  + filename).getCanonicalPath();
80      }
81  
82      @Test
83      public void testIsProperUtilsClass() throws ReflectiveOperationException {
84          assertTrue("Constructor is not private", TestUtil.isUtilsClassHasPrivateConstructor(
85              JavadocPropertiesGenerator.class, false));
86      }
87  
88      @Test
89      public void testNonExistentArgument() throws Exception {
90          JavadocPropertiesGenerator.main("--nonexistent-argument");
91  
92          final String expected = String.format(Locale.ROOT, "Missing required options "
93                  + "[--destfile=<outputFile>, params[0]=<inputFile>]%n")
94                  + USAGE;
95          assertEquals("Unexpected error log", expected, systemErr.getLog());
96          assertEquals("Unexpected output log", "", systemOut.getLog());
97      }
98  
99      @Test
100     public void testNoDestfileSpecified() throws Exception {
101         JavadocPropertiesGenerator.main(getPath("InputMain.java"));
102 
103         final String expected = String.format(Locale.ROOT,
104                 "Missing required option '--destfile=<outputFile>'%n") + USAGE;
105         assertEquals("Unexpected error log", expected, systemErr.getLog());
106         assertEquals("Unexpected output log", "", systemOut.getLog());
107     }
108 
109     @Test
110     public void testNoInputSpecified() throws Exception {
111         JavadocPropertiesGenerator.main("--destfile", DESTFILE.getAbsolutePath());
112 
113         final String expected = String.format(Locale.ROOT,
114                 "Missing required parameter: <inputFile>%n") + USAGE;
115         assertEquals("Unexpected error log", expected, systemErr.getLog());
116         assertEquals("Unexpected output log", "", systemOut.getLog());
117     }
118 
119     @Test
120     public void testNotClass() throws Exception {
121         JavadocPropertiesGenerator.main("--destfile", DESTFILE.getAbsolutePath(),
122             getPath("InputJavadocPropertiesGeneratorNotClass.java"));
123         assertEquals("Unexpected error log", "", systemErr.getLog());
124         assertEquals("Unexpected output log", "", systemOut.getLog());
125     }
126 
127     @Test
128     public void testNotExistentInputSpecified() {
129         try {
130             JavadocPropertiesGenerator.main(
131                 "--destfile", DESTFILE.getAbsolutePath(), "NotExistent.java");
132             fail("Exception was expected");
133         }
134         catch (CheckstyleException ex) {
135             assertEquals("Invalid error message",
136                 "Failed to write javadoc properties of 'NotExistent.java' to '"
137                     + DESTFILE.getAbsolutePath() + "'",
138                 ex.getMessage());
139 
140             final Throwable cause = ex.getCause();
141             assertTrue("Invalid error message", cause instanceof FileNotFoundException);
142             assertTrue("Invalid error message", cause.getMessage().contains("NotExistent.java"));
143         }
144         assertEquals("Unexpected error log", "", systemErr.getLog());
145         assertEquals("Unexpected output log", "", systemOut.getLog());
146     }
147 
148     @Test
149     public void testInvalidDestinationSpecified() throws Exception {
150 
151         try {
152             // Passing a folder name will cause the FileNotFoundException.
153             JavadocPropertiesGenerator.main("--destfile", "..",
154                 getPath("InputJavadocPropertiesGeneratorCorrect.java"));
155             fail("Exception was expected");
156         }
157         catch (CheckstyleException ex) {
158             final String expectedError = "Failed to write javadoc properties of '"
159                 + getPath("InputJavadocPropertiesGeneratorCorrect.java") + "' to '..'";
160             assertEquals("Invalid error message", expectedError, ex.getMessage());
161 
162             final Throwable cause = ex.getCause();
163             assertTrue("Invalid error message", cause instanceof FileNotFoundException);
164             assertTrue("Invalid error message", cause.getMessage().contains(".."));
165         }
166         assertEquals("Unexpected error log", "", systemErr.getLog());
167         assertEquals("Unexpected output log", "", systemOut.getLog());
168     }
169 
170     @Test
171     public void testCorrect() throws Exception {
172         final String expectedContent = "EOF1=The end of file token." + EOL
173             + "EOF2=The end of file token." + EOL
174             + "TYPE_EXTENSION_AND='&amp;' symbol when used in a generic upper or lower bounds"
175             + " constrain e.g&#46;"
176             + " <code>Comparable<T extends Serializable & CharSequence></code>!" + EOL
177             + "LCURLY=A left curly brace (<code>{</code>)." + EOL
178             + "DEPRECATED_LITERAL='@deprecated' literal in @deprecated Javadoc tag?" + EOL;
179 
180         JavadocPropertiesGenerator.main(getPath("InputJavadocPropertiesGeneratorCorrect.java"),
181             "--destfile", DESTFILE.getAbsolutePath());
182         assertEquals("Unexpected error log", "", systemErr.getLog());
183         assertEquals("Unexpected output log", "", systemOut.getLog());
184         final String fileContent = FileUtils.readFileToString(DESTFILE, StandardCharsets.UTF_8);
185         assertEquals("File content is not expected", expectedContent, fileContent);
186     }
187 
188     @Test
189     public void testEmptyJavadoc() throws Exception {
190         JavadocPropertiesGenerator.main(getPath("InputJavadocPropertiesGeneratorEmptyJavadoc.java"),
191             "--destfile", DESTFILE.getAbsolutePath());
192         assertEquals("Unexpected error log", "", systemErr.getLog());
193         assertEquals("Unexpected output log", "", systemOut.getLog());
194         assertEquals("File '" + DESTFILE + "' must be empty", 0, FileUtils.sizeOf(DESTFILE));
195     }
196 
197     @Test
198     public void testNotConstants() throws Exception {
199         JavadocPropertiesGenerator.main(getPath("InputJavadocPropertiesGeneratorNotConstants.java"),
200             "--destfile", DESTFILE.getAbsolutePath());
201         assertEquals("Unexpected error log", "", systemErr.getLog());
202         assertEquals("Unexpected output log", "", systemOut.getLog());
203         assertEquals("File '" + DESTFILE + "' must be empty", 0, FileUtils.sizeOf(DESTFILE));
204     }
205 
206     @Test
207     public void testHelp() throws Exception {
208         JavadocPropertiesGenerator.main("-h");
209         assertEquals("Unexpected error log", "", systemErr.getLog());
210         assertEquals("Unexpected output log", USAGE, systemOut.getLog());
211     }
212 
213     @Test
214     public void testJavadocParseError() throws Exception {
215         try {
216             JavadocPropertiesGenerator.main(
217                 getPath("InputJavadocPropertiesGeneratorJavadocParseError.java"),
218                 "--destfile", DESTFILE.getAbsolutePath());
219             fail("Exception was expected");
220         }
221         catch (IllegalArgumentException ex) {
222             assertTrue("Invalid error message", ex.getMessage().contains(
223                 "mismatched input '<EOF>' expecting JAVADOC_INLINE_TAG_END"));
224         }
225         assertEquals("File '" + DESTFILE + "' must be empty", 0, FileUtils.sizeOf(DESTFILE));
226     }
227 
228     @Test
229     public void testNotImplementedTag() throws Exception {
230         try {
231             JavadocPropertiesGenerator.main(
232                 getPath("InputJavadocPropertiesGeneratorNotImplementedTag.java"),
233                 "--destfile", DESTFILE.getAbsolutePath());
234             fail("Exception was expected");
235         }
236         catch (CheckstyleException ex) {
237             assertEquals("Invalid error message", "Unsupported inline tag LINK_LITERAL",
238                 ex.getMessage());
239         }
240         assertEquals("File '" + DESTFILE + "' must be empty", 0, FileUtils.sizeOf(DESTFILE));
241     }
242 
243     @Test
244     public void testParseError() throws Exception {
245         try {
246             JavadocPropertiesGenerator.main(
247                 getNonCompilablePath("InputJavadocPropertiesGeneratorParseError.java"),
248                 "--destfile", DESTFILE.getAbsolutePath());
249             fail("Exception was expected");
250         }
251         catch (CheckstyleException ex) {
252             assertTrue("Invalid error message",
253                 ex.getMessage().contains("InputJavadocPropertiesGeneratorParseError.java"));
254 
255             final Throwable cause = ex.getCause().getCause();
256             assertTrue("Invalid error message", cause instanceof MismatchedTokenException);
257             assertTrue("Invalid error message",
258                 cause.getMessage().contains("expecting RCURLY, found '!'"));
259         }
260     }
261 
262 }