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