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