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