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.regexp;
21  
22  import static com.puppycrawl.tools.checkstyle.checks.regexp.MultilineDetector.MSG_EMPTY;
23  import static com.puppycrawl.tools.checkstyle.checks.regexp.MultilineDetector.MSG_REGEXP_EXCEEDED;
24  import static com.puppycrawl.tools.checkstyle.checks.regexp.MultilineDetector.MSG_REGEXP_MINIMUM;
25  import static com.puppycrawl.tools.checkstyle.checks.regexp.MultilineDetector.MSG_STACKOVERFLOW;
26  
27  import java.io.File;
28  import java.nio.charset.StandardCharsets;
29  import java.nio.file.Files;
30  
31  import org.junit.Assert;
32  import org.junit.Rule;
33  import org.junit.Test;
34  import org.junit.rules.TemporaryFolder;
35  
36  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
37  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
38  import com.puppycrawl.tools.checkstyle.api.FileText;
39  import com.puppycrawl.tools.checkstyle.internal.testmodules.TestLoggingReporter;
40  import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
41  
42  public class RegexpMultilineCheckTest extends AbstractModuleTestSupport {
43  
44      @Rule
45      public final TemporaryFolder temporaryFolder = new TemporaryFolder();
46  
47      @Override
48      protected String getPackageLocation() {
49          return "com/puppycrawl/tools/checkstyle/checks/regexp/regexpmultiline";
50      }
51  
52      @Test
53      public void testIt() throws Exception {
54          final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
55          checkConfig.addAttribute("format", "System\\.(out)|(err)\\.print(ln)?\\(");
56          final String[] expected = {
57              "69: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "System\\.(out)|(err)\\.print(ln)?\\("),
58          };
59          verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
60      }
61  
62      @Test
63      public void testMessageProperty()
64              throws Exception {
65          final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
66          checkConfig.addAttribute("format", "System\\.(out)|(err)\\.print(ln)?\\(");
67          checkConfig.addAttribute("message", "Bad line :(");
68          final String[] expected = {
69              "69: " + "Bad line :(",
70          };
71          verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
72      }
73  
74      @Test
75      public void testIgnoreCaseTrue() throws Exception {
76          final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
77          checkConfig.addAttribute("format", "SYSTEM\\.(OUT)|(ERR)\\.PRINT(LN)?\\(");
78          checkConfig.addAttribute("ignoreCase", "true");
79          final String[] expected = {
80              "69: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "SYSTEM\\.(OUT)|(ERR)\\.PRINT(LN)?\\("),
81          };
82          verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
83      }
84  
85      @Test
86      public void testIgnoreCaseFalse() throws Exception {
87          final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
88          checkConfig.addAttribute("format", "SYSTEM\\.(OUT)|(ERR)\\.PRINT(LN)?\\(");
89          checkConfig.addAttribute("ignoreCase", "false");
90          final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
91          verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
92      }
93  
94      @Test
95      public void testIllegalFailBelowErrorLimit() throws Exception {
96          final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
97          checkConfig.addAttribute("format", "^import");
98          final String[] expected = {
99              "7: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "^import"),
100             "8: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "^import"),
101             "9: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "^import"),
102         };
103         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
104     }
105 
106     @Test
107     public void testCarriageReturn() throws Exception {
108         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
109         checkConfig.addAttribute("format", "\\r");
110         checkConfig.addAttribute("maximum", "0");
111         final String[] expected = {
112             "1: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "\\r"),
113             "3: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "\\r"),
114         };
115 
116         final File file = temporaryFolder.newFile();
117         Files.write(file.toPath(),
118             "first line \r\n second line \n\r third line".getBytes(StandardCharsets.UTF_8));
119 
120         verify(checkConfig, file.getPath(), expected);
121     }
122 
123     @Test
124     public void testMaximum() throws Exception {
125         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
126         checkConfig.addAttribute("format", "\\r");
127         checkConfig.addAttribute("maximum", "1");
128         final String[] expected = {
129             "3: " + getCheckMessage(MSG_REGEXP_EXCEEDED, "\\r"),
130         };
131 
132         final File file = temporaryFolder.newFile();
133         Files.write(file.toPath(),
134                 "first line \r\n second line \n\r third line".getBytes(StandardCharsets.UTF_8));
135 
136         verify(checkConfig, file.getPath(), expected);
137     }
138 
139     /**
140      * Done as a UT cause new instance of Detector is created each time 'verify' executed.
141      * @throws Exception some Exception
142      */
143     @Test
144     public void testStateIsBeingReset() throws Exception {
145         final TestLoggingReporter reporter = new TestLoggingReporter();
146         final DetectorOptions detectorOptions = DetectorOptions.newBuilder()
147                 .reporter(reporter)
148                 .format("\\r")
149                 .maximum(1)
150                 .build();
151 
152         final MultilineDetector detector =
153                 new MultilineDetector(detectorOptions);
154         final File file = temporaryFolder.newFile();
155         Files.write(file.toPath(),
156                 "first line \r\n second line \n\r third line".getBytes(StandardCharsets.UTF_8));
157 
158         detector.processLines(new FileText(file, StandardCharsets.UTF_8.name()));
159         detector.processLines(new FileText(file, StandardCharsets.UTF_8.name()));
160         Assert.assertEquals("Logged unexpected amount of issues",
161                 2, reporter.getLogCount());
162     }
163 
164     @Test
165     public void testDefaultConfiguration() throws Exception {
166         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
167         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
168         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
169     }
170 
171     @Test
172     public void testNullFormat() throws Exception {
173         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
174         checkConfig.addAttribute("format", null);
175         final String[] expected = {
176             "0: " + getCheckMessage(MSG_EMPTY),
177         };
178         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
179     }
180 
181     @Test
182     public void testEmptyFormat() throws Exception {
183         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
184         checkConfig.addAttribute("format", "");
185         final String[] expected = {
186             "0: " + getCheckMessage(MSG_EMPTY),
187         };
188         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
189     }
190 
191     @Test
192     public void testNoStackOverflowError() throws Exception {
193         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
194         // http://madbean.com/2004/mb2004-20/
195         checkConfig.addAttribute("format", "(x|y)*");
196 
197         final String[] expected = {
198             "0: " + getCheckMessage(MSG_STACKOVERFLOW),
199         };
200 
201         final File file = temporaryFolder.newFile();
202         Files.write(file.toPath(), makeLargeXyString().toString().getBytes(StandardCharsets.UTF_8));
203 
204         verify(checkConfig, file.getPath(), expected);
205     }
206 
207     @Test
208     public void testMinimum() throws Exception {
209         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
210         checkConfig.addAttribute("format", "\\r");
211         checkConfig.addAttribute("minimum", "5");
212         final String[] expected = {
213             "0: " + getCheckMessage(MSG_REGEXP_MINIMUM, "5", "\\r"),
214         };
215 
216         final File file = temporaryFolder.newFile();
217         Files.write(file.toPath(), "".getBytes(StandardCharsets.UTF_8));
218 
219         verify(checkConfig, file.getPath(), expected);
220     }
221 
222     private static CharSequence makeLargeXyString() {
223         // now needs 10'000 or 100'000, as just 1000 is no longer enough today to provoke the
224         // StackOverflowError
225         final int size = 100000;
226         final StringBuilder largeString = new StringBuilder(size);
227         for (int i = 0; i < size / 2; i++) {
228             largeString.append("xy");
229         }
230         return largeString;
231     }
232 
233     @Test
234     public void testSetMessage() throws Exception {
235         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
236         checkConfig.addAttribute("format", "\\n");
237         checkConfig.addAttribute("minimum", "500");
238         checkConfig.addAttribute("message", "someMessage");
239 
240         final String[] expected = new String[223];
241         for (int i = 0; i < 223; i++) {
242             expected[i] = i + ": someMessage";
243         }
244 
245         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
246     }
247 
248     @Test
249     public void testGoodLimit() throws Exception {
250         final DefaultConfiguration checkConfig = createModuleConfig(RegexpMultilineCheck.class);
251         checkConfig.addAttribute("format", "^import");
252         checkConfig.addAttribute("maximum", "5000");
253         final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
254         verify(checkConfig, getPath("InputRegexpMultilineSemantic.java"), expected);
255     }
256 
257 }