1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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.internal.powermock;
21  
22  import static org.junit.Assert.assertEquals;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  import static org.mockito.Mockito.when;
26  import static org.powermock.api.mockito.PowerMockito.mockStatic;
27  
28  import java.io.File;
29  import java.io.IOException;
30  import java.net.URL;
31  import java.util.ArrayList;
32  import java.util.Arrays;
33  import java.util.Collections;
34  import java.util.List;
35  
36  import org.apache.tools.ant.BuildException;
37  import org.apache.tools.ant.Project;
38  import org.junit.Test;
39  import org.junit.runner.RunWith;
40  import org.powermock.api.mockito.PowerMockito;
41  import org.powermock.core.classloader.annotations.PrepareForTest;
42  import org.powermock.modules.junit4.PowerMockRunner;
43  
44  import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
45  import com.puppycrawl.tools.checkstyle.Definitions;
46  import com.puppycrawl.tools.checkstyle.ant.CheckstyleAntTask;
47  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
48  
49  @RunWith(PowerMockRunner.class)
50  @PrepareForTest(CheckstyleAntTask.class)
51  public class CheckstyleAntTaskPowerTest extends AbstractPathTestSupport {
52  
53      private static final String FLAWLESS_INPUT =
54              "InputCheckstyleAntTaskFlawless.java";
55      private static final String CONFIG_FILE =
56              "InputCheckstyleAntTaskTestChecks.xml";
57  
58      @Override
59      protected String getPackageLocation() {
60          return "com/puppycrawl/tools/checkstyle/ant/checkstyleanttask/";
61      }
62  
63      @Test
64      public final void testExecuteLogOutput() throws Exception {
65          final CheckstyleAntTaskLogStub antTask = new CheckstyleAntTaskLogStub();
66          final URL url = new File(getPath(CONFIG_FILE)).toURI().toURL();
67          antTask.setProject(new Project());
68          antTask.setConfig(url.toString());
69          antTask.setFile(new File(getPath(FLAWLESS_INPUT)));
70  
71          mockStatic(System.class);
72          when(System.currentTimeMillis()).thenReturn(1L);
73  
74          antTask.execute();
75  
76          final LocalizedMessage auditStartedMessage = new LocalizedMessage(1,
77                  Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditStarted",
78                  null, null,
79                  getClass(), null);
80          final LocalizedMessage auditFinishedMessage = new LocalizedMessage(1,
81                  Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditFinished",
82                  null, null,
83                  getClass(), null);
84  
85          final List<MessageLevelPair> expectedList = Arrays.asList(
86                  new MessageLevelPair("checkstyle version ", Project.MSG_VERBOSE),
87                  new MessageLevelPair("Adding standalone file for audit", Project.MSG_VERBOSE),
88                  new MessageLevelPair("To locate the files took 0 ms.", Project.MSG_VERBOSE),
89                  new MessageLevelPair("Running Checkstyle ", Project.MSG_INFO),
90                  new MessageLevelPair("Using configuration ", Project.MSG_VERBOSE),
91                  new MessageLevelPair(auditStartedMessage.getMessage(), Project.MSG_DEBUG),
92                  new MessageLevelPair(auditFinishedMessage.getMessage(), Project.MSG_DEBUG),
93                  new MessageLevelPair("To process the files took 0 ms.", Project.MSG_VERBOSE),
94                  new MessageLevelPair("Total execution took 0 ms.", Project.MSG_VERBOSE)
95          );
96  
97          final List<MessageLevelPair> loggedMessages = antTask.getLoggedMessages();
98  
99          assertEquals("Amount of log messages is unexpected",
100                 expectedList.size(), loggedMessages.size());
101         for (int i = 0; i < expectedList.size(); i++) {
102             final MessageLevelPair expected = expectedList.get(i);
103             final MessageLevelPair actual = loggedMessages.get(i);
104             assertTrue("Log messages were expected",
105                     actual.getMsg().startsWith(expected.getMsg()));
106             assertEquals("Log messages were expected",
107                     expected.getLevel(), actual.getLevel());
108         }
109     }
110 
111     @Test
112     public void testCheckerException() throws IOException {
113         final CheckstyleAntTask antTask = new CheckstyleAntTaskStub();
114         antTask.setConfig(getPath(CONFIG_FILE));
115         antTask.setProject(new Project());
116         antTask.setFile(new File(""));
117         try {
118             antTask.execute();
119             fail("Exception is expected");
120         }
121         catch (BuildException ex) {
122             assertTrue("Error message is unexpected",
123                     ex.getMessage().startsWith("Unable to process files:"));
124         }
125     }
126 
127     /**
128      * Non meaningful javadoc just to contain "noinspection" tag.
129      * Till https://youtrack.jetbrains.com/issue/IDEA-187210
130      * @noinspection JUnitTestCaseWithNoTests
131      */
132     private static class CheckstyleAntTaskStub extends CheckstyleAntTask {
133 
134         @Override
135         protected List<File> scanFileSets() {
136             final File mock = PowerMockito.mock(File.class);
137             // Assume that I/O error is happened when we try to invoke 'lastModified()' method.
138             final Exception expectedError = new RuntimeException("");
139             when(mock.lastModified()).thenThrow(expectedError);
140             final List<File> list = new ArrayList<>();
141             list.add(mock);
142             return list;
143         }
144 
145     }
146 
147     /**
148      * Non meaningful javadoc just to contain "noinspection" tag.
149      * Till https://youtrack.jetbrains.com/issue/IDEA-187210
150      * @noinspection JUnitTestCaseWithNoTests
151      */
152     private static class CheckstyleAntTaskLogStub extends CheckstyleAntTask {
153 
154         private final List<MessageLevelPair> loggedMessages = new ArrayList<>();
155 
156         @Override
157         public void log(String msg, int msgLevel) {
158             loggedMessages.add(new MessageLevelPair(msg, msgLevel));
159         }
160 
161         @Override
162         public void log(String msg, Throwable t, int msgLevel) {
163             loggedMessages.add(new MessageLevelPair(msg, msgLevel));
164         }
165 
166         public List<MessageLevelPair> getLoggedMessages() {
167             return Collections.unmodifiableList(loggedMessages);
168         }
169 
170     }
171 
172     /**
173      * Non meaningful javadoc just to contain "noinspection" tag.
174      * Till https://youtrack.jetbrains.com/issue/IDEA-187210
175      * @noinspection JUnitTestCaseWithNoTests
176      */
177     private static final class MessageLevelPair {
178 
179         private final String msg;
180         private final int level;
181 
182         /* package */ MessageLevelPair(String msg, int level) {
183             this.msg = msg;
184             this.level = level;
185         }
186 
187         public String getMsg() {
188             return msg;
189         }
190 
191         public int getLevel() {
192             return level;
193         }
194 
195     }
196 
197 }