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.ant;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
24 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
25
26 import java.io.File;
27 import java.io.IOException;
28 import java.net.URL;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.Locale;
34 import java.util.Map;
35 import java.util.Optional;
36 import java.util.ResourceBundle;
37 import java.util.regex.Matcher;
38 import java.util.regex.Pattern;
39
40 import org.apache.tools.ant.BuildException;
41 import org.apache.tools.ant.Location;
42 import org.apache.tools.ant.Project;
43 import org.apache.tools.ant.types.FileSet;
44 import org.apache.tools.ant.types.Path;
45 import org.apache.tools.ant.types.resources.FileResource;
46 import org.junit.jupiter.api.Test;
47 import org.junit.jupiter.api.io.TempDir;
48
49 import com.google.common.base.Splitter;
50 import com.google.common.collect.Iterables;
51 import com.google.common.truth.StandardSubjectBuilder;
52 import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
53 import com.puppycrawl.tools.checkstyle.DefaultLogger;
54 import com.puppycrawl.tools.checkstyle.Definitions;
55 import com.puppycrawl.tools.checkstyle.SarifLogger;
56 import com.puppycrawl.tools.checkstyle.XMLLogger;
57 import com.puppycrawl.tools.checkstyle.internal.testmodules.CheckstyleAntTaskLogStub;
58 import com.puppycrawl.tools.checkstyle.internal.testmodules.CheckstyleAntTaskStub;
59 import com.puppycrawl.tools.checkstyle.internal.testmodules.MessageLevelPair;
60 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestRootModuleChecker;
61
62 public class CheckstyleAntTaskTest extends AbstractPathTestSupport {
63
64 private static final String FLAWLESS_INPUT =
65 "InputCheckstyleAntTaskFlawless.java";
66 private static final String VIOLATED_INPUT =
67 "InputCheckstyleAntTaskError.java";
68 private static final String WARNING_INPUT =
69 "InputCheckstyleAntTaskWarning.java";
70 private static final String CONFIG_FILE =
71 "InputCheckstyleAntTaskTestChecks.xml";
72 private static final String CUSTOM_ROOT_CONFIG_FILE =
73 "InputCheckstyleAntTaskConfigCustomRootModule.xml";
74 private static final String NOT_EXISTING_FILE = "target/not_existing.xml";
75 private static final String FAILURE_PROPERTY_VALUE = "myValue";
76
77 @TempDir
78 public File temporaryFolder;
79
80 @Override
81 protected String getPackageLocation() {
82 return "com/puppycrawl/tools/checkstyle/ant/checkstyleanttask/";
83 }
84
85 private CheckstyleAntTask getCheckstyleAntTask() throws IOException {
86 return getCheckstyleAntTask(CONFIG_FILE);
87 }
88
89 private CheckstyleAntTask getCheckstyleAntTask(String configFile) throws IOException {
90 final CheckstyleAntTask antTask = new CheckstyleAntTask();
91 antTask.setConfig(getPath(configFile));
92 antTask.setProject(new Project());
93 return antTask;
94 }
95
96 @Test
97 public final void testDefaultFlawless() throws IOException {
98 TestRootModuleChecker.reset();
99 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
100 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
101 antTask.execute();
102
103 assertWithMessage("Checker is not processed")
104 .that(TestRootModuleChecker.isProcessed())
105 .isTrue();
106 }
107
108 @Test
109 public final void testPathsOneFile() throws IOException {
110
111 TestRootModuleChecker.reset();
112
113 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
114 final FileSet examinationFileSet = new FileSet();
115 examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
116 final Path sourcePath = new Path(antTask.getProject());
117 sourcePath.addFileset(examinationFileSet);
118 antTask.addPath(sourcePath);
119
120
121 antTask.execute();
122
123
124 assertWithMessage("Checker is not processed")
125 .that(TestRootModuleChecker.isProcessed())
126 .isTrue();
127 final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
128 assertWithMessage("There are more files to check than expected")
129 .that(filesToCheck)
130 .hasSize(1);
131 assertWithMessage("The path of file differs from expected")
132 .that(filesToCheck.get(0).getAbsolutePath())
133 .isEqualTo(getPath(FLAWLESS_INPUT));
134 }
135
136 @Test
137 public final void testPathsFileWithLogVerification() throws IOException {
138
139 TestRootModuleChecker.reset();
140 final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
141 antTask.setConfig(getPath(CUSTOM_ROOT_CONFIG_FILE));
142 antTask.setProject(new Project());
143 final FileSet examinationFileSet = new FileSet();
144 examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
145 final Path sourcePath = new Path(antTask.getProject());
146 sourcePath.addFileset(examinationFileSet);
147 antTask.addPath(sourcePath);
148 antTask.addPath(new Path(new Project()));
149
150
151 antTask.execute();
152
153
154 final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
155
156 assertWithMessage("Scanning path was not logged")
157 .that(loggedMessages.stream().filter(
158 msg -> msg.getMsg().startsWith("1) Scanning path")).count())
159 .isEqualTo(1);
160
161 assertWithMessage("Scanning path was not logged")
162 .that(loggedMessages.stream().filter(
163 msg -> msg.getMsg().startsWith("1) Adding 1 files from path")).count())
164 .isEqualTo(1);
165
166 assertWithMessage("Scanning empty was logged")
167 .that(loggedMessages.stream().filter(
168 msg -> msg.getMsg().startsWith("2) Adding 0 files from path ")).count())
169 .isEqualTo(0);
170
171 assertWithMessage("Checker is not processed")
172 .that(TestRootModuleChecker.isProcessed())
173 .isTrue();
174 final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
175 assertWithMessage("There are more files to check than expected")
176 .that(filesToCheck)
177 .hasSize(1);
178 assertWithMessage("The path of file differs from expected")
179 .that(filesToCheck.get(0).getAbsolutePath())
180 .isEqualTo(getPath(FLAWLESS_INPUT));
181 }
182
183 @Test
184 public final void testBaseDirPresence() throws IOException {
185 TestRootModuleChecker.reset();
186
187 final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
188 antTask.setConfig(getPath(CUSTOM_ROOT_CONFIG_FILE));
189
190 final Project project = new Project();
191 project.setBaseDir(new File("."));
192 antTask.setProject(new Project());
193
194 final FileSet fileSet = new FileSet();
195 fileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
196 antTask.addFileset(fileSet);
197
198 antTask.scanFileSets();
199
200 final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
201
202 final String expectedPath = new File(getPath(".")).getAbsolutePath();
203 final boolean containsBaseDir = loggedMessages.stream()
204 .anyMatch(msg -> msg.getMsg().contains(expectedPath));
205
206 assertWithMessage("Base directory should be present in logs.")
207 .that(containsBaseDir)
208 .isTrue();
209 }
210
211 @Test
212 public final void testPathsDirectoryWithNestedFile() throws IOException {
213
214 TestRootModuleChecker.reset();
215
216 final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
217 antTask.setConfig(getPath(CUSTOM_ROOT_CONFIG_FILE));
218 antTask.setProject(new Project());
219
220 final FileResource fileResource = new FileResource(
221 antTask.getProject(), getPath(""));
222 final Path sourcePath = new Path(antTask.getProject());
223 sourcePath.add(fileResource);
224 antTask.addPath(sourcePath);
225
226
227 antTask.execute();
228
229
230 assertWithMessage("Checker is not processed")
231 .that(TestRootModuleChecker.isProcessed())
232 .isTrue();
233 final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
234 assertWithMessage("There are more files to check than expected")
235 .that(filesToCheck)
236 .hasSize(9);
237 assertWithMessage("The path of file differs from expected")
238 .that(filesToCheck.get(6).getAbsolutePath())
239 .isEqualTo(getPath(FLAWLESS_INPUT));
240 assertWithMessage("Amount of logged messages in unexpected")
241 .that(antTask.getLoggedMessages())
242 .hasSize(8);
243 }
244
245 @Test
246 public final void testCustomRootModule() throws IOException {
247 TestRootModuleChecker.reset();
248
249 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
250 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
251 antTask.execute();
252
253 assertWithMessage("Checker is not processed")
254 .that(TestRootModuleChecker.isProcessed())
255 .isTrue();
256 }
257
258 @Test
259 public final void testFileSet() throws IOException {
260 TestRootModuleChecker.reset();
261 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
262 final FileSet examinationFileSet = new FileSet();
263 examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
264 antTask.addFileset(examinationFileSet);
265 antTask.execute();
266
267 assertWithMessage("Checker is not processed")
268 .that(TestRootModuleChecker.isProcessed())
269 .isTrue();
270 final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
271 assertWithMessage("There are more files to check than expected")
272 .that(filesToCheck)
273 .hasSize(1);
274 assertWithMessage("The path of file differs from expected")
275 .that(filesToCheck.get(0).getAbsolutePath())
276 .isEqualTo(getPath(FLAWLESS_INPUT));
277 }
278
279 @Test
280 public final void testNoConfigFile() throws IOException {
281 final CheckstyleAntTask antTask = new CheckstyleAntTask();
282 antTask.setProject(new Project());
283 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
284 final Location fileLocation = new Location("build.xml", 42, 10);
285 antTask.setLocation(fileLocation);
286
287 final BuildException ex = getExpectedThrowable(BuildException.class,
288 antTask::execute,
289 "BuildException is expected");
290 assertWithMessage("Error message is unexpected")
291 .that(ex.getMessage())
292 .isEqualTo("Must specify 'config'.");
293 assertWithMessage("Location is missing in exception")
294 .that(ex.getLocation())
295 .isEqualTo(fileLocation);
296 }
297
298 @Test
299 public void testNoFileOrPathSpecified() {
300 final CheckstyleAntTask antTask = new CheckstyleAntTask();
301 antTask.setProject(new Project());
302
303 final Location fileLocation = new Location("build.xml", 42, 10);
304 antTask.setLocation(fileLocation);
305
306 final BuildException ex = getExpectedThrowable(BuildException.class,
307 antTask::execute,
308 "BuildException is expected");
309
310 assertWithMessage("Error message is unexpected")
311 .that(ex.getMessage())
312 .isEqualTo("Must specify at least one of 'file' or nested 'fileset' or 'path'.");
313 assertWithMessage("Location is missing in the exception")
314 .that(ex.getLocation())
315 .isEqualTo(fileLocation);
316 }
317
318 @Test
319 public final void testNonExistentConfig() throws IOException {
320 final CheckstyleAntTask antTask = new CheckstyleAntTask();
321 antTask.setConfig(getPath(NOT_EXISTING_FILE));
322 antTask.setProject(new Project());
323 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
324 final BuildException ex = getExpectedThrowable(BuildException.class,
325 antTask::execute,
326 "BuildException is expected");
327
328 final String expectedExceptionFormat = String.format(Locale.ROOT,
329 "Unable to create Root Module: config {%s}.", getPath(NOT_EXISTING_FILE));
330 assertWithMessage("Error message is unexpected")
331 .that(ex.getMessage())
332 .isEqualTo(expectedExceptionFormat);
333 }
334
335 @Test
336 public final void testEmptyConfigFile() throws IOException {
337 final CheckstyleAntTask antTask = new CheckstyleAntTask();
338 antTask.setConfig(getPath("InputCheckstyleAntTaskEmptyConfig.xml"));
339 antTask.setProject(new Project());
340 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
341 final BuildException ex = getExpectedThrowable(BuildException.class,
342 antTask::execute,
343 "BuildException is expected");
344 final String expectedMessage = String.format(Locale.ROOT,
345 "Unable to create Root Module: config {%s}.",
346 getPath("InputCheckstyleAntTaskEmptyConfig.xml"));
347 assertWithMessage("Error message is unexpected")
348 .that(ex.getMessage())
349 .isEqualTo(expectedMessage);
350 }
351
352 @Test
353 public final void testNoFile() throws IOException {
354 final CheckstyleAntTask antTask = getCheckstyleAntTask();
355 final BuildException ex = getExpectedThrowable(BuildException.class,
356 antTask::execute,
357 "BuildException is expected");
358 assertWithMessage("Error message is unexpected")
359 .that(ex.getMessage())
360 .isEqualTo("Must specify at least one of 'file' or nested 'fileset' or 'path'.");
361 }
362
363 @Test
364 public final void testMaxWarningExceeded() throws IOException {
365 final CheckstyleAntTask antTask = getCheckstyleAntTask();
366 antTask.setFile(new File(getPath(WARNING_INPUT)));
367 antTask.setMaxWarnings(0);
368 final Location fileLocation = new Location("build.xml", 42, 10);
369 antTask.setLocation(fileLocation);
370
371 final BuildException ex = getExpectedThrowable(BuildException.class,
372 antTask::execute,
373 "BuildException is expected");
374 assertWithMessage("Error message is unexpected")
375 .that(ex.getMessage())
376 .isEqualTo("Got 0 errors (max allowed: 0) and 1 warnings.");
377 assertWithMessage("Location is missing in exception")
378 .that(ex.getLocation())
379 .isEqualTo(fileLocation);
380 }
381
382 @Test
383 public final void testMaxErrorsExceeded() throws IOException {
384 final CheckstyleAntTask antTask = getCheckstyleAntTask();
385 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
386 antTask.setMaxErrors(1);
387
388 final BuildException ex = getExpectedThrowable(BuildException.class,
389 antTask::execute,
390 "BuildException is expected");
391 assertWithMessage("Failure message should include maxErrors value")
392 .that(ex.getMessage())
393 .contains("max allowed: 1");
394 }
395
396 @Test
397 public final void testMaxErrors() throws IOException {
398 TestRootModuleChecker.reset();
399
400 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
401 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
402 antTask.setMaxErrors(2);
403 antTask.execute();
404
405 assertWithMessage("Checker is not processed")
406 .that(TestRootModuleChecker.isProcessed())
407 .isTrue();
408 }
409
410 @Test
411 public final void testFailureProperty() throws IOException {
412 final CheckstyleAntTask antTask = new CheckstyleAntTask();
413 antTask.setConfig(getPath(CONFIG_FILE));
414 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
415
416 final Project project = new Project();
417 final String failurePropertyName = "myProperty";
418 project.setProperty(failurePropertyName, FAILURE_PROPERTY_VALUE);
419
420 antTask.setProject(project);
421 antTask.setFailureProperty(failurePropertyName);
422 final BuildException ex = getExpectedThrowable(BuildException.class,
423 antTask::execute,
424 "BuildException is expected");
425 assertWithMessage("Error message is unexpected")
426 .that(ex.getMessage())
427 .isEqualTo("Got 2 errors (max allowed: 0) and 0 warnings.");
428 final Map<String, Object> hashtable = project.getProperties();
429 final Object propertyValue = hashtable.get(failurePropertyName);
430 assertWithMessage("Number of errors is unexpected")
431 .that(propertyValue)
432 .isEqualTo("Got 2 errors (max allowed: 0) and 0 warnings.");
433 }
434
435 @Test
436 public final void testOverrideProperty() throws IOException {
437 TestRootModuleChecker.reset();
438
439 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
440 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
441 final CheckstyleAntTask.Property property = new CheckstyleAntTask.Property();
442 property.setKey("lineLength.severity");
443 property.setValue("ignore");
444 antTask.addProperty(property);
445 antTask.execute();
446
447 assertWithMessage("Property key should not be empty")
448 .that(property.getKey())
449 .isNotEmpty();
450 assertWithMessage("Checker is not processed")
451 .that(TestRootModuleChecker.isProcessed())
452 .isTrue();
453 assertWithMessage("Property should be passed to checker with correct value")
454 .that(TestRootModuleChecker.getProperty())
455 .isEqualTo("ignore");
456
457 }
458
459 @Test
460 public final void testExecuteIgnoredModules() throws IOException {
461 final CheckstyleAntTask antTask = getCheckstyleAntTask();
462 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
463 antTask.setFailOnViolation(false);
464 antTask.setExecuteIgnoredModules(true);
465
466 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
467 final File outputFile = new File("target/ant_task_plain_output.txt");
468 formatter.setTofile(outputFile);
469 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
470 formatterType.setValue("plain");
471 formatter.setType(formatterType);
472 formatter.createListener(null);
473
474 antTask.addFormatter(formatter);
475 antTask.execute();
476
477 final ResourceBundle bundle = ResourceBundle.getBundle(
478 Definitions.CHECKSTYLE_BUNDLE, Locale.ROOT);
479 final String auditStartedMessage = bundle.getString(DefaultLogger.AUDIT_STARTED_MESSAGE);
480 final String auditFinishedMessage = bundle.getString(DefaultLogger.AUDIT_FINISHED_MESSAGE);
481 final List<String> output = readWholeFile(outputFile);
482 final String errorMessage = "Content of file with violations differs from expected";
483 assertWithMessage(errorMessage)
484 .that(output.get(0))
485 .isEqualTo(auditStartedMessage);
486 assertWithMessage(errorMessage)
487 .that(output.get(1))
488 .matches("^\\[WARN].*InputCheckstyleAntTaskError.java:4: .*"
489 + "@incomplete=Some javadoc \\[WriteTag]");
490 assertWithMessage(errorMessage)
491 .that(output.get(2))
492 .matches("^\\[ERROR].*InputCheckstyleAntTaskError.java:7: "
493 + "Line is longer than 70 characters \\(found 80\\). \\[LineLength]");
494 assertWithMessage(errorMessage)
495 .that(output.get(3))
496 .matches("^\\[ERROR].*InputCheckstyleAntTaskError.java:9: "
497 + "Line is longer than 70 characters \\(found 81\\). \\[LineLength]");
498 assertWithMessage(errorMessage)
499 .that(output.get(4))
500 .isEqualTo(auditFinishedMessage);
501 }
502
503 @Test
504 public final void testConfigurationByUrl() throws IOException {
505 final CheckstyleAntTask antTask = new CheckstyleAntTask();
506 antTask.setProject(new Project());
507 final URL url = new File(getPath(CONFIG_FILE)).toURI().toURL();
508 antTask.setConfig(url.toString());
509 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
510
511 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
512 final File outputFile = new File("target/ant_task_config_by_url.txt");
513 formatter.setTofile(outputFile);
514 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
515 formatterType.setValue("plain");
516 formatter.setType(formatterType);
517 formatter.createListener(null);
518 antTask.addFormatter(formatter);
519
520 antTask.execute();
521
522 final List<String> output = readWholeFile(outputFile);
523 final int sizeOfOutputWithNoViolations = 2;
524 assertWithMessage("No violations expected")
525 .that(output)
526 .hasSize(sizeOfOutputWithNoViolations);
527 }
528
529 @Test
530 public final void testConfigurationByResource() throws IOException {
531 final CheckstyleAntTask antTask = new CheckstyleAntTask();
532 antTask.setProject(new Project());
533 antTask.setConfig(getPath(CONFIG_FILE));
534 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
535
536 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
537 final File outputFile = new File("target/ant_task_config_by_url.txt");
538 formatter.setTofile(outputFile);
539 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
540 formatterType.setValue("plain");
541 formatter.setType(formatterType);
542 formatter.createListener(null);
543 antTask.addFormatter(formatter);
544
545 antTask.execute();
546
547 final List<String> output = readWholeFile(outputFile);
548 final int sizeOfOutputWithNoViolations = 2;
549 assertWithMessage("No violations expected")
550 .that(output)
551 .hasSize(sizeOfOutputWithNoViolations);
552 }
553
554 @Test
555 public final void testSimultaneousConfiguration() throws IOException {
556 final File file = new File(getPath(CONFIG_FILE));
557 final URL url = file.toURI().toURL();
558
559 final CheckstyleAntTask antTask = new CheckstyleAntTask();
560 antTask.setConfig(url.toString());
561 final BuildException ex = getExpectedThrowable(BuildException.class,
562 () -> antTask.setConfig("Any string value"),
563 "BuildException is expected");
564 final String expected = "Attribute 'config' has already been set";
565 assertWithMessage("Error message is unexpected")
566 .that(ex.getMessage())
567 .isEqualTo(expected);
568 }
569
570 @Test
571 public final void testSetPropertiesFile() throws IOException {
572 TestRootModuleChecker.reset();
573
574 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
575 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
576 antTask.setProperties(new File(getPath(
577 "InputCheckstyleAntTaskCheckstyleAntTest.properties")));
578 antTask.execute();
579
580 assertWithMessage("Property is not set")
581 .that(TestRootModuleChecker.getProperty())
582 .isEqualTo("ignore");
583 }
584
585 @Test
586 public final void testSetPropertiesNonExistentFile() throws IOException {
587 final CheckstyleAntTask antTask = getCheckstyleAntTask();
588 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
589 antTask.setProperties(new File(getPath(NOT_EXISTING_FILE)));
590 final BuildException ex = getExpectedThrowable(BuildException.class,
591 antTask::execute,
592 "BuildException is expected");
593 assertWithMessage("Error message is unexpected")
594 .that(ex.getMessage())
595 .startsWith("Error loading Properties file");
596 }
597
598 @Test
599 public final void testXmlOutput() throws IOException {
600 final CheckstyleAntTask antTask = getCheckstyleAntTask();
601 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
602 antTask.setFailOnViolation(false);
603 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
604 final File outputFile = new File("target/log.xml");
605 formatter.setTofile(outputFile);
606 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
607 formatterType.setValue("xml");
608 formatter.setType(formatterType);
609 antTask.addFormatter(formatter);
610 antTask.execute();
611
612 final List<String> expected = readWholeFile(
613 new File(getPath("ExpectedCheckstyleAntTaskXmlOutput.xml")));
614 final List<String> actual = readWholeFile(outputFile);
615 for (int i = 0; i < expected.size(); i++) {
616 final String line = expected.get(i);
617 if (!line.startsWith("<checkstyle version") && !line.startsWith("<file")) {
618 assertWithMessage("Content of file with violations differs from expected")
619 .that(actual.get(i))
620 .isEqualTo(line);
621 }
622 }
623 }
624
625 @Test
626 public final void testSarifOutput() throws IOException {
627 final CheckstyleAntTask antTask = getCheckstyleAntTask();
628 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
629 antTask.setFailOnViolation(false);
630 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
631 final File outputFile = new File("target/log.sarif");
632 formatter.setTofile(outputFile);
633 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
634 formatterType.setValue("sarif");
635 formatter.setType(formatterType);
636 antTask.addFormatter(formatter);
637 antTask.execute();
638
639 final List<String> expected = readWholeFile(
640 new File(getPath("ExpectedCheckstyleAntTaskSarifOutput.sarif")));
641 final List<String> actual = readWholeFile(outputFile);
642 for (int lineNumber = 0; lineNumber < expected.size(); lineNumber++) {
643 final String line = expected.get(lineNumber);
644 final StandardSubjectBuilder assertWithMessage =
645 assertWithMessage("Content of file with violations differs from expected");
646 if (line.trim().startsWith("\"uri\"")) {
647 final String expectedPathEnd = Iterables.get(
648 Splitter.on("**").split(line), 1);
649
650 final String actualLine = actual.get(lineNumber).replaceAll("\\\\", "/");
651 assertWithMessage
652 .that(actualLine)
653 .endsWith(expectedPathEnd);
654 }
655 else {
656 assertWithMessage
657 .that(actual.get(lineNumber))
658 .isEqualTo(line);
659 }
660 }
661 }
662
663 @Test
664 public final void testCreateListenerException() throws IOException {
665 final CheckstyleAntTask antTask = getCheckstyleAntTask();
666 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
667 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
668 final File outputFile = new File("target/");
669 formatter.setTofile(outputFile);
670 antTask.addFormatter(formatter);
671 final BuildException ex = getExpectedThrowable(BuildException.class,
672 antTask::execute,
673 "BuildException is expected");
674 assertWithMessage("Error message is unexpected")
675 .that(ex.getMessage())
676 .isEqualTo("Unable to create listeners: formatters "
677 + "{" + List.of(formatter) + "}.");
678 }
679
680 @Test
681 public final void testCreateListenerExceptionWithXmlLogger() throws IOException {
682 final CheckstyleAntTask antTask = getCheckstyleAntTask();
683 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
684 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
685 final File outputFile = new File("target/");
686 formatter.setTofile(outputFile);
687 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
688 formatterType.setValue("xml");
689 formatter.setType(formatterType);
690 antTask.addFormatter(formatter);
691 final BuildException ex = getExpectedThrowable(BuildException.class,
692 antTask::execute,
693 "BuildException is expected");
694 assertWithMessage("Error message is unexpected")
695 .that(ex.getMessage())
696 .startsWith("Unable to create listeners: formatters");
697 }
698
699 @Test
700 public final void testCreateListenerExceptionWithSarifLogger() throws IOException {
701 final CheckstyleAntTask antTask = getCheckstyleAntTask();
702 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
703 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
704 final File outputFile = new File("target/");
705 formatter.setTofile(outputFile);
706 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
707 formatterType.setValue("sarif");
708 formatter.setType(formatterType);
709 antTask.addFormatter(formatter);
710 final BuildException ex = getExpectedThrowable(BuildException.class,
711 antTask::execute,
712 "BuildException is expected");
713 assertWithMessage("Error message is unexpected")
714 .that(ex.getMessage())
715 .startsWith("Unable to create listeners: formatters");
716 }
717
718 @Test
719 public void testSetInvalidType() {
720 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
721 final BuildException ex = getExpectedThrowable(BuildException.class,
722 () -> formatterType.setValue("foo"),
723 "BuildException is expected");
724 assertWithMessage("Error message is unexpected")
725 .that(ex.getMessage())
726 .isEqualTo("foo is not a legal value for this attribute");
727 }
728
729 @Test
730 public void testSetFileValueByFile() throws IOException {
731 final String filename = getPath("InputCheckstyleAntTaskCheckstyleAntTest.properties");
732 final CheckstyleAntTask.Property property = new CheckstyleAntTask.Property();
733 property.setFile(new File(filename));
734 assertWithMessage("File path is unexpected")
735 .that(new File(filename).getAbsolutePath())
736 .isEqualTo(property.getValue());
737 }
738
739 @Test
740 public void testDefaultLoggerListener() throws IOException {
741 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
742 formatter.setUseFile(false);
743 assertWithMessage("Listener instance has unexpected type")
744 .that(formatter.createListener(null))
745 .isInstanceOf(DefaultLogger.class);
746 }
747
748 @Test
749 public void testDefaultLoggerListenerWithToFile() throws IOException {
750 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
751 formatter.setUseFile(false);
752 formatter.setTofile(new File("target/"));
753 assertWithMessage("Listener instance has unexpected type")
754 .that(formatter.createListener(null))
755 .isInstanceOf(DefaultLogger.class);
756 }
757
758 @Test
759 public void testXmlLoggerListener() throws IOException {
760 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
761 formatterType.setValue("xml");
762 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
763 formatter.setType(formatterType);
764 formatter.setUseFile(false);
765 assertWithMessage("Listener instance has unexpected type")
766 .that(formatter.createListener(null))
767 .isInstanceOf(XMLLogger.class);
768 }
769
770 @Test
771 public void testXmlLoggerListenerWithToFile() throws IOException {
772 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
773 formatterType.setValue("xml");
774 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
775 formatter.setType(formatterType);
776 formatter.setUseFile(false);
777 formatter.setTofile(new File("target/"));
778 assertWithMessage("Listener instance has unexpected type")
779 .that(formatter.createListener(null))
780 .isInstanceOf(XMLLogger.class);
781 }
782
783 @Test
784 public void testDefaultLoggerWithNullToFile() throws IOException {
785 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
786 formatter.setTofile(null);
787 assertWithMessage("Listener instance has unexpected type")
788 .that(formatter.createListener(null))
789 .isInstanceOf(DefaultLogger.class);
790 }
791
792 @Test
793 public void testXmlLoggerWithNullToFile() throws IOException {
794 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
795 formatterType.setValue("xml");
796 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
797 formatter.setType(formatterType);
798 formatter.setTofile(null);
799 assertWithMessage("Listener instance has unexpected type")
800 .that(formatter.createListener(null))
801 .isInstanceOf(XMLLogger.class);
802 }
803
804 @Test
805 public void testSarifLoggerListener() throws IOException {
806 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
807 formatterType.setValue("sarif");
808 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
809 formatter.setType(formatterType);
810 formatter.setUseFile(false);
811 assertWithMessage("Listener instance has unexpected type")
812 .that(formatter.createListener(null))
813 .isInstanceOf(SarifLogger.class);
814 }
815
816 @Test
817 public void testSarifLoggerListenerWithToFile() throws IOException {
818 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
819 formatterType.setValue("sarif");
820 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
821 formatter.setType(formatterType);
822 formatter.setUseFile(false);
823 formatter.setTofile(new File("target/"));
824 assertWithMessage("Listener instance has unexpected type")
825 .that(formatter.createListener(null))
826 .isInstanceOf(SarifLogger.class);
827 }
828
829 @Test
830 public void testSarifLoggerWithNullToFile() throws IOException {
831 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
832 formatterType.setValue("sarif");
833 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
834 formatter.setType(formatterType);
835 formatter.setTofile(null);
836 assertWithMessage("Listener instance has unexpected type")
837 .that(formatter.createListener(null))
838 .isInstanceOf(SarifLogger.class);
839 }
840
841
842
843
844 @Test
845 public void testCreateClasspath() {
846 final CheckstyleAntTask antTask = new CheckstyleAntTask();
847 final Project mockProject = new Project();
848 antTask.setProject(mockProject);
849
850 assertWithMessage("Classpath should belong to the expected project")
851 .that(antTask.createClasspath().getProject())
852 .isEqualTo(mockProject);
853
854 assertWithMessage("Invalid classpath")
855 .that(antTask.createClasspath().toString())
856 .isEmpty();
857 }
858
859 @Test
860 public void testDestroyed() throws IOException {
861 TestRootModuleChecker.reset();
862
863 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
864 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
865 antTask.setMaxWarnings(0);
866 antTask.execute();
867
868 assertWithMessage("Checker is not destroyed")
869 .that(TestRootModuleChecker.isDestroyed())
870 .isTrue();
871 }
872
873 @Test
874 public void testMaxWarnings() throws IOException {
875 TestRootModuleChecker.reset();
876
877 final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
878 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
879 antTask.setMaxWarnings(0);
880 antTask.execute();
881
882 assertWithMessage("Checker is not processed")
883 .that(TestRootModuleChecker.isProcessed())
884 .isTrue();
885 }
886
887 @Test
888 public final void testExecuteLogOutput() throws Exception {
889 final URL url = new File(getPath(CONFIG_FILE)).toURI().toURL();
890 final ResourceBundle bundle = ResourceBundle.getBundle(
891 Definitions.CHECKSTYLE_BUNDLE, Locale.ROOT);
892 final String auditStartedMessage = bundle.getString(DefaultLogger.AUDIT_STARTED_MESSAGE);
893 final String auditFinishedMessage = bundle.getString(DefaultLogger.AUDIT_FINISHED_MESSAGE);
894
895 final List<MessageLevelPair> expectedList = Arrays.asList(
896 new MessageLevelPair("checkstyle version .*", Project.MSG_VERBOSE),
897 new MessageLevelPair("Adding standalone file for audit", Project.MSG_VERBOSE),
898 new MessageLevelPair("To locate the files took \\d+ ms.", Project.MSG_VERBOSE),
899 new MessageLevelPair("Running Checkstyle on 1 files", Project.MSG_INFO),
900 new MessageLevelPair("Using configuration file:.*", Project.MSG_VERBOSE),
901 new MessageLevelPair(auditStartedMessage, Project.MSG_DEBUG),
902 new MessageLevelPair(auditFinishedMessage, Project.MSG_DEBUG),
903 new MessageLevelPair("To process the files took \\d+ ms.", Project.MSG_VERBOSE),
904 new MessageLevelPair("Total execution took \\d+ ms.", Project.MSG_VERBOSE)
905 );
906
907 final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
908 antTask.setProject(new Project());
909 antTask.setConfig(url.toString());
910 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
911
912 antTask.execute();
913
914 final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
915
916 assertWithMessage("Amount of log messages is unexpected")
917 .that(loggedMessages)
918 .hasSize(expectedList.size());
919
920 for (int i = 0; i < expectedList.size(); i++) {
921 final MessageLevelPair expected = expectedList.get(i);
922 final MessageLevelPair actual = loggedMessages.get(i);
923 assertWithMessage("Log messages should match")
924 .that(actual.getMsg())
925 .matches(expected.getMsg());
926 assertWithMessage("Log levels should be equal")
927 .that(actual.getLevel())
928 .isEqualTo(expected.getLevel());
929 }
930 }
931
932 @Test
933 public void testCheckerException() throws IOException {
934 final CheckstyleAntTask antTask = new CheckstyleAntTaskStub();
935 antTask.setConfig(getPath(CONFIG_FILE));
936 antTask.setProject(new Project());
937 antTask.setFile(new File(""));
938 final BuildException ex = getExpectedThrowable(BuildException.class,
939 antTask::execute,
940 "BuildException is expected");
941 assertWithMessage("Error message is unexpected")
942 .that(ex)
943 .hasMessageThat()
944 .startsWith("Unable to process files:");
945 }
946
947 @Test
948 public void testLoggedTime() throws IOException {
949 final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
950 antTask.setConfig(getPath(CONFIG_FILE));
951 antTask.setProject(new Project());
952 antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
953 final long startTime = System.currentTimeMillis();
954 antTask.execute();
955 final long endTime = System.currentTimeMillis();
956 final long testingTime = endTime - startTime;
957 final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
958
959 assertLoggedTime(loggedMessages, testingTime, "Total execution");
960 assertLoggedTime(loggedMessages, testingTime, "To locate the files");
961 assertLoggedTime(loggedMessages, testingTime, "To process the files");
962 }
963
964 private static void assertLoggedTime(List<MessageLevelPair> loggedMessages,
965 long testingTime, String expectedMsg) {
966
967 final Optional<MessageLevelPair> optionalMessageLevelPair = loggedMessages.stream()
968 .filter(msg -> msg.getMsg().startsWith(expectedMsg))
969 .findFirst();
970
971 assertWithMessage("Message should be present.")
972 .that(optionalMessageLevelPair.isPresent())
973 .isTrue();
974
975 final long actualTime = getNumberFromLine(optionalMessageLevelPair.orElseThrow().getMsg());
976
977 assertWithMessage("Logged time in '" + expectedMsg + "' "
978 + "must be less than the testing time")
979 .that(actualTime)
980 .isAtMost(testingTime);
981 }
982
983 private static List<String> readWholeFile(File outputFile) throws IOException {
984 return Files.readAllLines(outputFile.toPath(), StandardCharsets.UTF_8);
985 }
986
987 private static long getNumberFromLine(String line) {
988 final Matcher matcher = Pattern.compile("(\\d+)").matcher(line);
989 matcher.find();
990 return Long.parseLong(matcher.group(1));
991 }
992
993 @Test
994 public void testMaxWarningDefault() throws IOException {
995 final CheckstyleAntTask antTask = getCheckstyleAntTask();
996 final File inputFile = new File(getPath(WARNING_INPUT));
997 final Location fileLocation = new Location("build.xml", 42, 10);
998
999 antTask.setFile(inputFile);
1000 antTask.setLocation(fileLocation);
1001 assertDoesNotThrow(antTask::execute, "BuildException is not expected");
1002 }
1003
1004 @Test
1005 public void testMultipleFormattersProduceOutputs() throws IOException {
1006 final CheckstyleAntTask antTask = getCheckstyleAntTask();
1007 antTask.setFile(new File(getPath(VIOLATED_INPUT)));
1008 antTask.setFailOnViolation(false);
1009
1010 final File firstOutput = new File(temporaryFolder, "ant_task_multi_formatter_1.txt");
1011 final File secondOutput = new File(temporaryFolder, "ant_task_multi_formatter_2.txt");
1012
1013 antTask.addFormatter(createPlainFormatter(firstOutput));
1014 antTask.addFormatter(createPlainFormatter(secondOutput));
1015
1016 antTask.execute();
1017
1018 assertWithMessage("First formatter output was not created")
1019 .that(firstOutput.exists())
1020 .isTrue();
1021 assertWithMessage("First formatter output is empty")
1022 .that(firstOutput.length())
1023 .isGreaterThan(0L);
1024 assertWithMessage("Second formatter output was not created")
1025 .that(secondOutput.exists())
1026 .isTrue();
1027 assertWithMessage("Second formatter output is empty")
1028 .that(secondOutput.length())
1029 .isGreaterThan(0L);
1030 }
1031
1032 private static CheckstyleAntTask.Formatter createPlainFormatter(File outputFile) {
1033 final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
1034 formatter.setTofile(outputFile);
1035 final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
1036 formatterType.setValue("plain");
1037 formatter.setType(formatterType);
1038 return formatter;
1039 }
1040
1041 }