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