diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/filters/AbstractPatchFilterEvaluationTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/filters/AbstractPatchFilterEvaluationTest.java index d7a94da4..a5e26495 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/filters/AbstractPatchFilterEvaluationTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/filters/AbstractPatchFilterEvaluationTest.java @@ -20,17 +20,18 @@ package com.puppycrawl.tools.checkstyle.filters; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FilenameFilter; import java.io.IOException; import java.io.InputStreamReader; import java.io.LineNumberReader; import java.nio.charset.StandardCharsets; import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -42,12 +43,33 @@ import com.puppycrawl.tools.checkstyle.PropertiesExpander; import com.puppycrawl.tools.checkstyle.api.Configuration; import com.puppycrawl.tools.checkstyle.api.RootModule; +import com.puppycrawl.tools.checkstyle.bdd.InlineConfigParser; +import com.puppycrawl.tools.checkstyle.bdd.TestInputViolation; import com.puppycrawl.tools.checkstyle.internal.utils.BriefUtLogger; +/** + * Base class for patch filter evaluation tests. + * + *

Each test bundle declares its expected violations in one of two ways:

+ * + * + *

The presence of {@code expected.txt} selects the mode, so bundles can be migrated to inline + * comments one at a time by adding the comments and deleting {@code expected.txt}.

+ */ abstract class AbstractPatchFilterEvaluationTest extends AbstractModuleTestSupport { private static final String CONTEXT_CONFIG_PATTERN = "(default|zero)ContextConfig.xml"; + private static final FilenameFilter INPUT_FILE_FILTER = + (dir, name) -> name.endsWith(".java") || name.endsWith(".properties"); + protected abstract String getPatchFileLocation(); protected void testByConfig(String configPath) @@ -63,7 +85,7 @@ protected void testByConfig(String configPath) final String path = getPath(inputFile); final int errorCounter = processFiles(rootModule, path); - assertResults(configPath, path, errorCounter, stream); + assertResults(path, errorCounter, stream); } private static RootModule createRootModule(Configuration config) throws Exception { @@ -77,36 +99,101 @@ private static RootModule createRootModule(Configuration config) throws Exceptio } private static int processFiles(RootModule rootModule, String path) throws Exception { - final File file = new File(path); - final File[] files = file.listFiles((dir, name) -> { - return name.endsWith(".java") || name.endsWith(".properties"); - }); + return rootModule.process(listInputFiles(path)); + } + + private static List listInputFiles(String path) throws IOException { + final File[] files = new File(path).listFiles(INPUT_FILE_FILTER); if (files == null) { throw new IOException("there is no java file in this directory."); } - - final List theFiles = Arrays.asList(files); + final List theFiles = new ArrayList<>(Arrays.asList(files)); Collections.sort(theFiles); - return rootModule.process(theFiles); + return theFiles; } - private void assertResults(String configPath, String path, int errorCounter, - ByteArrayOutputStream stream) throws IOException { + private void assertResults(String path, int errorCounter, ByteArrayOutputStream stream) + throws Exception { try (ByteArrayInputStream inputStream = new ByteArrayInputStream(stream.toByteArray()); LineNumberReader lnr = new LineNumberReader( new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - final String expectedFile = configPath.replaceFirst(CONTEXT_CONFIG_PATTERN, - "expected.txt"); - final Path expectedFilePath = Paths.get(getPath(expectedFile)); - final List expected = Files.readAllLines(expectedFilePath); final List actuals = lnr.lines().toList(); - - for (int index = 0; index < expected.size(); index++) { - final String expectedResult = path + File.separator + expected.get(index); - assertEquals(expectedResult, actuals.get(index), - "error message " + index + ". Expected file: " + expectedFilePath); + final File expectedFile = new File(path, "expected.txt"); + if (expectedFile.exists()) { + assertLegacyResults(expectedFile, path, errorCounter, actuals); + } + else { + assertInlineResults(path, errorCounter, actuals); } - assertEquals(expected.size(), errorCounter, "unexpected output: " + lnr.readLine()); + } + } + + private static void assertLegacyResults(File expectedFile, String path, int errorCounter, + List actuals) throws IOException { + final List expected = Files.readAllLines(expectedFile.toPath()); + for (int index = 0; index < expected.size(); index++) { + final String expectedResult = path + File.separator + expected.get(index); + assertEquals(expectedResult, actuals.get(index), + "error message " + index + ". Expected file: " + expectedFile); + } + assertEquals(expected.size(), errorCounter, "unexpected output"); + } + + /** + * Verifies the actual output against inline {@code // violation 'message'} comments in the + * bundle's input files. Violations are parsed with the main library's + * {@link InlineConfigParser#getViolationsFromInputFile(String)} and checked per file, then a + * total count guards against any reported violation that is not attributed to a file. + * + * @param path the directory containing the bundle's input files + * @param errorCounter number of violations reported by checkstyle + * @param actuals actual output lines + * @throws Exception if an input file cannot be parsed + */ + private static void assertInlineResults(String path, int errorCounter, List actuals) + throws Exception { + int expectedTotal = 0; + for (File file : listInputFiles(path)) { + final List violations = + InlineConfigParser.getViolationsFromInputFile(file.getPath()); + final String prefix = file.getPath() + ":"; + final List actualViolations = actuals.stream() + .filter(line -> line.startsWith(prefix)) + .map(line -> line.substring(prefix.length())) + .toList(); + verifyViolations(file.getPath(), violations, actualViolations); + expectedTotal += violations.size(); + } + assertEquals(expectedTotal, errorCounter, + "number of violations does not match inline comments"); + } + + /** + * Replicates {@code AbstractModuleTestSupport.verifyViolations}, which is not visible here: + * the reported violation lines must equal the commented lines, then each violation must match + * its {@link TestInputViolation#toRegex()}. The column is not asserted, matching the + * inline-violation convention shared with checkstyle: these filters operate on lines. + * + * @param file file path, for assertion messages + * @param testInputViolations expected violations parsed from inline comments + * @param actualViolations actual violations for the file, as {@code line:column: message} + */ + private static void verifyViolations(String file, + List testInputViolations, + List actualViolations) { + final List actualViolationLines = actualViolations.stream() + .map(violation -> violation.substring(0, violation.indexOf(':'))) + .map(Integer::valueOf) + .toList(); + final List expectedViolationLines = testInputViolations.stream() + .map(TestInputViolation::getLineNo) + .toList(); + assertEquals(expectedViolationLines, actualViolationLines, + "Violation lines for " + file + " differ."); + for (int index = 0; index < actualViolations.size(); index++) { + assertTrue(actualViolations.get(index).matches( + testInputViolations.get(index).toRegex()), + "Actual and expected violations differ for " + file); } } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test.java index 41cc056b..1e3b8e39 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test.java @@ -9,7 +9,7 @@ public class Test { // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warn + // Contains a tab -> <- //warn // filtered violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test2.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test2.java index a250be0c..2fe600c6 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test2.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/Test2.java @@ -1,5 +1,5 @@ package Checker.FileTabCharacter; public class Test2 { - // Contains a tab -> <- //warn // violation without filter + // Contains a tab -> <- //warn // violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/defaultContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/defaultContext.patch index a051e2f7..865521ed 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/defaultContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/defaultContext.patch @@ -7,7 +7,7 @@ index d57b91c..41cc056 100644 // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns - // Contains a tab -> <- //warn + // Contains a tab -> <- //warn // filtered violation 'Line contains a tab character.' diff --git a/Test2.java b/Test2.java @@ -18,5 +18,5 @@ index 6055de3..b4ea012 100644 package Checker.FileTabCharacter; public class Test2 { -+ // Contains a tab -> <- //warn // violation without filter ++ // Contains a tab -> <- //warn // violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/expected.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/expected.txt deleted file mode 100644 index 26d89a35..00000000 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/newline/expected.txt +++ /dev/null @@ -1 +0,0 @@ -Test2.java:4:25: Line contains a tab character. \ No newline at end of file diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test.java index 41cc056b..1e3b8e39 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test.java @@ -9,7 +9,7 @@ public class Test { // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warn + // Contains a tab -> <- //warn // filtered violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test2.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test2.java index a250be0c..2fe600c6 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test2.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/Test2.java @@ -1,5 +1,5 @@ package Checker.FileTabCharacter; public class Test2 { - // Contains a tab -> <- //warn // violation without filter + // Contains a tab -> <- //warn // violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/defaultContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/defaultContext.patch index a051e2f7..865521ed 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/defaultContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/defaultContext.patch @@ -7,7 +7,7 @@ index d57b91c..41cc056 100644 // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns - // Contains a tab -> <- //warn + // Contains a tab -> <- //warn // filtered violation 'Line contains a tab character.' diff --git a/Test2.java b/Test2.java @@ -18,5 +18,5 @@ index 6055de3..b4ea012 100644 package Checker.FileTabCharacter; public class Test2 { -+ // Contains a tab -> <- //warn // violation without filter ++ // Contains a tab -> <- //warn // violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/expected.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/expected.txt deleted file mode 100644 index 26d89a35..00000000 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/MoveCodeToAnotherFileWithMinorChanges/patchedline/expected.txt +++ /dev/null @@ -1 +0,0 @@ -Test2.java:4:25: Line contains a tab character. \ No newline at end of file diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/Test.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/Test.java index aada79dc..b7bd0ddc 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/Test.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/Test.java @@ -7,11 +7,11 @@ public class Test { - // Contains a tab -> <- //warns // violation without filter + // Contains a tab -> <- //warns // violation 'Line contains a tab character.' // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns - // Contains a tab -> <- //warns + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/defaultContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/defaultContext.patch index 6294898a..4804a570 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/defaultContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/defaultContext.patch @@ -6,7 +6,7 @@ index 63f6e7c..8e0f63c 100644 -+ // Contains a tab -> <- //warns // violation without filter ++ // Contains a tab -> <- //warns // violation 'Line contains a tab character.' // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/expected.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/expected.txt deleted file mode 100644 index b6202e4e..00000000 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/expected.txt +++ /dev/null @@ -1 +0,0 @@ -Test.java:10:25: Line contains a tab character. \ No newline at end of file diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/zeroContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/zeroContext.patch index cb4eba70..3d92e070 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/zeroContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/newline/zeroContext.patch @@ -3,4 +3,4 @@ index 63f6e7c..8e0f63c 100644 --- a/Test.java +++ b/Test.java @@ -9,0 +10 @@ public class Test { -+ // Contains a tab -> <- //warns // violation without filter ++ // Contains a tab -> <- //warns // violation 'Line contains a tab character.' diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/Test.java b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/Test.java index aada79dc..b7bd0ddc 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/Test.java +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/Test.java @@ -7,11 +7,11 @@ public class Test { - // Contains a tab -> <- //warns // violation without filter + // Contains a tab -> <- //warns // violation 'Line contains a tab character.' // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns - // Contains a tab -> <- //warns + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/defaultContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/defaultContext.patch index 6294898a..4804a570 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/defaultContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/defaultContext.patch @@ -6,7 +6,7 @@ index 63f6e7c..8e0f63c 100644 -+ // Contains a tab -> <- //warns // violation without filter ++ // Contains a tab -> <- //warns // violation 'Line contains a tab character.' // Long line ---------------------------------------------------------------- // Long line ---------------------------------------------------------------- - // Contains a tab -> <- //warns + // Contains a tab -> <- //warns // filtered violation 'Line contains a tab character.' diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/expected.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/expected.txt deleted file mode 100644 index b6202e4e..00000000 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/expected.txt +++ /dev/null @@ -1 +0,0 @@ -Test.java:10:25: Line contains a tab character. \ No newline at end of file diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/zeroContext.patch b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/zeroContext.patch index cb4eba70..3d92e070 100644 --- a/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/zeroContext.patch +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/filters/suppressionpatchfilter/FileTabCharacter/SingleNewLine/patchedline/zeroContext.patch @@ -3,4 +3,4 @@ index 63f6e7c..8e0f63c 100644 --- a/Test.java +++ b/Test.java @@ -9,0 +10 @@ public class Test { -+ // Contains a tab -> <- //warns // violation without filter ++ // Contains a tab -> <- //warns // violation 'Line contains a tab character.'