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