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