View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2024 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.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_NO_NEWLINE_EOF;
24  import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_UNABLE_OPEN;
25  import static com.puppycrawl.tools.checkstyle.checks.NewlineAtEndOfFileCheck.MSG_KEY_WRONG_ENDING;
26  
27  import java.io.File;
28  import java.io.FileNotFoundException;
29  import java.io.RandomAccessFile;
30  import java.util.ArrayList;
31  import java.util.Iterator;
32  import java.util.List;
33  import java.util.Set;
34  
35  import org.junit.jupiter.api.Test;
36  
37  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
38  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
39  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
40  import com.puppycrawl.tools.checkstyle.api.FileText;
41  import com.puppycrawl.tools.checkstyle.api.Violation;
42  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
43  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
44  
45  public class NewlineAtEndOfFileCheckTest
46      extends AbstractModuleTestSupport {
47  
48      @Override
49      protected String getPackageLocation() {
50          return "com/puppycrawl/tools/checkstyle/checks/newlineatendoffile";
51      }
52  
53      @Test
54      public void testNewlineLfAtEndOfFile() throws Exception {
55          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
56          verifyWithInlineConfigParser(
57                  getPath("InputNewlineAtEndOfFileLf.java"),
58              expected);
59      }
60  
61      @Test
62      public void testNewlineLfAtEndOfFileLfNotOverlapWithCrLf() throws Exception {
63          final String[] expected = {
64              "1: " + getCheckMessage(MSG_KEY_WRONG_ENDING),
65          };
66          verifyWithInlineConfigParser(
67                  getPath("InputNewlineAtEndOfFileCrlf.java"),
68              expected);
69      }
70  
71      @Test
72      public void testNewlineCrlfAtEndOfFile() throws Exception {
73          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
74          verifyWithInlineConfigParser(
75                  getPath("InputNewlineAtEndOfFileCrlf3.java"),
76              expected);
77      }
78  
79      @Test
80      public void testNewlineCrAtEndOfFile() throws Exception {
81          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
82          verifyWithInlineConfigParser(
83                  getPath("InputNewlineAtEndOfFileCr.java"),
84              expected);
85      }
86  
87      @Test
88      public void testAnyNewlineAtEndOfFile() throws Exception {
89          final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
90          verifyWithInlineConfigParser(
91                  getPath("InputNewlineAtEndOfFileCrlf2.java"),
92              expected);
93          verifyWithInlineConfigParser(
94                  getPath("InputNewlineAtEndOfFileLf2.java"),
95              expected);
96          verifyWithInlineConfigParser(
97                  getPath("InputNewlineAtEndOfFileCr2.java"),
98              expected);
99      }
100 
101     @Test
102     public void testNoNewlineLfAtEndOfFile() throws Exception {
103         final String[] expected = {
104             "1: " + getCheckMessage(MSG_KEY_NO_NEWLINE_EOF),
105         };
106         verifyWithInlineConfigParser(
107                 getPath("InputNewlineAtEndOfFileNoNewline.java"),
108             expected);
109     }
110 
111     @Test
112     public void testNoNewlineAtEndOfFile() throws Exception {
113         final String msgKeyNoNewlineEof = "File does not end with a newline :)";
114         final String[] expected = {
115             "1: " + msgKeyNoNewlineEof,
116         };
117         verifyWithInlineConfigParser(
118                 getPath("InputNewlineAtEndOfFileNoNewline2.java"),
119             expected);
120     }
121 
122     @Test
123     public void testSetLineSeparatorFailure()
124             throws Exception {
125         final DefaultConfiguration checkConfig =
126             createModuleConfig(NewlineAtEndOfFileCheck.class);
127         checkConfig.addProperty("lineSeparator", "ct");
128         try {
129             createChecker(checkConfig);
130             assertWithMessage("exception expected").fail();
131         }
132         catch (CheckstyleException ex) {
133             assertWithMessage("Error message is unexpected")
134                     .that(ex.getMessage())
135                     .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle."
136                             + "checks.NewlineAtEndOfFileCheck - "
137                             + "Cannot set property 'lineSeparator' to 'ct'");
138         }
139     }
140 
141     @Test
142     public void testEmptyFileFile() throws Exception {
143         final DefaultConfiguration checkConfig =
144             createModuleConfig(NewlineAtEndOfFileCheck.class);
145         checkConfig.addProperty("lineSeparator", LineSeparatorOption.LF.toString());
146         final String[] expected = {
147             "1: " + getCheckMessage(MSG_KEY_NO_NEWLINE_EOF),
148         };
149         verify(
150             checkConfig,
151             getPath("InputNewlineAtEndOfFileEmptyFile.txt"),
152             expected);
153     }
154 
155     @Test
156     public void testFileWithEmptyLineOnly() throws Exception {
157         final DefaultConfiguration checkConfig =
158                 createModuleConfig(NewlineAtEndOfFileCheck.class);
159         checkConfig.addProperty("lineSeparator", LineSeparatorOption.LF.toString());
160         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
161         verify(
162                 checkConfig,
163                 getPath("InputNewlineAtEndOfFileNewlineAtEnd.txt"),
164                 expected);
165     }
166 
167     @Test
168     public void testFileWithEmptyLineOnlyWithLfCrCrlf() throws Exception {
169         final DefaultConfiguration checkConfig =
170                 createModuleConfig(NewlineAtEndOfFileCheck.class);
171         checkConfig.addProperty("lineSeparator", LineSeparatorOption.LF_CR_CRLF.toString());
172         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
173         verify(
174                 checkConfig,
175                 getPath("InputNewlineAtEndOfFileNewlineAtEndLf.txt"),
176                 expected);
177     }
178 
179     @Test
180     public void testWrongFile() throws Exception {
181         final DefaultConfiguration checkConfig = createModuleConfig(NewlineAtEndOfFileCheck.class);
182         final NewlineAtEndOfFileCheck check = new NewlineAtEndOfFileCheck();
183         check.configure(checkConfig);
184         final List<String> lines = new ArrayList<>(1);
185         lines.add("txt");
186         final File impossibleFile = new File("");
187         final FileText fileText = new FileText(impossibleFile, lines);
188         final Set<Violation> violations = check.process(impossibleFile, fileText);
189         assertWithMessage("Amount of violations is unexpected")
190                 .that(violations)
191                 .hasSize(1);
192         final Iterator<Violation> iterator = violations.iterator();
193         assertWithMessage("Violation message differs from expected")
194                 .that(iterator.next().getViolation())
195                 .isEqualTo(getCheckMessage(MSG_KEY_UNABLE_OPEN, ""));
196     }
197 
198     @Test
199     public void testWrongSeparatorLength() throws Exception {
200         try (RandomAccessFile file =
201                      new ReadZeroRandomAccessFile(getPath("InputNewlineAtEndOfFileLf.java"), "r")) {
202             TestUtil.invokeMethod(new NewlineAtEndOfFileCheck(), "endsWithNewline", file,
203                 LineSeparatorOption.LF);
204             assertWithMessage("ReflectiveOperationException is expected").fail();
205         }
206         catch (ReflectiveOperationException ex) {
207             assertWithMessage("Error message is unexpected")
208                 .that(ex)
209                     .hasCauseThat()
210                         .hasMessageThat()
211                         .isEqualTo("Unable to read 1 bytes, got 0");
212         }
213     }
214 
215     @Test
216     public void testTrimOptionProperty() throws Exception {
217         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
218         verifyWithInlineConfigParser(
219                 getPath("InputNewlineAtEndOfFileTestTrimProperty.java"),
220                 expected);
221     }
222 
223     private static final class ReadZeroRandomAccessFile extends RandomAccessFile {
224 
225         private ReadZeroRandomAccessFile(String name, String mode)
226                 throws FileNotFoundException {
227             super(name, mode);
228         }
229 
230         @Override
231         public int read(byte[] bytes) {
232             return 0;
233         }
234     }
235 
236 }