View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.header;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.header.RegexpHeaderCheck.MSG_HEADER_MISMATCH;
24  import static com.puppycrawl.tools.checkstyle.checks.header.RegexpHeaderCheck.MSG_HEADER_MISSING;
25  
26  import java.util.List;
27  import java.util.Locale;
28  import java.util.regex.Pattern;
29  
30  import org.junit.jupiter.api.Test;
31  
32  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
33  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
34  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
35  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
36  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
37  
38  /**
39   * Unit test for RegexpHeaderCheck.
40   */
41  public class RegexpHeaderCheckTest extends AbstractModuleTestSupport {
42  
43      @Override
44      protected String getPackageLocation() {
45          return "com/puppycrawl/tools/checkstyle/checks/header/regexpheader";
46      }
47  
48      /**
49       * Test of setHeader method, of class RegexpHeaderCheck.
50       */
51      @Test
52      public void testSetHeaderNull() {
53          // check null passes
54          final RegexpHeaderCheck instance = new RegexpHeaderCheck();
55          // recreate for each test because multiple invocations fail
56          final String header = null;
57          instance.setHeader(header);
58          final List<Pattern> headerRegexps = TestUtil.getInternalStateListPattern(
59                  instance, "headerRegexps");
60  
61          assertWithMessage("When header is null regexps should not be set")
62                  .that(headerRegexps)
63                  .isEmpty();
64      }
65  
66      /**
67       * Test of setHeader method, of class RegexpHeaderCheck.
68       */
69      @Test
70      public void testSetHeaderEmpty() {
71          // check null passes
72          final RegexpHeaderCheck instance = new RegexpHeaderCheck();
73          // check empty string passes
74          final String header = "";
75          instance.setHeader(header);
76          final List<Pattern> headerRegexps = TestUtil.getInternalStateListPattern(
77                  instance, "headerRegexps");
78  
79          assertWithMessage("When header is empty regexps should not be set")
80                  .that(headerRegexps)
81                  .isEmpty();
82      }
83  
84      /**
85       * Test of setHeader method, of class RegexpHeaderCheck.
86       */
87  
88      @Test
89      public void testSetHeaderSimple() {
90          final RegexpHeaderCheck instance = new RegexpHeaderCheck();
91          // check valid header passes
92          final String header = "abc.*";
93          instance.setHeader(header);
94          final List<Pattern> headerRegexps = TestUtil.getInternalStateListPattern(
95                  instance, "headerRegexps");
96          assertWithMessage("Expected one pattern")
97              .that(headerRegexps.size())
98              .isEqualTo(1);
99          assertWithMessage("Invalid header regexp")
100             .that(headerRegexps.get(0).pattern())
101             .isEqualTo(header);
102     }
103 
104     /**
105      * Test of setHeader method, of class RegexpHeaderCheck.
106      */
107     @Test
108     public void testSetHeader() {
109         // check invalid header passes
110         final RegexpHeaderCheck instance = new RegexpHeaderCheck();
111         try {
112             final String header = "^/**\\n * Licensed to the Apache Software Foundation (ASF)";
113             instance.setHeader(header);
114             assertWithMessage(String.format(Locale.ROOT, "%s should have been thrown",
115                     IllegalArgumentException.class)).fail();
116         }
117         catch (IllegalArgumentException exc) {
118             assertWithMessage("Invalid exception message")
119                 .that(exc.getMessage())
120                 .isEqualTo("Unable to parse format: ^/**\\n *"
121                     + " Licensed to the Apache Software Foundation (ASF)");
122         }
123     }
124 
125     @Test
126     public void testDefaultConfiguration() throws Exception {
127         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
128         createChecker(checkConfig);
129         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
130         // Content header is conflicting with Input inline header
131         verify(checkConfig, getPath("InputRegexpHeaderDefaultConfig.java"), expected);
132     }
133 
134     @Test
135     public void testEmptyFilename() throws Exception {
136         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
137         checkConfig.addProperty("headerFile", "");
138         try {
139             createChecker(checkConfig);
140             assertWithMessage("Checker creation should not succeed with invalid headerFile").fail();
141         }
142         catch (CheckstyleException exc) {
143             assertWithMessage("Invalid exception message")
144                 .that(exc.getMessage())
145                 .isEqualTo("cannot initialize module"
146                     + " com.puppycrawl.tools.checkstyle.checks.header.RegexpHeaderCheck"
147                     + " - Cannot set property 'headerFile' to ''");
148         }
149     }
150 
151     @Test
152     public void testRegexpHeader() throws Exception {
153         final DefaultConfiguration checkConfig =
154                 createModuleConfig(RegexpHeaderCheck.class);
155         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader.header"));
156         final String[] expected = {
157             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "// Created: 2002"),
158         };
159         // Content header is conflicting with Input inline header
160         verify(checkConfig, getPath("InputRegexpHeaderIgnore.java"), expected);
161     }
162 
163     @Test
164     public void testNonMatchingRegexpHeader() throws Exception {
165         final DefaultConfiguration checkConfig =
166             createModuleConfig(RegexpHeaderCheck.class);
167         checkConfig.addProperty("header",
168                                 "\\/\\/ Nth Line of Header\\n\\/\\/ Nth Line of Header\\n");
169         checkConfig.addProperty("multiLines", "1");
170         final String[] expected = {
171             "1: " + getCheckMessage(MSG_HEADER_MISMATCH, "\\/\\/ Nth Line of Header"),
172         };
173         // Content header is conflicting with Input inline header
174         verify(checkConfig, getPath("InputRegexpHeaderNonMatching.java"), expected);
175     }
176 
177     @Test
178     public void testRegexpHeaderUrl() throws Exception {
179         final DefaultConfiguration checkConfig =
180                 createModuleConfig(RegexpHeaderCheck.class);
181         checkConfig.addProperty("headerFile", getUriString("InputRegexpHeader.header"));
182         final String[] expected = {
183             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "// Created: 2002"),
184         };
185         // Content header is conflicting with Input inline header
186         verify(checkConfig, getPath("InputRegexpHeaderIgnore.java"), expected);
187     }
188 
189     @Test
190     public void testInlineRegexpHeader() throws Exception {
191         final DefaultConfiguration checkConfig =
192                 createModuleConfig(RegexpHeaderCheck.class);
193         checkConfig.addProperty("header", "^/*$\\n// .*\\n// Created: 2002\\n^//.*\\n^//.*");
194         final String[] expected = {
195             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "// Created: 2002"),
196         };
197         // Content header is conflicting with Input inline header
198         verify(checkConfig, getPath("InputRegexpHeaderIgnore.java"), expected);
199     }
200 
201     @Test
202     public void testFailureForMultilineRegexp() throws Exception {
203         final DefaultConfiguration checkConfig =
204                 createModuleConfig(RegexpHeaderCheck.class);
205         checkConfig.addProperty("header", "^(.*\\n.*)");
206         try {
207             createChecker(checkConfig);
208             assertWithMessage(
209                     "Checker creation should not succeed when regexp spans multiple lines").fail();
210         }
211         catch (CheckstyleException exc) {
212             assertWithMessage("Invalid exception message")
213                 .that(exc.getMessage())
214                 .isEqualTo("cannot initialize module"
215                     + " com.puppycrawl.tools.checkstyle.checks.header.RegexpHeaderCheck"
216                     + " - Cannot set property 'header' to '^(.*\\n.*)'");
217         }
218     }
219 
220     @Test
221     public void testInlineRegexpHeaderConsecutiveNewlines() throws Exception {
222         final DefaultConfiguration checkConfig =
223                 createModuleConfig(RegexpHeaderCheck.class);
224         checkConfig.addProperty("header", "^/*$\\n// .*\\n\\n// Created: 2017\\n^//.*");
225         final String[] expected = {
226             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "^$"),
227         };
228         // Content header is conflicting with Input inline header
229         verify(checkConfig, getPath("InputRegexpHeaderConsecutiveNewLines.java"), expected);
230     }
231 
232     @Test
233     public void testInlineRegexpHeaderConsecutiveNewlinesThroughConfigFile() throws Exception {
234         final DefaultConfiguration checkConfig =
235                 createModuleConfig(RegexpHeaderCheck.class);
236         checkConfig.addProperty("headerFile", getUriString("InputRegexpHeaderNewLines.header"));
237         final String[] expected = {
238             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "^$"),
239         };
240         // Content header is conflicting with Input inline header
241         verify(checkConfig, getPath("InputRegexpHeaderConsecutiveNewLines.java"), expected);
242     }
243 
244     @Test
245     public void testRegexpHeaderIgnore() throws Exception {
246         final DefaultConfiguration checkConfig =
247                 createModuleConfig(RegexpHeaderCheck.class);
248         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader1.header"));
249         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
250         // Content header is conflicting with Input inline header
251         verify(checkConfig, getPath("InputRegexpHeaderIgnore.java"), expected);
252     }
253 
254     @Test
255     public void testRegexpHeaderMulti1() throws Exception {
256         final DefaultConfiguration checkConfig =
257                 createModuleConfig(RegexpHeaderCheck.class);
258         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
259         checkConfig.addProperty("multiLines", "3, 6");
260         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
261         // Content header is conflicting with Input inline header
262         verify(checkConfig, getPath("InputRegexpHeaderDefaultConfig.java"), expected);
263     }
264 
265     @Test
266     public void testRegexpHeaderMulti2() throws Exception {
267         final DefaultConfiguration checkConfig =
268                 createModuleConfig(RegexpHeaderCheck.class);
269         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
270         checkConfig.addProperty("multiLines", "3, 6");
271         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
272         // Content header is conflicting with Input inline header
273         verify(checkConfig, getPath("InputRegexpHeaderMulti2.java"), expected);
274     }
275 
276     @Test
277     public void testRegexpHeaderMulti3() throws Exception {
278         final DefaultConfiguration checkConfig =
279                 createModuleConfig(RegexpHeaderCheck.class);
280         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
281         checkConfig.addProperty("multiLines", "3, 7");
282         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
283         // Content header is conflicting with Input inline header
284         verify(checkConfig, getPath("InputRegexpHeaderDefaultConfig.java"), expected);
285     }
286 
287     @Test
288     public void testRegexpHeaderMulti4() throws Exception {
289         final DefaultConfiguration checkConfig =
290                 createModuleConfig(RegexpHeaderCheck.class);
291         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
292         checkConfig.addProperty("multiLines", "3, 5, 6, 7");
293         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
294         // Content header is conflicting with Input inline header
295         verify(checkConfig, getPath("InputRegexpHeaderMulti4.java"), expected);
296     }
297 
298     @Test
299     public void testRegexpHeaderMulti5() throws Exception {
300         final DefaultConfiguration checkConfig =
301                 createModuleConfig(RegexpHeaderCheck.class);
302         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
303         checkConfig.addProperty("multiLines", "3");
304         final String[] expected = {
305             "1: " + getCheckMessage(MSG_HEADER_MISSING),
306         };
307         // Content header is conflicting with Input inline header
308         verify(checkConfig, getPath("InputRegexpHeaderMulti5.java"), expected);
309     }
310 
311     @Test
312     public void testRegexpHeaderMulti6() throws Exception {
313         final DefaultConfiguration checkConfig =
314                 createModuleConfig(RegexpHeaderCheck.class);
315         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2_4.header"));
316         checkConfig.addProperty("multiLines", "8974382");
317         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
318         // Content header is conflicting with Input inline header
319         verify(checkConfig, getPath("InputRegexpHeaderMulti6.java"), expected);
320     }
321 
322     @Test
323     public void testRegexpHeaderSmallHeader() throws Exception {
324         final DefaultConfiguration checkConfig =
325                 createModuleConfig(RegexpHeaderCheck.class);
326         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
327         checkConfig.addProperty("multiLines", "3, 6");
328         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
329         // Content header is conflicting with Input inline header
330         verify(checkConfig, getPath("InputRegexpHeaderSmallHeader.java"), expected);
331     }
332 
333     @Test
334     public void testEmptyMultiline()
335             throws Exception {
336         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
337         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader2.header"));
338         checkConfig.addProperty("multiLines", "");
339         final String[] expected = {
340             "1: " + getCheckMessage(MSG_HEADER_MISSING),
341         };
342         // Content header is conflicting with Input inline header
343         verify(checkConfig, getPath("InputRegexpHeaderSmallHeader.java"), expected);
344     }
345 
346     @Test
347     public void testRegexpHeaderMulti52()
348             throws Exception {
349         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
350         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader3.header"));
351         final String[] expected = {
352             "1: " + getCheckMessage(MSG_HEADER_MISSING),
353         };
354         // Content header is conflicting with Input inline header
355         verify(checkConfig, getPath("InputRegexpHeaderMulti52.java"), expected);
356     }
357 
358     @Test
359     public void testIgnoreLinesSorted() throws Exception {
360         final DefaultConfiguration checkConfig =
361                 createModuleConfig(RegexpHeaderCheck.class);
362         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader5.header"));
363         checkConfig.addProperty("multiLines", "7,5,3");
364         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
365         // Content header is conflicting with Input inline header
366         verify(checkConfig, getPath("InputRegexpHeaderIgnoreLinesSorted.java"), expected);
367     }
368 
369     @Test
370     public void testHeaderWithInvalidRegexp() throws Exception {
371         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
372         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader.invalid.header"));
373         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
374         final String path = getPath("InputRegexpHeaderMulti52.java");
375         try {
376             // Content header is conflicting with Input inline header
377             verify(checkConfig, path, expected);
378             assertWithMessage("IllegalArgumentException is expected").fail();
379         }
380         catch (IllegalArgumentException exc) {
381             assertWithMessage("Invalid exception message")
382                 .that(exc.getMessage())
383                 .isEqualTo("line 3 in header specification is not a regular expression");
384         }
385     }
386 
387     @Test
388     public void testNoWarningIfSingleLinedLeft() throws Exception {
389         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
390         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader4.header"));
391         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
392         // Content header is conflicting with Input inline header
393         verify(checkConfig, getPath("InputRegexpHeaderMulti5.java"), expected);
394     }
395 
396     @Test
397     public void testNoHeaderMissingErrorInCaseHeaderSizeEqualToFileSize() throws Exception {
398         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
399         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader3.header"));
400         checkConfig.addProperty("multiLines", "1");
401         final String[] expected = {
402             "5: " + getCheckMessage(MSG_HEADER_MISMATCH, "^$"),
403         };
404         // Content header is conflicting with Input inline header
405         verify(checkConfig, getPath("InputRegexpHeaderMulti52.java"), expected);
406     }
407 
408     @Test
409     public void testCharsetProperty1() throws Exception {
410         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
411         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader7.header"));
412         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
413         final String path = getPath("InputRegexpHeader4.java");
414         // Content header is conflicting with Input inline header
415         verify(checkConfig, path, expected);
416     }
417 
418     @Test
419     public void testCharsetProperty2() throws Exception {
420         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
421         checkConfig.addProperty("charset", "US-ASCII");
422         checkConfig.addProperty("headerFile", getPath("InputRegexpHeader7.header"));
423         final String[] expected = {
424             // -@cs[RegexpSinglelineJava] need for testing
425             "3: " + getCheckMessage(MSG_HEADER_MISMATCH, "// some.class.��������.passed"),
426         };
427         final String path = getPath("InputRegexpHeader4.java");
428         // Content header is conflicting with Input inline header
429         verify(checkConfig, path, expected);
430 
431     }
432 
433     @Test
434     public void testCharsetProperty3() throws Exception {
435         final DefaultConfiguration checkConfig = createModuleConfig(RegexpHeaderCheck.class);
436         checkConfig.addProperty("headerFile",
437                 getPath("InputRegexpHeader7.header"));
438         checkConfig.addProperty("charset", "US-ASCII");
439         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
440         final String path = getPath("InputRegexpHeader3.java");
441         // Content header is conflicting with Input inline header
442         verify(checkConfig, path, expected);
443     }
444 }