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 "19: " + 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 testMethod() throws Exception {
127 final String[] expected = {
128 "24: " + getCheckMessage(MSG_WRITE_TAG, "@todo",
129 "Add a constructor comment"),
130 "36: " + getCheckMessage(MSG_WRITE_TAG, "@todo", "Add a comment"),
131 };
132 verifyWithInlineConfigParserTwice(
133 getPath("InputWriteTagMethod.java"), expected);
134 }
135
136 @Test
137 public void testSeverity() throws Exception {
138 final String[] expected = {
139 "16: " + getCheckMessage(MSG_WRITE_TAG, "@author", "Daniel Grenner"),
140 };
141 verifyWithInlineConfigParserTwice(
142 getPath("InputWriteTagSeverity.java"), expected);
143 }
144
145
146
147
148
149
150
151
152
153
154
155 @Test
156 @SuppressForbidden
157 public void testResetSeverityLevel() throws Exception {
158
159 final Checker checker = new Checker();
160
161 final TreeWalker treeWalker = new TreeWalker();
162 final PackageObjectFactory factory = new PackageObjectFactory(
163 new HashSet<>(), Thread.currentThread().getContextClassLoader());
164
165 treeWalker.setModuleFactory(factory);
166 treeWalker.finishLocalSetup();
167
168 final DefaultConfiguration writeTagConfig = createModuleConfig(WriteTagCheck.class);
169 writeTagConfig.addProperty("tag", "@author");
170 writeTagConfig.addProperty("tagFormat", "Mohanad");
171 writeTagConfig.addProperty("tagSeverity", "warning");
172
173 treeWalker.setupChild(writeTagConfig);
174
175 checker.addFileSetCheck(treeWalker);
176
177 final ByteArrayOutputStream out = TestUtil.getInternalState(this, "stream");
178 final DefaultLogger logger = new DefaultLogger(out,
179 AbstractAutomaticBean.OutputStreamOptions.CLOSE);
180 checker.addListener(logger);
181
182 execute(checker, getPath("InputWriteTagResetSeverity.java"));
183
184 final String output = out.toString();
185
186
187 final Pattern severityPattern = Pattern.compile("\\[(ERROR|WARN|INFO|IGNORE)]");
188
189 final Matcher matcher = severityPattern.matcher(output);
190
191
192 final boolean firstMatchFound = matcher.find();
193 assertWithMessage("Severity level should be wrapped in a square bracket []")
194 .that(firstMatchFound)
195 .isTrue();
196
197 final String tagExpectedSeverityLevel = "warn";
198 final String firstSeverityLevel = matcher.group(1).toLowerCase(Locale.ENGLISH);
199
200 assertWithMessage("First log should have an error severity level")
201 .that(firstSeverityLevel)
202 .isEqualTo(tagExpectedSeverityLevel);
203
204
205
206 final boolean secondMatchFound = matcher.find();
207 assertWithMessage("Severity level should be wrapped in a square bracket []")
208 .that(secondMatchFound)
209 .isTrue();
210
211 final String expectedSeverityLevelAfterReset = "error";
212
213 final String secondSeverityLevel = matcher.group(1).toLowerCase(Locale.ENGLISH);
214
215 assertWithMessage("Second violation's severity level"
216 + " should have been reset back to default (error)")
217 .that(secondSeverityLevel)
218 .isEqualTo(expectedSeverityLevelAfterReset);
219
220 }
221
222 @Test
223 public void testIgnoreMissing() throws Exception {
224 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
225 verifyWithInlineConfigParserTwice(getPath("InputWriteTagIgnore.java"), expected);
226 }
227
228 @Test
229 public void testRegularEx() throws Exception {
230 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
231 verifyWithInlineConfigParserTwice(
232 getPath("InputWriteTagRegularExpression.java"), expected);
233 }
234
235 @Test
236 public void testRegularExError() throws Exception {
237 final String[] expected = {
238 "15: " + getCheckMessage(MSG_TAG_FORMAT, "@author", "ABC"),
239 };
240 verifyWithInlineConfigParserTwice(
241 getPath("InputWriteTagExpressionError.java"), expected);
242 }
243
244 @Test
245 public void testEnumsAndAnnotations() throws Exception {
246 final String[] expected = {
247 "16: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
248 "This enum needs more code..."),
249 "21: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
250 "This enum constant needs more code..."),
251 "28: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
252 "This annotation needs more code..."),
253 "33: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
254 "This annotation field needs more code..."),
255 };
256 verifyWithInlineConfigParserTwice(
257 getPath("InputWriteTagEnumsAndAnnotations.java"), expected);
258 }
259
260 @Test
261 public void testNoJavadocs() throws Exception {
262 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
263
264 verifyWithInlineConfigParserTwice(getPath("InputWriteTagNoJavadoc.java"), expected);
265 }
266
267 @Test
268 public void testWriteTagRecordsAndCompactCtors() throws Exception {
269 final String[] expected = {
270 "19: " + getCheckMessage(MSG_TAG_FORMAT, "@incomplete", "\\S"),
271 "26: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
272 "Failed to recognize 'record' introduced in Java 14."),
273 "37: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
274 "Failed to recognize 'record' introduced in Java 14."),
275 "48: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
276 "Failed to recognize 'record' introduced in Java 14."),
277 "62: " + getCheckMessage(MSG_WRITE_TAG, "@incomplete",
278 "Failed to recognize 'record' introduced in Java 14."),
279 };
280 verifyWithInlineConfigParserTwice(
281 getNonCompilablePath("InputWriteTagRecordsAndCompactCtors.java"), expected);
282 }
283
284 @Override
285 protected void verify(Checker checker,
286 File[] processedFiles,
287 String messageFileName,
288 String... expected)
289 throws Exception {
290 getStream().flush();
291 final List<File> theFiles = new ArrayList<>();
292 Collections.addAll(theFiles, processedFiles);
293 final int errs = checker.process(theFiles);
294
295
296 try (ByteArrayInputStream localStream =
297 new ByteArrayInputStream(getStream().toByteArray());
298 LineNumberReader lnr = new LineNumberReader(
299 new InputStreamReader(localStream, StandardCharsets.UTF_8))) {
300 for (int i = 0; i < expected.length; i++) {
301 final String expectedResult = messageFileName + ":" + expected[i];
302 final String actual = lnr.readLine();
303 assertWithMessage("error message " + i)
304 .that(actual)
305 .isEqualTo(expectedResult);
306 }
307
308 assertWithMessage("unexpected output: " + lnr.readLine())
309 .that(errs)
310 .isAtMost(expected.length);
311 }
312 checker.destroy();
313 }
314
315 }