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