View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2018 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.checks;
21  
22  import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_NO_NEWLINE_EOF;
23  import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_UNABLE_OPEN;
24  import static java.util.Locale.ENGLISH;
25  import static org.junit.Assert.assertEquals;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  import static org.mockito.ArgumentMatchers.any;
29  import static org.mockito.ArgumentMatchers.anyBoolean;
30  import static org.mockito.Mockito.times;
31  import static org.powermock.api.mockito.PowerMockito.doNothing;
32  import static org.powermock.api.mockito.PowerMockito.mock;
33  import static org.powermock.api.mockito.PowerMockito.mockStatic;
34  import static org.powermock.api.mockito.PowerMockito.verifyStatic;
35  import static org.powermock.api.mockito.PowerMockito.when;
36  
37  import java.io.File;
38  import java.io.IOException;
39  import java.io.RandomAccessFile;
40  import java.lang.reflect.InvocationTargetException;
41  import java.lang.reflect.Method;
42  import java.util.ArrayList;
43  import java.util.Iterator;
44  import java.util.List;
45  import java.util.Set;
46  
47  import org.junit.Test;
48  import org.junit.runner.RunWith;
49  import org.powermock.core.classloader.annotations.PrepareForTest;
50  import org.powermock.modules.junit4.PowerMockRunner;
51  
52  import com.google.common.io.Closeables;
53  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
54  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
55  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
56  import com.puppycrawl.tools.checkstyle.api.FileText;
57  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
58  import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
59  
60  @RunWith(PowerMockRunner.class)
61  @PrepareForTest(Closeables.class)
62  public class NewlineAtEndOfFileCheckTest
63      extends AbstractModuleTestSupport {
64  
65      @Override
66      protected String getPackageLocation() {
67          return "com/puppycrawl/tools/checkstyle/checks/newlineatendoffile";
68      }
69  
70      @Test
71      public void testNewlineLfAtEndOfFile() throws Exception {
72          final DefaultConfiguration checkConfig =
73              createModuleConfig(NewlineAtEndOfFileCheck.class);
74          checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF.toString());
75          final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
76          verify(
77              createChecker(checkConfig),
78              getPath("InputNewlineAtEndOfFileLf.java"),
79              expected);
80      }
81  
82      /**
83       * Pitest requires all closes of streams and readers to be verified. Using PowerMock
84       * is almost only possibility to check it without rewriting production code.
85       *
86       * @throws Exception when code tested throws some exception
87       */
88      @Test
89      public void testCloseRandomAccessFile() throws Exception {
90          mockStatic(Closeables.class);
91          doNothing().when(Closeables.class);
92          Closeables.close(any(RandomAccessFile.class), anyBoolean());
93  
94          final DefaultConfiguration checkConfig =
95                  createModuleConfig(NewlineAtEndOfFileCheck.class);
96          checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF.toString());
97          final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
98          verify(
99                  createChecker(checkConfig),
100                 getPath("InputNewlineAtEndOfFileLf.java"),
101                 expected);
102 
103         verifyStatic(Closeables.class, times(1));
104         Closeables.close(any(RandomAccessFile.class), anyBoolean());
105     }
106 
107     @Test
108     public void testNewlineCrlfAtEndOfFile() throws Exception {
109         final DefaultConfiguration checkConfig =
110             createModuleConfig(NewlineAtEndOfFileCheck.class);
111         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.CRLF.toString());
112         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
113         verify(
114             createChecker(checkConfig),
115             getPath("InputNewlineAtEndOfFileCrlf.java"),
116             expected);
117     }
118 
119     @Test
120     public void testNewlineCrAtEndOfFile() throws Exception {
121         final DefaultConfiguration checkConfig =
122             createModuleConfig(NewlineAtEndOfFileCheck.class);
123         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.CR.toString());
124         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
125         verify(
126             createChecker(checkConfig),
127             getPath("InputNewlineAtEndOfFileCr.java"),
128             expected);
129     }
130 
131     @Test
132     public void testAnyNewlineAtEndOfFile() throws Exception {
133         final DefaultConfiguration checkConfig =
134             createModuleConfig(NewlineAtEndOfFileCheck.class);
135         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF_CR_CRLF.toString());
136         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
137         verify(
138             createChecker(checkConfig),
139             getPath("InputNewlineAtEndOfFileCrlf.java"),
140             expected);
141         verify(
142             createChecker(checkConfig),
143             getPath("InputNewlineAtEndOfFileLf.java"),
144             expected);
145         verify(
146             createChecker(checkConfig),
147             getPath("InputNewlineAtEndOfFileCr.java"),
148             expected);
149     }
150 
151     @Test
152     public void testNoNewlineLfAtEndOfFile() throws Exception {
153         final DefaultConfiguration checkConfig =
154             createModuleConfig(NewlineAtEndOfFileCheck.class);
155         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF.toString());
156         final String[] expected = {
157             "0: " + getCheckMessage(MSG_KEY_NO_NEWLINE_EOF),
158         };
159         verify(
160             createChecker(checkConfig),
161             getPath("InputNewlineAtEndOfFileNoNewline.java"),
162             expected);
163     }
164 
165     @Test
166     public void testNoNewlineAtEndOfFile() throws Exception {
167         final DefaultConfiguration checkConfig =
168             createModuleConfig(NewlineAtEndOfFileCheck.class);
169         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF_CR_CRLF.toString());
170         final String[] expected = {
171             "0: " + getCheckMessage(MSG_KEY_NO_NEWLINE_EOF),
172         };
173         verify(
174             createChecker(checkConfig),
175             getPath("InputNewlineAtEndOfFileNoNewline.java"),
176             expected);
177     }
178 
179     @Test
180     public void testSetLineSeparatorFailure()
181             throws Exception {
182         final DefaultConfiguration checkConfig =
183             createModuleConfig(NewlineAtEndOfFileCheck.class);
184         checkConfig.addAttribute("lineSeparator", "ct");
185         try {
186             createChecker(checkConfig);
187             fail("exception expected");
188         }
189         catch (CheckstyleException ex) {
190             assertTrue("Error message is unexpected",
191                     ex.getMessage().startsWith(
192                     "cannot initialize module com.puppycrawl.tools.checkstyle."
193                             + "checks.NewlineAtEndOfFileCheck - "
194                             + "Cannot set property 'lineSeparator' to 'ct' in module"));
195         }
196     }
197 
198     @Test
199     public void testEmptyFileFile() throws Exception {
200         final DefaultConfiguration checkConfig =
201             createModuleConfig(NewlineAtEndOfFileCheck.class);
202         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF.toString());
203         final String[] expected = {
204             "0: " + getCheckMessage(MSG_KEY_NO_NEWLINE_EOF),
205         };
206         verify(
207             createChecker(checkConfig),
208             getPath("InputNewlineAtEndOfFileEmptyFile.txt"),
209             expected);
210     }
211 
212     @Test
213     public void testFileWithEmptyLineOnly() throws Exception {
214         final DefaultConfiguration checkConfig =
215                 createModuleConfig(NewlineAtEndOfFileCheck.class);
216         checkConfig.addAttribute("lineSeparator", LineSeparatorOption.LF.toString());
217         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
218         verify(
219                 createChecker(checkConfig),
220                 getPath("InputNewlineAtEndOfFileNewlineAtEnd.txt"),
221                 expected);
222     }
223 
224     @Test
225     public void testWrongFile() throws Exception {
226         final DefaultConfiguration checkConfig = createModuleConfig(NewlineAtEndOfFileCheck.class);
227         final NewlineAtEndOfFileCheck check = new NewlineAtEndOfFileCheck();
228         check.configure(checkConfig);
229         final List<String> lines = new ArrayList<>(1);
230         lines.add("txt");
231         final File impossibleFile = new File("");
232         final FileText fileText = new FileText(impossibleFile, lines);
233         final Set<LocalizedMessage> messages = check.process(impossibleFile, fileText);
234         assertEquals("Amount of messages is unexpected",
235                 1, messages.size());
236         final Iterator<LocalizedMessage> iterator = messages.iterator();
237         assertEquals("Violation message differs from expected",
238                 getCheckMessage(MSG_KEY_UNABLE_OPEN, ""), iterator.next().getMessage());
239     }
240 
241     @Test
242     public void testWrongSeparatorLength() throws Exception {
243         final NewlineAtEndOfFileCheck check = new NewlineAtEndOfFileCheck();
244         final DefaultConfiguration checkConfig = createModuleConfig(NewlineAtEndOfFileCheck.class);
245         check.configure(checkConfig);
246 
247         final Method method = NewlineAtEndOfFileCheck.class
248                 .getDeclaredMethod("endsWithNewline", RandomAccessFile.class);
249         method.setAccessible(true);
250         final RandomAccessFile file = mock(RandomAccessFile.class);
251         when(file.length()).thenReturn(2_000_000L);
252         try {
253             method.invoke(new NewlineAtEndOfFileCheck(), file);
254             fail("Exception is expected");
255         }
256         catch (InvocationTargetException ex) {
257             assertTrue("Error type is unexpected",
258                     ex.getCause() instanceof IOException);
259             if (System.getProperty("os.name").toLowerCase(ENGLISH).startsWith("windows")) {
260                 assertEquals("Error message is unexpected",
261                         "Unable to read 2 bytes, got 0", ex.getCause().getMessage());
262             }
263             else {
264                 assertEquals("Error message is unexpected",
265                         "Unable to read 1 bytes, got 0", ex.getCause().getMessage());
266             }
267         }
268     }
269 
270 }