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