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