1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
29 import java.io.ByteArrayOutputStream;
30 import java.io.File;
31 import java.io.IOException;
32 import java.lang.reflect.InvocationTargetException;
33 import java.lang.reflect.Method;
34 import java.nio.charset.StandardCharsets;
35 import java.nio.file.Files;
36 import java.nio.file.Paths;
37 import java.util.ArrayList;
38 import java.util.List;
39 import java.util.Locale;
40 import java.util.logging.Handler;
41 import java.util.logging.Level;
42 import java.util.logging.Logger;
43 import java.util.regex.Pattern;
44
45 import org.junit.Before;
46 import org.junit.Rule;
47 import org.junit.Test;
48 import org.junit.contrib.java.lang.system.ExpectedSystemExit;
49 import org.junit.contrib.java.lang.system.SystemErrRule;
50 import org.junit.contrib.java.lang.system.SystemOutRule;
51 import org.junit.rules.TemporaryFolder;
52 import org.powermock.reflect.Whitebox;
53
54 import com.puppycrawl.tools.checkstyle.api.AuditListener;
55 import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
56 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
57 import com.puppycrawl.tools.checkstyle.api.Configuration;
58 import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
59 import com.puppycrawl.tools.checkstyle.internal.testmodules.TestRootModuleChecker;
60
61 public class MainTest {
62
63 private static final String SHORT_USAGE = String.format(Locale.ROOT,
64 "Usage: checkstyle [OPTIONS]... FILES...%n"
65 + "Try 'checkstyle --help' for more information.%n");
66
67 private static final String USAGE = String.format(Locale.ROOT,
68 "Usage: checkstyle [-dghjJtTV] [--executeIgnoredModules] [--tabWidth=<tabWidth>]%n"
69 + " [-c=<configurationFile>] [-C=<checkerThreadsNumber>]"
70 + " [-f=<format>]%n"
71 + " [-o=<outputPath>] [-p=<propertiesFile>]"
72 + " [-s=<suppressionLineColumnNumber>]%n"
73 + " [-W=<treeWalkerThreadsNumber>] [-e=<exclude>]..."
74 + " [-x=<excludeRegex>]... <files>...%n"
75 + "Checkstyle verifies that the specified source code files adhere to the specified"
76 + " rules. By default%n"
77 + "errors are reported to standard out in plain format. Checkstyle requires a"
78 + " configuration XML file%n"
79 + "that configures the checks to apply.%n"
80 + " <files>... One or more source files to verify%n"
81 + " --executeIgnoredModules%n"
82 + " Allows ignored modules to be run.%n"
83 + " --tabWidth=<tabWidth> Sets the length of the tab character. Used only with"
84 + " \"-s\" option. Default%n"
85 + " value is 8%n"
86 + " -c=<configurationFile> Sets the check configuration file to use.%n"
87 + " -C, --checker-threads-number=<checkerThreadsNumber>%n"
88 + " (experimental) The number of Checker threads (must be"
89 + " greater than zero)%n"
90 + " -d, --debug Print all debug logging of CheckStyle utility%n"
91 + " -e, --exclude=<exclude> Directory/File path to exclude from CheckStyle%n"
92 + " -f=<format> Sets the output format. Valid values: xml, plain."
93 + " Defaults to plain%n"
94 + " -g, --generate-xpath-suppression%n"
95 + " Generates to output a suppression.xml to use to suppress"
96 + " all violations from%n"
97 + " user's config%n"
98 + " -h, --help Show this help message and exit.%n"
99 + " -j, --javadocTree Print Parse tree of the Javadoc comment%n"
100 + " -J, --treeWithJavadoc Print full Abstract Syntax Tree of the file%n"
101 + " -o=<outputPath> Sets the output file. Defaults to stdout%n"
102 + " -p=<propertiesFile> Loads the properties file%n"
103 + " -s=<suppressionLineColumnNumber>%n"
104 + " Print xpath suppressions at the file's line and column"
105 + " position. Argument is%n"
106 + " the line and column number (separated by a : ) in the"
107 + " file that the%n"
108 + " suppression should be generated for%n"
109 + " -t, --tree Print Abstract Syntax Tree(AST) of the file%n"
110 + " -T, --treeWithComments Print Abstract Syntax Tree(AST) of the file including"
111 + " comments%n"
112 + " -V, --version Print version information and exit.%n"
113 + " -W, --tree-walker-threads-number=<treeWalkerThreadsNumber>%n"
114 + " (experimental) The number of TreeWalker threads (must be"
115 + " greater than zero)%n"
116 + " -x, --exclude-regexp=<excludeRegex>%n"
117 + " Regular expression of directory/file to exclude from"
118 + " CheckStyle%n");
119
120 private static final Logger LOG = Logger.getLogger(MainTest.class.getName()).getParent();
121 private static final Handler[] HANDLERS = LOG.getHandlers();
122 private static final Level ORIGINAL_LOG_LEVEL = LOG.getLevel();
123
124 private static final String EOL = System.getProperty("line.separator");
125
126 @Rule
127 public final TemporaryFolder temporaryFolder = new TemporaryFolder();
128 @Rule
129 public final ExpectedSystemExit exit = ExpectedSystemExit.none();
130 @Rule
131 public final SystemErrRule systemErr = new SystemErrRule().enableLog().mute();
132 @Rule
133 public final SystemOutRule systemOut = new SystemOutRule().enableLog().mute();
134
135 private final LocalizedMessage auditStartMessage = new LocalizedMessage(1,
136 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditStarted", null, null,
137 getClass(), null);
138
139 private final LocalizedMessage auditFinishMessage = new LocalizedMessage(1,
140 Definitions.CHECKSTYLE_BUNDLE, "DefaultLogger.auditFinished", null, null,
141 getClass(), null);
142
143 private final LocalizedMessage errorCounterOneMessage = new LocalizedMessage(1,
144 Definitions.CHECKSTYLE_BUNDLE, Main.ERROR_COUNTER,
145 new String[] {String.valueOf(1)}, null, getClass(), null);
146
147 private static String getPath(String filename) {
148 return "src/test/resources/com/puppycrawl/tools/checkstyle/main/" + filename;
149 }
150
151 private static String getNonCompilablePath(String filename) {
152 return "src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/main/" + filename;
153 }
154
155 private static String getFilePath(String filename) throws IOException {
156 return new File(getPath(filename)).getCanonicalPath();
157 }
158
159 @Before
160 public void setUp() {
161
162
163 LOG.setLevel(ORIGINAL_LOG_LEVEL);
164
165 for (Handler handler : LOG.getHandlers()) {
166 boolean found = false;
167
168 for (Handler savedHandler : HANDLERS) {
169 if (handler == savedHandler) {
170 found = true;
171 break;
172 }
173 }
174
175 if (!found) {
176 LOG.removeHandler(handler);
177 }
178 }
179 }
180
181 @Test
182 public void testIsProperUtilsClass() throws ReflectiveOperationException {
183 assertTrue("Constructor is not private",
184 isUtilsClassHasPrivateConstructor(Main.class, false));
185 }
186
187 @Test
188 public void testVersionPrint()
189 throws Exception {
190 exit.checkAssertionAfterwards(() -> {
191 assertEquals("Unexpected output log",
192 "Checkstyle version: null" + System.lineSeparator(),
193 systemOut.getLog());
194 assertEquals("Unexpected system error log", "", systemErr.getLog());
195 });
196 Main.main("-V");
197 }
198
199 @Test
200 public void testUsageHelpPrint()
201 throws Exception {
202 exit.checkAssertionAfterwards(() -> {
203 assertEquals("Unexpected output log",
204 USAGE,
205 systemOut.getLog());
206 assertEquals("Unexpected system error log", "", systemErr.getLog());
207 });
208 Main.main("-h");
209 }
210
211 @Test
212 public void testWrongArgument()
213 throws Exception {
214 exit.expectSystemExitWithStatus(-1);
215 exit.checkAssertionAfterwards(() -> {
216 final String usage = "Unknown option: -w" + EOL
217 + SHORT_USAGE;
218 assertEquals("Unexpected output log", "", systemOut.getLog());
219 assertEquals("Unexpected system error log", usage, systemErr.getLog());
220 });
221
222
223
224 Main.main("-w", "file");
225 }
226
227 @Test
228 public void testWrongArgumentMissingFiles()
229 throws Exception {
230 exit.expectSystemExitWithStatus(-1);
231 exit.checkAssertionAfterwards(() -> {
232
233
234 final String usage = "Missing required parameter: <files>" + EOL
235 + SHORT_USAGE;
236 assertEquals("Unexpected output log", "", systemOut.getLog());
237 assertEquals("Unexpected system error log", usage, systemErr.getLog());
238 });
239 Main.main("-w");
240 }
241
242 @Test
243 public void testNoConfigSpecified()
244 throws Exception {
245 exit.expectSystemExitWithStatus(-1);
246 exit.checkAssertionAfterwards(() -> {
247 assertEquals("Unexpected output log",
248 "Must specify a config XML file." + System.lineSeparator(),
249 systemOut.getLog());
250 assertEquals("Unexpected system error log", "", systemErr.getLog());
251 });
252 Main.main(getPath("InputMain.java"));
253 }
254
255 @Test
256 public void testNonExistentTargetFile()
257 throws Exception {
258 exit.expectSystemExitWithStatus(-1);
259 exit.checkAssertionAfterwards(() -> {
260 assertEquals("Unexpected output log", "Files to process must be specified, found 0."
261 + System.lineSeparator(), systemOut.getLog());
262 assertEquals("Unexpected system error log", "", systemErr.getLog());
263 });
264 Main.main("-c", "/google_checks.xml", "NonExistentFile.java");
265 }
266
267 @Test
268 public void testNonExistentConfigFile()
269 throws Exception {
270 exit.expectSystemExitWithStatus(-1);
271 exit.checkAssertionAfterwards(() -> {
272 assertEquals("Unexpected output log", "Could not find config XML file "
273 + "'src/main/resources/non_existent_config.xml'." + EOL,
274 systemOut.getLog());
275 assertEquals("Unexpected system error log", "", systemErr.getLog());
276 });
277 Main.main("-c", "src/main/resources/non_existent_config.xml",
278 getPath("InputMain.java"));
279 }
280
281 @Test
282 public void testNonExistentOutputFormat() throws Exception {
283 exit.expectSystemExitWithStatus(-1);
284 exit.checkAssertionAfterwards(() -> {
285 assertEquals("Unexpected output log", "", systemOut.getLog());
286 assertEquals("Unexpected system error log",
287 "Invalid value for option '-f': expected one of [XML, PLAIN]"
288 + " (case-insensitive) but was 'xmlp'"
289 + EOL + SHORT_USAGE, systemErr.getLog());
290 });
291 Main.main("-c", "/google_checks.xml", "-f", "xmlp",
292 getPath("InputMain.java"));
293 }
294
295 @Test
296 public void testNonExistentClass() throws Exception {
297 exit.expectSystemExitWithStatus(-2);
298 exit.checkAssertionAfterwards(() -> {
299 final String expectedExceptionMessage = errorCounterOneMessage.getMessage() + EOL;
300 assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
301
302 final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
303 + " cannot initialize module TreeWalker - ";
304 assertTrue("Unexpected system error log", systemErr.getLog().startsWith(cause));
305 });
306
307 Main.main("-c", getPath("InputMainConfig-non-existent-classname.xml"),
308 getPath("InputMain.java"));
309 }
310
311 @Test
312 public void testExistingTargetFile() throws Exception {
313 exit.checkAssertionAfterwards(() -> {
314 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
315 + auditFinishMessage.getMessage() + EOL,
316 systemOut.getLog());
317 assertEquals("Unexpected system error log", "", systemErr.getLog());
318 });
319 Main.main("-c", getPath("InputMainConfig-classname.xml"),
320 getPath("InputMain.java"));
321 }
322
323 @Test
324 public void testExistingTargetFileXmlOutput() throws Exception {
325 exit.checkAssertionAfterwards(() -> {
326 final String expectedPath = getFilePath("InputMain.java");
327 final String version = Main.class.getPackage().getImplementationVersion();
328 assertEquals("Unexpected output log", "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL
329 + "<checkstyle version=\"" + version + "\">" + EOL
330 + "<file name=\"" + expectedPath + "\">" + EOL
331 + "</file>" + EOL
332 + "</checkstyle>" + EOL, systemOut.getLog());
333 assertEquals("Unexpected system error log", "", systemErr.getLog());
334 });
335 Main.main("-c", getPath("InputMainConfig-classname.xml"),
336 "-f", "xml",
337 getPath("InputMain.java"));
338 }
339
340 @Test
341 public void testExistingTargetFilePlainOutput() throws Exception {
342 exit.checkAssertionAfterwards(() -> {
343 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
344 + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
345 assertEquals("Unexpected system error log", "", systemErr.getLog());
346 });
347 Main.main("-c", getPath("InputMainConfig-classname.xml"),
348 "-f", "plain",
349 getPath("InputMain.java"));
350 }
351
352 @Test
353 public void testExistingTargetFileWithViolations() throws Exception {
354 exit.checkAssertionAfterwards(() -> {
355 final LocalizedMessage invalidPatternMessageMain = new LocalizedMessage(1,
356 "com.puppycrawl.tools.checkstyle.checks.naming.messages",
357 "name.invalidPattern", new String[] {"InputMain", "^[a-z0-9]*$"},
358 null, getClass(), null);
359 final LocalizedMessage invalidPatternMessageMainInner = new LocalizedMessage(1,
360 "com.puppycrawl.tools.checkstyle.checks.naming.messages",
361 "name.invalidPattern", new String[] {"InputMainInner", "^[a-z0-9]*$"},
362 null, getClass(), null);
363 final String expectedPath = getFilePath("InputMain.java");
364 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
365 + "[WARN] " + expectedPath + ":3:14: "
366 + invalidPatternMessageMain.getMessage()
367 + " [TypeName]" + EOL
368 + "[WARN] " + expectedPath + ":5:7: "
369 + invalidPatternMessageMainInner.getMessage()
370 + " [TypeName]" + EOL
371 + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
372 assertEquals("Unexpected system error log", "", systemErr.getLog());
373 });
374 Main.main("-c", getPath("InputMainConfig-classname2.xml"),
375 getPath("InputMain.java"));
376 }
377
378 @Test
379 public void testExistingTargetFileWithError()
380 throws Exception {
381 exit.expectSystemExitWithStatus(2);
382 exit.checkAssertionAfterwards(() -> {
383 final LocalizedMessage errorCounterTwoMessage = new LocalizedMessage(1,
384 Definitions.CHECKSTYLE_BUNDLE, Main.ERROR_COUNTER,
385 new String[] {String.valueOf(2)}, null, getClass(), null);
386 final LocalizedMessage invalidPatternMessageMain = new LocalizedMessage(1,
387 "com.puppycrawl.tools.checkstyle.checks.naming.messages",
388 "name.invalidPattern", new String[] {"InputMain", "^[a-z0-9]*$"},
389 null, getClass(), null);
390 final LocalizedMessage invalidPatternMessageMainInner = new LocalizedMessage(1,
391 "com.puppycrawl.tools.checkstyle.checks.naming.messages",
392 "name.invalidPattern", new String[] {"InputMainInner", "^[a-z0-9]*$"},
393 null, getClass(), null);
394 final String expectedPath = getFilePath("InputMain.java");
395 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
396 + "[ERROR] " + expectedPath + ":3:14: "
397 + invalidPatternMessageMain.getMessage() + " [TypeName]" + EOL
398 + "[ERROR] " + expectedPath + ":5:7: "
399 + invalidPatternMessageMainInner.getMessage() + " [TypeName]" + EOL
400 + auditFinishMessage.getMessage() + EOL
401 + errorCounterTwoMessage.getMessage() + EOL, systemOut.getLog());
402 assertEquals("Unexpected system error log", "", systemErr.getLog());
403 });
404 Main.main("-c",
405 getPath("InputMainConfig-classname2-error.xml"),
406 getPath("InputMain.java"));
407 }
408
409
410
411
412
413
414
415 @Test
416 public void testExistingTargetFileWithOneError()
417 throws Exception {
418 exit.expectSystemExitWithStatus(1);
419 exit.checkAssertionAfterwards(() -> {
420 final LocalizedMessage errorCounterTwoMessage = new LocalizedMessage(1,
421 Definitions.CHECKSTYLE_BUNDLE, Main.ERROR_COUNTER,
422 new String[] {String.valueOf(1)}, null, getClass(), null);
423 final LocalizedMessage invalidPatternMessageMain = new LocalizedMessage(1,
424 "com.puppycrawl.tools.checkstyle.checks.naming.messages",
425 "name.invalidPattern", new String[] {"InputMain1", "^[a-z0-9]*$"},
426 null, getClass(), null);
427 final String expectedPath = getFilePath("InputMain1.java");
428 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
429 + "[ERROR] " + expectedPath + ":3:14: "
430 + invalidPatternMessageMain.getMessage() + " [TypeName]" + EOL
431 + auditFinishMessage.getMessage() + EOL
432 + errorCounterTwoMessage.getMessage() + EOL, systemOut.getLog());
433 assertEquals("Unexpected system error log", "", systemErr.getLog());
434 });
435 Main.main("-c",
436 getPath("InputMainConfig-classname2-error.xml"),
437 getPath("InputMain1.java"));
438 }
439
440 @Test
441 public void testExistentTargetFilePlainOutputToNonExistentFile()
442 throws Exception {
443 exit.checkAssertionAfterwards(() -> {
444 assertEquals("Unexpected output log", "", systemOut.getLog());
445 assertEquals("Unexpected system error log", "", systemErr.getLog());
446 });
447 Main.main("-c", getPath("InputMainConfig-classname.xml"),
448 "-f", "plain",
449 "-o", temporaryFolder.getRoot() + "/output.txt",
450 getPath("InputMain.java"));
451 }
452
453 @Test
454 public void testExistingTargetFilePlainOutputToFile()
455 throws Exception {
456 final File file = temporaryFolder.newFile("file.output");
457 exit.checkAssertionAfterwards(() -> {
458 assertEquals("Unexpected output log", "", systemOut.getLog());
459 assertEquals("Unexpected system error log", "", systemErr.getLog());
460 });
461 Main.main("-c", getPath("InputMainConfig-classname.xml"),
462 "-f", "plain",
463 "-o", file.getCanonicalPath(),
464 getPath("InputMain.java"));
465 }
466
467 @Test
468 public void testCreateNonExistentOutputFile() throws Exception {
469 final String outputFile = temporaryFolder.getRoot().getCanonicalPath() + "nonexistent.out";
470 assertFalse("File must not exist", new File(outputFile).exists());
471 Main.main("-c", getPath("InputMainConfig-classname.xml"),
472 "-f", "plain",
473 "-o", outputFile,
474 getPath("InputMain.java"));
475 assertTrue("File must exist", new File(outputFile).exists());
476 }
477
478 @Test
479 public void testExistingTargetFilePlainOutputProperties() throws Exception {
480
481 exit.checkAssertionAfterwards(() -> {
482 assertEquals("Unexpected output log", auditStartMessage.getMessage() + EOL
483 + auditFinishMessage.getMessage() + EOL, systemOut.getLog());
484 assertEquals("Unexpected system error log", "", systemErr.getLog());
485 });
486 Main.main("-c", getPath("InputMainConfig-classname-prop.xml"),
487 "-p", getPath("InputMainMycheckstyle.properties"),
488 getPath("InputMain.java"));
489 }
490
491 @Test
492 public void testExistingTargetFilePlainOutputNonexistentProperties()
493 throws Exception {
494 exit.expectSystemExitWithStatus(-1);
495 exit.checkAssertionAfterwards(() -> {
496 assertEquals("Unexpected output log", "Could not find file 'nonexistent.properties'."
497 + System.lineSeparator(), systemOut.getLog());
498 assertEquals("Unexpected system error log", "", systemErr.getLog());
499 });
500 Main.main("-c", getPath("InputMainConfig-classname-prop.xml"),
501 "-p", "nonexistent.properties",
502 getPath("InputMain.java"));
503 }
504
505 @Test
506 public void testExistingIncorrectConfigFile()
507 throws Exception {
508 exit.expectSystemExitWithStatus(-2);
509 exit.checkAssertionAfterwards(() -> {
510 final String output = errorCounterOneMessage.getMessage() + EOL;
511 assertEquals("Unexpected output log", output, systemOut.getLog());
512 final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
513 + "CheckstyleException: unable to parse configuration stream - ";
514 assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
515 });
516 Main.main("-c", getPath("InputMainConfig-Incorrect.xml"),
517 getPath("InputMain.java"));
518 }
519
520 @Test
521 public void testExistingIncorrectChildrenInConfigFile()
522 throws Exception {
523 exit.expectSystemExitWithStatus(-2);
524 exit.checkAssertionAfterwards(() -> {
525 final String output = errorCounterOneMessage.getMessage() + EOL;
526 assertEquals("Unexpected output log", output, systemOut.getLog());
527 final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
528 + "CheckstyleException: cannot initialize module RegexpSingleline"
529 + " - RegexpSingleline is not allowed as a child in RegexpSingleline";
530 assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
531 });
532 Main.main("-c", getPath("InputMainConfig-incorrectChildren.xml"),
533 getPath("InputMain.java"));
534 }
535
536 @Test
537 public void testExistingIncorrectChildrenInConfigFile2()
538 throws Exception {
539 exit.expectSystemExitWithStatus(-2);
540 exit.checkAssertionAfterwards(() -> {
541 final String output = errorCounterOneMessage.getMessage() + EOL;
542 assertEquals("Unexpected output log", output, systemOut.getLog());
543 final String errorOutput = "com.puppycrawl.tools.checkstyle.api."
544 + "CheckstyleException: cannot initialize module TreeWalker - "
545 + "cannot initialize module JavadocMethod - "
546 + "JavadocVariable is not allowed as a child in JavadocMethod";
547 assertTrue("Unexpected system error log", systemErr.getLog().startsWith(errorOutput));
548 });
549 Main.main("-c", getPath("InputMainConfig-incorrectChildren2.xml"),
550 getPath("InputMain.java"));
551 }
552
553 @Test
554 public void testLoadPropertiesIoException() throws Exception {
555 final Class<?>[] param = new Class<?>[1];
556 param[0] = File.class;
557 final Class<?> cliOptionsClass = Class.forName(Main.class.getName());
558 final Method method = cliOptionsClass.getDeclaredMethod("loadProperties", param);
559 method.setAccessible(true);
560 try {
561 method.invoke(null, new File("."));
562 fail("Exception was expected");
563 }
564 catch (InvocationTargetException ex) {
565 assertTrue("Invalid error cause",
566 ex.getCause() instanceof CheckstyleException);
567
568
569
570 final LocalizedMessage loadPropertiesMessage = new LocalizedMessage(1,
571 Definitions.CHECKSTYLE_BUNDLE, Main.LOAD_PROPERTIES_EXCEPTION,
572 new String[] {""}, null, getClass(), null);
573 final String causeMessage = ex.getCause().getLocalizedMessage();
574 final String localizedMessage = loadPropertiesMessage.getMessage();
575 final boolean samePrefix = causeMessage.substring(0, causeMessage.indexOf(' '))
576 .equals(localizedMessage
577 .substring(0, localizedMessage.indexOf(' ')));
578 final boolean sameSuffix =
579 causeMessage.substring(causeMessage.lastIndexOf(' '))
580 .equals(localizedMessage
581 .substring(localizedMessage.lastIndexOf(' ')));
582 assertTrue("Invalid error message", samePrefix || sameSuffix);
583 assertTrue("Invalid error message", causeMessage.contains(".'"));
584 }
585 }
586
587 @Test
588 public void testExistingDirectoryWithViolations() throws Exception {
589
590 final String[][] outputValues = {
591 {"InputMainComplexityOverflow", "1", "172"},
592 };
593
594 final int allowedLength = 170;
595 final String msgKey = "maxLen.file";
596 final String bundle = "com.puppycrawl.tools.checkstyle.checks.sizes.messages";
597
598 exit.checkAssertionAfterwards(() -> {
599 final String expectedPath = getFilePath("") + File.separator;
600 final StringBuilder sb = new StringBuilder(28);
601 sb.append(auditStartMessage.getMessage())
602 .append(EOL);
603 final String format = "[WARN] " + expectedPath + outputValues[0][0] + ".java:"
604 + outputValues[0][1] + ": ";
605 for (String[] outputValue : outputValues) {
606 final String localizedMessage = new LocalizedMessage(1, bundle,
607 msgKey, new Integer[] {Integer.valueOf(outputValue[2]), allowedLength},
608 null, getClass(), null).getMessage();
609 final String line = format + localizedMessage + " [FileLength]";
610 sb.append(line).append(EOL);
611 }
612 sb.append(auditFinishMessage.getMessage())
613 .append(EOL);
614 assertEquals("Unexpected output log", sb.toString(), systemOut.getLog());
615 assertEquals("Unexpected system error log", "", systemErr.getLog());
616 });
617
618 Main.main("-c", getPath("InputMainConfig-filelength.xml"),
619 getPath(""));
620 }
621
622
623
624
625
626 @Test
627 public void testListFilesNotFile() throws Exception {
628 final File fileMock = new File("") {
629 private static final long serialVersionUID = 1L;
630
631 @Override
632 public boolean canRead() {
633 return true;
634 }
635
636 @Override
637 public boolean isDirectory() {
638 return false;
639 }
640
641 @Override
642 public boolean isFile() {
643 return false;
644 }
645 };
646
647 final List<File> result = Whitebox.invokeMethod(Main.class, "listFiles",
648 fileMock, new ArrayList<Pattern>());
649 assertEquals("Invalid result size", 0, result.size());
650 }
651
652
653
654
655
656 @Test
657 public void testListFilesDirectoryWithNull() throws Exception {
658 final File[] nullResult = null;
659 final File fileMock = new File("") {
660 private static final long serialVersionUID = 1L;
661
662 @Override
663 public boolean canRead() {
664 return true;
665 }
666
667 @Override
668 public boolean isDirectory() {
669 return true;
670 }
671
672 @Override
673 public File[] listFiles() {
674 return nullResult;
675 }
676 };
677
678 final List<File> result = Whitebox.invokeMethod(Main.class, "listFiles",
679 fileMock, new ArrayList<Pattern>());
680 assertEquals("Invalid result size", 0, result.size());
681 }
682
683 @Test
684 public void testFileReferenceDuringException() throws Exception {
685 exit.expectSystemExitWithStatus(-2);
686 exit.checkAssertionAfterwards(() -> {
687 final String expectedExceptionMessage = auditStartMessage.getMessage() + EOL
688 + errorCounterOneMessage.getMessage() + EOL;
689 assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
690
691 final String exceptionFirstLine = "com.puppycrawl.tools.checkstyle.api."
692 + "CheckstyleException: Exception was thrown while processing "
693 + new File(getNonCompilablePath("InputMainIncorrectClass.java")).getPath()
694 + EOL;
695 assertTrue("Unexpected system error log",
696 systemErr.getLog().startsWith(exceptionFirstLine));
697 });
698
699
700 Main.main("-c", getPath("InputMainConfig-classname.xml"),
701 getNonCompilablePath("InputMainIncorrectClass.java"));
702 }
703
704 @Test
705 public void testPrintTreeOnMoreThanOneFile() throws Exception {
706 exit.expectSystemExitWithStatus(-1);
707 exit.checkAssertionAfterwards(() -> {
708 assertEquals("Unexpected output log", "Printing AST is allowed for only one file."
709 + System.lineSeparator(), systemOut.getLog());
710 assertEquals("Unexpected system error log", "", systemErr.getLog());
711 });
712
713 Main.main("-t", getPath(""));
714 }
715
716 @Test
717 public void testPrintTreeOption() throws Exception {
718 final String expected = "PACKAGE_DEF -> package [1:0]" + EOL
719 + "|--ANNOTATIONS -> ANNOTATIONS [1:39]" + EOL
720 + "|--DOT -> . [1:39]" + EOL
721 + "| |--DOT -> . [1:28]" + EOL
722 + "| | |--DOT -> . [1:22]" + EOL
723 + "| | | |--DOT -> . [1:11]" + EOL
724 + "| | | | |--IDENT -> com [1:8]" + EOL
725 + "| | | | `--IDENT -> puppycrawl [1:12]" + EOL
726 + "| | | `--IDENT -> tools [1:23]" + EOL
727 + "| | `--IDENT -> checkstyle [1:29]" + EOL
728 + "| `--IDENT -> main [1:40]" + EOL
729 + "`--SEMI -> ; [1:44]" + EOL
730 + "CLASS_DEF -> CLASS_DEF [3:0]" + EOL
731 + "|--MODIFIERS -> MODIFIERS [3:0]" + EOL
732 + "| `--LITERAL_PUBLIC -> public [3:0]" + EOL
733 + "|--LITERAL_CLASS -> class [3:7]" + EOL
734 + "|--IDENT -> InputMain [3:13]" + EOL
735 + "`--OBJBLOCK -> OBJBLOCK [3:23]" + EOL
736 + " |--LCURLY -> { [3:23]" + EOL
737 + " `--RCURLY -> } [4:0]" + EOL
738 + "CLASS_DEF -> CLASS_DEF [5:0]" + EOL
739 + "|--MODIFIERS -> MODIFIERS [5:0]" + EOL
740 + "|--LITERAL_CLASS -> class [5:0]" + EOL
741 + "|--IDENT -> InputMainInner [5:6]" + EOL
742 + "`--OBJBLOCK -> OBJBLOCK [5:21]" + EOL
743 + " |--LCURLY -> { [5:21]" + EOL
744 + " `--RCURLY -> } [6:0]" + EOL;
745
746 exit.checkAssertionAfterwards(() -> {
747 assertEquals("Unexpected output log", expected, systemOut.getLog());
748 assertEquals("Unexpected system error log", "", systemErr.getLog());
749 });
750 Main.main("-t", getPath("InputMain.java"));
751 }
752
753 @Test
754 public void testPrintTreeCommentsOption() throws Exception {
755 final String expected = "PACKAGE_DEF -> package [1:0]" + EOL
756 + "|--ANNOTATIONS -> ANNOTATIONS [1:39]" + EOL
757 + "|--DOT -> . [1:39]" + EOL
758 + "| |--DOT -> . [1:28]" + EOL
759 + "| | |--DOT -> . [1:22]" + EOL
760 + "| | | |--DOT -> . [1:11]" + EOL
761 + "| | | | |--IDENT -> com [1:8]" + EOL
762 + "| | | | `--IDENT -> puppycrawl [1:12]" + EOL
763 + "| | | `--IDENT -> tools [1:23]" + EOL
764 + "| | `--IDENT -> checkstyle [1:29]" + EOL
765 + "| `--IDENT -> main [1:40]" + EOL
766 + "`--SEMI -> ; [1:44]" + EOL
767 + "CLASS_DEF -> CLASS_DEF [3:0]" + EOL
768 + "|--MODIFIERS -> MODIFIERS [3:0]" + EOL
769 + "| |--BLOCK_COMMENT_BEGIN -> /* [2:0]" + EOL
770 + "| | |--COMMENT_CONTENT -> comment [2:2]" + EOL
771 + "| | `--BLOCK_COMMENT_END -> */ [2:8]" + EOL
772 + "| `--LITERAL_PUBLIC -> public [3:0]" + EOL
773 + "|--LITERAL_CLASS -> class [3:7]" + EOL
774 + "|--IDENT -> InputMain [3:13]" + EOL
775 + "`--OBJBLOCK -> OBJBLOCK [3:23]" + EOL
776 + " |--LCURLY -> { [3:23]" + EOL
777 + " `--RCURLY -> } [4:0]" + EOL
778 + "CLASS_DEF -> CLASS_DEF [5:0]" + EOL
779 + "|--MODIFIERS -> MODIFIERS [5:0]" + EOL
780 + "|--LITERAL_CLASS -> class [5:0]" + EOL
781 + "|--IDENT -> InputMainInner [5:6]" + EOL
782 + "`--OBJBLOCK -> OBJBLOCK [5:21]" + EOL
783 + " |--LCURLY -> { [5:21]" + EOL
784 + " `--RCURLY -> } [6:0]" + EOL;
785
786 exit.checkAssertionAfterwards(() -> {
787 assertEquals("Unexpected output log", expected, systemOut.getLog());
788 assertEquals("Unexpected system error log", "", systemErr.getLog());
789 });
790 Main.main("-T", getPath("InputMain.java"));
791 }
792
793 @Test
794 public void testPrintTreeJavadocOption() throws Exception {
795 final String expected = new String(Files.readAllBytes(Paths.get(
796 getPath("InputMainExpectedInputJavadocComment.txt"))), StandardCharsets.UTF_8)
797 .replaceAll("\\\\r\\\\n", "\\\\n").replaceAll("\r\n", "\n");
798
799 exit.checkAssertionAfterwards(() -> {
800 assertEquals("Unexpected output log",
801 expected, systemOut.getLog().replaceAll("\\\\r\\\\n", "\\\\n")
802 .replaceAll("\r\n", "\n"));
803 assertEquals("Unexpected system error log",
804 "", systemErr.getLog());
805 });
806 Main.main("-j", getPath("InputMainJavadocComment.javadoc"));
807 }
808
809 @Test
810 public void testPrintSuppressionOption() throws Exception {
811 final String expected = "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]"
812 + EOL
813 + "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]/MODIFIERS" + EOL
814 + "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]/LITERAL_CLASS"
815 + EOL;
816
817 exit.checkAssertionAfterwards(() -> {
818 assertEquals("Unexpected output log",
819 expected, systemOut.getLog());
820 assertEquals("Unexpected system error log",
821 "", systemErr.getLog());
822 });
823 Main.main(getPath("InputMainSuppressionsStringPrinter.java"),
824 "-s", "3:1");
825 }
826
827 @Test
828 public void testPrintSuppressionAndTabWidthOption() throws Exception {
829 final String expected = "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]"
830 + "/OBJBLOCK"
831 + "/METHOD_DEF[./IDENT[@text='getName']]/SLIST/VARIABLE_DEF[./IDENT[@text='var']]"
832 + EOL
833 + "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]/OBJBLOCK"
834 + "/METHOD_DEF[./IDENT[@text='getName']]/SLIST/VARIABLE_DEF[./IDENT[@text='var']]"
835 + "/MODIFIERS" + EOL
836 + "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]/OBJBLOCK"
837 + "/METHOD_DEF[./IDENT[@text='getName']]/SLIST/VARIABLE_DEF[./IDENT[@text='var']]"
838 + "/TYPE" + EOL
839 + "/CLASS_DEF[./IDENT[@text='InputMainSuppressionsStringPrinter']]/OBJBLOCK"
840 + "/METHOD_DEF[./IDENT[@text='getName']]/SLIST/VARIABLE_DEF[./IDENT[@text='var']]"
841 + "/TYPE/LITERAL_INT"
842 + EOL;
843
844 exit.checkAssertionAfterwards(() -> {
845 assertEquals("Unexpected output log",
846 expected, systemOut.getLog());
847 assertEquals("Unexpected system error log",
848 "", systemErr.getLog());
849 });
850 Main.main(getPath("InputMainSuppressionsStringPrinter.java"),
851 "-s", "7:9", "--tabWidth", "2");
852 }
853
854 @Test
855 public void testPrintSuppressionConflictingOptionsTvsC() throws Exception {
856 exit.expectSystemExitWithStatus(-1);
857 exit.checkAssertionAfterwards(() -> {
858 assertEquals("Unexpected output log", "Option '-s' cannot be used with other options."
859 + System.lineSeparator(), systemOut.getLog());
860 assertEquals("Unexpected system error log", "", systemErr.getLog());
861 });
862
863 Main.main("-c", "/google_checks.xml",
864 getPath(""), "-s", "2:4");
865 }
866
867 @Test
868 public void testPrintSuppressionConflictingOptionsTvsP() throws Exception {
869 exit.expectSystemExitWithStatus(-1);
870 exit.checkAssertionAfterwards(() -> {
871 assertEquals("Unexpected output log", "Option '-s' cannot be used with other options."
872 + System.lineSeparator(), systemOut.getLog());
873 assertEquals("Unexpected system error log", "", systemErr.getLog());
874 });
875
876 Main.main("-p", getPath("InputMainMycheckstyle.properties"), "-s", "2:4", getPath(""));
877 }
878
879 @Test
880 public void testPrintSuppressionConflictingOptionsTvsF() throws Exception {
881 exit.expectSystemExitWithStatus(-1);
882 exit.checkAssertionAfterwards(() -> {
883 assertEquals("Unexpected output log", "Option '-s' cannot be used with other options."
884 + System.lineSeparator(), systemOut.getLog());
885 assertEquals("Unexpected system error log", "", systemErr.getLog());
886 });
887
888 Main.main("-f", "plain", "-s", "2:4", getPath(""));
889 }
890
891 @Test
892 public void testPrintSuppressionConflictingOptionsTvsO() throws Exception {
893 final File file = temporaryFolder.newFile("file.output");
894
895 exit.expectSystemExitWithStatus(-1);
896 exit.checkAssertionAfterwards(() -> {
897 assertEquals("Unexpected output log", "Option '-s' cannot be used with other options."
898 + System.lineSeparator(), systemOut.getLog());
899 assertEquals("Unexpected system error log", "", systemErr.getLog());
900 });
901
902 Main.main("-o", file.getCanonicalPath(), "-s", "2:4", getPath(""));
903 }
904
905 @Test
906 public void testPrintSuppressionOnMoreThanOneFile() throws Exception {
907 exit.expectSystemExitWithStatus(-1);
908 exit.checkAssertionAfterwards(() -> {
909 assertEquals("Unexpected output log", "Printing xpath suppressions is allowed for "
910 + "only one file."
911 + System.lineSeparator(), systemOut.getLog());
912 assertEquals("Unexpected system error log", "", systemErr.getLog());
913 });
914
915 Main.main("-s", "2:4", getPath(""), getPath(""));
916 }
917
918 @Test
919 public void testGenerateXpathSuppressionOptionOne() throws Exception {
920 final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL
921 + "<!DOCTYPE suppressions PUBLIC" + EOL
922 + " \"-//Checkstyle//DTD SuppressionXpathFilter Experimental Configuration 1.2"
923 + "//EN\"" + EOL
924 + " \"https://checkstyle.org/dtds/suppressions_1_2_xpath_experimental.dtd\">"
925 + EOL
926 + "<suppressions>" + EOL
927 + "<suppress-xpath" + EOL
928 + " files=\"InputMainComplexityOverflow.java\"" + EOL
929 + " checks=\"JavadocMethodCheck\"" + EOL
930 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
931 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]\"/>" + EOL
932 + "<suppress-xpath" + EOL
933 + " files=\"InputMainComplexityOverflow.java\"" + EOL
934 + " checks=\"LeftCurlyCheck\"" + EOL
935 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
936 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST\"/>" + EOL
937 + "<suppress-xpath" + EOL
938 + " files=\"InputMainComplexityOverflow.java\"" + EOL
939 + " checks=\"EmptyBlockCheck\"" + EOL
940 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
941 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
942 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST"
943 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
944 + "<suppress-xpath" + EOL
945 + " files=\"InputMainComplexityOverflow.java\"" + EOL
946 + " checks=\"EmptyBlockCheck\"" + EOL
947 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
948 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
949 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
950 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
951 + "<suppress-xpath" + EOL
952 + " files=\"InputMainComplexityOverflow.java\"" + EOL
953 + " checks=\"EmptyBlockCheck\"" + EOL
954 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
955 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
956 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST"
957 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
958 + "<suppress-xpath" + EOL
959 + " files=\"InputMainComplexityOverflow.java\"" + EOL
960 + " checks=\"EmptyBlockCheck\"" + EOL
961 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
962 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
963 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
964 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
965 + "<suppress-xpath" + EOL
966 + " files=\"InputMainComplexityOverflow.java\"" + EOL
967 + " checks=\"EmptyBlockCheck\"" + EOL
968 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
969 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
970 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
971 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
972 + "<suppress-xpath" + EOL
973 + " files=\"InputMainComplexityOverflow.java\"" + EOL
974 + " checks=\"EmptyBlockCheck\"" + EOL
975 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
976 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
977 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
978 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
979 + "<suppress-xpath" + EOL
980 + " files=\"InputMainComplexityOverflow.java\"" + EOL
981 + " checks=\"EmptyBlockCheck\"" + EOL
982 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
983 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
984 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
985 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
986 + "<suppress-xpath" + EOL
987 + " files=\"InputMainComplexityOverflow.java\"" + EOL
988 + " checks=\"EmptyBlockCheck\"" + EOL
989 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
990 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
991 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
992 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
993 + "<suppress-xpath" + EOL
994 + " files=\"InputMainComplexityOverflow.java\"" + EOL
995 + " checks=\"EmptyBlockCheck\"" + EOL
996 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
997 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
998 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
999 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
1000 + "<suppress-xpath" + EOL
1001 + " files=\"InputMainComplexityOverflow.java\"" + EOL
1002 + " checks=\"EmptyBlockCheck\"" + EOL
1003 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainComplexityOverflow']]/OBJBLOCK"
1004 + "/METHOD_DEF[./IDENT[@text='provokeNpathIntegerOverflow']]/SLIST/LITERAL_IF/SLIST"
1005 + "/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST/LITERAL_IF"
1006 + "/SLIST/LITERAL_IF/SLIST/LITERAL_IF/SLIST\"/>" + EOL
1007 + "</suppressions>" + EOL;
1008
1009 exit.checkAssertionAfterwards(() -> {
1010 assertEquals("Unexpected output log",
1011 expected, systemOut.getLog());
1012 assertEquals("Unexpected system error log",
1013 "", systemErr.getLog());
1014 });
1015 Main.main("-c", "/google_checks.xml", "--generate-xpath-suppression",
1016 getPath("InputMainComplexityOverflow.java"));
1017 }
1018
1019 @Test
1020 public void testGenerateXpathSuppressionOptionTwo() throws Exception {
1021 final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL
1022 + "<!DOCTYPE suppressions PUBLIC" + EOL
1023 + " \"-//Checkstyle//DTD SuppressionXpathFilter Experimental Configuration 1.2"
1024 + "//EN\"" + EOL
1025 + " \"https://checkstyle.org/dtds/suppressions_1_2_xpath_experimental.dtd\">" + EOL
1026 + "<suppressions>" + EOL
1027 + "<suppress-xpath" + EOL
1028 + " files=\"InputMainGenerateXpathSuppressions.java\"" + EOL
1029 + " checks=\"ExplicitInitializationCheck\"" + EOL
1030 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainGenerateXpathSuppressions']]"
1031 + "/OBJBLOCK/VARIABLE_DEF/IDENT[@text='low']\"/>" + EOL
1032 + "<suppress-xpath" + EOL
1033 + " files=\"InputMainGenerateXpathSuppressions.java\"" + EOL
1034 + " checks=\"IllegalThrowsCheck\"" + EOL
1035 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainGenerateXpathSuppressions']]"
1036 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/LITERAL_THROWS"
1037 + "/IDENT[@text='RuntimeException']\"/>" + EOL
1038 + "<suppress-xpath" + EOL
1039 + " files=\"InputMainGenerateXpathSuppressions.java\"" + EOL
1040 + " checks=\"NestedForDepthCheck\"" + EOL
1041 + " query=\"/CLASS_DEF[./IDENT[@text='InputMainGenerateXpathSuppressions']]"
1042 + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/SLIST/LITERAL_FOR/SLIST"
1043 + "/LITERAL_FOR/SLIST"
1044 + "/LITERAL_FOR\"/>" + EOL
1045 + "</suppressions>" + EOL;
1046
1047 exit.checkAssertionAfterwards(() -> {
1048 assertEquals("Unexpected output log",
1049 expected, systemOut.getLog());
1050 assertEquals("Unexpected system error log",
1051 "", systemErr.getLog());
1052 });
1053 Main.main("-c", getPath("InputMainConfig-xpath-suppressions.xml"),
1054 "--generate-xpath-suppression",
1055 getPath("InputMainGenerateXpathSuppressions.java"));
1056 }
1057
1058 @Test
1059 public void testGenerateXpathSuppressionOptionEmptyConfig() throws Exception {
1060 final String expected = "";
1061
1062 exit.checkAssertionAfterwards(() -> {
1063 assertEquals("Unexpected output log",
1064 expected, systemOut.getLog());
1065 assertEquals("Unexpected system error log",
1066 "", systemErr.getLog());
1067 });
1068 Main.main("-c", getPath("InputMainConfig-empty.xml"), "--generate-xpath-suppression",
1069 getPath("InputMainComplexityOverflow.java"));
1070 }
1071
1072 @Test
1073 public void testGenerateXpathSuppressionOptionDefaultTabWidth() throws Exception {
1074 final String expected = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + EOL
1075 + "<!DOCTYPE suppressions PUBLIC" + EOL
1076 + " \"-//Checkstyle//DTD SuppressionXpathFilter Experimental Configuration 1.2"
1077 + "//EN\"" + EOL
1078 + " \"https://checkstyle.org/dtds/suppressions_1_2_xpath_experimental.dtd\">"
1079 + EOL
1080 + "<suppressions>" + EOL
1081 + "<suppress-xpath" + EOL
1082 + " files=\"InputMainGenerateXpathSuppressionsTabWidth.java\"" + EOL
1083 + " checks=\"ExplicitInitializationCheck\"" + EOL
1084 + " query=\"/CLASS_DEF[./IDENT["
1085 + "@text='InputMainGenerateXpathSuppressionsTabWidth']]"
1086 + "/OBJBLOCK/VARIABLE_DEF/IDENT[@text='low']\"/>" + EOL
1087 + "</suppressions>" + EOL;
1088
1089 exit.checkAssertionAfterwards(() -> {
1090 assertEquals("Unexpected output log",
1091 expected, systemOut.getLog());
1092 assertEquals("Unexpected system error log",
1093 "", systemErr.getLog());
1094 });
1095 Main.main("-c", getPath("InputMainConfig-xpath-suppressions.xml"),
1096 "--generate-xpath-suppression",
1097 getPath("InputMainGenerateXpathSuppressionsTabWidth.java"));
1098 }
1099
1100 @Test
1101 public void testGenerateXpathSuppressionOptionCustomTabWidth() throws Exception {
1102 final String expected = "";
1103
1104 exit.checkAssertionAfterwards(() -> {
1105 assertEquals("Unexpected output log",
1106 expected, systemOut.getLog());
1107 assertEquals("Unexpected system error log",
1108 "", systemErr.getLog());
1109 });
1110 Main.main("-c", getPath("InputMainConfig-xpath-suppressions.xml"),
1111 "--generate-xpath-suppression",
1112 "--tabWidth", "20",
1113 getPath("InputMainGenerateXpathSuppressionsTabWidth.java"));
1114 }
1115
1116 @Test
1117 public void testPrintFullTreeOption() throws Exception {
1118 final String expected = new String(Files.readAllBytes(Paths.get(
1119 getPath("InputMainExpectedInputAstTreeStringPrinterJavadoc.txt"))),
1120 StandardCharsets.UTF_8).replaceAll("\\\\r\\\\n", "\\\\n")
1121 .replaceAll("\r\n", "\n");
1122
1123 exit.checkAssertionAfterwards(() -> {
1124 assertEquals("Unexpected output log",
1125 expected, systemOut.getLog().replaceAll("\\\\r\\\\n", "\\\\n")
1126 .replaceAll("\r\n", "\n"));
1127 assertEquals("Unexpected system error log", "", systemErr.getLog());
1128 });
1129 Main.main("-J", getPath("InputMainAstTreeStringPrinterJavadoc.java"));
1130 }
1131
1132 @Test
1133 public void testConflictingOptionsTvsC() throws Exception {
1134 exit.expectSystemExitWithStatus(-1);
1135 exit.checkAssertionAfterwards(() -> {
1136 assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
1137 + System.lineSeparator(), systemOut.getLog());
1138 assertEquals("Unexpected system error log", "", systemErr.getLog());
1139 });
1140
1141 Main.main("-c", "/google_checks.xml", "-t", getPath(""));
1142 }
1143
1144 @Test
1145 public void testConflictingOptionsTvsP() throws Exception {
1146 exit.expectSystemExitWithStatus(-1);
1147 exit.checkAssertionAfterwards(() -> {
1148 assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
1149 + System.lineSeparator(), systemOut.getLog());
1150 assertEquals("Unexpected system error log", "", systemErr.getLog());
1151 });
1152
1153 Main.main("-p", getPath("InputMainMycheckstyle.properties"), "-t", getPath(""));
1154 }
1155
1156 @Test
1157 public void testConflictingOptionsTvsF() throws Exception {
1158 exit.expectSystemExitWithStatus(-1);
1159 exit.checkAssertionAfterwards(() -> {
1160 assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
1161 + System.lineSeparator(), systemOut.getLog());
1162 assertEquals("Unexpected system error log", "", systemErr.getLog());
1163 });
1164
1165 Main.main("-f", "plain", "-t", getPath(""));
1166 }
1167
1168 @Test
1169 public void testConflictingOptionsTvsS() throws Exception {
1170 final File file = temporaryFolder.newFile("file.output");
1171
1172 exit.expectSystemExitWithStatus(-1);
1173 exit.checkAssertionAfterwards(() -> {
1174 assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
1175 + System.lineSeparator(), systemOut.getLog());
1176 assertEquals("Unexpected system error log", "", systemErr.getLog());
1177 });
1178
1179 Main.main("-s", file.getCanonicalPath(), "-t", getPath(""));
1180 }
1181
1182 @Test
1183 public void testConflictingOptionsTvsO() throws Exception {
1184 final File file = temporaryFolder.newFile("file.output");
1185
1186 exit.expectSystemExitWithStatus(-1);
1187 exit.checkAssertionAfterwards(() -> {
1188 assertEquals("Unexpected output log", "Option '-t' cannot be used with other options."
1189 + System.lineSeparator(), systemOut.getLog());
1190 assertEquals("Unexpected system error log", "", systemErr.getLog());
1191 });
1192
1193 Main.main("-o", file.getCanonicalPath(), "-t", getPath(""));
1194 }
1195
1196 @Test
1197 public void testDebugOption() throws Exception {
1198 exit.checkAssertionAfterwards(() -> assertNotEquals("Unexpected system error log",
1199 "", systemErr.getLog()));
1200 Main.main("-c", "/google_checks.xml", getPath("InputMain.java"), "-d");
1201 }
1202
1203 @Test
1204 public void testExcludeOption() throws Exception {
1205 exit.expectSystemExitWithStatus(-1);
1206 exit.checkAssertionAfterwards(() -> {
1207 assertEquals("Unexpected output log", "Files to process must be specified, found 0."
1208 + System.lineSeparator(), systemOut.getLog());
1209 assertEquals("Unexpected system error log", "", systemErr.getLog());
1210 });
1211 Main.main("-c", "/google_checks.xml", getFilePath(""), "-e", getFilePath(""));
1212 }
1213
1214 @Test
1215 public void testExcludeOptionFile() throws Exception {
1216 exit.expectSystemExitWithStatus(-1);
1217 exit.checkAssertionAfterwards(() -> {
1218 assertEquals("Unexpected output log", "Files to process must be specified, found 0."
1219 + System.lineSeparator(), systemOut.getLog());
1220 assertEquals("Unexpected system error log", "", systemErr.getLog());
1221 });
1222 Main.main("-c", "/google_checks.xml", getFilePath("InputMain.java"), "-e",
1223 getFilePath("InputMain.java"));
1224 }
1225
1226 @Test
1227 public void testExcludeRegexpOption() throws Exception {
1228 exit.expectSystemExitWithStatus(-1);
1229 exit.checkAssertionAfterwards(() -> {
1230 assertEquals("Unexpected output log", "Files to process must be specified, found 0."
1231 + System.lineSeparator(), systemOut.getLog());
1232 assertEquals("Unexpected output log", "", systemErr.getLog());
1233 });
1234 Main.main("-c", "/google_checks.xml", getFilePath(""), "-x", ".");
1235 }
1236
1237 @Test
1238 public void testExcludeRegexpOptionFile() throws Exception {
1239 exit.expectSystemExitWithStatus(-1);
1240 exit.checkAssertionAfterwards(() -> {
1241 assertEquals("Unexpected output log", "Files to process must be specified, found 0."
1242 + System.lineSeparator(), systemOut.getLog());
1243 assertEquals("Unexpected output log", "", systemErr.getLog());
1244 });
1245 Main.main("-c", "/google_checks.xml", getFilePath("InputMain.java"), "-x", ".");
1246 }
1247
1248 @Test
1249 @SuppressWarnings("unchecked")
1250 public void testExcludeDirectoryNotMatch() throws Exception {
1251 final Class<?> optionsClass = Class.forName(Main.class.getName());
1252 final Method method = optionsClass.getDeclaredMethod("listFiles", File.class, List.class);
1253 method.setAccessible(true);
1254 final List<Pattern> list = new ArrayList<>();
1255 list.add(Pattern.compile("BAD_PATH"));
1256
1257 final List<File> result = (List<File>) method.invoke(null, new File(getFilePath("")),
1258 list);
1259 assertNotEquals("Invalid result size", 0, result.size());
1260 }
1261
1262 @Test
1263 public void testCustomRootModule() throws Exception {
1264 TestRootModuleChecker.reset();
1265
1266 exit.checkAssertionAfterwards(() -> {
1267 assertEquals("Unexpected output log", "", systemOut.getLog());
1268 assertEquals("Unexpected system error log", "", systemErr.getLog());
1269 assertTrue("Invalid Checker state", TestRootModuleChecker.isProcessed());
1270 });
1271 Main.main("-c", getPath("InputMainConfig-custom-root-module.xml"),
1272 getPath("InputMain.java"));
1273 assertTrue("RootModule should be destroyed", TestRootModuleChecker.isDestroyed());
1274 }
1275
1276 @Test
1277 public void testCustomSimpleRootModule() throws Exception {
1278 TestRootModuleChecker.reset();
1279 exit.expectSystemExitWithStatus(-2);
1280 exit.checkAssertionAfterwards(() -> {
1281 final String checkstylePackage = "com.puppycrawl.tools.checkstyle.";
1282 final LocalizedMessage unableToInstantiateExceptionMessage = new LocalizedMessage(1,
1283 Definitions.CHECKSTYLE_BUNDLE,
1284 "PackageObjectFactory.unableToInstantiateExceptionMessage",
1285 new String[] {"TestRootModuleChecker", checkstylePackage
1286 + "TestRootModuleChecker, "
1287 + "TestRootModuleCheckerCheck, " + checkstylePackage
1288 + "TestRootModuleCheckerCheck"},
1289 null, getClass(), null);
1290 assertEquals("Unexpected output log", errorCounterOneMessage.getMessage() + EOL,
1291 systemOut.getLog());
1292 assertTrue("Unexpected system error log",
1293 systemErr.getLog().startsWith(checkstylePackage + "api.CheckstyleException: "
1294 + unableToInstantiateExceptionMessage.getMessage()));
1295 assertFalse("Invalid checker state", TestRootModuleChecker.isProcessed());
1296 });
1297 Main.main("-c", getPath("InputMainConfig-custom-simple-root-module.xml"),
1298 getPath("InputMain.java"));
1299 }
1300
1301 @Test
1302 public void testExecuteIgnoredModule() throws Exception {
1303 exit.expectSystemExitWithStatus(-2);
1304 exit.checkAssertionAfterwards(() -> {
1305 final String expectedExceptionMessage = errorCounterOneMessage.getMessage() + EOL;
1306 assertEquals("Unexpected output log", expectedExceptionMessage, systemOut.getLog());
1307
1308 final String cause = "com.puppycrawl.tools.checkstyle.api.CheckstyleException:"
1309 + " cannot initialize module TreeWalker - ";
1310 assertTrue("Unexpected system error log", systemErr.getLog().startsWith(cause));
1311 });
1312
1313 Main.main("-c", getPath("InputMainConfig-non-existent-classname-ignore.xml"),
1314 "--executeIgnoredModules",
1315 getPath("InputMain.java"));
1316 }
1317
1318 @Test
1319 public void testInvalidCheckerThreadsNumber() throws Exception {
1320 exit.expectSystemExitWithStatus(-1);
1321 exit.checkAssertionAfterwards(() -> {
1322 assertEquals("Unexpected output log", "", systemOut.getLog());
1323 assertEquals("Unexpected system error log",
1324 "Invalid value for option '--checker-threads-number': 'invalid' is not an int"
1325 + EOL + SHORT_USAGE, systemErr.getLog());
1326 });
1327 Main.main("-C", "invalid", "-c", "/google_checks.xml", getPath("InputMain.java"));
1328 }
1329
1330 @Test
1331 public void testInvalidTreeWalkerThreadsNumber() throws Exception {
1332 exit.expectSystemExitWithStatus(-1);
1333 exit.checkAssertionAfterwards(() -> {
1334 assertEquals("Unexpected output log", "", systemOut.getLog());
1335 assertEquals("Unexpected system error log",
1336 "Invalid value for option '--tree-walker-threads-number': "
1337 + "'invalid' is not an int" + EOL + SHORT_USAGE, systemErr.getLog());
1338 });
1339 Main.main("-W", "invalid", "-c", "/google_checks.xml", getPath("InputMain.java"));
1340 }
1341
1342 @Test
1343 public void testZeroCheckerThreadsNumber() throws Exception {
1344 exit.expectSystemExitWithStatus(-1);
1345 exit.checkAssertionAfterwards(() -> {
1346 assertEquals("Unexpected output log", "Checker threads number must be greater than zero"
1347 + System.lineSeparator(), systemOut.getLog());
1348 assertEquals("Unexpected system error log", "", systemErr.getLog());
1349 });
1350 Main.main("-C", "0", "-c", "/google_checks.xml", getPath("InputMain.java"));
1351 }
1352
1353 @Test
1354 public void testZeroTreeWalkerThreadsNumber() throws Exception {
1355 exit.expectSystemExitWithStatus(-1);
1356 exit.checkAssertionAfterwards(() -> {
1357 assertEquals("Unexpected output log",
1358 "TreeWalker threads number must be greater than zero"
1359 + System.lineSeparator(), systemOut.getLog());
1360 assertEquals("Unexpected system error log", "", systemErr.getLog());
1361 });
1362 Main.main("-W", "0", "-c", "/google_checks.xml", getPath("InputMain.java"));
1363 }
1364
1365 @Test
1366 public void testCheckerThreadsNumber() throws Exception {
1367 TestRootModuleChecker.reset();
1368
1369 exit.checkAssertionAfterwards(() -> {
1370 assertEquals("Unexpected output log", "", systemOut.getLog());
1371 assertEquals("Unexpected system error log", "", systemErr.getLog());
1372 assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
1373 final DefaultConfiguration config =
1374 (DefaultConfiguration) TestRootModuleChecker.getConfig();
1375 final ThreadModeSettings multiThreadModeSettings = config.getThreadModeSettings();
1376 assertEquals("Invalid checker thread number",
1377 4, multiThreadModeSettings.getCheckerThreadsNumber());
1378 assertEquals("Invalid checker thread number",
1379 1, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1380 });
1381 Main.main("-C", "4", "-c", getPath("InputMainConfig-custom-root-module.xml"),
1382 getPath("InputMain.java"));
1383 }
1384
1385 @Test
1386 public void testTreeWalkerThreadsNumber() throws Exception {
1387 TestRootModuleChecker.reset();
1388
1389 exit.checkAssertionAfterwards(() -> {
1390 assertEquals("Unexpected output log", "", systemOut.getLog());
1391 assertEquals("Unexpected system error log", "", systemErr.getLog());
1392 assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
1393 final DefaultConfiguration config =
1394 (DefaultConfiguration) TestRootModuleChecker.getConfig();
1395 final ThreadModeSettings multiThreadModeSettings = config.getThreadModeSettings();
1396 assertEquals("Invalid checker thread number",
1397 1, multiThreadModeSettings.getCheckerThreadsNumber());
1398 assertEquals("Invalid checker thread number",
1399 4, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1400 });
1401 Main.main("-W", "4", "-c", getPath("InputMainConfig-custom-root-module.xml"),
1402 getPath("InputMain.java"));
1403 }
1404
1405 @Test
1406 public void testModuleNameInSingleThreadMode() throws Exception {
1407 TestRootModuleChecker.reset();
1408
1409 exit.checkAssertionAfterwards(() -> {
1410 assertEquals("Unexpected output log", "", systemOut.getLog());
1411 assertEquals("Unexpected system error log", "", systemErr.getLog());
1412 assertTrue("Invalid checker state", TestRootModuleChecker.isProcessed());
1413 final DefaultConfiguration config =
1414 (DefaultConfiguration) TestRootModuleChecker.getConfig();
1415 final ThreadModeSettings multiThreadModeSettings =
1416 config.getThreadModeSettings();
1417 assertEquals("Invalid checker thread number",
1418 1, multiThreadModeSettings.getCheckerThreadsNumber());
1419 assertEquals("Invalid checker thread number",
1420 1, multiThreadModeSettings.getTreeWalkerThreadsNumber());
1421 final Configuration checkerConfiguration = config
1422 .getChildren()[0];
1423 assertEquals("Invalid checker name", "Checker", checkerConfiguration.getName());
1424 final Configuration treeWalkerConfig = checkerConfiguration.getChildren()[0];
1425 assertEquals("Invalid checker children name", "TreeWalker", treeWalkerConfig.getName());
1426 });
1427 Main.main("-C", "1", "-W", "1", "-c", getPath("InputMainConfig-multi-thread-mode.xml"),
1428 getPath("InputMain.java"));
1429 }
1430
1431 @Test
1432 public void testModuleNameInMultiThreadMode() throws Exception {
1433 TestRootModuleChecker.reset();
1434
1435 try {
1436 Main.main("-C", "4", "-W", "4", "-c", getPath("InputMainConfig-multi-thread-mode.xml"),
1437 getPath("InputMain.java"));
1438 fail("An exception is expected");
1439 }
1440 catch (IllegalArgumentException ex) {
1441 assertEquals("Invalid error message",
1442 "Multi thread mode for Checker module is not implemented",
1443 ex.getMessage());
1444 }
1445 }
1446
1447 @Test
1448 public void testMissingFiles() throws Exception {
1449 exit.expectSystemExitWithStatus(-1);
1450 exit.checkAssertionAfterwards(() -> {
1451 final String usage = "Missing required parameter: <files>" + EOL + SHORT_USAGE;
1452 assertEquals("Unexpected output log", "", systemOut.getLog());
1453 assertEquals("Unexpected system error log", usage, systemErr.getLog());
1454 });
1455 Main.main();
1456 }
1457
1458 @Test
1459 public void testOutputFormatToStringLowercase() {
1460 assertEquals("expected xml", "xml", Main.OutputFormat.XML.toString());
1461 assertEquals("expected plain", "plain", Main.OutputFormat.PLAIN.toString());
1462 }
1463
1464 @Test
1465 public void testXmlOutputFormatCreateListener() {
1466 final ByteArrayOutputStream out = new ByteArrayOutputStream();
1467 final AuditListener listener = Main.OutputFormat.XML.createListener(out,
1468 AutomaticBean.OutputStreamOptions.CLOSE);
1469 assertTrue("listener is XMLLogger", listener instanceof XMLLogger);
1470 }
1471
1472 @Test
1473 public void testPlainOutputFormatCreateListener() {
1474 final ByteArrayOutputStream out = new ByteArrayOutputStream();
1475 final AuditListener listener = Main.OutputFormat.PLAIN.createListener(out,
1476 AutomaticBean.OutputStreamOptions.CLOSE);
1477 assertTrue("listener is DefaultLogger", listener instanceof DefaultLogger);
1478 }
1479
1480 }