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;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.Checker.EXCEPTION_MSG;
24 import static com.puppycrawl.tools.checkstyle.DefaultLogger.AUDIT_FINISHED_MESSAGE;
25 import static com.puppycrawl.tools.checkstyle.DefaultLogger.AUDIT_STARTED_MESSAGE;
26 import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_NO_NEWLINE_EOF;
27 import static com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck.MSG_KEY;
28 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
29
30 import java.io.BufferedReader;
31 import java.io.BufferedWriter;
32 import java.io.ByteArrayInputStream;
33 import java.io.ByteArrayOutputStream;
34 import java.io.File;
35 import java.io.IOError;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.io.InputStreamReader;
39 import java.io.LineNumberReader;
40 import java.io.OutputStream;
41 import java.io.Serial;
42 import java.io.UnsupportedEncodingException;
43 import java.nio.charset.StandardCharsets;
44 import java.nio.file.Files;
45 import java.util.ArrayList;
46 import java.util.Arrays;
47 import java.util.Collections;
48 import java.util.HashSet;
49 import java.util.List;
50 import java.util.Locale;
51 import java.util.Objects;
52 import java.util.Properties;
53 import java.util.Set;
54 import java.util.SortedSet;
55 import java.util.TreeSet;
56 import java.util.UUID;
57
58 import org.apache.tools.ant.BuildException;
59 import org.apache.tools.ant.Project;
60 import org.junit.jupiter.api.Test;
61 import org.junit.jupiter.api.io.TempDir;
62
63 import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean.OutputStreamOptions;
64 import com.puppycrawl.tools.checkstyle.ant.CheckstyleAntTask;
65 import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
66 import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
67 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
68 import com.puppycrawl.tools.checkstyle.api.AuditListener;
69 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
70 import com.puppycrawl.tools.checkstyle.api.Configuration;
71 import com.puppycrawl.tools.checkstyle.api.Context;
72 import com.puppycrawl.tools.checkstyle.api.DetailAST;
73 import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
74 import com.puppycrawl.tools.checkstyle.api.FileText;
75 import com.puppycrawl.tools.checkstyle.api.Filter;
76 import com.puppycrawl.tools.checkstyle.api.FilterSet;
77 import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
78 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
79 import com.puppycrawl.tools.checkstyle.api.Violation;
80 import com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck;
81 import com.puppycrawl.tools.checkstyle.checks.TranslationCheck;
82 import com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck;
83 import com.puppycrawl.tools.checkstyle.checks.sizes.LineLengthCheck;
84 import com.puppycrawl.tools.checkstyle.filefilters.BeforeExecutionExclusionFileFilter;
85 import com.puppycrawl.tools.checkstyle.filters.SuppressionFilter;
86 import com.puppycrawl.tools.checkstyle.internal.testmodules.CheckWhichThrowsError;
87 import com.puppycrawl.tools.checkstyle.internal.testmodules.DebugAuditAdapter;
88 import com.puppycrawl.tools.checkstyle.internal.testmodules.DebugFilter;
89 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestBeforeExecutionFileFilter;
90 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestFileSetCheck;
91 import com.puppycrawl.tools.checkstyle.internal.utils.CloseAndFlushTestByteArrayOutputStream;
92 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
93 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
94 import de.thetaphi.forbiddenapis.SuppressForbidden;
95
96
97
98
99
100
101
102
103 public class CheckerTest extends AbstractModuleTestSupport {
104
105 @TempDir
106 public File temporaryFolder;
107
108 private File createTempFile(String prefix) throws IOException {
109 return createTempFile(prefix, ".tmp");
110 }
111
112 private File createTempFile(String prefix, String suffix) throws IOException {
113 final String name = Objects.requireNonNull(prefix)
114 + UUID.randomUUID()
115 + Objects.requireNonNull(suffix);
116 return Files.createFile(temporaryFolder.toPath().resolve(name)).toFile();
117 }
118
119 @Override
120 public String getPackageLocation() {
121 return "com/puppycrawl/tools/checkstyle/checker";
122 }
123
124 private String getLocalizedMessage(String messageKey, Object... args) {
125 final LocalizedMessage localizedMessage = new LocalizedMessage(
126 Definitions.CHECKSTYLE_BUNDLE, getClass(),
127 messageKey, args);
128
129 return localizedMessage.getMessage();
130 }
131
132 @Test
133 public void testDestroy() throws Exception {
134 final Checker checker = new Checker();
135 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
136 checker.addListener(auditAdapter);
137 final TestFileSetCheck fileSet = new TestFileSetCheck();
138 checker.addFileSetCheck(fileSet);
139 final DebugFilter filter = new DebugFilter();
140 checker.addFilter(filter);
141 final TestBeforeExecutionFileFilter fileFilter = new TestBeforeExecutionFileFilter();
142 checker.addBeforeExecutionFileFilter(fileFilter);
143
144
145 checker.destroy();
146
147 final File tempFile = createTempFile("junit");
148 checker.process(Collections.singletonList(tempFile));
149 final SortedSet<Violation> violations = new TreeSet<>();
150 violations.add(new Violation(1, 0, "a Bundle", "message.key",
151 new Object[] {"arg"}, null, getClass(), null));
152 checker.fireErrors("Some File Name", violations);
153
154 assertWithMessage("Checker.destroy() doesn't remove listeners.")
155 .that(auditAdapter.wasCalled())
156 .isFalse();
157 assertWithMessage("Checker.destroy() doesn't remove file sets.")
158 .that(fileSet.wasCalled())
159 .isFalse();
160 assertWithMessage("Checker.destroy() doesn't remove filters.")
161 .that(filter.wasCalled())
162 .isFalse();
163 assertWithMessage("Checker.destroy() doesn't remove file filters.")
164 .that(fileFilter.wasCalled())
165 .isFalse();
166 }
167
168 @Test
169 public void testAddListener() throws Exception {
170 final Checker checker = new Checker();
171 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
172 checker.addListener(auditAdapter);
173
174 checker.process(List.of());
175 assertWithMessage("Audit start event should identify the checker")
176 .that(auditAdapter.getAuditStartedEvent().getSource())
177 .isSameInstanceAs(checker);
178 assertWithMessage("Audit finish event should identify the checker")
179 .that(auditAdapter.getAuditFinishedEvent().getSource())
180 .isSameInstanceAs(checker);
181
182 auditAdapter.resetListener();
183 checker.fireFileStarted("Some File Name");
184 assertWithMessage("Checker.fireFileStarted() doesn't call listener")
185 .that(auditAdapter.wasCalled())
186 .isTrue();
187 assertWithMessage("Checker.fireFileStarted() doesn't pass event")
188 .that(auditAdapter.wasEventPassed())
189 .isTrue();
190
191 auditAdapter.resetListener();
192 checker.fireFileFinished("Some File Name");
193 assertWithMessage("Checker.fireFileFinished() doesn't call listener")
194 .that(auditAdapter.wasCalled())
195 .isTrue();
196 assertWithMessage("Checker.fireFileFinished() doesn't pass event")
197 .that(auditAdapter.wasEventPassed())
198 .isTrue();
199
200 auditAdapter.resetListener();
201 final SortedSet<Violation> violations = new TreeSet<>();
202 violations.add(new Violation(1, 0, "a Bundle", "message.key",
203 new Object[] {"arg"}, null, getClass(), null));
204 checker.fireErrors("Some File Name", violations);
205 assertWithMessage("Checker.fireErrors() doesn't call listener")
206 .that(auditAdapter.wasCalled())
207 .isTrue();
208 assertWithMessage("Checker.fireErrors() doesn't pass event")
209 .that(auditAdapter.wasEventPassed())
210 .isTrue();
211 }
212
213 @Test
214 public void testRemoveListener() throws Exception {
215 final Checker checker = new Checker();
216 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
217 final DebugAuditAdapter aa2 = new DebugAuditAdapter();
218 checker.addListener(auditAdapter);
219 checker.addListener(aa2);
220 checker.removeListener(auditAdapter);
221
222 checker.process(List.of());
223 assertWithMessage("Remaining listener should receive the audit start event")
224 .that(aa2.getAuditStartedEvent().getSource())
225 .isSameInstanceAs(checker);
226 assertWithMessage("Removed listener should not receive the audit start event")
227 .that(auditAdapter.getAuditStartedEvent())
228 .isNull();
229 assertWithMessage("Remaining listener should receive the audit finish event")
230 .that(aa2.getAuditFinishedEvent().getSource())
231 .isSameInstanceAs(checker);
232 assertWithMessage("Removed listener should not receive the audit finish event")
233 .that(auditAdapter.getAuditFinishedEvent())
234 .isNull();
235
236 aa2.resetListener();
237 checker.fireFileStarted("Some File Name");
238 assertWithMessage("Checker.fireFileStarted() doesn't call listener")
239 .that(aa2.wasCalled())
240 .isTrue();
241 assertWithMessage("Checker.fireFileStarted() does call removed listener")
242 .that(auditAdapter.wasCalled())
243 .isFalse();
244
245 aa2.resetListener();
246 checker.fireFileFinished("Some File Name");
247 assertWithMessage("Checker.fireFileFinished() doesn't call listener")
248 .that(aa2.wasCalled())
249 .isTrue();
250 assertWithMessage("Checker.fireFileFinished() does call removed listener")
251 .that(auditAdapter.wasCalled())
252 .isFalse();
253
254 aa2.resetListener();
255 final SortedSet<Violation> violations = new TreeSet<>();
256 violations.add(new Violation(1, 0, "a Bundle", "message.key",
257 new Object[] {"arg"}, null, getClass(), null));
258 checker.fireErrors("Some File Name", violations);
259 assertWithMessage("Checker.fireErrors() doesn't call listener")
260 .that(aa2.wasCalled())
261 .isTrue();
262 assertWithMessage("Checker.fireErrors() does call removed listener")
263 .that(auditAdapter.wasCalled())
264 .isFalse();
265 }
266
267 @Test
268 public void testAddBeforeExecutionFileFilter() throws Exception {
269 final Checker checker = new Checker();
270 final TestBeforeExecutionFileFilter filter = new TestBeforeExecutionFileFilter();
271
272 checker.addBeforeExecutionFileFilter(filter);
273
274 filter.resetFilter();
275 checker.process(Collections.singletonList(new File("dummy.java")));
276 assertWithMessage("Checker.acceptFileStarted() doesn't call filter")
277 .that(filter.wasCalled())
278 .isTrue();
279 }
280
281 @Test
282 public void testRemoveBeforeExecutionFileFilter() throws Exception {
283 final Checker checker = new Checker();
284 final TestBeforeExecutionFileFilter filter = new TestBeforeExecutionFileFilter();
285 final TestBeforeExecutionFileFilter f2 = new TestBeforeExecutionFileFilter();
286 checker.addBeforeExecutionFileFilter(filter);
287 checker.addBeforeExecutionFileFilter(f2);
288 checker.removeBeforeExecutionFileFilter(filter);
289
290 f2.resetFilter();
291 checker.process(Collections.singletonList(new File("dummy.java")));
292 assertWithMessage("Checker.acceptFileStarted() doesn't call filter")
293 .that(f2.wasCalled())
294 .isTrue();
295 assertWithMessage("Checker.acceptFileStarted() does call removed filter")
296 .that(filter.wasCalled())
297 .isFalse();
298 }
299
300 @Test
301 public void testAddFilter() {
302 final Checker checker = new Checker();
303 final DebugFilter filter = new DebugFilter();
304
305 checker.addFilter(filter);
306
307 filter.resetFilter();
308 final SortedSet<Violation> violations = new TreeSet<>();
309 violations.add(new Violation(1, 0, "a Bundle", "message.key",
310 new Object[] {"arg"}, null, getClass(), null));
311 checker.fireErrors("Some File Name", violations);
312 assertWithMessage("Checker.fireErrors() doesn't call filter")
313 .that(filter.wasCalled())
314 .isTrue();
315 }
316
317 @Test
318 public void testRemoveFilter() {
319 final Checker checker = new Checker();
320 final DebugFilter filter = new DebugFilter();
321 final DebugFilter f2 = new DebugFilter();
322 checker.addFilter(filter);
323 checker.addFilter(f2);
324 checker.removeFilter(filter);
325
326 f2.resetFilter();
327 final SortedSet<Violation> violations = new TreeSet<>();
328 violations.add(new Violation(1, 0, "a Bundle", "message.key",
329 new Object[] {"arg"}, null, getClass(), null));
330 checker.fireErrors("Some File Name", violations);
331 assertWithMessage("Checker.fireErrors() doesn't call filter")
332 .that(f2.wasCalled())
333 .isTrue();
334 assertWithMessage("Checker.fireErrors() does call removed filter")
335 .that(filter.wasCalled())
336 .isFalse();
337 }
338
339 @Test
340 public void testFileExtensions() throws Exception {
341 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
342 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
343 checkerConfig.addProperty("cacheFile", createTempFile("junit").getPath());
344
345 final Checker checker = new Checker();
346 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
347 checker.configure(checkerConfig);
348
349 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
350 checker.addListener(auditAdapter);
351
352 final List<File> files = new ArrayList<>();
353 final File file = new File("file.pdf");
354 files.add(file);
355 final File otherFile = new File("file.java");
356 files.add(otherFile);
357 final String[] fileExtensions = {"java", "xml", "properties"};
358 checker.setFileExtensions(fileExtensions);
359 checker.setCacheFile(createTempFile("junit").getPath());
360 final int counter = checker.process(files);
361
362
363 final int numLegalFiles = 1;
364 final PropertyCacheFile cache = TestUtil.getInternalState(checker,
365 "cacheFile", PropertyCacheFile.class);
366 assertWithMessage("There were more legal files than expected")
367 .that(counter)
368 .isEqualTo(numLegalFiles);
369 assertWithMessage("Audit was started on larger amount of files than expected")
370 .that(auditAdapter.getNumFilesStarted())
371 .isEqualTo(numLegalFiles);
372 assertWithMessage("Audit was finished on larger amount of files than expected")
373 .that(auditAdapter.getNumFilesFinished())
374 .isEqualTo(numLegalFiles);
375 assertWithMessage("Cache shout not contain any file")
376 .that(cache.get(new File("file.java").getCanonicalPath()))
377 .isNull();
378 }
379
380 @Test
381 public void testIgnoredFileExtensions() throws Exception {
382 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
383 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
384 final File tempFile = createTempFile("junit");
385 checkerConfig.addProperty("cacheFile", tempFile.getPath());
386
387 final Checker checker = new Checker();
388 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
389 checker.configure(checkerConfig);
390
391 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
392 checker.addListener(auditAdapter);
393
394 final List<File> allIgnoredFiles = new ArrayList<>();
395 final File ignoredFile = new File("file.pdf");
396 allIgnoredFiles.add(ignoredFile);
397 final String[] fileExtensions = {"java", "xml", "properties"};
398 checker.setFileExtensions(fileExtensions);
399 checker.setCacheFile(createTempFile("junit").getPath());
400 final int counter = checker.process(allIgnoredFiles);
401
402
403 final int numLegalFiles = 0;
404 assertWithMessage("There were more legal files than expected")
405 .that(counter)
406 .isEqualTo(numLegalFiles);
407 assertWithMessage("Audit was started on larger amount of files than expected")
408 .that(auditAdapter.getNumFilesStarted())
409 .isEqualTo(numLegalFiles);
410 assertWithMessage("Audit was finished on larger amount of files than expected")
411 .that(auditAdapter.getNumFilesFinished())
412 .isEqualTo(numLegalFiles);
413 }
414
415 @Test
416 public void testSetters() {
417
418 final Checker checker = new Checker();
419 checker.setBasedir("some");
420 checker.setSeverity("ignore");
421
422 final PackageObjectFactory factory = new PackageObjectFactory(
423 new HashSet<>(), Thread.currentThread().getContextClassLoader());
424 checker.setModuleFactory(factory);
425
426 checker.setFileExtensions((String[]) null);
427 checker.setFileExtensions(".java", "xml");
428
429 final UnsupportedEncodingException exc =
430 getExpectedThrowable(UnsupportedEncodingException.class, () -> {
431 checker.setCharset("UNKNOWN-CHARSET");
432 }, "Exception is expected");
433 assertWithMessage("Error message is not expected")
434 .that(exc.getMessage())
435 .isEqualTo("unsupported charset: 'UNKNOWN-CHARSET'");
436 }
437
438 @Test
439 public void testSetSeverity() throws Exception {
440 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
441
442 verifyWithInlineXmlConfig(getPath("InputCheckerTestSeverity.java"), expected);
443 }
444
445 @Test
446 public void testNoClassLoaderNoModuleFactory() {
447 final Checker checker = new Checker();
448
449 final CheckstyleException exc =
450 getExpectedThrowable(CheckstyleException.class,
451 checker::finishLocalSetup, "Exception is expected");
452 assertWithMessage("Error message is not expected")
453 .that(exc.getMessage())
454 .isEqualTo("if no custom moduleFactory is set,"
455 + " moduleClassLoader must be specified");
456 }
457
458 @Test
459 public void testNoModuleFactory() throws Exception {
460 final Checker checker = new Checker();
461 final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
462
463 checker.setModuleClassLoader(classLoader);
464 checker.finishLocalSetup();
465 final Context actualCtx = TestUtil.getInternalState(checker, "childContext", Context.class);
466
467 assertWithMessage("Default module factory should be created when it is not specified")
468 .that(actualCtx.get("moduleFactory"))
469 .isNotNull();
470 }
471
472 @Test
473 public void testFinishLocalSetupFullyInitialized() throws Exception {
474 final Checker checker = new Checker();
475 final ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
476 checker.setModuleClassLoader(contextClassLoader);
477 final PackageObjectFactory factory = new PackageObjectFactory(
478 new HashSet<>(), contextClassLoader);
479 checker.setModuleFactory(factory);
480 checker.setBasedir("testBaseDir");
481 checker.setLocaleLanguage("it");
482 checker.setLocaleCountry("IT");
483 checker.finishLocalSetup();
484
485 final Context context = TestUtil.getInternalState(checker, "childContext", Context.class);
486 final String encoding = StandardCharsets.UTF_8.name();
487 assertWithMessage("Charset was different than expected")
488 .that(context.get("charset"))
489 .isEqualTo(encoding);
490 assertWithMessage("Severity is set to unexpected value")
491 .that(context.get("severity"))
492 .isEqualTo("error");
493 assertWithMessage("Basedir is set to unexpected value")
494 .that(context.get("basedir"))
495 .isEqualTo("testBaseDir");
496
497 final Locale locale = TestUtil.getInternalStaticState(LocalizedMessage.class,
498 "messageLocale", Locale.class);
499 assertWithMessage("Locale is set to unexpected value")
500 .that(locale)
501 .isEqualTo(Locale.ITALY);
502 }
503
504 @Test
505 public void testSetupChildExceptions() {
506 final Checker checker = new Checker();
507 final PackageObjectFactory factory = new PackageObjectFactory(
508 new HashSet<>(), Thread.currentThread().getContextClassLoader());
509 checker.setModuleFactory(factory);
510
511 final Configuration config = new DefaultConfiguration("java.lang.String");
512 final CheckstyleException exc =
513 getExpectedThrowable(CheckstyleException.class, () -> {
514 checker.setupChild(config);
515 }, "Exception is expected");
516 assertWithMessage("Error message is not expected")
517 .that(exc.getMessage())
518 .isEqualTo("java.lang.String is not allowed as a child in Checker");
519 }
520
521 @Test
522 public void testSetupChildInvalidProperty() {
523 final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
524 checkConfig.addProperty("$$No such property", null);
525 final CheckstyleException exc =
526 getExpectedThrowable(CheckstyleException.class, () -> {
527 createChecker(checkConfig);
528 }, "Exception is expected");
529 assertWithMessage("Error message is not expected")
530 .that(exc.getMessage())
531 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker"
532 + " - cannot initialize module " + checkConfig.getName());
533 }
534
535 @Test
536 public void testSetupChildListener() throws Exception {
537 final Checker checker = new Checker();
538 final PackageObjectFactory factory = new PackageObjectFactory(
539 new HashSet<>(), Thread.currentThread().getContextClassLoader());
540 checker.setModuleFactory(factory);
541
542 final Configuration config = new DefaultConfiguration(
543 DebugAuditAdapter.class.getCanonicalName());
544 checker.setupChild(config);
545
546 final List<AuditListener> listeners = TestUtil.getInternalStateListAuditListener(checker,
547 "listeners");
548 assertWithMessage("Invalid child listener class")
549 .that(listeners.getLast() instanceof DebugAuditAdapter)
550 .isTrue();
551 }
552
553 @Test
554 public void testDestroyCheckerWithWrongCacheFileNameLength() throws Exception {
555 final Checker checker = new Checker();
556 final PackageObjectFactory factory = new PackageObjectFactory(
557 new HashSet<>(), Thread.currentThread().getContextClassLoader());
558 checker.setModuleFactory(factory);
559 checker.configure(new DefaultConfiguration("default config"));
560
561
562
563 checker.setCacheFile(String.format(Locale.ENGLISH, "%0300d", 0));
564 final IllegalStateException exc =
565 getExpectedThrowable(IllegalStateException.class,
566 checker::destroy, "Exception did not happen");
567 assertWithMessage("Cause of exception differs from IOException")
568 .that(exc.getCause())
569 .isInstanceOf(IOException.class);
570 assertWithMessage("Exception message differ")
571 .that(exc.getMessage())
572 .isEqualTo(getLocalizedMessage(
573 "Checker.cacheFilesException"));
574 }
575
576
577
578
579 @Test
580 public void testCacheAndCheckWhichDoesNotImplementExternalResourceHolderInterface()
581 throws Exception {
582 assertWithMessage("ExternalResourceHolder has changed his parent")
583 .that(ExternalResourceHolder.class.isAssignableFrom(HiddenFieldCheck.class))
584 .isFalse();
585 final DefaultConfiguration checkConfig = createModuleConfig(HiddenFieldCheck.class);
586
587 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
588 treeWalkerConfig.addChild(checkConfig);
589
590 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
591 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
592
593 final File cacheFile = createTempFile("junit");
594 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
595
596 final File tmpFile = createTempFile("file", ".java");
597
598 execute(checkerConfig, tmpFile.getPath());
599 final Properties cacheAfterFirstRun = new Properties();
600 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
601 cacheAfterFirstRun.load(reader);
602 }
603
604
605 execute(checkerConfig, tmpFile.getPath());
606 final Properties cacheAfterSecondRun = new Properties();
607 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
608 cacheAfterSecondRun.load(reader);
609 }
610
611 assertWithMessage("Cache from first run differs from second run cache")
612 .that(cacheAfterSecondRun)
613 .isEqualTo(cacheAfterFirstRun);
614 }
615
616 @Test
617 public void testWithCacheWithNoViolation() throws Exception {
618 final Checker checker = new Checker();
619 final PackageObjectFactory factory = new PackageObjectFactory(
620 new HashSet<>(), Thread.currentThread().getContextClassLoader());
621 checker.setModuleFactory(factory);
622 checker.configure(createModuleConfig(TranslationCheck.class));
623
624 final File cacheFile = createTempFile("junit");
625 checker.setCacheFile(cacheFile.getPath());
626
627 checker.setupChild(createModuleConfig(TranslationCheck.class));
628 final File tmpFile = createTempFile("file", ".java");
629 final List<File> files = new ArrayList<>(1);
630 files.add(tmpFile);
631 checker.process(files);
632
633
634 checker.destroy();
635
636 final Properties cache = new Properties();
637 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
638 cache.load(reader);
639 }
640
641
642 final int expectedNumberOfObjectsInCache = 2;
643 assertWithMessage("Cache has unexpected size")
644 .that(cache)
645 .hasSize(expectedNumberOfObjectsInCache);
646
647 final String expectedConfigHash = "D581D4A2BD482D4E1EF1F82459356BA2D8A3B" + "FC3";
648 assertWithMessage("Cache has unexpected hash")
649 .that(cache.getProperty(PropertyCacheFile.CONFIG_HASH_KEY))
650 .isEqualTo(expectedConfigHash);
651
652 assertWithMessage("Cache file has null path")
653 .that(cache.getProperty(tmpFile.getPath()))
654 .isNotNull();
655 }
656
657 @Test
658 public void testClearExistingCache() throws Exception {
659 final DefaultConfiguration checkerConfig = createRootConfig(null);
660 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
661 final File cacheFile = createTempFile("junit");
662 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
663
664 final Checker checker = new Checker();
665 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
666 checker.configure(checkerConfig);
667 checker.addListener(getBriefUtLogger());
668
669 checker.clearCache();
670
671 checker.destroy();
672
673 final Properties cacheAfterClear = new Properties();
674 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
675 cacheAfterClear.load(reader);
676 }
677
678 assertWithMessage("Cache has unexpected size")
679 .that(cacheAfterClear)
680 .hasSize(1);
681 assertWithMessage("Cache has null hash")
682 .that(cacheAfterClear.getProperty(PropertyCacheFile.CONFIG_HASH_KEY))
683 .isNotNull();
684
685 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
686
687
688 execute(checkerConfig, pathToEmptyFile);
689 final Properties cacheAfterSecondRun = new Properties();
690 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
691 cacheAfterSecondRun.load(reader);
692 }
693
694 assertWithMessage("Cache has null path")
695 .that(cacheAfterSecondRun.getProperty(pathToEmptyFile))
696 .isNotNull();
697 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
698 assertWithMessage("Cash have changed it hash")
699 .that(cacheHash)
700 .isEqualTo(cacheAfterClear.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
701 final int expectedNumberOfObjectsInCacheAfterSecondRun = 2;
702 assertWithMessage("Cache has changed number of items")
703 .that(cacheAfterSecondRun)
704 .hasSize(expectedNumberOfObjectsInCacheAfterSecondRun);
705 }
706
707 @Test
708 public void testClearCache() throws Exception {
709 final DefaultConfiguration violationCheck =
710 createModuleConfig(DummyFileSetViolationCheck.class);
711 final DefaultConfiguration checkerConfig = new DefaultConfiguration("myConfig");
712 checkerConfig.addProperty("charset", "UTF-8");
713 final File cacheFile = createTempFile("junit");
714 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
715 checkerConfig.addChild(violationCheck);
716 final Checker checker = new Checker();
717 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
718 checker.configure(checkerConfig);
719 checker.addListener(getBriefUtLogger());
720
721 checker.process(Collections.singletonList(new File("dummy.java")));
722 checker.clearCache();
723
724 final PropertyCacheFile cache = TestUtil.getInternalState(checker,
725 "cacheFile", PropertyCacheFile.class);
726 cache.persist();
727
728 final Properties cacheAfterClear = new Properties();
729 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
730 cacheAfterClear.load(reader);
731 }
732
733 assertWithMessage("Cache has unexpected size")
734 .that(cacheAfterClear)
735 .hasSize(1);
736 }
737
738 @Test
739 public void setFileExtension() {
740 final Checker checker = new Checker();
741 checker.setFileExtensions(".test1", "test2");
742 final String[] actual = TestUtil.getInternalState(checker,
743 "fileExtensions", String[].class);
744 assertWithMessage("Extensions are not expected")
745 .that(actual)
746 .isEqualTo(new String[] {".test1", ".test2"});
747 }
748
749 @Test
750 public void testClearCacheWhenCacheFileIsNotSet() {
751
752
753 final Checker checker = new Checker();
754 checker.clearCache();
755 final PropertyCacheFile cache = TestUtil.getInternalState(checker,
756 "cacheFile", PropertyCacheFile.class);
757 assertWithMessage("If cache file is not set the cache should default to null")
758 .that(cache)
759 .isNull();
760 }
761
762
763
764
765
766
767
768
769 @Test
770 public void testCatchErrorInProcessFilesMethod() {
771
772 final String errorMessage = "Java Virtual Machine is broken"
773 + " or has run out of resources necessary for it to continue operating.";
774 final Error expectedError = new IOError(new InternalError(errorMessage));
775
776 final File mock = new File("testFile") {
777 @Serial
778 private static final long serialVersionUID = 1L;
779
780
781
782
783
784
785
786
787 @Override
788 public long lastModified() {
789 throw expectedError;
790 }
791 };
792
793 final Checker checker = new Checker();
794 final List<File> filesToProcess = new ArrayList<>();
795 filesToProcess.add(mock);
796 final Error error =
797 getExpectedThrowable(Error.class, () -> {
798 checker.process(filesToProcess);
799 }, "IOError is expected!");
800 assertWithMessage("Error cause differs from IOError")
801 .that(error.getCause())
802 .isInstanceOf(IOError.class);
803 assertWithMessage("Error cause is not InternalError")
804 .that(error.getCause().getCause())
805 .isInstanceOf(InternalError.class);
806 assertWithMessage("Error message is not expected")
807 .that(error)
808 .hasCauseThat()
809 .hasCauseThat()
810 .hasMessageThat()
811 .isEqualTo(errorMessage);
812 assertWithMessage("Error message differs")
813 .that(error.getMessage())
814 .isEqualTo(getLocalizedMessage(
815 "Checker.error", mock.getPath()));
816 }
817
818
819
820
821
822
823
824
825 @Test
826 public void testCatchErrorWithNoFileName() {
827
828 final String errorMessage = "Java Virtual Machine is broken"
829 + " or has run out of resources necessary for it to continue operating.";
830 final Error expectedError = new IOError(new InternalError(errorMessage));
831
832 final File mock = new File("testFile") {
833 @Serial
834 private static final long serialVersionUID = 1L;
835
836
837
838
839
840
841
842 @Override
843 public long lastModified() {
844 throw expectedError;
845 }
846
847 @Override
848 public String getAbsolutePath() {
849 return null;
850 }
851 };
852
853 final Checker checker = new Checker();
854 final List<File> filesToProcess = new ArrayList<>();
855 filesToProcess.add(mock);
856 final Error error =
857 getExpectedThrowable(Error.class, () -> {
858 checker.process(filesToProcess);
859 }, "IOError is expected!");
860 assertWithMessage("Error cause differs from IOError")
861 .that(error)
862 .hasCauseThat()
863 .isInstanceOf(IOError.class);
864 assertWithMessage("Error cause is not InternalError")
865 .that(error)
866 .hasCauseThat()
867 .hasCauseThat()
868 .isInstanceOf(InternalError.class);
869 assertWithMessage("Error message is not expected")
870 .that(error)
871 .hasCauseThat()
872 .hasCauseThat()
873 .hasMessageThat()
874 .isEqualTo(errorMessage);
875 }
876
877
878
879
880 @Test
881 public void testCacheAndFilterWhichDoesNotImplementExternalResourceHolderInterface()
882 throws Exception {
883 assertWithMessage("ExternalResourceHolder has changed its parent")
884 .that(ExternalResourceHolder.class.isAssignableFrom(DummyFilter.class))
885 .isFalse();
886 final DefaultConfiguration filterConfig = createModuleConfig(DummyFilter.class);
887
888 final DefaultConfiguration checkerConfig = createRootConfig(filterConfig);
889 final File cacheFile = createTempFile("junit");
890 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
891
892 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
893
894 execute(checkerConfig, pathToEmptyFile);
895 final Properties cacheAfterFirstRun = new Properties();
896 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
897 cacheAfterFirstRun.load(reader);
898 }
899
900
901 execute(checkerConfig, pathToEmptyFile);
902 final Properties cacheAfterSecondRun = new Properties();
903 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
904 cacheAfterSecondRun.load(reader);
905 }
906
907 final String cacheFilePath = cacheAfterSecondRun.getProperty(pathToEmptyFile);
908 assertWithMessage("Cache file has changed its path")
909 .that(cacheFilePath)
910 .isEqualTo(cacheAfterFirstRun.getProperty(pathToEmptyFile));
911 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
912 assertWithMessage("Cache has changed its hash")
913 .that(cacheHash)
914 .isEqualTo(cacheAfterFirstRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
915 final int expectedNumberOfObjectsInCache = 2;
916 assertWithMessage("Number of items in cache differs from expected")
917 .that(cacheAfterFirstRun)
918 .hasSize(expectedNumberOfObjectsInCache);
919 assertWithMessage("Number of items in cache differs from expected")
920 .that(cacheAfterSecondRun)
921 .hasSize(expectedNumberOfObjectsInCache);
922 }
923
924
925
926
927
928 @Test
929 public void testCacheAndCheckWhichAddsNewResourceLocationButKeepsSameCheckerInstance()
930 throws Exception {
931
932
933
934
935
936
937 final DynamicalResourceHolderCheck check = new DynamicalResourceHolderCheck();
938 final String firstExternalResourceLocation = getPath("InputCheckerImportControlOne.xml");
939 final String firstExternalResourceKey = PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
940 + firstExternalResourceLocation;
941 check.setFirstExternalResourceLocation(firstExternalResourceLocation);
942
943 final DefaultConfiguration checkerConfig = createRootConfig(null);
944 final File cacheFile = createTempFile("junit");
945 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
946
947 final Checker checker = new Checker();
948 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
949 checker.addFileSetCheck(check);
950 checker.addFilter(new DummyFilterSet());
951 checker.configure(checkerConfig);
952 checker.addListener(getBriefUtLogger());
953
954 final String pathToEmptyFile = createTempFile("file", ".java").getPath();
955
956 execute(checker, pathToEmptyFile);
957 final Properties cacheAfterFirstRun = new Properties();
958 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
959 cacheAfterFirstRun.load(reader);
960 }
961
962 final int expectedNumberOfObjectsInCacheAfterFirstRun = 4;
963 assertWithMessage("Number of items in cache differs from expected")
964 .that(cacheAfterFirstRun)
965 .hasSize(expectedNumberOfObjectsInCacheAfterFirstRun);
966
967
968 final String secondExternalResourceLocation = "InputCheckerImportControlTwo.xml";
969 final String secondExternalResourceKey = PropertyCacheFile.EXTERNAL_RESOURCE_KEY_PREFIX
970 + secondExternalResourceLocation;
971 check.setSecondExternalResourceLocation(secondExternalResourceLocation);
972
973 checker.addFileSetCheck(check);
974 checker.configure(checkerConfig);
975
976 execute(checker, pathToEmptyFile);
977 final Properties cacheAfterSecondRun = new Properties();
978 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
979 cacheAfterSecondRun.load(reader);
980 }
981
982 final String cacheFilePath = cacheAfterSecondRun.getProperty(pathToEmptyFile);
983 assertWithMessage("Cache file has changed its path")
984 .that(cacheFilePath)
985 .isEqualTo(cacheAfterFirstRun.getProperty(pathToEmptyFile));
986 final String cacheHash = cacheAfterSecondRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY);
987 assertWithMessage("Cache has changed its hash")
988 .that(cacheHash)
989 .isEqualTo(cacheAfterFirstRun.getProperty(PropertyCacheFile.CONFIG_HASH_KEY));
990 final String resourceKey = cacheAfterSecondRun.getProperty(firstExternalResourceKey);
991 assertWithMessage("Cache has changed its resource key")
992 .that(resourceKey)
993 .isEqualTo(cacheAfterFirstRun.getProperty(firstExternalResourceKey));
994 assertWithMessage("Cache has null as a resource key")
995 .that(cacheAfterFirstRun.getProperty(firstExternalResourceKey))
996 .isNotNull();
997 final int expectedNumberOfObjectsInCacheAfterSecondRun = 4;
998 assertWithMessage("Number of items in cache differs from expected")
999 .that(cacheAfterSecondRun)
1000 .hasSize(expectedNumberOfObjectsInCacheAfterSecondRun);
1001 assertWithMessage("Cache has not null as a resource key")
1002 .that(cacheAfterFirstRun.getProperty(secondExternalResourceKey))
1003 .isNull();
1004 assertWithMessage("Cache has null as a resource key")
1005 .that(cacheAfterSecondRun.getProperty(secondExternalResourceKey))
1006 .isNotNull();
1007 }
1008
1009 @Test
1010 public void testClearLazyLoadCacheInDetailAST() throws Exception {
1011
1012 final String filePath = getPath("InputCheckerClearDetailAstLazyLoadCache.java");
1013
1014 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
1015 verifyWithInlineConfigParser(filePath, expected);
1016 }
1017
1018 @Test
1019 public void testCacheOnViolationSuppression() throws Exception {
1020 final File cacheFile = createTempFile("junit");
1021 final DefaultConfiguration violationCheck =
1022 createModuleConfig(DummyFileSetViolationCheck.class);
1023
1024 final DefaultConfiguration filterConfig = createModuleConfig(SuppressionFilter.class);
1025 filterConfig.addProperty("file", getPath("InputCheckerSuppressAll.xml"));
1026
1027 final DefaultConfiguration checkerConfig = createRootConfig(violationCheck);
1028 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1029 checkerConfig.addChild(filterConfig);
1030
1031 final String fileViolationPath = createTempFile("ViolationFile", ".java").getPath();
1032
1033 execute(checkerConfig, fileViolationPath);
1034
1035 try (InputStream input = Files.newInputStream(cacheFile.toPath())) {
1036 final Properties details = new Properties();
1037 details.load(input);
1038
1039 assertWithMessage("suppressed violation file saved in cache")
1040 .that(details.getProperty(fileViolationPath))
1041 .isNotNull();
1042 }
1043 }
1044
1045 @Test
1046 public void testXmlReportFinishedOnProcessingException() throws Exception {
1047 final DefaultConfiguration checkConfig = createModuleConfig(CheckWhichThrowsError.class);
1048 final DefaultConfiguration treewalkerConfig = createModuleConfig(TreeWalker.class);
1049 treewalkerConfig.addChild(checkConfig);
1050 final Checker checker = createChecker(createRootConfig(treewalkerConfig));
1051 final ByteArrayOutputStream output = new ByteArrayOutputStream();
1052 checker.addListener(new XMLLogger(output, OutputStreamOptions.NONE));
1053 final String filePath = getPath("InputChecker.java");
1054
1055 final CheckstyleException exception = getExpectedThrowable(CheckstyleException.class,
1056 () -> checker.process(List.of(new File(filePath))), "Exception is expected");
1057
1058 assertWithMessage("Processing failure must still be propagated")
1059 .that(exception).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class);
1060 assertWithMessage("XML report must close the file and audit after a failure")
1061 .that(output.toString(StandardCharsets.UTF_8))
1062 .endsWith("</file>" + System.lineSeparator()
1063 + "</checkstyle>" + System.lineSeparator());
1064 checker.destroy();
1065 }
1066
1067 @Test
1068 public void testProcessingExceptionPreservedWhenCompletionFails() throws Exception {
1069 final DefaultConfiguration checkConfig = createModuleConfig(CheckWhichThrowsError.class);
1070 final DefaultConfiguration treewalkerConfig = createModuleConfig(TreeWalker.class);
1071 treewalkerConfig.addChild(checkConfig);
1072 final Checker checker = createChecker(createRootConfig(treewalkerConfig));
1073 final IllegalStateException fileFailure = new IllegalStateException("file completion");
1074 final IllegalStateException auditFailure = new IllegalStateException("audit completion");
1075 checker.addListener(new DefaultLogger(new ByteArrayOutputStream(),
1076 OutputStreamOptions.NONE) {
1077 @Override
1078 public void fileFinished(AuditEvent event) {
1079 throw fileFailure;
1080 }
1081
1082 @Override
1083 public void auditFinished(AuditEvent event) {
1084 throw auditFailure;
1085 }
1086 });
1087
1088 final CheckstyleException exception = getExpectedThrowable(CheckstyleException.class,
1089 () -> checker.process(List.of(new File(getPath("InputChecker.java")))),
1090 "Processing exception is expected");
1091
1092 assertWithMessage("Processing failure must remain the primary cause")
1093 .that(exception).hasCauseThat().isInstanceOf(IndexOutOfBoundsException.class);
1094 assertWithMessage("File completion failure must be suppressed")
1095 .that(exception.getCause().getSuppressed()).asList().containsExactly(fileFailure);
1096 assertWithMessage("Audit completion failure must be suppressed")
1097 .that(exception.getSuppressed()).asList().containsExactly(auditFailure);
1098 checker.destroy();
1099 }
1100
1101 @Test
1102 public void testHaltOnException() throws Exception {
1103 final DefaultConfiguration checkConfig =
1104 createModuleConfig(CheckWhichThrowsError.class);
1105 final String filePath = getPath("InputChecker.java");
1106 final CheckstyleException exc =
1107 getExpectedThrowable(CheckstyleException.class, () -> {
1108 execute(checkConfig, filePath);
1109 }, "Exception is expected");
1110 assertWithMessage("Error message is not expected")
1111 .that(exc.getMessage())
1112 .isEqualTo("Exception was thrown while processing " + filePath);
1113 }
1114
1115 @Test
1116 public void testExceptionWithCache() throws Exception {
1117 final File cacheFile = createTempFile("junit");
1118
1119 final DefaultConfiguration checkConfig =
1120 createModuleConfig(CheckWhichThrowsError.class);
1121
1122 final DefaultConfiguration treewalkerConfig =
1123 createModuleConfig(TreeWalker.class);
1124 treewalkerConfig.addChild(checkConfig);
1125
1126 final DefaultConfiguration checkerConfig = createRootConfig(treewalkerConfig);
1127 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1128 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1129 checkerConfig.addChild(treewalkerConfig);
1130
1131 final Checker checker = createChecker(checkerConfig);
1132
1133 final String filePath = getPath("InputChecker.java");
1134 final CheckstyleException exc =
1135 getExpectedThrowable(CheckstyleException.class, () -> {
1136 checker.process(Collections.singletonList(new File(filePath)));
1137 }, "Exception is expected");
1138 assertWithMessage("Error message is not expected")
1139 .that(exc.getMessage())
1140 .isEqualTo("Exception was thrown while processing " + filePath);
1141
1142
1143 checker.destroy();
1144
1145 final Properties cache = new Properties();
1146 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1147 cache.load(reader);
1148 }
1149
1150 assertWithMessage("Cache has unexpected size")
1151 .that(cache)
1152 .hasSize(1);
1153 assertWithMessage("testFile is not in cache")
1154 .that(cache.getProperty(filePath))
1155 .isNull();
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165 @Test
1166 public void testCatchErrorWithCache() throws Exception {
1167 final File cacheFile = createTempFile("junit");
1168
1169 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1170 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1171 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1172
1173 final String errorMessage = "Java Virtual Machine is broken"
1174 + " or has run out of resources necessary for it to continue operating.";
1175 final Error expectedError = new IOError(new InternalError(errorMessage));
1176
1177 final File mock = new File("testFile") {
1178 @Serial
1179 private static final long serialVersionUID = 1L;
1180 @Override
1181 public String getAbsolutePath() {
1182 return "testFile";
1183 }
1184
1185
1186
1187
1188
1189
1190
1191
1192 @Override
1193 public File getAbsoluteFile() {
1194 throw expectedError;
1195 }
1196 };
1197
1198 final Checker checker = new Checker();
1199 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1200 checker.configure(checkerConfig);
1201 final ByteArrayOutputStream output = new ByteArrayOutputStream();
1202 checker.addListener(new XMLLogger(output, OutputStreamOptions.NONE));
1203 final List<File> filesToProcess = new ArrayList<>();
1204 filesToProcess.add(mock);
1205 final Error error =
1206 getExpectedThrowable(Error.class, () -> {
1207 checker.process(filesToProcess);
1208 }, "IOError is expected!");
1209 assertWithMessage("Error cause differs from IOError")
1210 .that(error.getCause())
1211 .isInstanceOf(IOError.class);
1212 assertWithMessage("Error message is not expected")
1213 .that(error)
1214 .hasCauseThat()
1215 .hasCauseThat()
1216 .hasMessageThat()
1217 .isEqualTo(errorMessage);
1218
1219
1220 checker.destroy();
1221
1222 assertWithMessage("XML report must close the file and audit after an error")
1223 .that(output.toString(StandardCharsets.UTF_8))
1224 .endsWith("</file>" + System.lineSeparator()
1225 + "</checkstyle>" + System.lineSeparator());
1226
1227 final Properties cache = new Properties();
1228 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1229 cache.load(reader);
1230 }
1231
1232 assertWithMessage("Cache has unexpected size")
1233 .that(cache)
1234 .hasSize(1);
1235 assertWithMessage("testFile is not in cache")
1236 .that(cache.getProperty("testFile"))
1237 .isNull();
1238 }
1239
1240
1241
1242
1243
1244
1245
1246
1247 @Test
1248 public void testCatchErrorWithCacheWithNoFileName() throws Exception {
1249 final File cacheFile = createTempFile("junit");
1250
1251 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1252 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1253 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1254
1255 final String errorMessage = "Java Virtual Machine is broken"
1256 + " or has run out of resources necessary for it to continue operating.";
1257 final Error expectedError = new IOError(new InternalError(errorMessage));
1258
1259 final File mock = new File("testFile") {
1260 @Serial
1261 private static final long serialVersionUID = 1L;
1262
1263
1264
1265
1266
1267
1268
1269
1270 @Override
1271 public String getAbsolutePath() {
1272 throw expectedError;
1273 }
1274 };
1275
1276 final Checker checker = new Checker();
1277 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1278 checker.configure(checkerConfig);
1279 final List<File> filesToProcess = new ArrayList<>();
1280 filesToProcess.add(mock);
1281 final Error error =
1282 getExpectedThrowable(Error.class, () -> {
1283 checker.process(filesToProcess);
1284 }, "IOError is expected!");
1285 assertWithMessage("Error cause differs from IOError")
1286 .that(error)
1287 .hasCauseThat()
1288 .isInstanceOf(IOError.class);
1289 assertWithMessage("Error message is not expected")
1290 .that(error)
1291 .hasCauseThat()
1292 .hasCauseThat()
1293 .hasMessageThat()
1294 .isEqualTo(errorMessage);
1295
1296
1297 checker.destroy();
1298
1299 final Properties cache = new Properties();
1300 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1301 cache.load(reader);
1302 }
1303
1304 assertWithMessage("Cache has unexpected size")
1305 .that(cache)
1306 .hasSize(1);
1307 }
1308
1309
1310
1311
1312
1313
1314
1315
1316 @Test
1317 public void testExceptionWithNoFileName() {
1318 final String errorMessage = "Security Exception";
1319 final RuntimeException expectedError = new SecurityException(errorMessage);
1320
1321 final File mock = new File("testFile") {
1322 @Serial
1323 private static final long serialVersionUID = 1L;
1324
1325
1326
1327
1328
1329
1330
1331
1332 @Override
1333 public String getAbsolutePath() {
1334 throw expectedError;
1335 }
1336 };
1337
1338 final Checker checker = new Checker();
1339 final List<File> filesToProcess = new ArrayList<>();
1340 filesToProcess.add(mock);
1341 final CheckstyleException exc =
1342 getExpectedThrowable(CheckstyleException.class, () -> {
1343 checker.process(filesToProcess);
1344 }, "SecurityException is expected!");
1345 assertWithMessage("Error cause differs from SecurityException")
1346 .that(exc)
1347 .hasCauseThat()
1348 .isInstanceOf(SecurityException.class);
1349 assertWithMessage("Error message is not expected")
1350 .that(exc)
1351 .hasCauseThat()
1352 .hasMessageThat()
1353 .isEqualTo(errorMessage);
1354 }
1355
1356
1357
1358
1359
1360
1361
1362
1363 @Test
1364 public void testExceptionWithCacheAndNoFileName() throws Exception {
1365 final File cacheFile = createTempFile("junit");
1366
1367 final DefaultConfiguration checkerConfig = new DefaultConfiguration("configuration");
1368 checkerConfig.addProperty("charset", StandardCharsets.UTF_8.name());
1369 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
1370
1371 final String errorMessage = "Security Exception";
1372 final RuntimeException expectedError = new SecurityException(errorMessage);
1373
1374 final File mock = new File("testFile") {
1375 @Serial
1376 private static final long serialVersionUID = 1L;
1377
1378
1379
1380
1381
1382
1383
1384
1385 @Override
1386 public String getAbsolutePath() {
1387 throw expectedError;
1388 }
1389 };
1390
1391 final Checker checker = new Checker();
1392 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1393 checker.configure(checkerConfig);
1394 final List<File> filesToProcess = new ArrayList<>();
1395 filesToProcess.add(mock);
1396 final CheckstyleException exc =
1397 getExpectedThrowable(CheckstyleException.class, () -> {
1398 checker.process(filesToProcess);
1399 }, "SecurityException is expected!");
1400 assertWithMessage("Error cause differs from SecurityException")
1401 .that(exc)
1402 .hasCauseThat()
1403 .isInstanceOf(SecurityException.class);
1404 assertWithMessage("Error message is not expected")
1405 .that(exc)
1406 .hasCauseThat()
1407 .hasMessageThat()
1408 .isEqualTo(errorMessage);
1409
1410
1411 checker.destroy();
1412
1413 final Properties cache = new Properties();
1414 try (BufferedReader reader = Files.newBufferedReader(cacheFile.toPath())) {
1415 cache.load(reader);
1416 }
1417
1418 assertWithMessage("Cache has unexpected size")
1419 .that(cache)
1420 .hasSize(1);
1421 }
1422
1423 @Test
1424 public void testHaltOnExceptionOff() throws Exception {
1425 final String filePath = getPath("InputChecker.java");
1426 final String[] expected = {
1427 "1: " + getCheckMessage(EXCEPTION_MSG, "java.lang.IndexOutOfBoundsException: test"),
1428 };
1429
1430 verifyWithInlineXmlConfig(filePath, expected);
1431 }
1432
1433 @Test
1434 public void testTabViolationDefault() throws Exception {
1435 final String[] expected = {
1436 "18:17: violation",
1437 "22:49: violation",
1438 };
1439 verifyWithInlineConfigParser(getPath("InputCheckerTabCharacter.java"),
1440 expected);
1441 }
1442
1443 @Test
1444 public void testTabViolationCustomWidth() throws Exception {
1445 final String[] expected = {
1446 "19:17: violation",
1447 "23:37: violation",
1448 };
1449
1450 verifyWithInlineXmlConfig(getPath("InputCheckerTabCharacterCustomWidth.java"), expected);
1451 }
1452
1453 @Test
1454 public void testCheckerProcessCallAllNeededMethodsOfFileSets() throws Exception {
1455 final DummyFileSet fileSet = new DummyFileSet();
1456 final Checker checker = new Checker();
1457 checker.addFileSetCheck(fileSet);
1458 checker.process(Collections.singletonList(new File("dummy.java")));
1459 final List<String> expected =
1460 Arrays.asList("beginProcessing", "finishProcessing", "destroy");
1461 assertWithMessage("Method calls were not expected")
1462 .that(fileSet.getMethodCalls())
1463 .isEqualTo(expected);
1464 }
1465
1466 @Test
1467 public void testSetFileSetCheckSetsMessageDispatcher() {
1468 final DummyFileSet fileSet = new DummyFileSet();
1469 final Checker checker = new Checker();
1470 checker.addFileSetCheck(fileSet);
1471 assertWithMessage("Message dispatcher was not expected")
1472 .that(fileSet.getInternalMessageDispatcher())
1473 .isEqualTo(checker);
1474 }
1475
1476 @Test
1477 public void testAddAuditListenerAsChild() throws Exception {
1478 final Checker checker = new Checker();
1479 final DebugAuditAdapter auditAdapter = new DebugAuditAdapter();
1480 final PackageObjectFactory factory = new PackageObjectFactory(
1481 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1482 @Override
1483 public Object createModule(String name) throws CheckstyleException {
1484 Object adapter = auditAdapter;
1485 if (!name.equals(DebugAuditAdapter.class.getName())) {
1486 adapter = super.createModule(name);
1487 }
1488 return adapter;
1489 }
1490 };
1491 checker.setModuleFactory(factory);
1492 checker.setupChild(createModuleConfig(DebugAuditAdapter.class));
1493
1494 checker.process(Collections.singletonList(new File("dummy.java")));
1495 assertWithMessage("Checker.fireAuditStarted() doesn't call listener")
1496 .that(auditAdapter.wasCalled())
1497 .isTrue();
1498 }
1499
1500 @Test
1501 public void testAddBeforeExecutionFileFilterAsChild() throws Exception {
1502 final Checker checker = new Checker();
1503 final TestBeforeExecutionFileFilter fileFilter = new TestBeforeExecutionFileFilter();
1504 final PackageObjectFactory factory = new PackageObjectFactory(
1505 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1506 @Override
1507 public Object createModule(String name) throws CheckstyleException {
1508 Object filter = fileFilter;
1509 if (!name.equals(TestBeforeExecutionFileFilter.class.getName())) {
1510 filter = super.createModule(name);
1511 }
1512 return filter;
1513 }
1514 };
1515 checker.setModuleFactory(factory);
1516 checker.setupChild(createModuleConfig(TestBeforeExecutionFileFilter.class));
1517 checker.process(Collections.singletonList(new File("dummy.java")));
1518 assertWithMessage("Checker.acceptFileStarted() doesn't call listener")
1519 .that(fileFilter.wasCalled())
1520 .isTrue();
1521 }
1522
1523 @Test
1524 public void testFileSetCheckInitWhenAddedAsChild() throws Exception {
1525 final Checker checker = new Checker();
1526 final DummyFileSet fileSet = new DummyFileSet();
1527 final PackageObjectFactory factory = new PackageObjectFactory(
1528 new HashSet<>(), Thread.currentThread().getContextClassLoader()) {
1529 @Override
1530 public Object createModule(String name) throws CheckstyleException {
1531 Object check = fileSet;
1532 if (!name.equals(DummyFileSet.class.getName())) {
1533 check = super.createModule(name);
1534 }
1535 return check;
1536 }
1537 };
1538 checker.setModuleFactory(factory);
1539 checker.finishLocalSetup();
1540 checker.setupChild(createModuleConfig(DummyFileSet.class));
1541 assertWithMessage("FileSetCheck.init() wasn't called")
1542 .that(fileSet.isInitCalled())
1543 .isTrue();
1544 }
1545
1546
1547 @Test
1548 public void testDefaultLoggerClosesItStreams() throws Exception {
1549 final Checker checker = new Checker();
1550 try (CloseAndFlushTestByteArrayOutputStream testInfoOutputStream =
1551 new CloseAndFlushTestByteArrayOutputStream();
1552 CloseAndFlushTestByteArrayOutputStream testErrorOutputStream =
1553 new CloseAndFlushTestByteArrayOutputStream()) {
1554 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1555 checker.addListener(new DefaultLogger(testInfoOutputStream,
1556 OutputStreamOptions.CLOSE, testErrorOutputStream, OutputStreamOptions.CLOSE));
1557
1558 final File tmpFile = createTempFile("file", ".java");
1559
1560 execute(checker, tmpFile.getPath());
1561
1562 assertWithMessage("Output stream close count")
1563 .that(testInfoOutputStream.getCloseCount())
1564 .isEqualTo(1);
1565 assertWithMessage("Output stream flush count")
1566 .that(testInfoOutputStream.getFlushCount())
1567 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(3));
1568 assertWithMessage("Error stream close count")
1569 .that(testErrorOutputStream.getCloseCount())
1570 .isEqualTo(1);
1571 assertWithMessage("Error stream flush count")
1572 .that(testErrorOutputStream.getFlushCount())
1573 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(1));
1574 }
1575 }
1576
1577
1578 @Test
1579 public void testXmlLoggerClosesItStreams() throws Exception {
1580 final Checker checker = new Checker();
1581 try (CloseAndFlushTestByteArrayOutputStream testInfoOutputStream =
1582 new CloseAndFlushTestByteArrayOutputStream()) {
1583 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1584 checker.addListener(new XMLLogger(testInfoOutputStream, OutputStreamOptions.CLOSE));
1585
1586 final File tmpFile = createTempFile("file", ".java");
1587
1588 execute(checker, tmpFile.getPath(), tmpFile.getPath());
1589
1590 assertWithMessage("Output stream close count")
1591 .that(testInfoOutputStream.getCloseCount())
1592 .isEqualTo(1);
1593 assertWithMessage("Output stream flush count")
1594 .that(testInfoOutputStream.getFlushCount())
1595 .isEqualTo(TestUtil.adjustFlushCountForOutputStreamClose(0));
1596 }
1597 }
1598
1599 @Test
1600 public void testDuplicatedModule() throws Exception {
1601
1602 final DefaultConfiguration moduleConfig1 =
1603 createModuleConfig(NewlineAtEndOfFileCheck.class);
1604 final DefaultConfiguration moduleConfig2 =
1605 createModuleConfig(NewlineAtEndOfFileCheck.class);
1606 moduleConfig2.addProperty("id", "ModuleId");
1607 final DefaultConfiguration root = new DefaultConfiguration("root");
1608 root.addChild(moduleConfig1);
1609 root.addChild(moduleConfig2);
1610 final Checker checker = new Checker();
1611 checker.setModuleClassLoader(Thread.currentThread().getContextClassLoader());
1612 checker.configure(root);
1613
1614
1615 final ByteArrayOutputStream out = TestUtil.getInternalState(this,
1616 "stream", ByteArrayOutputStream.class);
1617 final DefaultLogger logger = new DefaultLogger(out, OutputStreamOptions.CLOSE, out,
1618 OutputStreamOptions.NONE, new AuditEventDefaultFormatter());
1619 checker.addListener(logger);
1620
1621 final File tempFile = createTempFile("file", ".java");
1622 try (BufferedWriter bufferedWriter = Files.newBufferedWriter(tempFile.toPath())) {
1623 bufferedWriter.write(';');
1624 }
1625 final String path = tempFile.getPath();
1626 final String violationMessage =
1627 getCheckMessage(NewlineAtEndOfFileCheck.class, MSG_KEY_NO_NEWLINE_EOF);
1628 final String[] expected = {
1629 "1: " + violationMessage + " [NewlineAtEndOfFile]",
1630 "1: " + violationMessage + " [ModuleId]",
1631 };
1632
1633
1634 out.flush();
1635 final int errs = checker.process(Collections.singletonList(new File(path)));
1636 try (ByteArrayInputStream inputStream =
1637 new ByteArrayInputStream(out.toByteArray());
1638 LineNumberReader lnr = new LineNumberReader(
1639 new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {
1640
1641 final List<String> actual = lnr.lines()
1642 .filter(line -> !getCheckMessage(AUDIT_STARTED_MESSAGE).equals(line))
1643 .filter(line -> !getCheckMessage(AUDIT_FINISHED_MESSAGE).equals(line))
1644 .limit(expected.length)
1645 .sorted()
1646 .toList();
1647 Arrays.sort(expected);
1648
1649 for (int index = 0; index < expected.length; index++) {
1650 final String expectedResult = "[ERROR] " + path + ":" + expected[index];
1651 assertWithMessage("error message %s", index)
1652 .that(actual.get(index))
1653 .isEqualTo(expectedResult);
1654 }
1655
1656 assertWithMessage("unexpected output: %s", lnr.readLine())
1657 .that(errs)
1658 .isEqualTo(expected.length);
1659 }
1660
1661 checker.destroy();
1662 }
1663
1664 @Test
1665 public void testCachedFile() throws Exception {
1666 final Checker checker = createChecker(createModuleConfig(TranslationCheck.class));
1667 final OutputStream infoStream = new ByteArrayOutputStream();
1668 final OutputStream errorStream = new ByteArrayOutputStream();
1669 final DefaultLoggerWithCounter loggerWithCounter =
1670 new DefaultLoggerWithCounter(infoStream, OutputStreamOptions.CLOSE,
1671 errorStream, OutputStreamOptions.CLOSE);
1672 checker.addListener(loggerWithCounter);
1673 final File cacheFile = createTempFile("cacheFile", ".txt");
1674 checker.setCacheFile(cacheFile.getAbsolutePath());
1675
1676 final File testFile = createTempFile("testFile", ".java");
1677 final List<File> files = List.of(testFile, testFile);
1678 checker.process(files);
1679
1680 assertWithMessage("Cached file should not be processed twice")
1681 .that(loggerWithCounter.fileStartedCount)
1682 .isEqualTo(1);
1683 assertWithMessage("Cached file should not receive a second completion event")
1684 .that(loggerWithCounter.fileFinishedCount)
1685 .isEqualTo(1);
1686
1687 checker.destroy();
1688 }
1689
1690 @Test
1691 public void testUnmappableCharacters() throws Exception {
1692 final String[] expected = {
1693 "14: " + getCheckMessage(LineLengthCheck.class, MSG_KEY, 80, 225),
1694 };
1695
1696 verifyWithInlineXmlConfig(getPath("InputCheckerTestCharset.java"),
1697 expected);
1698 }
1699
1700
1701
1702
1703
1704
1705
1706
1707 @SuppressForbidden
1708 @Test
1709 public void testViolationMessageOnIoException() throws Exception {
1710 final DefaultConfiguration checkConfig =
1711 createModuleConfig(CheckWhichThrowsError.class);
1712
1713 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
1714 treeWalkerConfig.addChild(checkConfig);
1715
1716 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
1717 checkerConfig.addChild(treeWalkerConfig);
1718
1719 checkerConfig.addProperty("haltOnException", "false");
1720 final File file = new File("InputNonChecker.java");
1721 final String filePath = file.getAbsolutePath();
1722 final String[] expected = {
1723 "1: " + getCheckMessage(EXCEPTION_MSG, filePath
1724 + " (No such file or directory)"),
1725 };
1726
1727 verify(checkerConfig, filePath, expected);
1728 }
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738 @Test
1739 public void testRelativizedFileExclusion() throws Exception {
1740 final DefaultConfiguration newLineAtEndOfFileConfig =
1741 createModuleConfig(NewlineAtEndOfFileCheck.class);
1742
1743 final DefaultConfiguration beforeExecutionExclusionFileFilterConfig =
1744 createModuleConfig(BeforeExecutionExclusionFileFilter.class);
1745
1746 beforeExecutionExclusionFileFilterConfig.addProperty("fileNamePattern",
1747 "^(?!InputCheckerTestExcludeRelativizedFile.*\\.java).*");
1748
1749 final DefaultConfiguration checkerConfig = createRootConfig(null);
1750 checkerConfig.addChild(newLineAtEndOfFileConfig);
1751 checkerConfig.addChild(beforeExecutionExclusionFileFilterConfig);
1752
1753
1754 checkerConfig.addProperty("basedir",
1755 temporaryFolder.getPath());
1756
1757 final String violationMessage =
1758 getCheckMessage(NewlineAtEndOfFileCheck.class, MSG_KEY_NO_NEWLINE_EOF);
1759
1760 final String[] expected = {
1761 "1: " + violationMessage,
1762 };
1763
1764 final File tempFile = createTempFile("InputCheckerTestExcludeRelativizedFile", ".java");
1765 try (BufferedWriter bufferedWriter = Files.newBufferedWriter(tempFile.toPath())) {
1766 bufferedWriter.write(';');
1767 }
1768
1769 final File[] processedFiles = {tempFile};
1770
1771 verify(createChecker(checkerConfig), processedFiles,
1772 tempFile.getName(), expected);
1773 }
1774
1775 @Test
1776 public void testBasedirPathMismatchExceptionMessage() throws IOException {
1777 final CheckstyleAntTask antTask = new CheckstyleAntTask();
1778 antTask.setProject(new Project());
1779 antTask.setConfig(getPath("InputCheckerTestConfigBasedirMismatch.xml"));
1780
1781 final File testFile = Files.createFile(
1782 temporaryFolder.toPath().resolve("TestBasedirMismatch.java"))
1783 .toFile();
1784
1785 antTask.setFile(testFile);
1786
1787 final BuildException ex = getExpectedThrowable(
1788 BuildException.class,
1789 antTask::execute,
1790 "BuildException is expected");
1791
1792 final IllegalStateException relativizeException = findRelativizePathException(ex);
1793 final String message = relativizeException.getMessage();
1794
1795 assertWithMessage("Exception message should mention failed relativization")
1796 .that(message)
1797 .contains("Failed to relativize path");
1798
1799 assertWithMessage("Exception message should mention base directory")
1800 .that(message)
1801 .contains("base directory");
1802
1803 assertWithMessage("Exception message should contain the file path")
1804 .that(message)
1805 .contains(testFile.getAbsolutePath());
1806 }
1807
1808 private static IllegalStateException findRelativizePathException(Throwable throwable) {
1809 Throwable current = throwable;
1810 while (current != null) {
1811 if (current instanceof IllegalStateException exception
1812 && current.getCause() instanceof IllegalArgumentException) {
1813 return exception;
1814 }
1815 current = current.getCause();
1816 }
1817 throw new AssertionError(
1818 "IllegalStateException from CommonUtil.relativizePath not found in cause chain");
1819 }
1820
1821 public static class DefaultLoggerWithCounter extends DefaultLogger {
1822
1823 private int fileStartedCount;
1824 private int fileFinishedCount;
1825
1826 public DefaultLoggerWithCounter(OutputStream infoStream,
1827 OutputStreamOptions infoStreamOptions,
1828 OutputStream errorStream,
1829 OutputStreamOptions errorStreamOptions) {
1830 super(infoStream, infoStreamOptions, errorStream, errorStreamOptions);
1831 }
1832
1833 @Override
1834 public void fileStarted(AuditEvent event) {
1835 fileStartedCount++;
1836 }
1837
1838 @Override
1839 public void fileFinished(AuditEvent event) {
1840 fileFinishedCount++;
1841 }
1842 }
1843
1844 public static class DummyFilter implements Filter {
1845
1846 @Override
1847 public boolean accept(AuditEvent event) {
1848 return false;
1849 }
1850
1851 }
1852
1853 public static class DummyFileSetViolationCheck extends AbstractFileSetCheck
1854 implements ExternalResourceHolder {
1855
1856 @Override
1857 protected void processFiltered(File file, FileText fileText) {
1858 log(1, "test");
1859 }
1860
1861 @Override
1862 public Set<String> getExternalResourceLocations() {
1863 final Set<String> externalResourceLocation = new HashSet<>(1);
1864 externalResourceLocation.add("non_existent_external_resource.xml");
1865 return externalResourceLocation;
1866 }
1867
1868 }
1869
1870 public static class DummyFilterSet extends FilterSet implements ExternalResourceHolder {
1871
1872 @Override
1873 public Set<String> getExternalResourceLocations() {
1874 final Set<String> strings = new HashSet<>();
1875 strings.add("test");
1876 return strings;
1877 }
1878
1879 }
1880
1881 public static final class DynamicalResourceHolderCheck extends AbstractFileSetCheck
1882 implements ExternalResourceHolder {
1883
1884 private String firstExternalResourceLocation;
1885 private String secondExternalResourceLocation;
1886
1887 public void setFirstExternalResourceLocation(String firstExternalResourceLocation) {
1888 this.firstExternalResourceLocation = firstExternalResourceLocation;
1889 }
1890
1891 public void setSecondExternalResourceLocation(String secondExternalResourceLocation) {
1892 this.secondExternalResourceLocation = secondExternalResourceLocation;
1893 }
1894
1895 @Override
1896 protected void processFiltered(File file, FileText fileText) {
1897
1898 }
1899
1900 @Override
1901 public Set<String> getExternalResourceLocations() {
1902 final Set<String> locations = new HashSet<>();
1903 locations.add(firstExternalResourceLocation);
1904
1905 if (secondExternalResourceLocation != null) {
1906 locations.add(secondExternalResourceLocation);
1907 }
1908 return locations;
1909 }
1910
1911 }
1912
1913 public static class CheckWhichDoesNotRequireCommentNodes extends AbstractCheck {
1914
1915
1916 private static final int METHOD_DEF_CHILD_COUNT = 7;
1917
1918 @Override
1919 public int[] getDefaultTokens() {
1920 return new int[] {TokenTypes.METHOD_DEF};
1921 }
1922
1923 @Override
1924 public int[] getAcceptableTokens() {
1925 return new int[] {TokenTypes.METHOD_DEF};
1926 }
1927
1928 @Override
1929 public int[] getRequiredTokens() {
1930 return new int[] {TokenTypes.METHOD_DEF};
1931 }
1932
1933 @Override
1934 public void visitToken(DetailAST ast) {
1935 if (ast.findFirstToken(TokenTypes.MODIFIERS).findFirstToken(
1936 TokenTypes.BLOCK_COMMENT_BEGIN) != null) {
1937 log(ast, "AST has incorrect structure structure."
1938 + " The check does not require comment nodes but there were comment nodes"
1939 + " in the AST.");
1940 }
1941 final int childCount = ast.getChildCount();
1942 if (childCount != METHOD_DEF_CHILD_COUNT) {
1943 final String msg = String.format(Locale.ENGLISH,
1944 "AST node in no comment tree has wrong number of children. "
1945 + "Expected is %d but was %d",
1946 METHOD_DEF_CHILD_COUNT, childCount);
1947 log(ast, msg);
1948 }
1949
1950 int actualChildCount = 0;
1951 for (DetailAST child = ast.getFirstChild().getFirstChild(); child != null; child =
1952 child.getNextSibling()) {
1953 actualChildCount++;
1954 }
1955 final int cacheChildCount = ast.getFirstChild().getChildCount();
1956 if (cacheChildCount != actualChildCount) {
1957 final String msg = String.format(Locale.ENGLISH,
1958 "AST node with no comment has wrong number of children. "
1959 + "Expected is %d but was %d",
1960 cacheChildCount, actualChildCount);
1961 log(ast, msg);
1962 }
1963 }
1964
1965 }
1966
1967 public static class CheckWhichRequiresCommentNodes extends AbstractCheck {
1968
1969
1970 private static final int METHOD_DEF_CHILD_COUNT = 7;
1971
1972 @Override
1973 public boolean isCommentNodesRequired() {
1974 return true;
1975 }
1976
1977 @Override
1978 public int[] getDefaultTokens() {
1979 return new int[] {TokenTypes.METHOD_DEF};
1980 }
1981
1982 @Override
1983 public int[] getAcceptableTokens() {
1984 return new int[] {TokenTypes.METHOD_DEF};
1985 }
1986
1987 @Override
1988 public int[] getRequiredTokens() {
1989 return new int[] {TokenTypes.METHOD_DEF};
1990 }
1991
1992
1993 @Override
1994 public void visitToken(DetailAST ast) {
1995 if (ast.findFirstToken(TokenTypes.MODIFIERS).findFirstToken(
1996 TokenTypes.BLOCK_COMMENT_BEGIN) == null) {
1997 log(ast, "Incorrect AST structure.");
1998 }
1999 final int childCount = ast.getChildCount();
2000 if (childCount != METHOD_DEF_CHILD_COUNT) {
2001 final String msg = String.format(Locale.ENGLISH,
2002 "AST node in comment tree has wrong number of children. "
2003 + "Expected is %d but was %d",
2004 METHOD_DEF_CHILD_COUNT, childCount);
2005 log(ast, msg);
2006 }
2007
2008 int actualChildCount = 0;
2009 for (DetailAST child = ast.getFirstChild().getFirstChild(); child != null; child =
2010 child.getNextSibling()) {
2011 actualChildCount++;
2012 }
2013 final int cacheChildCount = ast.getFirstChild().getChildCount();
2014 if (cacheChildCount != actualChildCount) {
2015 final String msg = String.format(Locale.ENGLISH,
2016 "AST node with comment has wrong number of children. "
2017 + "Expected is %d but was %d",
2018 cacheChildCount, actualChildCount);
2019 log(ast, msg);
2020 }
2021 }
2022
2023 }
2024
2025 public static final class DummyFileSet extends AbstractFileSetCheck {
2026
2027 private final List<String> methodCalls = new ArrayList<>();
2028
2029 private boolean initCalled;
2030
2031 @Override
2032 public void init() {
2033 super.init();
2034 initCalled = true;
2035 }
2036
2037 @Override
2038 public void beginProcessing(String charset) {
2039 methodCalls.add("beginProcessing");
2040 super.beginProcessing(charset);
2041 }
2042
2043 @Override
2044 public void finishProcessing() {
2045 methodCalls.add("finishProcessing");
2046 super.finishProcessing();
2047 }
2048
2049 @Override
2050 protected void processFiltered(File file, FileText fileText) {
2051 methodCalls.add("processFiltered");
2052 }
2053
2054 @Override
2055 public void destroy() {
2056 methodCalls.add("destroy");
2057 super.destroy();
2058 }
2059
2060 public List<String> getMethodCalls() {
2061 return Collections.unmodifiableList(methodCalls);
2062 }
2063
2064 public boolean isInitCalled() {
2065 return initCalled;
2066 }
2067
2068 public MessageDispatcher getInternalMessageDispatcher() {
2069 return getMessageDispatcher();
2070 }
2071
2072 }
2073
2074 }