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.imports;
21  
22  import static com.google.common.truth.Truth.assertWithMessage;
23  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_LEX;
24  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_LINE_SEPARATOR;
25  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_NONGROUP_EXPECTED;
26  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_NONGROUP_IMPORT;
27  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_ORDER;
28  import static com.puppycrawl.tools.checkstyle.checks.imports.CustomImportOrderCheck.MSG_SEPARATED_IN_GROUP;
29  
30  import java.io.File;
31  
32  import org.junit.jupiter.api.Test;
33  
34  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
35  import com.puppycrawl.tools.checkstyle.Checker;
36  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
37  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
38  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
39  import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
40  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
41  
42  public class CustomImportOrderCheckTest extends AbstractModuleTestSupport {
43  
44      /** Shortcuts to make code more compact. */
45      private static final String STATIC = CustomImportOrderCheck.STATIC_RULE_GROUP;
46      private static final String SAME = CustomImportOrderCheck.SAME_PACKAGE_RULE_GROUP;
47      private static final String THIRD = CustomImportOrderCheck.THIRD_PARTY_PACKAGE_RULE_GROUP;
48      private static final String STD = CustomImportOrderCheck.STANDARD_JAVA_PACKAGE_RULE_GROUP;
49      private static final String SPECIAL = CustomImportOrderCheck.SPECIAL_IMPORTS_RULE_GROUP;
50  
51      @Override
52      protected String getPackageLocation() {
53          return "com/puppycrawl/tools/checkstyle/checks/imports/customimportorder";
54      }
55  
56      @Test
57      public void testGetRequiredTokens() {
58          final CustomImportOrderCheck checkObj = new CustomImportOrderCheck();
59          final int[] expected = {
60              TokenTypes.IMPORT,
61              TokenTypes.STATIC_IMPORT,
62              TokenTypes.PACKAGE_DEF,
63          };
64          assertWithMessage("Default required tokens are invalid")
65              .that(checkObj.getRequiredTokens())
66              .isEqualTo(expected);
67      }
68  
69      @Test
70      public void testCustom() throws Exception {
71          final String[] expected = {
72              "16:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
73                      "java.io.File.createTempFile"),
74              "17:1: " + getCheckMessage(MSG_LEX, "java.awt.print.Paper.*",
75                      "java.io.File.createTempFile"),
76              "20:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Button"),
77              "21:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Frame"),
78              "22:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Dialog"),
79              "23:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.color.ColorSpace"),
80              "24:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.event.ActionEvent"),
81              "25:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "javax.swing.JComponent"),
82              "26:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "javax.swing.JTable"),
83              "27:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.File"),
84              "28:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.IOException"),
85              "29:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.InputStream"),
86              "30:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.Reader"),
87          };
88  
89          verifyWithInlineConfigParser(
90                  getPath("InputCustomImportOrderDefault.java"), expected);
91      }
92  
93      /**
94       * Checks different group orderings and imports which are out of those
95       * specified in the configuration.
96       */
97      @Test
98      public void testStaticStandardThird() throws Exception {
99          final String[] expected = {
100             "16:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
101                     "java.io.File.createTempFile"),
102             "17:1: " + getCheckMessage(MSG_LEX, "java.awt.print.Paper.*",
103                     "java.io.File.createTempFile"),
104             "22:1: " + getCheckMessage(MSG_LEX, "java.awt.Dialog", "java.awt.Frame"),
105             "27:1: " + getCheckMessage(MSG_LEX, "java.io.File", "javax.swing.JTable"),
106             "28:1: " + getCheckMessage(MSG_LEX, "java.io.IOException", "javax.swing.JTable"),
107             "29:1: " + getCheckMessage(MSG_LEX, "java.io.InputStream", "javax.swing.JTable"),
108             "30:1: " + getCheckMessage(MSG_LEX, "java.io.Reader", "javax.swing.JTable"),
109             "34:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "com.google.common.collect.*"),
110             "34:1: " + getCheckMessage(MSG_LEX, "com.google.common.collect.*",
111                     "com.google.errorprone.annotations.*"),
112         };
113 
114         verifyWithInlineConfigParser(
115                 getPath("InputCustomImportOrderDefault3.java"), expected);
116     }
117 
118     @Test
119     public void testStaticStandardThirdListCustomRules() throws Exception {
120         final String[] expected = {
121             "16:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
122                     "java.io.File.createTempFile"),
123             "17:1: " + getCheckMessage(MSG_LEX, "java.awt.print.Paper.*",
124                     "java.io.File.createTempFile"),
125             "22:1: " + getCheckMessage(MSG_LEX, "java.awt.Dialog", "java.awt.Frame"),
126             "27:1: " + getCheckMessage(MSG_LEX, "java.io.File", "javax.swing.JTable"),
127             "28:1: " + getCheckMessage(MSG_LEX, "java.io.IOException", "javax.swing.JTable"),
128             "29:1: " + getCheckMessage(MSG_LEX, "java.io.InputStream", "javax.swing.JTable"),
129             "30:1: " + getCheckMessage(MSG_LEX, "java.io.Reader", "javax.swing.JTable"),
130             "34:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "com.google.common.collect.*"),
131             "34:1: " + getCheckMessage(MSG_LEX, "com.google.common.collect.*",
132                     "com.google.errorprone.annotations.*"),
133         };
134 
135         verifyWithInlineConfigParser(
136                 getPath("InputCustomImportOrderListRules.java"), expected);
137     }
138 
139     @Test
140     public void testStaticStandardThirdListCustomRulesWhitespace() throws Exception {
141         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
142 
143         verifyWithInlineConfigParser(
144                 getPath("InputCustomImportOrderListRulesWhitespace.java"), expected);
145     }
146 
147     @Test
148     public void testInputCustomImportOrderSingleLineList() throws Exception {
149         final String[] expected = {
150             "14:112: " + getCheckMessage(MSG_LINE_SEPARATOR,
151                 "java.util.Map"),
152             "15:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
153                 "com.google.common.annotations.Beta"),
154             "22:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
155                 "com.puppycrawl.tools.checkstyle.*"),
156             "26:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
157                 "picocli.*"),
158         };
159         verifyWithInlineConfigParser(
160                 getPath("InputCustomImportOrderSingleLineList.java"),
161             expected);
162     }
163 
164     /**
165      * Checks different combinations for same_package group.
166      */
167     @Test
168     public void testNonSpecifiedImports() throws Exception {
169         final String[] expected = {
170             "16:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
171                 "java.io.File.createTempFile"),
172             "17:1: " + getCheckMessage(MSG_LEX, "java.awt.print.Paper.*",
173                 "java.io.File.createTempFile"),
174             "22:1: " + getCheckMessage(MSG_LEX, "java.awt.Dialog", "java.awt.Frame"),
175             "27:1: " + getCheckMessage(MSG_LEX, "java.io.File", "javax.swing.JTable"),
176             "28:1: " + getCheckMessage(MSG_LEX, "java.io.IOException", "javax.swing.JTable"),
177             "29:1: " + getCheckMessage(MSG_LEX, "java.io.InputStream", "javax.swing.JTable"),
178             "30:1: " + getCheckMessage(MSG_LEX, "java.io.Reader", "javax.swing.JTable"),
179             "32:1: " + getCheckMessage(MSG_ORDER, SAME, THIRD, "com.puppycrawl.tools.checkstyle.*"),
180             "34:1: " + getCheckMessage(MSG_NONGROUP_IMPORT, "com.google.common.collect.*"),
181             "35:1: " + getCheckMessage(MSG_LINE_SEPARATOR, "org.junit.*"),
182         };
183 
184         verifyWithInlineConfigParser(
185                 getPath("InputCustomImportOrderDefault4.java"), expected);
186     }
187 
188     @Test
189     public void testOrderRuleEmpty() throws Exception {
190         final String[] expected = {
191             "17:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.List"),
192         };
193 
194         verifyWithInlineConfigParser(
195                 getPath("InputCustomImportOrderEmptyRule.java"), expected);
196     }
197 
198     @Test
199     public void testOrderRuleWithOneGroup() throws Exception {
200         final String[] expected = {
201             "16:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
202                     "java.io.File.createTempFile"),
203             "19:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.List"),
204             "19:1: " + getCheckMessage(MSG_LEX, "java.util.List", "javax.swing.WindowConstants.*"),
205             "20:1: " + getCheckMessage(MSG_LEX, "java.util.StringTokenizer",
206                     "javax.swing.WindowConstants.*"),
207             "21:1: " + getCheckMessage(MSG_LEX, "java.util.*", "javax.swing.WindowConstants.*"),
208             "22:1: " + getCheckMessage(MSG_LEX, "java.util.concurrent.AbstractExecutorService",
209                     "javax.swing.WindowConstants.*"),
210             "23:1: " + getCheckMessage(MSG_LEX, "java.util.concurrent.*",
211                     "javax.swing.WindowConstants.*"),
212             "26:1: " + getCheckMessage(MSG_LEX, "com.google.errorprone.annotations.*",
213                     "com.google.errorprone.annotations.concurrent.*"),
214             "28:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "com.google.common.base.*"),
215             "28:1: " + getCheckMessage(MSG_LEX, "com.google.common.base.*",
216                     "com.google.errorprone.annotations.concurrent.*"),
217         };
218 
219         verifyWithInlineConfigParser(
220                 getPath("InputCustomImportOrderDefault2.java"), expected);
221     }
222 
223     @Test
224     public void testStaticSamePackage() throws Exception {
225         final String[] expected = {
226             "17:1: " + getCheckMessage(MSG_LEX, "java.util.*", "java.util.StringTokenizer"),
227             "18:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.concurrent.*"),
228             "19:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC, "java.awt.Button.ABORT"),
229             "20:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
230                     "javax.swing.WindowConstants.*"),
231             "21:1: " + getCheckMessage(MSG_LEX, "com.puppycrawl.tools.*",
232                     "java.util.StringTokenizer"),
233             "22:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
234                     "java.util.concurrent.AbstractExecutorService"),
235             "23:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
236                     "java.io.File.createTempFile"),
237             "24:1: " + getCheckMessage(MSG_LEX, "com.*", "java.util.StringTokenizer"),
238         };
239 
240         verifyWithInlineConfigParser(
241                 getNonCompilablePath("InputCustomImportOrderSamePackage.java"),
242             expected);
243     }
244 
245     @Test
246     public void testWithoutLineSeparator() throws Exception {
247         final String[] expected = {
248             "17:1: " + getCheckMessage(MSG_LEX, "java.util.*", "java.util.StringTokenizer"),
249             "18:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.concurrent.*"),
250             "19:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC, "java.awt.Button.ABORT"),
251             "20:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
252                     "javax.swing.WindowConstants.*"),
253             "21:1: " + getCheckMessage(MSG_LEX, "com.puppycrawl.tools.*",
254                     "java.util.StringTokenizer"),
255             "22:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
256                     "java.util.concurrent.AbstractExecutorService"),
257             "23:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
258                     "java.io.File.createTempFile"),
259             "24:1: " + getCheckMessage(MSG_LEX, "com.*", "java.util.StringTokenizer"),
260         };
261 
262         verifyWithInlineConfigParser(
263                 getNonCompilablePath("InputCustomImportOrderSamePackage2.java"),
264             expected);
265     }
266 
267     @Test
268     public void testWithoutLineSeparator2() throws Exception {
269         final String[] expected = {
270             "16:1: " + getCheckMessage(MSG_LEX, "java.io.File.createTempFile",
271                 "javax.swing.WindowConstants.*"),
272             "20:1: " + getCheckMessage(MSG_LEX, "java.util.concurrent.locks.*",
273                 "java.util.concurrent.locks.AbstractOwnableSynchronizer.*"),
274         };
275 
276         verifyWithInlineConfigParser(
277                 getPath("InputCustomImportOrder_NoSeparator.java"), expected);
278     }
279 
280     @Test
281     public void testNoValid() throws Exception {
282         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
283 
284         verifyWithInlineConfigParser(
285                 getPath("InputCustomImportOrderNoValid.java"), expected);
286     }
287 
288     @Test
289     public void testPossibleIndexOutOfBoundsException() throws Exception {
290         final String[] expected = {
291             "17:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, THIRD, "org.w3c.dom.Node"),
292         };
293 
294         verifyWithInlineConfigParser(
295                 getPath("InputCustomImportOrderPossibleIndexOutOfBoundsException.java"), expected);
296     }
297 
298     @Test
299     public void testDefaultPackage2() throws Exception {
300 
301         final String[] expected = {
302             "19:1: " + getCheckMessage(MSG_LEX, "java.awt.Button.ABORT",
303                     "java.io.File.createTempFile"),
304             "22:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Button"),
305             "23:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Frame"),
306             "24:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.Dialog"),
307             "25:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.awt.event.ActionEvent"),
308             "26:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "javax.swing.JComponent"),
309             "27:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "javax.swing.JTable"),
310             "28:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.File"),
311             "29:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.IOException"),
312             "30:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.InputStream"),
313             "31:1: " + getCheckMessage(MSG_ORDER, STD, THIRD, "java.io.Reader"),
314             "35:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "com.google.common.*"),
315             "35:1: " + getCheckMessage(MSG_LEX, "com.google.common.*", "com.puppycrawl.tools.*"),
316         };
317 
318         verifyWithInlineConfigParser(
319                 getNonCompilablePath("InputCustomImportOrderDefaultPackage.java"),
320             expected);
321     }
322 
323     @Test
324     public void testWithoutThirdPartyPackage() throws Exception {
325         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
326 
327         verifyWithInlineConfigParser(
328                 getNonCompilablePath("InputCustomImportOrderThirdPartyPackage.java"), expected);
329     }
330 
331     @Test
332     public void testThirdPartyAndSpecialImports() throws Exception {
333         final String[] expected = {
334             "23:1: " + getCheckMessage(MSG_ORDER, THIRD, SPECIAL,
335                 "com.google.common.collect.HashMultimap"),
336         };
337 
338         verifyWithInlineConfigParser(
339                 getNonCompilablePath("InputCustomImportOrderThirdPartyAndSpecial.java"), expected);
340     }
341 
342     @Test
343     public void testCompareImports() throws Exception {
344         final String[] expected = {
345             "16:1: " + getCheckMessage(MSG_LEX, "java.util.Map",
346                 "java.util.Map.Entry"),
347         };
348 
349         verifyWithInlineConfigParser(
350                 getPath("InputCustomImportOrderCompareImports.java"), expected);
351     }
352 
353     @Test
354     public void testFindBetterPatternMatch() throws Exception {
355         final String[] expected = {
356             "20:1: " + getCheckMessage(MSG_ORDER, THIRD, SPECIAL,
357                 "com.google.common.annotations.Beta"),
358         };
359 
360         verifyWithInlineConfigParser(
361                 getPath("InputCustomImportOrderFindBetterPatternMatch.java"), expected);
362     }
363 
364     @Test
365     public void testBeginTreeClear() throws Exception {
366         final DefaultConfiguration checkConfig =
367             createModuleConfig(CustomImportOrderCheck.class);
368         checkConfig.addProperty("specialImportsRegExp", "com");
369         checkConfig.addProperty("separateLineBetweenGroups", "false");
370         checkConfig.addProperty("customImportOrderRules",
371             "STANDARD_JAVA_PACKAGE###SPECIAL_IMPORTS");
372         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
373         final Checker checker = createChecker(checkConfig);
374         final String fileName1 = getPath("InputCustomImportOrderImportsContainingJava.java");
375         final String fileName2 = getPath("InputCustomImportOrderNoValid.java");
376         final File[] files = {
377             new File(fileName1),
378             new File(fileName2),
379         };
380         verify(checker, files, fileName1, expected);
381     }
382 
383     @Test
384     public void testImportsContainingJava() throws Exception {
385         final String[] expected = {
386             "17:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
387                     "com.google.errorprone.annotations.*"),
388         };
389 
390         verifyWithInlineConfigParser(
391                 getPath("InputCustomImportOrderImportsContainingJava.java"), expected);
392     }
393 
394     @Test
395     public void testGetAcceptableTokens() {
396         final CustomImportOrderCheck testCheckObject =
397                 new CustomImportOrderCheck();
398         final int[] actual = testCheckObject.getAcceptableTokens();
399         final int[] expected = {
400             TokenTypes.IMPORT,
401             TokenTypes.STATIC_IMPORT,
402             TokenTypes.PACKAGE_DEF,
403         };
404 
405         assertWithMessage("Default acceptable tokens are invalid")
406             .that(actual)
407             .isEqualTo(expected);
408     }
409 
410     @Test
411     // UT uses Reflection to avoid removing null-validation from static method,
412     // which is a candidate for utility method in the future
413     public void testGetFullImportIdent() throws Exception {
414         final Class<?> clazz = CustomImportOrderCheck.class;
415         final Object t = TestUtil.instantiate(clazz);
416         final Object actual = TestUtil.invokeMethod(t, "getFullImportIdent", new Object[] {null});
417 
418         final String expected = "";
419         assertWithMessage("Invalid getFullImportIdent result")
420             .that(actual)
421             .isEqualTo(expected);
422     }
423 
424     @Test
425     public void testSamePackageDepth2() throws Exception {
426         final String[] expected = {
427             "20:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.*"),
428             "21:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.List"),
429             "22:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.StringTokenizer"),
430             "23:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.concurrent.*"),
431             "24:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
432                     "java.util.concurrent.AbstractExecutorService"),
433             "25:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
434                     "java.util.concurrent.locks.LockSupport"),
435             "26:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.regex.Pattern"),
436             "27:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.regex.Matcher"),
437         };
438 
439         verifyWithInlineConfigParser(
440                 getNonCompilablePath("InputCustomImportOrderSamePackageDepth25.java"),
441             expected);
442     }
443 
444     @Test
445     public void testSamePackageDepth3() throws Exception {
446         final String[] expected = {
447             "23:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME, "java.util.concurrent.*"),
448             "24:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
449                 "java.util.concurrent.AbstractExecutorService"),
450             "25:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
451                 "java.util.concurrent.locks.LockSupport"),
452             };
453 
454         verifyWithInlineConfigParser(
455                 getNonCompilablePath("InputCustomImportOrderSamePackageDepth252.java"),
456             expected);
457     }
458 
459     @Test
460     public void testSamePackageDepth4() throws Exception {
461         final String[] expected = {
462             "25:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SAME,
463                 "java.util.concurrent.locks.LockSupport"),
464             };
465 
466         verifyWithInlineConfigParser(
467                 getNonCompilablePath("InputCustomImportOrderSamePackageDepth253.java"),
468             expected);
469     }
470 
471     @Test
472     public void testSamePackageDepthLongerThenActualPackage() throws Exception {
473         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
474 
475         verifyWithInlineConfigParser(
476                 getNonCompilablePath("InputCustomImportOrderSamePackageDepth254.java"),
477                 expected);
478     }
479 
480     @Test
481     public void testSamePackageDepthNegative() throws Exception {
482 
483         try {
484             final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
485 
486             verifyWithInlineConfigParser(
487                     getPath("InputCustomImportOrderDefault5.java"), expected);
488             assertWithMessage("exception expected").fail();
489         }
490         catch (CheckstyleException exc) {
491             assertWithMessage("Invalid exception message")
492                 .that(exc)
493                 .hasMessageThat()
494                 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker - "
495                         + "cannot initialize module com.puppycrawl.tools.checkstyle.checks"
496                         + ".imports.CustomImportOrderCheck - "
497                         + "Cannot set property 'customImportOrderRules' to "
498                         + "'SAME_PACKAGE(-1)'");
499             assertWithMessage("Invalid exception message")
500                 .that(exc.getCause().getCause().getCause().getCause().getMessage())
501                 .isEqualTo("SAME_PACKAGE rule parameter should be positive integer: "
502                         + "SAME_PACKAGE(-1)");
503         }
504     }
505 
506     @Test
507     public void testSamePackageDepthZero() throws Exception {
508         try {
509             final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
510 
511             verifyWithInlineConfigParser(
512                     getPath("InputCustomImportOrderDefault6.java"), expected);
513             assertWithMessage("exception expected").fail();
514         }
515         catch (CheckstyleException exc) {
516             assertWithMessage("Invalid exception message")
517                 .that(exc.getMessage())
518                 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker - "
519                         + "cannot initialize module com.puppycrawl.tools.checkstyle.checks"
520                         + ".imports.CustomImportOrderCheck - "
521                         + "Cannot set property 'customImportOrderRules' to "
522                         + "'SAME_PACKAGE(0)'");
523             assertWithMessage("Invalid exception message")
524                 .that(exc.getCause().getCause().getCause().getCause().getMessage())
525                 .isEqualTo("SAME_PACKAGE rule parameter should be positive integer: "
526                         + "SAME_PACKAGE(0)");
527         }
528     }
529 
530     @Test
531     public void testUnsupportedRule() throws Exception {
532         try {
533             final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
534 
535             verifyWithInlineConfigParser(
536                     getPath("InputCustomImportOrderDefault7.java"), expected);
537             assertWithMessage("exception expected").fail();
538         }
539         catch (CheckstyleException exc) {
540             assertWithMessage("Invalid exception message")
541                 .that(exc.getMessage())
542                 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker - "
543                         + "cannot initialize module com.puppycrawl.tools.checkstyle.checks"
544                         + ".imports.CustomImportOrderCheck - "
545                         + "Cannot set property 'customImportOrderRules' to "
546                         + "'SAME_PACKAGE(3)###UNSUPPORTED_RULE'");
547             assertWithMessage("Invalid exception message")
548                 .that(exc.getCause().getCause().getCause().getCause().getMessage())
549                 .isEqualTo("Unexpected rule: UNSUPPORTED_RULE");
550         }
551     }
552 
553     @Test
554     public void testSamePackageDepthNotInt() throws Exception {
555         try {
556             final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
557 
558             verifyWithInlineConfigParser(
559                     getPath("InputCustomImportOrderDefault8.java"), expected);
560             assertWithMessage("exception expected").fail();
561         }
562         catch (CheckstyleException exc) {
563             assertWithMessage("Invalid exception message")
564                 .that(exc.getMessage())
565                 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker - "
566                         + "cannot initialize module com.puppycrawl.tools.checkstyle.checks"
567                         + ".imports.CustomImportOrderCheck - "
568                         + "Cannot set property 'customImportOrderRules' to "
569                         + "'SAME_PACKAGE(INT_IS_REQUIRED_HERE)'");
570             assertWithMessage("Invalid exception message")
571                 .that(exc.getCause().getCause().getCause().getCause().getMessage())
572                 .isEqualTo("For input string: \"INT_IS_REQUIRED_HERE\"");
573         }
574     }
575 
576     @Test
577     public void testNoImports() throws Exception {
578         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
579 
580         verifyWithInlineConfigParser(
581                 getPath("InputCustomImportOrder_NoImports.java"), expected);
582     }
583 
584     @Test
585     public void testDefaultConfiguration() throws Exception {
586         final String[] expected = {
587             "20:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.awt.Button"),
588             "32:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.io.*"),
589             "34:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "com.google.common.collect.*"),
590         };
591         verifyWithInlineConfigParser(
592                 getPath("InputCustomImportOrderDefault9.java"), expected);
593     }
594 
595     @Test
596     public void testRulesWithOverlappingPatterns() throws Exception {
597         final String[] expected = {
598             "23:1: " + getCheckMessage(MSG_ORDER, THIRD, STD,
599                 "com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocNodeImpl"),
600             "27:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
601                 "com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck"),
602             "33:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
603                 "com.puppycrawl.tools.checkstyle.checks.javadoc.InvalidJavadocTag"),
604             "35:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD,
605                 "com.puppycrawl.tools.checkstyle.checks.javadoc.WriteTagCheck"),
606             "39:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SPECIAL,
607                 "com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocTag"),
608             "40:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD,
609                 "com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck"),
610             "41:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD,
611                 "com.puppycrawl.tools.checkstyle.checks.javadoc.NonEmptyAtclauseDescriptionCheck"),
612             };
613 
614         verifyWithInlineConfigParser(
615                 getPath("InputCustomImportOrder_OverlappingPatterns.java"), expected);
616     }
617 
618     @Test
619     public void testMultiplePatternMatchesSecondPatternIsLonger() throws Exception {
620         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
621         verifyWithInlineConfigParser(
622                 getPath("InputCustomImportOrder_MultiplePatternMatches.java"),
623             expected);
624     }
625 
626     @Test
627     public void testMultiplePatternMatchesFirstPatternHasLaterPosition() throws Exception {
628         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
629         verifyWithInlineConfigParser(
630                 getPath("InputCustomImportOrder_MultiplePatternMatches2.java"),
631             expected);
632     }
633 
634     @Test
635     public void testMultiplePatternMatchesFirstPatternHasEarlierPosition() throws Exception {
636         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
637         verifyWithInlineConfigParser(
638                 getPath("InputCustomImportOrder_MultiplePatternMatches3.java"),
639             expected);
640     }
641 
642     @Test
643     public void testMultiplePatternMultipleImportFirstPatternHasLaterPosition() throws Exception {
644         final String[] expected = {
645             "16:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD, "org.junit.Test"),
646         };
647         verifyWithInlineConfigParser(
648                 getPath("InputCustomImportOrder_MultiplePatternMultipleImport.java"),
649             expected);
650     }
651 
652     @Test
653     public void testNoPackage() throws Exception {
654         final String[] expected = {
655             "17:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.*"),
656             "19:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.HashMap"),
657             "23:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "javax.net.ServerSocketFactory"),
658             "26:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "javax.net.SocketFactory"),
659         };
660         verifyWithInlineConfigParser(
661                 getNonCompilablePath("InputCustomImportOrderNoPackage.java"),
662             expected);
663     }
664 
665     @Test
666     public void testNoPackage2() throws Exception {
667         final String[] expected = {
668             "18:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
669                 "com.sun.accessibility.internal.resources.*"),
670             "22:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.Arrays"),
671             "30:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
672                 "org.apache.commons.beanutils.converters.ArrayConverter"),
673         };
674         verifyWithInlineConfigParser(
675                 getNonCompilablePath("InputCustomImportOrderNoPackage2.java"),
676             expected);
677     }
678 
679     @Test
680     public void testNoPackage3() throws Exception {
681         final String[] expected = {
682             "17:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
683                 "java.util.Map"),
684             "25:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
685                 "org.apache.*"),
686             "29:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
687                 "antlr.*"),
688         };
689         verifyWithInlineConfigParser(
690                 getNonCompilablePath("InputCustomImportOrderNoPackage3.java"),
691             expected);
692     }
693 
694     @Test
695     public void testInputCustomImportOrderSingleLine() throws Exception {
696         final String[] expected = {
697             "14:112: " + getCheckMessage(MSG_LINE_SEPARATOR,
698                 "java.util.Map"),
699             "15:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
700                 "com.google.common.annotations.Beta"),
701             "22:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
702                 "com.puppycrawl.tools.checkstyle.*"),
703             "26:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
704                 "picocli.*"),
705         };
706         verifyWithInlineConfigParser(
707                 getPath("InputCustomImportOrderSingleLine.java"),
708             expected);
709     }
710 
711     @Test
712     public void testInputCustomImportOrderSingleLine2() throws Exception {
713         final String[] expected = {
714             "14:118: " + getCheckMessage(MSG_LINE_SEPARATOR,
715                 "java.util.Map"),
716         };
717         verifyWithInlineConfigParser(
718                 getNonCompilablePath("InputCustomImportOrderSingleLine2.java"),
719             expected);
720     }
721 
722     @Test
723     public void testInputCustomImportOrderThirdPartyAndSpecial2() throws Exception {
724         final String[] expected = {
725             "21:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
726                 "javax.swing.WindowConstants.*"),
727             "24:1: " + getCheckMessage(MSG_LINE_SEPARATOR,
728                 "java.awt.Button"),
729             "28:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
730                 "java.awt.Dialog"),
731             "34:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
732                 "com.google.common.*"),
733             "40:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
734                 "org.apache.commons.collections.*"),
735             "45:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
736                 "com.puppycrawl.tools.checkstyle.checks.imports.AbstractImportRule"),
737             "51:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
738                 "antlr.Token"),
739             "53:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
740                 "antlr.collections.AST"),
741         };
742         verifyWithInlineConfigParser(
743                 getNonCompilablePath("InputCustomImportOrderThirdPartyAndSpecial2.java"), expected);
744     }
745 
746     @Test
747     public void testInputCustomImportOrderMultipleViolationsSameLine() throws Exception {
748         final String[] expected = {
749             "17:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
750                 "java.util.Collections.*"),
751             "18:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STATIC,
752                 "java.lang.String.CASE_INSENSITIVE_ORDER"),
753             "21:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP,
754                 "java.net.Socket"),
755             "21:1: " + getCheckMessage(MSG_LEX, "java.net.Socket",
756                 "java.util.*"),
757         };
758         verifyWithInlineConfigParser(
759                 getNonCompilablePath("InputCustomImportOrderViolationsSameLine.java"),
760             expected);
761     }
762 
763     @Test
764     public void testInputCustomImportOrderSpanMultipleLines() throws Exception {
765         final String[] expected = {
766             "30:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.BitSet"),
767             "45:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "java.util.HashSet"),
768             "49:1: " + getCheckMessage(MSG_LINE_SEPARATOR, "org.apache.tools.ant.*"),
769             "54:1: " + getCheckMessage(MSG_LINE_SEPARATOR, "com.puppycrawl.tools.checkstyle.*"),
770             "58:1: " + getCheckMessage(MSG_LINE_SEPARATOR, "picocli.*"),
771             "61:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "picocli.CommandLine"),
772         };
773         verifyWithInlineConfigParser(
774                 getPath("InputCustomImportOrderSpanMultipleLines.java"), expected);
775     }
776 
777     @Test
778     public void testInputCustomImportOrderEclipseDefaultPositive() throws Exception {
779         final String[] expected = {
780             "22:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD, "java.awt.Button"),
781             "23:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD, "java.awt.Dialog"),
782             "24:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, STD, "java.io.InputStream"),
783             "26:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SPECIAL, "javax.swing.JComponent"),
784             "27:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, SPECIAL, "javax.swing.JTable"),
785             "29:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, THIRD, "org.junit.Test"),
786             "30:1: " + getCheckMessage(MSG_NONGROUP_EXPECTED, THIRD,
787                     "org.mockito.Mock"),
788             "34:1: " + getCheckMessage(MSG_SEPARATED_IN_GROUP, "sun.tools.java.ArrayType"),
789         };
790         verifyWithInlineConfigParser(
791                 getNonCompilablePath("InputCustomImportOrderEclipseDefaultPositive.java"),
792                 expected);
793     }
794 
795     @Test
796     public void testInputCustomImportOrderSpecialImportsRegExp() throws Exception {
797         final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
798         verifyWithInlineConfigParser(
799                 getPath("InputCustomImportOrderSpecialImportsRegExp.java"),
800                 expected);
801     }
802 }