View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2017 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.ant;
21  
22  import static org.hamcrest.CoreMatchers.is;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertNotNull;
25  import static org.junit.Assert.assertThat;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  import static org.mockito.Matchers.any;
29  import static org.mockito.Mockito.times;
30  import static org.mockito.Mockito.when;
31  import static org.powermock.api.mockito.PowerMockito.doNothing;
32  import static org.powermock.api.mockito.PowerMockito.mockStatic;
33  import static org.powermock.api.mockito.PowerMockito.verifyStatic;
34  
35  import java.io.File;
36  import java.io.IOException;
37  import java.io.InputStream;
38  import java.net.URL;
39  import java.nio.charset.StandardCharsets;
40  import java.util.ArrayList;
41  import java.util.Arrays;
42  import java.util.Collections;
43  import java.util.List;
44  import java.util.Map;
45  
46  import org.apache.commons.io.FileUtils;
47  import org.apache.tools.ant.AntClassLoader;
48  import org.apache.tools.ant.BuildException;
49  import org.apache.tools.ant.Project;
50  import org.apache.tools.ant.types.FileSet;
51  import org.apache.tools.ant.types.Path;
52  import org.apache.tools.ant.types.Reference;
53  import org.apache.tools.ant.types.resources.FileResource;
54  import org.junit.Test;
55  import org.junit.runner.RunWith;
56  import org.mockito.internal.util.reflection.Whitebox;
57  import org.powermock.api.mockito.PowerMockito;
58  import org.powermock.core.classloader.annotations.PrepareForTest;
59  import org.powermock.modules.junit4.PowerMockRunner;
60  
61  import com.google.common.io.Closeables;
62  import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
63  import com.puppycrawl.tools.checkstyle.DefaultLogger;
64  import com.puppycrawl.tools.checkstyle.Definitions;
65  import com.puppycrawl.tools.checkstyle.XMLLogger;
66  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
67  import com.puppycrawl.tools.checkstyle.internal.testmodules.CheckerStub;
68  import com.puppycrawl.tools.checkstyle.internal.testmodules.TestRootModuleChecker;
69  
70  @RunWith(PowerMockRunner.class)
71  @PrepareForTest({CheckstyleAntTask.class, Closeables.class})
72  public class CheckstyleAntTaskTest extends AbstractPathTestSupport {
73  
74      private static final String FLAWLESS_INPUT =
75              "InputCheckstyleAntTaskFlawless.java";
76      private static final String VIOLATED_INPUT =
77              "InputCheckstyleAntTaskError.java";
78      private static final String WARNING_INPUT =
79              "InputCheckstyleAntTaskWarning.java";
80      private static final String CONFIG_FILE =
81              "InputCheckstyleAntTaskTestChecks.xml";
82      private static final String CUSTOM_ROOT_CONFIG_FILE =
83              "InputCheckstyleAntTaskConfigCustomRootModule.xml";
84      private static final String NOT_EXISTING_FILE = "target/not_existing.xml";
85      private static final String FAILURE_PROPERTY_VALUE = "myValue";
86  
87      @Override
88      protected String getPackageLocation() {
89          return "com/puppycrawl/tools/checkstyle/ant/checkstyleanttask/";
90      }
91  
92      private CheckstyleAntTask getCheckstyleAntTask() throws IOException {
93          return getCheckstyleAntTask(CONFIG_FILE);
94      }
95  
96      private CheckstyleAntTask getCheckstyleAntTask(String configFile) throws IOException {
97          final CheckstyleAntTask antTask = new CheckstyleAntTask();
98          antTask.setConfig(getPath(configFile));
99          antTask.setProject(new Project());
100         return antTask;
101     }
102 
103     @Test
104     public final void testDefaultFlawless() throws IOException {
105         TestRootModuleChecker.reset();
106         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
107         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
108         antTask.execute();
109 
110         assertTrue("Checker is not processed",
111             TestRootModuleChecker.isProcessed());
112     }
113 
114     @Test
115     public final void testPathsOneFile() throws IOException {
116         // given
117         TestRootModuleChecker.reset();
118 
119         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
120         final FileSet examinationFileSet = new FileSet();
121         examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
122         final Path sourcePath = new Path(antTask.getProject());
123         sourcePath.addFileset(examinationFileSet);
124         antTask.addPath(sourcePath);
125 
126         // when
127         antTask.execute();
128 
129         // then
130         assertTrue("Checker is not processed",
131                 TestRootModuleChecker.isProcessed());
132         final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
133         assertThat("There more files to check then expected",
134                 filesToCheck.size(), is(1));
135         assertThat("The path of file differs from expected",
136                 filesToCheck.get(0).getAbsolutePath(), is(getPath(FLAWLESS_INPUT)));
137     }
138 
139     @Test
140     public final void testPathsFileWithLogVerification() throws IOException {
141         // given
142         TestRootModuleChecker.reset();
143         final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
144         antTask.setConfig(getPath(CUSTOM_ROOT_CONFIG_FILE));
145         antTask.setProject(new Project());
146         final FileSet examinationFileSet = new FileSet();
147         examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
148         final Path sourcePath = new Path(antTask.getProject());
149         sourcePath.addFileset(examinationFileSet);
150         antTask.addPath(sourcePath);
151         antTask.addPath(new Path(new Project()));
152 
153         // when
154         antTask.execute();
155 
156         // then
157         final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
158 
159         assertEquals("Scanning path was not logged", 1, loggedMessages.stream().filter(
160             msg -> msg.getMsg().startsWith("1) Scanning path")).count());
161 
162         assertEquals("Scanning path was not logged", 1, loggedMessages.stream().filter(
163             msg -> msg.getMsg().startsWith("1) Adding 1 files from path")).count());
164 
165         assertEquals("Scanning empty was logged", 0, loggedMessages.stream().filter(
166             msg -> msg.getMsg().startsWith("2) Adding 0 files from path ")).count());
167 
168         assertTrue("Checker is not processed",
169                 TestRootModuleChecker.isProcessed());
170         final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
171         assertThat("There more files to check then expected",
172                 filesToCheck.size(), is(1));
173         assertThat("The path of file differs from expected",
174                 filesToCheck.get(0).getAbsolutePath(), is(getPath(FLAWLESS_INPUT)));
175     }
176 
177     @Test
178     public final void testPathsDirectoryWithNestedFile() throws IOException {
179         // given
180         TestRootModuleChecker.reset();
181 
182         final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
183         antTask.setConfig(getPath(CUSTOM_ROOT_CONFIG_FILE));
184         antTask.setProject(new Project());
185 
186         final FileResource fileResource = new FileResource(
187             antTask.getProject(), getPath(""));
188         final Path sourcePath = new Path(antTask.getProject());
189         sourcePath.add(fileResource);
190         antTask.addPath(sourcePath);
191 
192         // when
193         antTask.execute();
194 
195         // then
196         assertTrue("Checker is not processed",
197                 TestRootModuleChecker.isProcessed());
198         final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
199         assertThat("There more files to check then expected",
200                 filesToCheck.size(), is(9));
201         assertThat("The path of file differs from expected",
202                 filesToCheck.get(5).getAbsolutePath(), is(getPath(FLAWLESS_INPUT)));
203         assertEquals("Amount of logged messages in unexpected",
204                 9, antTask.getLoggedMessages().size());
205     }
206 
207     @Test
208     public final void testCustomRootModule() throws IOException {
209         TestRootModuleChecker.reset();
210 
211         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
212         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
213         antTask.execute();
214 
215         assertTrue("Checker is not processed",
216                 TestRootModuleChecker.isProcessed());
217     }
218 
219     @Test
220     public final void testFileSet() throws IOException {
221         TestRootModuleChecker.reset();
222         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
223         final FileSet examinationFileSet = new FileSet();
224         examinationFileSet.setFile(new File(getPath(FLAWLESS_INPUT)));
225         antTask.addFileset(examinationFileSet);
226         antTask.execute();
227 
228         assertTrue("Checker is not processed",
229             TestRootModuleChecker.isProcessed());
230         final List<File> filesToCheck = TestRootModuleChecker.getFilesToCheck();
231         assertThat("There more files to check then expected",
232             filesToCheck.size(), is(1));
233         assertThat("The path of file differs from expected",
234             filesToCheck.get(0).getAbsolutePath(), is(getPath(FLAWLESS_INPUT)));
235     }
236 
237     @Test
238     public final void testNoConfigFile() throws IOException {
239         final CheckstyleAntTask antTask = new CheckstyleAntTask();
240         antTask.setProject(new Project());
241         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
242         try {
243             antTask.execute();
244             fail("Exception is expected");
245         }
246         catch (BuildException ex) {
247             assertEquals("Error message is unexpected",
248                     "Must specify 'config'.", ex.getMessage());
249         }
250     }
251 
252     @Test
253     public final void testNonExistentConfig() throws IOException {
254         final CheckstyleAntTask antTask = new CheckstyleAntTask();
255         antTask.setConfig(getPath(NOT_EXISTING_FILE));
256         antTask.setProject(new Project());
257         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
258         try {
259             antTask.execute();
260             fail("Exception is expected");
261         }
262         catch (BuildException ex) {
263             assertTrue("Error message is unexpected",
264                     ex.getMessage().startsWith("Unable to create Root Module: config"));
265         }
266     }
267 
268     @Test
269     public final void testEmptyConfigFile() throws IOException {
270         final CheckstyleAntTask antTask = new CheckstyleAntTask();
271         antTask.setConfig(getPath("InputCheckstyleAntTaskEmptyConfig.xml"));
272         antTask.setProject(new Project());
273         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
274         try {
275             antTask.execute();
276             fail("Exception is expected");
277         }
278         catch (BuildException ex) {
279             assertTrue("Error message is unexpected",
280                     ex.getMessage().startsWith("Unable to create Root Module: config"));
281         }
282     }
283 
284     @Test
285     public final void testNoFile() throws IOException {
286         final CheckstyleAntTask antTask = getCheckstyleAntTask();
287         try {
288             antTask.execute();
289             fail("Exception is expected");
290         }
291         catch (BuildException ex) {
292             assertEquals("Error message is unexpected",
293                     "Must specify at least one of 'file' or nested 'fileset' or 'path'.",
294                 ex.getMessage());
295         }
296     }
297 
298     @Test
299     public final void testMaxWarningExceeded() throws IOException {
300         final CheckstyleAntTask antTask = getCheckstyleAntTask();
301         antTask.setFile(new File(getPath(WARNING_INPUT)));
302         antTask.setMaxWarnings(0);
303         try {
304             antTask.execute();
305             fail("Exception is expected");
306         }
307         catch (BuildException ex) {
308             assertEquals("Error message is unexpected",
309                     "Got 0 errors and 1 warnings.", ex.getMessage());
310         }
311     }
312 
313     @Test
314     public final void testMaxErrors() throws IOException {
315         TestRootModuleChecker.reset();
316 
317         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
318         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
319         antTask.setMaxErrors(2);
320         antTask.execute();
321 
322         assertTrue("Checker is not processed",
323             TestRootModuleChecker.isProcessed());
324     }
325 
326     @Test
327     public final void testFailureProperty() throws IOException {
328         final CheckstyleAntTask antTask = new CheckstyleAntTask();
329         antTask.setConfig(getPath(CONFIG_FILE));
330         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
331 
332         final Project project = new Project();
333         final String failurePropertyName = "myProperty";
334         project.setProperty(failurePropertyName, FAILURE_PROPERTY_VALUE);
335 
336         antTask.setProject(project);
337         antTask.setFailureProperty(failurePropertyName);
338         try {
339             antTask.execute();
340             fail("Exception is expected");
341         }
342         catch (BuildException ignored) {
343             final Map<String, Object> hashtable = project.getProperties();
344             final Object propertyValue = hashtable.get(failurePropertyName);
345             assertEquals("Number of errors is unexpected",
346                     "Got 2 errors and 0 warnings.", propertyValue);
347         }
348     }
349 
350     @Test
351     public final void testOverrideProperty() throws IOException {
352         TestRootModuleChecker.reset();
353 
354         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
355         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
356         final CheckstyleAntTask.Property property = new CheckstyleAntTask.Property();
357         property.setKey("lineLength.severity");
358         property.setValue("ignore");
359         antTask.addProperty(property);
360         antTask.execute();
361 
362         assertTrue("Checker is not processed",
363             TestRootModuleChecker.isProcessed());
364     }
365 
366     @Test
367     public final void testExecuteIgnoredModules() throws IOException {
368         final CheckstyleAntTask antTask = getCheckstyleAntTask();
369         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
370         antTask.setFailOnViolation(false);
371         antTask.setExecuteIgnoredModules(true);
372 
373         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
374         final File outputFile = new File("target/ant_task_plain_output.txt");
375         formatter.setTofile(outputFile);
376         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
377         formatterType.setValue("plain");
378         formatter.setType(formatterType);
379         formatter.createListener(null);
380 
381         antTask.addFormatter(formatter);
382         antTask.execute();
383 
384         final LocalizedMessage auditStartedMessage = new LocalizedMessage(0,
385                 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditStarted",
386                 null, null,
387                 getClass(), null);
388         final LocalizedMessage auditFinishedMessage = new LocalizedMessage(0,
389                 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditFinished",
390                 null, null,
391                 getClass(), null);
392 
393         final List<String> output = FileUtils.readLines(outputFile, StandardCharsets.UTF_8);
394         final String errorMessage = "Content of file with violations differs from expected";
395         assertEquals(errorMessage, auditStartedMessage.getMessage(), output.get(0));
396         assertTrue(errorMessage, output.get(1).startsWith("[WARN]"));
397         assertTrue(errorMessage, output.get(1).endsWith("InputCheckstyleAntTaskError.java:4: "
398                 + "@incomplete=Some javadoc [WriteTag]"));
399         assertTrue(errorMessage, output.get(2).startsWith("[ERROR]"));
400         assertTrue(errorMessage, output.get(2).endsWith("InputCheckstyleAntTaskError.java:7: "
401                 + "Line is longer than 70 characters (found 80). [LineLength]"));
402         assertTrue(errorMessage, output.get(3).startsWith("[ERROR]"));
403         assertTrue(errorMessage, output.get(3).endsWith("InputCheckstyleAntTaskError.java:9: "
404                 + "Line is longer than 70 characters (found 81). [LineLength]"));
405         assertEquals(errorMessage, auditFinishedMessage.getMessage(), output.get(4));
406     }
407 
408     @Test
409     public final void testConfigurationByUrl() throws IOException {
410         final CheckstyleAntTask antTask = new CheckstyleAntTask();
411         antTask.setProject(new Project());
412         final URL url = new File(getPath(CONFIG_FILE)).toURI().toURL();
413         antTask.setConfig(url.toString());
414         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
415 
416         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
417         final File outputFile = new File("target/ant_task_config_by_url.txt");
418         formatter.setTofile(outputFile);
419         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
420         formatterType.setValue("plain");
421         formatter.setType(formatterType);
422         formatter.createListener(null);
423         antTask.addFormatter(formatter);
424 
425         antTask.execute();
426 
427         final List<String> output = FileUtils.readLines(outputFile, StandardCharsets.UTF_8);
428         final int sizeOfOutputWithNoViolations = 2;
429         assertEquals("No violations expected", sizeOfOutputWithNoViolations, output.size());
430     }
431 
432     @Test
433     public final void testConfigurationByResource() throws IOException {
434         final CheckstyleAntTask antTask = new CheckstyleAntTask();
435         antTask.setProject(new Project());
436         antTask.setConfig(getPath(CONFIG_FILE));
437         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
438 
439         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
440         final File outputFile = new File("target/ant_task_config_by_url.txt");
441         formatter.setTofile(outputFile);
442         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
443         formatterType.setValue("plain");
444         formatter.setType(formatterType);
445         formatter.createListener(null);
446         antTask.addFormatter(formatter);
447 
448         antTask.execute();
449 
450         final List<String> output = FileUtils.readLines(outputFile, StandardCharsets.UTF_8);
451         final int sizeOfOutputWithNoViolations = 2;
452         assertEquals("No violations expected", sizeOfOutputWithNoViolations, output.size());
453     }
454 
455     @Test
456     public final void testSimultaneousConfiguration() throws IOException {
457         final File file = new File(getPath(CONFIG_FILE));
458         final URL url = file.toURI().toURL();
459         final String expected = "Attribute 'config' has already been set";
460         try {
461             final CheckstyleAntTask antTask = new CheckstyleAntTask();
462             antTask.setConfig(url.toString());
463             antTask.setConfig(file.toString());
464             fail("Exception is expected");
465         }
466         catch (BuildException ex) {
467             assertEquals("Error message is unexpected",
468                     expected, ex.getMessage());
469         }
470     }
471 
472     @Test
473     public final void testSetPropertiesFile() throws IOException {
474         //check if input stream finally closed
475         mockStatic(Closeables.class);
476         doNothing().when(Closeables.class);
477         Closeables.closeQuietly(any(InputStream.class));
478 
479         TestRootModuleChecker.reset();
480 
481         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
482         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
483         antTask.setProperties(new File(getPath(
484                 "InputCheckstyleAntTaskCheckstyleAntTest.properties")));
485         antTask.execute();
486 
487         assertEquals("Property is not set",
488                 "ignore", TestRootModuleChecker.getProperty());
489         verifyStatic(times(1));
490         Closeables.closeQuietly(any(InputStream.class));
491     }
492 
493     @Test
494     public final void testSetPropertiesNonExistentFile() throws IOException {
495         final CheckstyleAntTask antTask = getCheckstyleAntTask();
496         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
497         antTask.setProperties(new File(getPath(NOT_EXISTING_FILE)));
498         try {
499             antTask.execute();
500             fail("Exception is expected");
501         }
502         catch (BuildException ex) {
503             assertTrue("Error message is unexpected",
504                     ex.getMessage().startsWith("Error loading Properties file"));
505         }
506     }
507 
508     @Test
509     public final void testXmlOutput() throws IOException {
510         final CheckstyleAntTask antTask = getCheckstyleAntTask();
511         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
512         antTask.setFailOnViolation(false);
513         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
514         final File outputFile = new File("target/log.xml");
515         formatter.setTofile(outputFile);
516         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
517         formatterType.setValue("xml");
518         formatter.setType(formatterType);
519         antTask.addFormatter(formatter);
520         antTask.execute();
521 
522         final List<String> expected = FileUtils.readLines(
523                 new File(getPath("InputCheckstyleAntTaskXmlOutput.xml")), StandardCharsets.UTF_8);
524         final List<String> actual = FileUtils.readLines(outputFile, StandardCharsets.UTF_8);
525         for (int i = 0; i < expected.size(); i++) {
526             final String line = expected.get(i);
527             if (!line.startsWith("<checkstyle version") && !line.startsWith("<file")) {
528                 assertEquals("Content of file with violations differs from expected",
529                         line, actual.get(i));
530             }
531         }
532     }
533 
534     @Test
535     public final void testCreateListenerException() throws IOException {
536         final CheckstyleAntTask antTask = getCheckstyleAntTask();
537         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
538         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
539         final File outputFile = new File("target/");
540         formatter.setTofile(outputFile);
541         antTask.addFormatter(formatter);
542         try {
543             antTask.execute();
544             fail("Exception is expected");
545         }
546         catch (BuildException ex) {
547             assertTrue("Error message is unexpected",
548                     ex.getMessage().startsWith("Unable to create listeners: formatters"));
549         }
550     }
551 
552     @Test
553     public final void testCreateListenerExceptionWithXmlLogger() throws IOException {
554         final CheckstyleAntTask antTask = getCheckstyleAntTask();
555         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
556         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
557         final File outputFile = new File("target/");
558         formatter.setTofile(outputFile);
559         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
560         formatterType.setValue("xml");
561         formatter.setType(formatterType);
562         antTask.addFormatter(formatter);
563         try {
564             antTask.execute();
565             fail("Exception is expected");
566         }
567         catch (BuildException ex) {
568             assertTrue("Error message is unexpected",
569                     ex.getMessage().startsWith("Unable to create listeners: formatters"));
570         }
571     }
572 
573     @Test
574     public void testSetInvalidType() {
575         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
576         try {
577             formatterType.setValue("foo");
578             fail("Exception is expected");
579         }
580         catch (BuildException ex) {
581             assertEquals("Error message is unexpected",
582                     "foo is not a legal value for this attribute", ex.getMessage());
583         }
584     }
585 
586     @Test
587     public void testSetClassName() {
588         final String customName = "customName";
589         final CheckstyleAntTask.Listener listener = new CheckstyleAntTask.Listener();
590         listener.setClassname(customName);
591         assertEquals("Class name is unexpected",
592                 customName, listener.getClassname());
593     }
594 
595     @Test
596     public void testSetFileValueByFile() throws IOException {
597         final String filename = getPath("InputCheckstyleAntTaskCheckstyleAntTest.properties");
598         final CheckstyleAntTask.Property property = new CheckstyleAntTask.Property();
599         property.setFile(new File(filename));
600         assertEquals("File path is unexpected",
601                 property.getValue(), new File(filename).getAbsolutePath());
602     }
603 
604     @Test
605     public void testDefaultLoggerListener() throws IOException {
606         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
607         formatter.setUseFile(false);
608         assertTrue("Listener instance has unexpected type",
609                 formatter.createListener(null) instanceof DefaultLogger);
610     }
611 
612     @Test
613     public void testDefaultLoggerListenerWithToFile() throws IOException {
614         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
615         formatter.setUseFile(false);
616         formatter.setTofile(new File("target/"));
617         assertTrue("Listener instance has unexpected type",
618                 formatter.createListener(null) instanceof DefaultLogger);
619     }
620 
621     @Test
622     public void testXmlLoggerListener() throws IOException {
623         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
624         formatterType.setValue("xml");
625         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
626         formatter.setType(formatterType);
627         formatter.setUseFile(false);
628         assertTrue("Listener instance has unexpected type",
629                 formatter.createListener(null) instanceof XMLLogger);
630     }
631 
632     @Test
633     public void testXmlLoggerListenerWithToFile() throws IOException {
634         final CheckstyleAntTask.FormatterType formatterType = new CheckstyleAntTask.FormatterType();
635         formatterType.setValue("xml");
636         final CheckstyleAntTask.Formatter formatter = new CheckstyleAntTask.Formatter();
637         formatter.setType(formatterType);
638         formatter.setUseFile(false);
639         formatter.setTofile(new File("target/"));
640         assertTrue("Listener instance has unexpected type",
641                 formatter.createListener(null) instanceof XMLLogger);
642     }
643 
644     @Test
645     public void testSetClasspath() {
646         final CheckstyleAntTask antTask = new CheckstyleAntTask();
647         final Project project = new Project();
648         final String path1 = "firstPath";
649         final String path2 = "secondPath";
650         antTask.setClasspath(new Path(project, path1));
651         antTask.setClasspath(new Path(project, path2));
652 
653         assertNotNull("Classpath should not be null",
654                 Whitebox.getInternalState(antTask, "classpath"));
655         final Path classpath = (Path) Whitebox.getInternalState(antTask, "classpath");
656         assertTrue("Classpath contain provided path", classpath.toString().contains(path1));
657         assertTrue("Classpath contain provided path", classpath.toString().contains(path2));
658     }
659 
660     @Test
661     public void testSetClasspathRef() {
662         final CheckstyleAntTask antTask = new CheckstyleAntTask();
663         antTask.setClasspathRef(new Reference(new Project(), "id"));
664 
665         assertNotNull("Classpath should not be null",
666             Whitebox.getInternalState(antTask, "classpath"));
667     }
668 
669     /** This test is created to satisfy pitest, it is hard to emulate Reference by Id. */
670     @Test
671     public void testSetClasspathRef1() {
672         final CheckstyleAntTask antTask = new CheckstyleAntTask();
673         final Project project = new Project();
674         antTask.setClasspath(new Path(project, "firstPath"));
675         antTask.setClasspathRef(new Reference(project, "idXX"));
676 
677         try {
678             assertNotNull("Classpath should not be null",
679                     Whitebox.getInternalState(antTask, "classpath"));
680             final Path classpath = (Path) Whitebox.getInternalState(antTask, "classpath");
681             classpath.list();
682             fail("Exception is expected");
683         }
684         catch (BuildException ex) {
685             assertEquals("unexpected exception message",
686                     "Reference idXX not found.", ex.getMessage());
687         }
688     }
689 
690     @Test
691     public void testCreateClasspath() {
692         final CheckstyleAntTask antTask = new CheckstyleAntTask();
693 
694         assertEquals("Invalid classpath", "", antTask.createClasspath().toString());
695 
696         antTask.setClasspath(new Path(new Project(), "/path"));
697 
698         assertEquals("Invalid classpath", "", antTask.createClasspath().toString());
699     }
700 
701     @Test
702     public void testDestroyed() throws IOException {
703         TestRootModuleChecker.reset();
704 
705         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
706         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
707         antTask.setMaxWarnings(0);
708         antTask.execute();
709 
710         assertTrue("Checker is not destroyed",
711                 TestRootModuleChecker.isDestroyed());
712     }
713 
714     @Test
715     public void testMaxWarnings() throws IOException {
716         TestRootModuleChecker.reset();
717 
718         final CheckstyleAntTask antTask = getCheckstyleAntTask(CUSTOM_ROOT_CONFIG_FILE);
719         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
720         antTask.setMaxWarnings(0);
721         antTask.execute();
722 
723         assertTrue("Checker is not processed",
724                 TestRootModuleChecker.isProcessed());
725     }
726 
727     @Test
728     public void testClassloaderInRootModule() throws IOException {
729         TestRootModuleChecker.reset();
730         CheckerStub.reset();
731 
732         final CheckstyleAntTask antTask =
733                 getCheckstyleAntTask(
734                         "InputCheckstyleAntTaskConfigCustomCheckerRootModule.xml");
735         antTask.setFile(new File(getPath(VIOLATED_INPUT)));
736 
737         antTask.execute();
738 
739         final ClassLoader classLoader = CheckerStub.getClassLoader();
740         assertTrue("Classloader is not set or has invalid type",
741                 classLoader instanceof AntClassLoader);
742     }
743 
744     @Test
745     public void testCheckerException() throws IOException {
746         final CheckstyleAntTask antTask = new CheckstyleAntTaskStub();
747         antTask.setConfig(getPath(CONFIG_FILE));
748         antTask.setProject(new Project());
749         antTask.setFile(new File(""));
750         try {
751             antTask.execute();
752             fail("Exception is expected");
753         }
754         catch (BuildException ex) {
755             assertTrue("Error message is unexpected",
756                     ex.getMessage().startsWith("Unable to process files:"));
757         }
758     }
759 
760     @Test
761     public final void testExecuteLogOutput() throws Exception {
762         final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
763         final URL url = new File(getPath(CONFIG_FILE)).toURI().toURL();
764         antTask.setProject(new Project());
765         antTask.setConfig(url.toString());
766         antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
767 
768         mockStatic(System.class);
769         when(System.currentTimeMillis()).thenReturn(1L);
770 
771         antTask.execute();
772 
773         final LocalizedMessage auditStartedMessage = new LocalizedMessage(0,
774                 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditStarted",
775                 null, null,
776                 getClass(), null);
777         final LocalizedMessage auditFinishedMessage = new LocalizedMessage(0,
778                 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditFinished",
779                 null, null,
780                 getClass(), null);
781 
782         final List<MessageLevelPair> expectedList = Arrays.asList(
783                 new MessageLevelPair("checkstyle version ", Project.MSG_VERBOSE),
784                 new MessageLevelPair("compiled on ", Project.MSG_VERBOSE),
785                 new MessageLevelPair("Adding standalone file for audit", Project.MSG_VERBOSE),
786                 new MessageLevelPair("To locate the files took 0 ms.", Project.MSG_VERBOSE),
787                 new MessageLevelPair("Running Checkstyle ", Project.MSG_INFO),
788                 new MessageLevelPair("Using configuration ", Project.MSG_VERBOSE),
789                 new MessageLevelPair(auditStartedMessage.getMessage(), Project.MSG_DEBUG),
790                 new MessageLevelPair(auditFinishedMessage.getMessage(), Project.MSG_DEBUG),
791                 new MessageLevelPair("To process the files took 0 ms.", Project.MSG_VERBOSE),
792                 new MessageLevelPair("Total execution took 0 ms.", Project.MSG_VERBOSE)
793         );
794 
795         final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
796 
797         assertEquals("Amount of log messages is unexpected",
798                 expectedList.size(), loggedMessages.size());
799         for (int i = 0; i < expectedList.size(); i++) {
800             final MessageLevelPair expected = expectedList.get(i);
801             final MessageLevelPair actual = loggedMessages.get(i);
802             assertTrue("Log messages were expected",
803                     actual.getMsg().startsWith(expected.getMsg()));
804             assertEquals("Log messages were expected",
805                     expected.getLevel(), actual.getLevel());
806         }
807 
808     }
809 
810     private static class CheckstyleAntTaskStub extends CheckstyleAntTask {
811         @Override
812         protected List<File> scanFileSets() {
813             final File mock = PowerMockito.mock(File.class);
814             // Assume that I/O error is happened when we try to invoke 'lastModified()' method.
815             final Exception expectedError = new RuntimeException("");
816             when(mock.lastModified()).thenThrow(expectedError);
817             final List<File> list = new ArrayList<>();
818             list.add(mock);
819             return list;
820         }
821     }
822 
823     private static class CheckstyleAntTaskLogStub extends CheckstyleAntTask {
824 
825         private final List<MessageLevelPair> loggedMessages = new ArrayList<>();
826 
827         @Override
828         public void log(String msg, int msgLevel) {
829             loggedMessages.add(new MessageLevelPair(msg, msgLevel));
830         }
831 
832         @Override
833         public void log(String msg, Throwable t, int msgLevel) {
834             loggedMessages.add(new MessageLevelPair(msg, msgLevel));
835 
836         }
837 
838         public List<MessageLevelPair> getLoggedMessages() {
839             return Collections.unmodifiableList(loggedMessages);
840         }
841     }
842 
843     private static final class MessageLevelPair {
844         private final String msg;
845         private final int level;
846 
847         MessageLevelPair(String msg, int level) {
848             this.msg = msg;
849             this.level = level;
850         }
851 
852         public String getMsg() {
853             return msg;
854         }
855 
856         public int getLevel() {
857             return level;
858         }
859     }
860 
861 }