View Javadoc
1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2017 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
23  import static org.junit.Assert.assertEquals;
24  import static org.junit.Assert.assertFalse;
25  import static org.junit.Assert.assertNotEquals;
26  import static org.junit.Assert.assertTrue;
27  import static org.junit.Assert.fail;
28  import static org.mockito.Matchers.any;
29  import static org.mockito.Mockito.times;
30  import static org.powermock.api.mockito.PowerMockito.doNothing;
31  import static org.powermock.api.mockito.PowerMockito.mock;
32  import static org.powermock.api.mockito.PowerMockito.mockStatic;
33  import static org.powermock.api.mockito.PowerMockito.verifyStatic;
34  import static org.powermock.api.mockito.PowerMockito.when;
35  
36  import java.io.File;
37  import java.io.IOException;
38  import java.io.InputStream;
39  import java.io.OutputStream;
40  import java.lang.reflect.InvocationTargetException;
41  import java.lang.reflect.Method;
42  import java.nio.charset.StandardCharsets;
43  import java.nio.file.Files;
44  import java.nio.file.Paths;
45  import java.util.ArrayList;
46  import java.util.List;
47  import java.util.Locale;
48  import java.util.ResourceBundle;
49  import java.util.logging.Handler;
50  import java.util.logging.Level;
51  import java.util.logging.Logger;
52  import java.util.regex.Pattern;
53  
54  import org.apache.commons.io.FileUtils;
55  import org.junit.Before;
56  import org.junit.Rule;
57  import org.junit.Test;
58  import org.junit.contrib.java.lang.system.ExpectedSystemExit;
59  import org.junit.contrib.java.lang.system.SystemErrRule;
60  import org.junit.contrib.java.lang.system.SystemOutRule;
61  import org.junit.rules.TemporaryFolder;
62  import org.junit.runner.RunWith;
63  import org.mockito.ArgumentCaptor;
64  import org.powermock.core.classloader.annotations.PrepareForTest;
65  import org.powermock.modules.junit4.PowerMockRunner;
66  
67  import com.google.common.io.Closeables;
68  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
69  import com.puppycrawl.tools.checkstyle.api.Configuration;
70  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
71  import com.puppycrawl.tools.checkstyle.internal.testmodules.TestRootModuleChecker;
72  import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
73  
74  @RunWith(PowerMockRunner.class)
75  @PrepareForTest({Main.class, CommonUtils.class, Closeables.class})
76  public class MainTest {
77      private static final String USAGE = String.format(Locale.ROOT,
78            "usage: java com.puppycrawl.tools.checkstyle.Main [options] -c <config.xml>"
79          + " file...%n"
80          + " -c <arg>                                Sets the check configuration file to use.%n"
81          + " -C,--checker-threads-number <arg>       (experimental) The number of Checker threads "
82          + "(must be%n"
83          + "                                         greater than zero)%n"
84          + " -d,--debug                              Print all debug logging of CheckStyle utility%n"
85          + " -e,--exclude <arg>                      Directory path to exclude from CheckStyle%n"
86          + " -executeIgnoredModules                  Allows ignored modules to be run.%n"
87          + " -f <arg>                                Sets the output format. (plain|xml). Defaults"
88          + " to plain%n"
89          + " -j,--javadocTree                        Print Parse tree of the Javadoc comment%n"
90          + " -J,--treeWithJavadoc                    Print full Abstract Syntax Tree of the file%n"
91          + " -o <arg>                                Sets the output file. Defaults to stdout%n"
92          + " -p <arg>                                Loads the properties file%n"
93          + " -t,--tree                               Print Abstract Syntax Tree(AST) of the file%n"
94          + " -T,--treeWithComments                   Print Abstract Syntax Tree(AST) of the file"
95          + " including%n"
96          + "                                         comments%n"
97          + " -v                                      Print product version and exit%n"
98          + " -W,--tree-walker-threads-number <arg>   (experimental) The number of TreeWalker threads"
99          + " (must be%n"
100         + "                                         greater than zero)%n"
101         + " -x,--exclude-regexp <arg>               Regular expression of directory to exclude from"
102         + " CheckStyle%n");
103 
104     private static final Logger LOG = Logger.getLogger(MainTest.class.getName()).getParent();
105     private static final Handler[] HANDLERS = LOG.getHandlers();
106     private static final Level ORIGINAL_LOG_LEVEL = LOG.getLevel();
107 
108     private static final String EOL = System.getProperty("line.separator");
109 
110     @Rule
111     public final TemporaryFolder temporaryFolder = new TemporaryFolder();
112     @Rule
113     public final ExpectedSystemExit exit = ExpectedSystemExit.none();
114     @Rule
115     public final SystemErrRule systemErr = new SystemErrRule().enableLog().mute();
116     @Rule
117     public final SystemOutRule systemOut = new SystemOutRule().enableLog().mute();
118 
119     private final LocalizedMessage auditStartMessage = new LocalizedMessage(0,
120             Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditStarted", null, null,
121             getClass(), null);
122 
123     private final LocalizedMessage auditFinishMessage = new LocalizedMessage(0,
124             Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditFinished", null, null,
125             getClass(), null);
126 
127     private final LocalizedMessage errorCounterOneMessage = new LocalizedMessage(0,
128             Definitions.CHECKSTYLE_BUNDLE, Main.ERROR_COUNTER,
129             new String[] {String.valueOf(1)}, null, getClass(), null);
130 
131     private static String getPath(String filename) {
132         return "src/test/resources/com/puppycrawl/tools/checkstyle/main/" + filename;
133     }
134 
135     private static String getNonCompilablePath(String filename) {
136         return "src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/main/" + filename;
137     }
138 
139     private static String getFilePath(String filename) throws IOException {
140         return new File(getPath(filename)).getCanonicalPath();
141     }
142 
143     @Before
144     public void setUp() {
145         // restore original logging level and HANDLERS to prevent bleeding into other tests
146 
147         LOG.setLevel(ORIGINAL_LOG_LEVEL);
148 
149         for (Handler handler : LOG.getHandlers()) {
150             boolean found = false;
151 
152             for (Handler savedHandler : HANDLERS) {
153                 if (handler == savedHandler) {
154                     found = true;
155                     break;
156                 }
157             }
158 
159             if (!found) {
160                 LOG.removeHandler(handler);
161             }
162         }
163     }
164 
165     @Test
166     public void testIsProperUtilsClass() throws ReflectiveOperationException {
167         assertTrue("Constructor is not private",
168                 isUtilsClassHasPrivateConstructor(Main.class, false));
169     }
170 
171     @Test
172     public void testVersionPrint()
173             throws Exception {
174 
175         exit.checkAssertionAfterwards(() -> {
176             assertEquals("Unexpected output log",
177                     "Checkstyle version: null" + System.lineSeparator(),
178                     systemOut.getLog());
179             assertEquals("Unexpected system error log", "", systemErr.getLog());
180         });
181         Main.main("-v");
182     }
183 
184     @Test
185     public void testWrongArgument()
186             throws Exception {
187         exit.expectSystemExitWithStatus(-1);
188         exit.checkAssertionAfterwards(() -> {
189             final String usage = "Unrecognized option: -w" + EOL
190                     + USAGE;
191             assertEquals("Unexpected output log", usage, systemOut.getLog());
192             assertEquals("Unexpected system error log", "", systemErr.getLog());
193         });
194         Main.main("-w");
195     }
196 
197     @Test
198     public void testNoConfigSpecified()
199             throws Exception {
200         exit.expectSystemExitWithStatus(-1);
201         exit.checkAssertionAfterwards(() -> {
202             assertEquals("Unexpected output log",
203                     "Must specify a config XML file." + System.lineSeparator(),
204                     systemOut.getLog());
205             assertEquals("Unexpected system error log", "", systemErr.getLog());
206         });
207         Main.main(getPath("InputMain.java"));
208     }
209 
210     @Test
211     public void testNonExistentTargetFile()
212             throws Exception {
213         exit.expectSystemExitWithStatus(-1);
214         exit.checkAssertionAfterwards(() -> {
215             assertEquals("Unexpected output log", "Files to process must be specified, found 0."
216                 + System.lineSeparator(), systemOut.getLog());
217             assertEquals("Unexpected system error log", "", systemErr.getLog());
218         });
219         Main.main("-c", "/google_checks.xml", "NonExistentFile.java");
220     }
221 
222     @Test
223     public void testNonExistentConfigFile()
224             throws Exception {
225         exit.expectSystemExitWithStatus(-1);
226         exit.checkAssertionAfterwards(() -> {
227             assertEquals("Unexpected output log", "Could not find config XML file "
228                         + "'src/main/resources/non_existent_config.xml'." + EOL,
229                     systemOut.getLog());
230             assertEquals("Unexpected system error log", "", systemErr.getLog());
231         });
232         Main.main("-c", "src/main/resources/non_existent_config.xml",
233                 getPath("InputMain.java"));
234     }
235 
236     @Test
237     public void testNonExistentOutputFormat() throws Exception {
238         exit.expectSystemExitWithStatus(-1);
239         exit.checkAssertionAfterwards(() -> {
240             assertEquals("Unexpected output log", "Invalid output format. "
241                     + "Found 'xmlp' but expected 'plain' or 'xml'." + EOL, systemOut.getLog());
242             assertEquals("Unexpected system error log", "", systemErr.getLog());
243         });
244         Main.main("-c", "/google_checks.xml", "-f", "xmlp",
245                 getPath("InputMain.java"));
246     }
247 
248     @Test
249     public void testNonExistentClass() throws Exception {
250         exit.expectSystemExitWithStatus(-2);
251         exit.checkAssertionAfterwards(() -> {
252             final String expectedExceptionMessage = errorCounterOneMessage.getMessage() + EOL;
253             assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
254 
255             final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
256                     + " cannot initialize module TreeWalker - ";
257             assertTrue("Unexpected system error log", systemErr.getLog().startsWith(cause));
258         });
259 
260         Main.main("-c", getPath("InputMainConfig-non-existent-classname.xml"),
261             getPath("InputMain.java"));
262     }
263 
264     @Test
265     public void testExistingTargetFile() throws Exception {
266 
267         exit.checkAssertionAfterwards(() -> {
268             assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
269                     + auditFinishMessage.getMessage() + EOL,
270                     systemOut.getLog());
271             assertEquals("Unexpected system error log", "", systemErr.getLog());
272         });
273         Main.main("-c", getPath("InputMainConfig-classname.xml"),
274                 getPath("InputMain.java"));
275     }
276 
277     @Test
278     public void testExistingTargetFileXmlOutput() throws Exception {
279 
280         exit.checkAssertionAfterwards(() -> {
281             final String expectedPath = getFilePath("InputMain.java");
282             final ResourceBundle compilationProperties =
283                     ResourceBundle.getBundle("checkstylecompilation", Locale.ROOT);
284             final String version = compilationProperties
285                 .getString("checkstyle.compile.version");
286             assertEquals("Unexpected output log", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL
287                     + "<checkstyle version=\"" + version + "\">" + EOL
288                     + "<file name=\"" + expectedPath + "\">" + EOL
289                     + "</file>" + EOL
290                     + "</checkstyle>" + EOL, systemOut.getLog());
291             assertEquals("Unexpected system error log", "", systemErr.getLog());
292         });
293         Main.main("-c", getPath("InputMainConfig-classname.xml"),
294                 "-f", "xml",
295                 getPath("InputMain.java"));
296     }
297 
298     @Test
299     public void testExistingTargetFilePlainOutput() throws Exception {
300 
301         exit.checkAssertionAfterwards(() -> {
302             assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
303                     + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
304             assertEquals("Unexpected system error log", "", systemErr.getLog());
305         });
306         Main.main("-c", getPath("InputMainConfig-classname.xml"),
307                 "-f", "plain",
308                 getPath("InputMain.java"));
309     }
310 
311     @Test
312     public void testExistingTargetFileWithViolations() throws Exception {
313         exit.checkAssertionAfterwards(() -> {
314             final LocalizedMessage invalidPatternMessageMain = new LocalizedMessage(0,
315                     "com.puppycrawl.tools.checkstyle.checks.naming.messages",
316                     "name.invalidPattern", new String[] {"InputMain", "^[a-z0-9]*$"},
317                     null, getClass(), null);
318             final LocalizedMessage invalidPatternMessageMainInner = new LocalizedMessage(0,
319                     "com.puppycrawl.tools.checkstyle.checks.naming.messages",
320                     "name.invalidPattern", new String[] {"InputMainInner", "^[a-z0-9]*$"},
321                     null, getClass(), null);
322             final String expectedPath = getFilePath("InputMain.java");
323             assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
324                             + "[WARN] " + expectedPath + ":3:14: "
325                             + invalidPatternMessageMain.getMessage()
326                             + " [TypeName]" + EOL
327                             + "[WARN] " + expectedPath + ":5:7: "
328                             + invalidPatternMessageMainInner.getMessage()
329                             + " [TypeName]" + EOL
330                             + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
331             assertEquals("Unexpected system error log", "", systemErr.getLog());
332         });
333         Main.main("-c", getPath("InputMainConfig-classname2.xml"),
334                 getPath("InputMain.java"));
335     }
336 
337     @Test
338     public void testExistingTargetFileWithError()
339             throws Exception {
340         exit.expectSystemExitWithStatus(2);
341         exit.checkAssertionAfterwards(() -> {
342             final LocalizedMessage errorCounterTwoMessage = new LocalizedMessage(0,
343                     Definitions.CHECKSTYLE_BUNDLE, Main.ERROR_COUNTER,
344                     new String[] {String.valueOf(2)}, null, getClass(), null);
345             final LocalizedMessage invalidPatternMessageMain = new LocalizedMessage(0,
346                     "com.puppycrawl.tools.checkstyle.checks.naming.messages",
347                     "name.invalidPattern", new String[] {"InputMain", "^[a-z0-9]*$"},
348                     null, getClass(), null);
349             final LocalizedMessage invalidPatternMessageMainInner = new LocalizedMessage(0,
350                     "com.puppycrawl.tools.checkstyle.checks.naming.messages",
351                     "name.invalidPattern", new String[] {"InputMainInner", "^[a-z0-9]*$"},
352                     null, getClass(), null);
353             final String expectedPath = getFilePath("InputMain.java");
354             assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
355                     + "[ERROR] " + expectedPath + ":3:14: "
356                     + invalidPatternMessageMain.getMessage() + " [TypeName]" + EOL
357                     + "[ERROR] " + expectedPath + ":5:7: "
358                     + invalidPatternMessageMainInner.getMessage() + " [TypeName]" + EOL
359                     + auditFinishMessage.getMessage() + EOL
360                     + errorCounterTwoMessage.getMessage() + EOL, systemOut.getLog());
361             assertEquals("Unexpected system error log", "", systemErr.getLog());
362         });
363         Main.main("-c",
364                 getPath("InputMainConfig-classname2-error.xml"),
365                 getPath("InputMain.java"));
366     }
367 
368     @Test
369     public void testExistentTargetFilePlainOutputToNonExistentFile()
370             throws Exception {
371 
372         exit.checkAssertionAfterwards(() -> {
373             assertEquals("Unexpected output log", "", systemOut.getLog());
374             assertEquals("Unexpected system error log", "", systemErr.getLog());
375         });
376         Main.main("-c", getPath("InputMainConfig-classname.xml"),
377                 "-f", "plain",
378                 "-o", temporaryFolder.getRoot() + "/output.txt",
379                 getPath("InputMain.java"));
380     }
381 
382     @Test
383     public void testExistingTargetFilePlainOutputToFile()
384             throws Exception {
385         final File file = temporaryFolder.newFile("file.output");
386         exit.checkAssertionAfterwards(() -> {
387             assertEquals("Unexpected output log", "", systemOut.getLog());
388             assertEquals("Unexpected system error log", "", systemErr.getLog());
389         });
390         Main.main("-c", getPath("InputMainConfig-classname.xml"),
391                 "-f", "plain",
392                 "-o", file.getCanonicalPath(),
393                 getPath("InputMain.java"));
394     }
395 
396     @Test
397     public void testCreateNonExistentOutputFile() throws Exception {
398         final String outputFile = temporaryFolder.getRoot().getCanonicalPath() + "nonexistent.out";
399         assertFalse("File must not exist", new File(outputFile).exists());
400         Main.main("-c", getPath("InputMainConfig-classname.xml"),
401                 "-f", "plain",
402                 "-o", outputFile,
403                 getPath("InputMain.java"));
404         assertTrue("File must exist", new File(outputFile).exists());
405     }
406 
407     @Test
408     public void testExistingTargetFilePlainOutputProperties() throws Exception {
409         mockStatic(Closeables.class);
410         doNothing().when(Closeables.class);
411         Closeables.closeQuietly(any(InputStream.class));
412 
413         //exit.expectSystemExitWithStatus(0);
414         exit.checkAssertionAfterwards(() -> {
415             assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
416                     + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
417             assertEquals("Unexpected system error log", "", systemErr.getLog());
418         });
419         Main.main("-c", getPath("InputMainConfig-classname-prop.xml"),
420                 "-p", getPath("InputMainMycheckstyle.properties"),
421                 getPath("InputMain.java"));
422 
423         verifyStatic(times(1));
424         Closeables.closeQuietly(any(InputStream.class));
425     }
426 
427     @Test
428     public void testExistingTargetFilePlainOutputNonexistentProperties()
429             throws Exception {
430         exit.expectSystemExitWithStatus(-1);
431         exit.checkAssertionAfterwards(() -> {
432             assertEquals("Unexpected output log", "Could not find file 'nonexistent.properties'."
433                     + System.lineSeparator(), systemOut.getLog());
434             assertEquals("Unexpected system error log", "", systemErr.getLog());
435         });
436         Main.main("-c", getPath("InputMainConfig-classname-prop.xml"),
437                 "-p", "nonexistent.properties",
438                 getPath("InputMain.java"));
439     }
440 
441     @Test
442     public void testExistingIncorrectConfigFile()
443             throws Exception {
444         exit.expectSystemExitWithStatus(-2);
445         exit.checkAssertionAfterwards(() -> {
446             final String output = errorCounterOneMessage.getMessage() + EOL;
447             assertEquals("Unexpected output log", output, systemOut.getLog());
448             final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
449                 + "CheckstyleException: unable to parse configuration stream - ";
450             assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
451         });
452         Main.main("-c", getPath("InputMainConfig-Incorrect.xml"),
453             getPath("InputMain.java"));
454     }
455 
456     @Test
457     public void testExistingIncorrectChildrenInConfigFile()
458             throws Exception {
459         exit.expectSystemExitWithStatus(-2);
460         exit.checkAssertionAfterwards(() -> {
461             final String output = errorCounterOneMessage.getMessage() + EOL;
462             assertEquals("Unexpected output log", output, systemOut.getLog());
463             final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
464                     + "CheckstyleException: cannot initialize module RegexpSingleline"
465                     + " - RegexpSingleline is not allowed as a child in RegexpSingleline";
466             assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
467         });
468         Main.main("-c", getPath("InputMainConfig-incorrectChildren.xml"),
469             getPath("InputMain.java"));
470     }
471 
472     @Test
473     public void testExistingIncorrectChildrenInConfigFile2()
474             throws Exception {
475         exit.expectSystemExitWithStatus(-2);
476         exit.checkAssertionAfterwards(() -> {
477             final String output = errorCounterOneMessage.getMessage() + EOL;
478             assertEquals("Unexpected output log", output, systemOut.getLog());
479             final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
480                     + "CheckstyleException: cannot initialize module TreeWalker"
481                     + " - JavadocVariable is not allowed as a child in JavadocMethod";
482             assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
483         });
484         Main.main("-c", getPath("InputMainConfig-incorrectChildren2.xml"),
485             getPath("InputMain.java"));
486     }
487 
488     @Test
489     public void testLoadPropertiesIoException() throws Exception {
490         final Class<?>[] param = new Class<?>[1];
491         param[0] = File.class;
492         final Method method = Main.class.getDeclaredMethod("loadProperties", param);
493         method.setAccessible(true);
494         try {
495             if (System.getProperty("os.name").toLowerCase(Locale.ENGLISH).startsWith("windows")) {
496                 // https://support.microsoft.com/en-us/kb/177506 but this only for NTFS
497                 // WindowsServer 2012 use Resilient File System (ReFS), so any name is ok
498                 final File file = new File(File.separator + ":invalid");
499                 if (file.exists()) {
500                     file.delete();
501                 }
502                 method.invoke(null, new File(file.getAbsolutePath()));
503             }
504             else {
505                 method.invoke(null, new File(File.separator + "\0:invalid"));
506             }
507             fail("Exception was expected");
508         }
509         catch (InvocationTargetException ex) {
510             assertTrue("Invalid error cause",
511                     ex.getCause() instanceof CheckstyleException);
512             // We do separate validation for message as in Windows
513             // disk drive letter appear in message,
514             // so we skip that drive letter for compatibility issues
515             final LocalizedMessage loadPropertiesMessage = new LocalizedMessage(0,
516                     Definitions.CHECKSTYLE_BUNDLE, Main.LOAD_PROPERTIES_EXCEPTION,
517                     new String[] {""}, null, getClass(), null);
518             final String causeMessage = ex.getCause().getLocalizedMessage();
519             final String localizedMessage = loadPropertiesMessage.getMessage();
520             final boolean samePrefix = causeMessage.substring(0, causeMessage.indexOf(' '))
521                     .equals(localizedMessage
522                             .substring(0, localizedMessage.indexOf(' ')));
523             final boolean sameSuffix =
524                     causeMessage.substring(causeMessage.lastIndexOf(' '), causeMessage.length())
525                     .equals(localizedMessage
526                             .substring(localizedMessage.lastIndexOf(' '),
527                                     localizedMessage.length()));
528             assertTrue("Invalid error message", samePrefix || sameSuffix);
529             assertTrue("Invalid error message",
530                     causeMessage.contains(":invalid"));
531         }
532     }
533 
534     @Test
535     public void testCreateListenerIllegalStateException() throws Exception {
536         final Method method = Main.class.getDeclaredMethod("createListener", String.class,
537             String.class);
538         method.setAccessible(true);
539         try {
540             method.invoke(null, "myformat", null);
541             fail("InvocationTargetException is expected");
542         }
543         catch (InvocationTargetException ex) {
544             final LocalizedMessage loadPropertiesMessage = new LocalizedMessage(0,
545                     Definitions.CHECKSTYLE_BUNDLE, Main.CREATE_LISTENER_EXCEPTION,
546                     new String[] {"myformat", "plain", "xml"}, null, getClass(), null);
547             assertEquals("Invalid error message",
548                     loadPropertiesMessage.getMessage(), ex.getCause().getLocalizedMessage());
549             assertTrue("Invalid error cause",
550                     ex.getCause() instanceof IllegalStateException);
551         }
552     }
553 
554     @Test
555     public void testCreateListenerWithLocationIllegalStateException() throws Exception {
556         mockStatic(CommonUtils.class);
557         doNothing().when(CommonUtils.class);
558         CommonUtils.close(any(OutputStream.class));
559 
560         final Method method = Main.class.getDeclaredMethod("createListener", String.class,
561             String.class);
562         method.setAccessible(true);
563         final String outDir = "myfolder123";
564         try {
565             method.invoke(null, "myformat", outDir);
566             fail("InvocationTargetException  is expected");
567         }
568         catch (InvocationTargetException ex) {
569             final LocalizedMessage createListenerMessage = new LocalizedMessage(0,
570                     Definitions.CHECKSTYLE_BUNDLE, Main.CREATE_LISTENER_EXCEPTION,
571                     new String[] {"myformat", "plain", "xml"}, null, getClass(), null);
572             assertEquals("Invalid error message",
573                     createListenerMessage.getMessage(), ex.getCause().getLocalizedMessage());
574             assertTrue("Invalid error cause",
575                     ex.getCause() instanceof IllegalStateException);
576         }
577         finally {
578             verifyStatic(times(1));
579             final ArgumentCaptor<OutputStream> out =
580                     ArgumentCaptor.forClass(OutputStream.class);
581             CommonUtils.close(out.capture());
582             out.getValue().close();
583             // method creates output folder
584             FileUtils.deleteQuietly(new File(outDir));
585         }
586     }
587 
588     @Test
589     public void testExistingDirectoryWithViolations() throws Exception {
590 
591         // we just reference there all violations
592         final String[][] outputValues = {
593                 {"InputMainComplexityOverflow", "1", "172"},
594         };
595 
596         final int allowedLength = 170;
597         final String msgKey = "maxLen.file";
598         final String bundle = "com.puppycrawl.tools.checkstyle.checks.sizes.messages";
599 
600         exit.checkAssertionAfterwards(() -> {
601             final String expectedPath = getFilePath("") + File.separator;
602             final StringBuilder sb = new StringBuilder(28);
603             sb.append(auditStartMessage.getMessage())
604                     .append(EOL);
605             final String format = "[WARN] " + expectedPath + outputValues[0][0] + ".java:"
606                     + outputValues[0][1] + ": ";
607             for (String[] outputValue : outputValues) {
608                 final String localizedMessage = new LocalizedMessage(0, bundle,
609                         msgKey, new Integer[] {Integer.valueOf(outputValue[2]), allowedLength},
610                         null, getClass(), null).getMessage();
611                 final String line = format + localizedMessage + " [FileLength]";
612                 sb.append(line).append(EOL);
613             }
614             sb.append(auditFinishMessage.getMessage())
615                     .append(EOL);
616             assertEquals("Unexpected output log", sb.toString(), systemOut.getLog());
617             assertEquals("Unexpected system error log", "", systemErr.getLog());
618         });
619 
620         Main.main("-c", getPath("InputMainConfig-filelength.xml"),
621                 getPath(""));
622     }
623 
624     @Test
625     @SuppressWarnings("unchecked")
626     public void testListFilesNotFile() throws Exception {
627         final Method method = Main.class.getDeclaredMethod("listFiles", File.class, List.class);
628         method.setAccessible(true);
629 
630         final File fileMock = mock(File.class);
631         when(fileMock.canRead()).thenReturn(true);
632         when(fileMock.isDirectory()).thenReturn(false);
633         when(fileMock.isFile()).thenReturn(false);
634 
635         final List<File> result = (List<File>) method.invoke(null, fileMock, null);
636         assertEquals("Invalid result size", 0, result.size());
637     }
638 
639     @Test
640     @SuppressWarnings("unchecked")
641     public void testListFilesDirectoryWithNull() throws Exception {
642         final Method method = Main.class.getDeclaredMethod("listFiles", File.class, List.class);
643         method.setAccessible(true);
644 
645         final File fileMock = mock(File.class);
646         when(fileMock.canRead()).thenReturn(true);
647         when(fileMock.isDirectory()).thenReturn(true);
648         when(fileMock.listFiles()).thenReturn(null);
649 
650         final List<File> result = (List<File>) method.invoke(null, fileMock,
651                 new ArrayList<Pattern>());
652         assertEquals("Invalid result size", 0, result.size());
653     }
654 
655     @Test
656     public void testFileReferenceDuringException() throws Exception {
657         exit.expectSystemExitWithStatus(-2);
658         exit.checkAssertionAfterwards(() -> {
659             final String expectedExceptionMessage = auditStartMessage.getMessage() + EOL
660                             + errorCounterOneMessage.getMessage() + EOL;
661             assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
662 
663             final String exceptionFirstLine = "com.puppycrawl.tools.checkstyle.api."
664                     + "CheckstyleException: Exception was thrown while processing "
665                     + new File(getNonCompilablePath("InputMainIncorrectClass.java")).getPath()
666                     + EOL;
667             assertTrue("Unexpected system error log",
668                     systemErr.getLog().startsWith(exceptionFirstLine));
669         });
670 
671         // We put xml as source to cause parse exception
672         Main.main("-c", getPath("InputMainConfig-classname.xml"),
673                 getNonCompilablePath("InputMainIncorrectClass.java"));
674     }
675 
676     @Test
677     public void testPrintTreeOnMoreThanOneFile() throws Exception {
678 
679         exit.expectSystemExitWithStatus(-1);
680         exit.checkAssertionAfterwards(() -> {
681             assertEquals("Unexpected output log", "Printing AST is allowed for only one file."
682                 + System.lineSeparator(), systemOut.getLog());
683             assertEquals("Unexpected system error log", "", systemErr.getLog());
684         });
685 
686         Main.main("-t", getPath(""));
687     }
688 
689     @Test
690     public void testPrintTreeOption() throws Exception {
691         final String expected = "PACKAGE_DEF -> package [1:0]" + EOL
692             + "|--ANNOTATIONS -> ANNOTATIONS [1:39]" + EOL
693             + "|--DOT -> . [1:39]" + EOL
694             + "|   |--DOT -> . [1:28]" + EOL
695             + "|   |   |--DOT -> . [1:22]" + EOL
696             + "|   |   |   |--DOT -> . [1:11]" + EOL
697             + "|   |   |   |   |--IDENT -> com [1:8]" + EOL
698             + "|   |   |   |   `--IDENT -> puppycrawl [1:12]" + EOL
699             + "|   |   |   `--IDENT -> tools [1:23]" + EOL
700             + "|   |   `--IDENT -> checkstyle [1:29]" + EOL
701             + "|   `--IDENT -> main [1:40]" + EOL
702             + "`--SEMI -> ; [1:44]" + EOL
703             + "CLASS_DEF -> CLASS_DEF [3:0]" + EOL
704             + "|--MODIFIERS -> MODIFIERS [3:0]" + EOL
705             + "|   `--LITERAL_PUBLIC -> public [3:0]" + EOL
706             + "|--LITERAL_CLASS -> class [3:7]" + EOL
707             + "|--IDENT -> InputMain [3:13]" + EOL
708             + "`--OBJBLOCK -> OBJBLOCK [3:23]" + EOL
709             + "    |--LCURLY -> { [3:23]" + EOL
710             + "    `--RCURLY -> } [4:0]" + EOL
711             + "CLASS_DEF -> CLASS_DEF [5:0]" + EOL
712             + "|--MODIFIERS -> MODIFIERS [5:0]" + EOL
713             + "|--LITERAL_CLASS -> class [5:0]" + EOL
714             + "|--IDENT -> InputMainInner [5:6]" + EOL
715             + "`--OBJBLOCK -> OBJBLOCK [5:21]" + EOL
716             + "    |--LCURLY -> { [5:21]" + EOL
717             + "    `--RCURLY -> } [6:0]" + EOL;
718 
719         exit.checkAssertionAfterwards(() -> {
720             assertEquals("Unexpected output log", expected, systemOut.getLog());
721             assertEquals("Unexpected system error log", "", systemErr.getLog());
722         });
723         Main.main("-t", getPath("InputMain.java"));
724     }
725 
726     @Test
727     public void testPrintTreeCommentsOption() throws Exception {
728         final String expected = "PACKAGE_DEF -> package [1:0]" + EOL
729             + "|--ANNOTATIONS -> ANNOTATIONS [1:39]" + EOL
730             + "|--DOT -> . [1:39]" + EOL
731             + "|   |--DOT -> . [1:28]" + EOL
732             + "|   |   |--DOT -> . [1:22]" + EOL
733             + "|   |   |   |--DOT -> . [1:11]" + EOL
734             + "|   |   |   |   |--IDENT -> com [1:8]" + EOL
735             + "|   |   |   |   `--IDENT -> puppycrawl [1:12]" + EOL
736             + "|   |   |   `--IDENT -> tools [1:23]" + EOL
737             + "|   |   `--IDENT -> checkstyle [1:29]" + EOL
738             + "|   `--IDENT -> main [1:40]" + EOL
739             + "`--SEMI -> ; [1:44]" + EOL
740             + "CLASS_DEF -> CLASS_DEF [3:0]" + EOL
741             + "|--MODIFIERS -> MODIFIERS [3:0]" + EOL
742             + "|   |--BLOCK_COMMENT_BEGIN -> /* [2:0]" + EOL
743             + "|   |   |--COMMENT_CONTENT -> comment [2:2]" + EOL
744             + "|   |   `--BLOCK_COMMENT_END -> */ [2:8]" + EOL
745             + "|   `--LITERAL_PUBLIC -> public [3:0]" + EOL
746             + "|--LITERAL_CLASS -> class [3:7]" + EOL
747             + "|--IDENT -> InputMain [3:13]" + EOL
748             + "`--OBJBLOCK -> OBJBLOCK [3:23]" + EOL
749             + "    |--LCURLY -> { [3:23]" + EOL
750             + "    `--RCURLY -> } [4:0]" + EOL
751             + "CLASS_DEF -> CLASS_DEF [5:0]" + EOL
752             + "|--MODIFIERS -> MODIFIERS [5:0]" + EOL
753             + "|--LITERAL_CLASS -> class [5:0]" + EOL
754             + "|--IDENT -> InputMainInner [5:6]" + EOL
755             + "`--OBJBLOCK -> OBJBLOCK [5:21]" + EOL
756             + "    |--LCURLY -> { [5:21]" + EOL
757             + "    `--RCURLY -> } [6:0]" + EOL;
758 
759         exit.checkAssertionAfterwards(() -> {
760             assertEquals("Unexpected output log", expected, systemOut.getLog());
761             assertEquals("Unexpected system error log", "", systemErr.getLog());
762         });
763         Main.main("-T", getPath("InputMain.java"));
764     }
765 
766     @Test
767     public void testPrintTreeJavadocOption() throws Exception {
768         final String expected = new String(Files.readAllBytes(Paths.get(
769             getPath("InputMainExpectedInputJavadocComment.txt"))), StandardCharsets.UTF_8)
770             .replaceAll("\\\\r\\\\n", "\\\\n");
771 
772         exit.checkAssertionAfterwards(() -> {
773             assertEquals("Unexpected output log",
774                     expected, systemOut.getLog().replaceAll("\\\\r\\\\n", "\\\\n"));
775             assertEquals("Unexpected system error log",
776                     "", systemErr.getLog());
777         });
778         Main.main("-j", getPath("InputMainJavadocComment.javadoc"));
779     }
780 
781     @Test
782     public void testPrintFullTreeOption() throws Exception {
783         final String expected = new String(Files.readAllBytes(Paths.get(
784             getPath("InputMainExpectedInputAstTreeStringPrinterJavadoc.txt"))),
785             StandardCharsets.UTF_8).replaceAll("\\\\r\\\\n", "\\\\n");
786 
787         exit.checkAssertionAfterwards(() -> {
788             assertEquals("Unexpected output log",
789                     expected, systemOut.getLog().replaceAll("\\\\r\\\\n", "\\\\n"));
790             assertEquals("Unexpected system error log", "", systemErr.getLog());
791         });
792         Main.main("-J", getPath("InputMainAstTreeStringPrinterJavadoc.java"));
793     }
794 
795     @Test
796     public void testConflictingOptionsTvsC() throws Exception {
797 
798         exit.expectSystemExitWithStatus(-1);
799         exit.checkAssertionAfterwards(() -> {
800             assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
801                 + System.lineSeparator(), systemOut.getLog());
802             assertEquals("Unexpected system error log", "", systemErr.getLog());
803         });
804 
805         Main.main("-c", "/google_checks.xml", "-t", getPath(""));
806     }
807 
808     @Test
809     public void testConflictingOptionsTvsP() throws Exception {
810 
811         exit.expectSystemExitWithStatus(-1);
812         exit.checkAssertionAfterwards(() -> {
813             assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
814                 + System.lineSeparator(), systemOut.getLog());
815             assertEquals("Unexpected system error log", "", systemErr.getLog());
816         });
817 
818         Main.main("-p", getPath("InputMainMycheckstyle.properties"), "-t", getPath(""));
819     }
820 
821     @Test
822     public void testConflictingOptionsTvsF() throws Exception {
823 
824         exit.expectSystemExitWithStatus(-1);
825         exit.checkAssertionAfterwards(() -> {
826             assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
827                 + System.lineSeparator(), systemOut.getLog());
828             assertEquals("Unexpected system error log", "", systemErr.getLog());
829         });
830 
831         Main.main("-f", "plain", "-t", getPath(""));
832     }
833 
834     @Test
835     public void testConflictingOptionsTvsO() throws Exception {
836         final File file = temporaryFolder.newFile("file.output");
837 
838         exit.expectSystemExitWithStatus(-1);
839         exit.checkAssertionAfterwards(() -> {
840             assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
841                 + System.lineSeparator(), systemOut.getLog());
842             assertEquals("Unexpected system error log", "", systemErr.getLog());
843         });
844 
845         Main.main("-o", file.getCanonicalPath(), "-t", getPath(""));
846     }
847 
848     @Test
849     public void testDebugOption() throws Exception {
850         exit.checkAssertionAfterwards(() -> assertNotEquals("Unexpected system error log",
851                         "", systemErr.getLog()));
852         Main.main("-c", "/google_checks.xml", getPath("InputMain.java"), "-d");
853     }
854 
855     @Test
856     public void testExcludeOption() throws Exception {
857         exit.expectSystemExitWithStatus(-1);
858         exit.checkAssertionAfterwards(() -> {
859             assertEquals("Unexpected output log", "Files to process must be specified, found 0."
860                 + System.lineSeparator(), systemOut.getLog());
861             assertEquals("Unexpected system error log", "", systemErr.getLog());
862         });
863         Main.main("-c", "/google_checks.xml", getFilePath(""), "-e", getFilePath(""));
864     }
865 
866     @Test
867     public void testExcludeRegexpOption() throws Exception {
868         exit.expectSystemExitWithStatus(-1);
869         exit.checkAssertionAfterwards(() -> {
870             assertEquals("Unexpected output log", "Files to process must be specified, found 0."
871                 + System.lineSeparator(), systemOut.getLog());
872             assertEquals("Unexpected output log", "", systemErr.getLog());
873         });
874         Main.main("-c", "/google_checks.xml", getFilePath(""), "-x", ".");
875     }
876 
877     @Test
878     @SuppressWarnings("unchecked")
879     public void testExcludeDirectoryNotMatch() throws Exception {
880         final Method method = Main.class.getDeclaredMethod("listFiles", File.class, List.class);
881         method.setAccessible(true);
882         final List<Pattern> list = new ArrayList<>();
883         list.add(Pattern.compile("BAD_PATH"));
884 
885         final List<File> result = (List<File>) method.invoke(null, new File(getFilePath("")),
886                 list);
887         assertNotEquals("Invalid result size", 0, result.size());
888     }
889 
890     @Test
891     public void testCustomRootModule() throws Exception {
892         TestRootModuleChecker.reset();
893 
894         exit.checkAssertionAfterwards(() -> {
895             assertEquals("Unexpected output log", "", systemOut.getLog());
896             assertEquals("Unexpected system error log", "", systemErr.getLog());
897             assertTrue("Invalid Checker state", TestRootModuleChecker.isProcessed());
898         });
899         Main.main("-c", getPath("InputMainConfig-custom-root-module.xml"),
900                 getPath("InputMain.java"));
901         assertTrue("RootModule should be destroyed", TestRootModuleChecker.isDestroyed());
902     }
903 
904     @Test
905     public void testCustomSimpleRootModule() throws Exception {
906         TestRootModuleChecker.reset();
907         exit.expectSystemExitWithStatus(-2);
908         exit.checkAssertionAfterwards(() -> {
909             final String checkstylePackage = "com.puppycrawl.tools.checkstyle.";
910             final LocalizedMessage unableToInstantiateExceptionMessage = new LocalizedMessage(0,
911                     Definitions.CHECKSTYLE_BUNDLE,
912                     "PackageObjectFactory.unableToInstantiateExceptionMessage",
913                     new String[] {"TestRootModuleChecker", checkstylePackage
914                             + "TestRootModuleChecker, "
915                             + "TestRootModuleCheckerCheck, " + checkstylePackage
916                             + "TestRootModuleCheckerCheck"},
917                     null, getClass(), null);
918             assertEquals("Unexpected output log", errorCounterOneMessage.getMessage() + EOL,
919                     systemOut.getLog());
920             assertTrue("Unexpected system error log",
921                     systemErr.getLog().startsWith(checkstylePackage + "api.CheckstyleException: "
922                     + unableToInstantiateExceptionMessage.getMessage()));
923             assertFalse("Invalid checker state", TestRootModuleChecker.isProcessed());
924         });
925         Main.main("-c", getPath("InputMainConfig-custom-simple-root-module.xml"),
926                 getPath("InputMain.java"));
927     }
928 
929     @Test
930     public void testExecuteIgnoredModule() throws Exception {
931         exit.expectSystemExitWithStatus(-2);
932         exit.checkAssertionAfterwards(() -> {
933             final String expectedExceptionMessage = errorCounterOneMessage.getMessage() + EOL;
934             assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
935 
936             final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
937                     + " cannot initialize module TreeWalker - ";
938             assertTrue("Unexpected system error log", systemErr.getLog().startsWith(cause));
939         });
940 
941         Main.main("-c", getPath("InputMainConfig-non-existent-classname-ignore.xml"),
942                 "-executeIgnoredModules",
943                 getPath("InputMain.java"));
944     }
945 
946     @Test
947     public void testInvalidCheckerThreadsNumber() throws Exception {
948         exit.expectSystemExitWithStatus(-1);
949         exit.checkAssertionAfterwards(() -> {
950             assertEquals("Unexpected output log", "Invalid Checker threads number"
951                 + System.lineSeparator(), systemOut.getLog());
952             assertEquals("Unexpected system error log", "", systemErr.getLog());
953         });
954         Main.main("-C", "invalid", "-c", "/google_checks.xml", getPath("InputMain.java"));
955     }
956 
957     @Test
958     public void testInvalidTreeWalkerThreadsNumber() throws Exception {
959         exit.expectSystemExitWithStatus(-1);
960         exit.checkAssertionAfterwards(() -> {
961             assertEquals("Unexpected output log", "Invalid TreeWalker threads number"
962                 + System.lineSeparator(), systemOut.getLog());
963             assertEquals("Unexpected system error log", "", systemErr.getLog());
964         });
965         Main.main("-W", "invalid", "-c", "/google_checks.xml", getPath("InputMain.java"));
966     }
967 
968     @Test
969     public void testZeroCheckerThreadsNumber() throws Exception {
970         exit.expectSystemExitWithStatus(-1);
971         exit.checkAssertionAfterwards(() -> {
972             assertEquals("Unexpected output log", "Checker threads number must be greater than zero"
973                 + System.lineSeparator(), systemOut.getLog());
974             assertEquals("Unexpected system error log", "", systemErr.getLog());
975         });
976         Main.main("-C", "0", "-c", "/google_checks.xml", getPath("InputMain.java"));
977     }
978 
979     @Test
980     public void testZeroTreeWalkerThreadsNumber() throws Exception {
981         exit.expectSystemExitWithStatus(-1);
982         exit.checkAssertionAfterwards(() -> {
983             assertEquals("Unexpected output log",
984                     "TreeWalker threads number must be greater than zero"
985                 + System.lineSeparator(), systemOut.getLog());
986             assertEquals("Unexpected system error log", "", systemErr.getLog());
987         });
988         Main.main("-W", "0", "-c", "/google_checks.xml", getPath("InputMain.java"));
989     }
990 
991     @Test
992     public void testCheckerThreadsNumber() throws Exception {
993         TestRootModuleChecker.reset();
994 
995         exit.checkAssertionAfterwards(() -> {
996             assertEquals("Unexpected output log", "", systemOut.getLog());
997             assertEquals("Unexpected system error log", "", systemErr.getLog());
998             assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
999             final DefaultConfiguration config =
1000                     (DefaultConfiguration) TestRootModuleChecker.getConfig();
1001             final ThreadModeSettings multiThreadModeSettings = config.getThreadModeSettings();
1002             assertEquals("Invalid checker thread number",
1003                     4, multiThreadModeSettings.getCheckerThreadsNumber());
1004             assertEquals("Invalid checker thread number",
1005                     1, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1006         });
1007         Main.main("-C", "4", "-c", getPath("InputMainConfig-custom-root-module.xml"),
1008             getPath("InputMain.java"));
1009     }
1010 
1011     @Test
1012     public void testTreeWalkerThreadsNumber() throws Exception {
1013         TestRootModuleChecker.reset();
1014 
1015         exit.checkAssertionAfterwards(() -> {
1016             assertEquals("Unexpected output log", "", systemOut.getLog());
1017             assertEquals("Unexpected system error log", "", systemErr.getLog());
1018             assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
1019             final DefaultConfiguration config =
1020                     (DefaultConfiguration) TestRootModuleChecker.getConfig();
1021             final ThreadModeSettings multiThreadModeSettings = config.getThreadModeSettings();
1022             assertEquals("Invalid checker thread number",
1023                     1, multiThreadModeSettings.getCheckerThreadsNumber());
1024             assertEquals("Invalid checker thread number",
1025                     4, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1026         });
1027         Main.main("-W", "4", "-c", getPath("InputMainConfig-custom-root-module.xml"),
1028             getPath("InputMain.java"));
1029     }
1030 
1031     @Test
1032     public void testModuleNameInSingleThreadMode() throws Exception {
1033         TestRootModuleChecker.reset();
1034 
1035         exit.checkAssertionAfterwards(() -> {
1036             assertEquals("Unexpected output log", "", systemOut.getLog());
1037             assertEquals("Unexpected system error log", "", systemErr.getLog());
1038             assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
1039             final DefaultConfiguration config =
1040                     (DefaultConfiguration) TestRootModuleChecker.getConfig();
1041             final ThreadModeSettings multiThreadModeSettings =
1042                 config.getThreadModeSettings();
1043             assertEquals("Invalid checker thread number",
1044                     1, multiThreadModeSettings.getCheckerThreadsNumber());
1045             assertEquals("Invalid checker thread number",
1046                     1, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1047             final Configuration checkerConfiguration = config
1048                 .getChildren()[0];
1049             assertEquals("Invalid checker name", "Checker", checkerConfiguration.getName());
1050             final Configuration treeWalkerConfig = checkerConfiguration.getChildren()[0];
1051             assertEquals("Invalid checker children name", "TreeWalker", treeWalkerConfig.getName());
1052         });
1053         Main.main("-C", "1", "-W", "1", "-c", getPath("InputMainConfig-multi-thread-mode.xml"),
1054             getPath("InputMain.java"));
1055     }
1056 
1057     @Test
1058     public void testModuleNameInMultiThreadMode() throws Exception {
1059         TestRootModuleChecker.reset();
1060 
1061         try {
1062             Main.main("-C", "4", "-W", "4", "-c", getPath("InputMainConfig-multi-thread-mode.xml"),
1063                 getPath("InputMain.java"));
1064             fail("An exception is expected");
1065         }
1066         catch (IllegalArgumentException ex) {
1067             assertEquals("Invalid error message",
1068                     "Multi thread mode for Checker module is not implemented",
1069                 ex.getMessage());
1070         }
1071     }
1072 }