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