1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.checks.javadoc;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.javadoc.WriteTagCheck.MSG_MISSING_TAG;
24 import static com.puppycrawl.tools.checkstyle.checks.javadoc.WriteTagCheck.MSG_TAG_FORMAT;
25 import static com.puppycrawl.tools.checkstyle.checks.javadoc.WriteTagCheck.MSG_WRITE_TAG;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.ByteArrayOutputStream;
29 import java.io.File;
30 import java.io.InputStreamReader;
31 import java.io.LineNumberReader;
32 import java.nio.charset.StandardCharsets;
33 import java.util.ArrayList;
34 import java.util.Collections;
35 import java.util.HashSet;
36 import java.util.List;
37 import java.util.Locale;
38 import java.util.regex.Matcher;
39 import java.util.regex.Pattern;
40
41 import org.junit.jupiter.api.Test;
42
43 import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean;
44 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
45 import com.puppycrawl.tools.checkstyle.Checker;
46 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
47 import com.puppycrawl.tools.checkstyle.DefaultLogger;
48 import com.puppycrawl.tools.checkstyle.PackageObjectFactory;
49 import com.puppycrawl.tools.checkstyle.TreeWalker;
50 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
51 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
52 import de.thetaphi.forbiddenapis.SuppressForbidden;
53
54
55
56
57 public class WriteTagCheckTest extends AbstractModuleTestSupport {
58
59 @Override
60 protected String getPackageLocation() {
61 return "com/puppycrawl/tools/checkstyle/checks/javadoc/writetag";
62 }
63
64 @Test
65 public void testDefaultSettings() throws Exception {
66 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
67 verifyWithInlineConfigParser(getPath("InputWriteTagDefault.java"), expected);
68 }
69
70 @Test
71 public void testTag() throws Exception {
72 final String[] expected = {
73 "15: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
74 };
75 verifyWithInlineConfigParserTwice(getPath("InputWriteTag.java"), expected);
76 }
77
78 @Test
79 public void testMissingFormat() throws Exception {
80 final String[] expected = {
81 "15: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
82 };
83 verifyWithInlineConfigParserTwice(
84 getPath("InputWriteTagMissingFormat.java"), expected);
85 }
86
87 @Test
88 public void testTagIncomplete() throws Exception {
89 final String[] expected = {
90 "16: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
91 "This class needs more code..."),
92 };
93 verifyWithInlineConfigParserTwice(
94 getPath("InputWriteTagIncomplete.java"), expected);
95 }
96
97 @Test
98 public void testDoubleTag() throws Exception {
99 final String[] expected = {
100 "18: " + getCheckMessage(MSG_WRITE_TAG, "@doubletag", "first text"),
101 "19: " + getCheckMessage(MSG_WRITE_TAG, "@doubletag", "second text"),
102 };
103 verifyWithInlineConfigParserTwice(
104 getPath("InputWriteTagDoubleTag.java"), expected);
105 }
106
107 @Test
108 public void testEmptyTag() throws Exception {
109 final String[] expected = {
110 "20: " + getCheckMessage(MSG_WRITE_TAG, "@emptytag", ""),
111 };
112 verifyWithInlineConfigParserTwice(
113 getPath("InputWriteTagEmptyTag.java"), expected);
114 }
115
116 @Test
117 public void testMissingTag() throws Exception {
118 final String[] expected = {
119 "20: " + getCheckMessage(MSG_MISSING_TAG, "@missingtag"),
120 };
121 verifyWithInlineConfigParserTwice(
122 getPath("InputWriteTagMissingTag.java"), expected);
123 }
124
125 @Test
126 public void testInterface() throws Exception {
127 final String[] expected = {
128 "15: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
129 };
130 verifyWithInlineConfigParserTwice(
131 getPath("InputWriteTagInterface.java"), expected
132 );
133 }
134
135 @Test
136 public void testBlockComment() throws Exception {
137 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
138 verifyWithInlineConfigParserTwice(
139 getPath("InputWriteTagBlockComment.java"), expected
140 );
141 }
142
143 @Test
144 public void testMethod() throws Exception {
145 final String[] expected = {
146 "24: " + getCheckMessage(MSG_WRITE_TAG, "@todo",
147 "Add a constructor comment"),
148 "36: " + getCheckMessage(MSG_WRITE_TAG, "@todo", "Add a comment"),
149 };
150 verifyWithInlineConfigParserTwice(
151 getPath("InputWriteTagMethod.java"), expected);
152 }
153
154 @Test
155 public void testSeverity() throws Exception {
156 final String[] expected = {
157 "16: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
158 };
159 verifyWithInlineConfigParserTwice(
160 getPath("InputWriteTagSeverity.java"), expected);
161 }
162
163
164
165
166
167
168
169
170
171
172
173 @SuppressForbidden
174 @Test
175 public void testResetSeverityLevel() throws Exception {
176
177 final Checker checker = new Checker();
178
179 final TreeWalker treeWalker = new TreeWalker();
180 final PackageObjectFactory factory = new PackageObjectFactory(
181 new HashSet<>(), Thread.currentThread().getContextClassLoader());
182
183 treeWalker.setModuleFactory(factory);
184 treeWalker.finishLocalSetup();
185
186 final DefaultConfiguration writeTagConfig = createModuleConfig(WriteTagCheck.class);
187 writeTagConfig.addProperty("tag", "@author");
188 writeTagConfig.addProperty("tagFormat", "Mohanad");
189 writeTagConfig.addProperty("tagSeverity", "warning");
190
191 treeWalker.setupChild(writeTagConfig);
192
193 checker.addFileSetCheck(treeWalker);
194
195 final ByteArrayOutputStream out = TestUtil.getInternalState(this, "stream",
196 ByteArrayOutputStream.class);
197 final DefaultLogger logger = new DefaultLogger(out,
198 AbstractAutomaticBean.OutputStreamOptions.CLOSE);
199 checker.addListener(logger);
200
201 execute(checker, getPath("InputWriteTagResetSeverity.java"));
202
203 final String output = out.toString(StandardCharsets.UTF_8);
204
205
206 final Pattern severityPattern = Pattern.compile("\\[(ERROR|WARN|INFO|IGNORE)]");
207
208 final Matcher matcher = severityPattern.matcher(output);
209
210
211 final boolean firstMatchFound = matcher.find();
212 assertWithMessage("Severity level should be wrapped in a square bracket []")
213 .that(firstMatchFound)
214 .isTrue();
215
216 final String tagExpectedSeverityLevel = "warn";
217 final String firstSeverityLevel = matcher.group(1).toLowerCase(Locale.ENGLISH);
218
219 assertWithMessage("First log should have an error severity level")
220 .that(firstSeverityLevel)
221 .isEqualTo(tagExpectedSeverityLevel);
222
223
224
225 final boolean secondMatchFound = matcher.find();
226 assertWithMessage("Severity level should be wrapped in a square bracket []")
227 .that(secondMatchFound)
228 .isTrue();
229
230 final String expectedSeverityLevelAfterReset = "error";
231
232 final String secondSeverityLevel = matcher.group(1).toLowerCase(Locale.ENGLISH);
233
234 assertWithMessage("Second violation's severity level"
235 + " should have been reset back to default (error)")
236 .that(secondSeverityLevel)
237 .isEqualTo(expectedSeverityLevelAfterReset);
238
239 }
240
241 @Test
242 public void testIgnoreMissing() throws Exception {
243 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
244 verifyWithInlineConfigParserTwice(getPath("InputWriteTagIgnore.java"), expected);
245 }
246
247 @Test
248 public void testRegularEx() throws Exception {
249 final String[] expected = {
250 "16: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
251 };
252
253 verifyWithInlineConfigParserTwice(
254 getPath("InputWriteTagRegularExpression.java"), expected);
255 }
256
257 @Test
258 public void testRegularExError() throws Exception {
259 final String[] expected = {
260 "15: " + getCheckMessage(MSG_TAG_FORMAT, "@author", "ABC"),
261 };
262 verifyWithInlineConfigParserTwice(
263 getPath("InputWriteTagExpressionError.java"), expected);
264 }
265
266 @Test
267 public void testEnumsAndAnnotations() throws Exception {
268 final String[] expected = {
269 "16: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
270 "This enum needs more code..."),
271 "21: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
272 "This enum constant needs more code..."),
273 "28: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
274 "This annotation needs more code..."),
275 "33: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
276 "This annotation field needs more code..."),
277 };
278 verifyWithInlineConfigParserTwice(
279 getPath("InputWriteTagEnumsAndAnnotations.java"), expected);
280 }
281
282 @Test
283 public void testNoJavadocs() throws Exception {
284 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
285
286 verifyWithInlineConfigParserTwice(getPath("InputWriteTagNoJavadoc.java"), expected);
287 }
288
289 @Test
290 public void testWriteTagRecordsAndCompactCtors() throws Exception {
291 final String[] expected = {
292 "19: " + getCheckMessage(MSG_TAG_FORMAT, "@incomplete", "\\S"),
293 "26: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
294 "Failed to recognize 'record' introduced in Java 14."),
295 "37: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
296 "Failed to recognize 'record' introduced in Java 14."),
297 "48: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
298 "Failed to recognize 'record' introduced in Java 14."),
299 "62: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
300 "Failed to recognize 'record' introduced in Java 14."),
301 };
302 verifyWithInlineConfigParserTwice(
303 getPath("InputWriteTagRecordsAndCompactCtors.java"), expected);
304 }
305
306 @Override
307 protected void verify(Checker checker,
308 File[] processedFiles,
309 String messageFileName,
310 String... expected)
311 throws Exception {
312 getStream().flush();
313 final List<File> theFiles = new ArrayList<>();
314 Collections.addAll(theFiles, processedFiles);
315 final int errs = checker.process(theFiles);
316
317
318 try (ByteArrayInputStream localStream =
319 new ByteArrayInputStream(getStream().toByteArray());
320 LineNumberReader lnr = new LineNumberReader(
321 new InputStreamReader(localStream, StandardCharsets.UTF_8))) {
322 for (int i = 0; i < expected.length; i++) {
323 final String expectedResult = messageFileName + ":" + expected[i];
324 final String actual = lnr.readLine();
325 assertWithMessage("error message " + i)
326 .that(actual)
327 .isEqualTo(expectedResult);
328 }
329
330 assertWithMessage("unexpected output: " + lnr.readLine())
331 .that(errs)
332 .isAtMost(expected.length);
333 }
334 checker.destroy();
335 }
336
337 }