Skip to content

Commit

Permalink
Issue #10745: Add inline config support for tests with multiple modules
Browse files Browse the repository at this point in the history
  • Loading branch information
shashwatj07 committed Aug 30, 2021
1 parent 71f7ced commit 525bc1e
Show file tree
Hide file tree
Showing 201 changed files with 1,889 additions and 1,859 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,15 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

import com.google.common.collect.Maps;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.Violation;
import com.puppycrawl.tools.checkstyle.bdd.InlineConfigParser;
import com.puppycrawl.tools.checkstyle.bdd.ModuleInputConfiguration;
import com.puppycrawl.tools.checkstyle.bdd.TestInputConfiguration;
import com.puppycrawl.tools.checkstyle.bdd.TestInputViolation;
import com.puppycrawl.tools.checkstyle.internal.utils.BriefUtLogger;
Expand Down Expand Up @@ -218,49 +215,42 @@ protected final String getUriString(String filename) {
}

protected final void verifyFilterWithInlineConfigParser(Configuration aConfig,
Configuration filterConfig,
String filePath, String[] expectedUnfiltered,
String... expectedFiltered)
String filePath,
String[] expectedUnfiltered,
String... expectedFiltered)
throws Exception {
final TestInputConfiguration checkTestInputConfiguration =
final TestInputConfiguration testInputConfiguration =
InlineConfigParser.parseWithFilteredViolations(filePath);
final DefaultConfiguration parsedCheckConfig =
checkTestInputConfiguration.createConfiguration();
final ModuleInputConfiguration checkModule =
checkTestInputConfiguration.getChildrenModules().get(0);
verifyConfig(aConfig, checkModule.createConfiguration(), checkModule);
verifyViolations(parsedCheckConfig, filePath, checkTestInputConfiguration);
verify(parsedCheckConfig, filePath, expectedUnfiltered);
final TestInputConfiguration filterTestInputConfiguration =
InlineConfigParser.parseFilter(filePath);
final ModuleInputConfiguration filterModule =
filterTestInputConfiguration.getChildrenModules().get(0);
verifyConfig(filterConfig, filterModule.createConfiguration(), filterModule);
parsedCheckConfig.addChild(filterModule.createConfiguration());
verifyViolations(parsedCheckConfig, filePath, filterTestInputConfiguration);
verify(parsedCheckConfig, filePath, expectedFiltered);
final DefaultConfiguration configWithoutFilters =
testInputConfiguration.createConfigurationWithoutFilters();
final List<TestInputViolation> violationsWithoutFilters =
new ArrayList<>(testInputConfiguration.getViolations());
violationsWithoutFilters.addAll(testInputConfiguration.getFilteredViolations());
Collections.sort(violationsWithoutFilters);
verifyViolations(configWithoutFilters, filePath, violationsWithoutFilters);
verify(configWithoutFilters, filePath, expectedUnfiltered);
final DefaultConfiguration configWithFilters =
testInputConfiguration.createConfiguration();
verifyViolations(configWithFilters, filePath, testInputConfiguration.getViolations());
verify(configWithFilters, filePath, expectedFiltered);
}

/**
* Performs verification of the file with the given file path using specified configuration
* and the array expected messages. Also performs verification of the config specified in
* input file.
*
* @param aConfig configuration.
* @param filePath file path to verify.
* @param expected an array of expected messages.
* @throws Exception if exception occurs during verification process.
*/
protected final void verifyWithInlineConfigParser(Configuration aConfig,
String filePath, String... expected)
protected final void verifyWithInlineConfigParser(String filePath, String... expected)
throws Exception {
final TestInputConfiguration testInputConfiguration =
InlineConfigParser.parse(filePath);
final Configuration parsedConfig = testInputConfiguration.createConfiguration();
final ModuleInputConfiguration checkModule =
testInputConfiguration.getChildrenModules().get(0);
verifyConfig(aConfig, checkModule.createConfiguration(), checkModule);
verifyViolations(parsedConfig, filePath, testInputConfiguration);
final DefaultConfiguration parsedConfig =
testInputConfiguration.createConfiguration();
verifyViolations(parsedConfig, filePath, testInputConfiguration.getViolations());
verify(parsedConfig, filePath, expected);
}

Expand Down Expand Up @@ -389,59 +379,27 @@ protected final void verifyWithLimitedResources(Configuration aConfig,
throws Exception {
// We return null here, which gives us a result to make an assertion about
final Void result = TestUtil.getResultWithLimitedResources(() -> {
verifyWithInlineConfigParser(aConfig, fileName, expected);
verifyWithInlineConfigParser(fileName, expected);
return null;
});
assertWithMessage("Verify should complete successfully.")
.that(result)
.isNull();
}

/**
* Performs verification of the config read from input file.
*
* @param testConfig hardcoded test config.
* @param parsedConfig parsed config from input file.
* @param moduleInputConfiguration ModuleInputConfiguration object.
* @throws CheckstyleException if property keys not found.
*/
private static void verifyConfig(Configuration testConfig,
Configuration parsedConfig,
ModuleInputConfiguration moduleInputConfiguration)
throws CheckstyleException {
assertWithMessage("Check name differs from expected.")
.that(testConfig.getName())
.isEqualTo(parsedConfig.getName());
for (String property : parsedConfig.getPropertyNames()) {
assertWithMessage("Property value for key %s differs from expected.", property)
.that(testConfig.getProperty(property))
.isEqualTo(parsedConfig.getProperty(property));
}
final List<String> testProperties =
new LinkedList<>(Arrays.asList(testConfig.getPropertyNames()));
testProperties.removeAll(Arrays.asList(parsedConfig.getPropertyNames()));
for (String property : testProperties) {
assertWithMessage("Property value for key %s differs from expected.", property)
.that(moduleInputConfiguration.getDefaultPropertyValue(property))
.isEqualTo(testConfig.getProperty(property));
}
}

/**
* Performs verification of violation lines.
*
* @param config parsed config.
* @param file file path.
* @param testInputConfiguration TestInputConfiguration object.
* @param testInputViolations List of TestInputViolation objects.
* @throws Exception if exception occurs during verification process.
*/
private void verifyViolations(Configuration config,
String file,
TestInputConfiguration testInputConfiguration)
List<TestInputViolation> testInputViolations)
throws Exception {
final List<String> actualViolations = getActualViolationsForFile(config, file);
final List<TestInputViolation> testInputViolations =
testInputConfiguration.getViolations();
assertWithMessage("Number of actual and expected violations differ.")
.that(actualViolations)
.hasSize(testInputViolations.size());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,8 @@ private static TestInputConfiguration parse(String inputFilePath,
final List<String> lines = readFile(filePath);
final TestInputConfiguration.Builder testInputConfigBuilder =
new TestInputConfiguration.Builder();
final ModuleInputConfiguration.Builder moduleInputConfigBuilder =
new ModuleInputConfiguration.Builder();
setModuleName(moduleInputConfigBuilder, inputFilePath, lines);
setProperties(moduleInputConfigBuilder, inputFilePath, lines, 2);
setModules(testInputConfigBuilder, inputFilePath, lines);
setViolations(testInputConfigBuilder, lines, setFilteredViolations);
testInputConfigBuilder.addChildModule(moduleInputConfigBuilder.build());
return testInputConfigBuilder.build();
}

Expand All @@ -115,26 +111,20 @@ public static TestInputConfiguration parseWithFilteredViolations(String inputFil
return parse(inputFilePath, true);
}

/**
* Parses the filter input file provided.
*
* @param inputFilePath the input file path.
* @throws Exception if unable to read file or file not formatted properly.
*/
public static TestInputConfiguration parseFilter(String inputFilePath)
private static void setModules(TestInputConfiguration.Builder testInputConfigBuilder,
String inputFilePath, List<String> lines)
throws Exception {
final Path filePath = Paths.get(inputFilePath);
final List<String> lines = readFile(filePath);
final TestInputConfiguration.Builder testInputConfigBuilder =
new TestInputConfiguration.Builder();
final ModuleInputConfiguration.Builder moduleInputConfigBuilder =
new ModuleInputConfiguration.Builder();
final int lineNo = getFilterConfigLineNo(lines);
setFilterName(moduleInputConfigBuilder, inputFilePath, lines, lineNo);
setProperties(moduleInputConfigBuilder, inputFilePath, lines, lineNo + 1);
setViolations(testInputConfigBuilder, lines, false);
testInputConfigBuilder.addChildModule(moduleInputConfigBuilder.build());
return testInputConfigBuilder.build();
int lineNo = 1;
do {
final ModuleInputConfiguration.Builder moduleInputConfigBuilder =
new ModuleInputConfiguration.Builder();
setModuleName(moduleInputConfigBuilder, inputFilePath, lines.get(lineNo));
setProperties(moduleInputConfigBuilder, inputFilePath, lines, lineNo + 1);
testInputConfigBuilder.addChildModule(moduleInputConfigBuilder.build());
do {
lineNo++;
} while (lines.get(lineNo).isEmpty() || !lines.get(lineNo - 1).isEmpty());
} while (!lines.get(lineNo).startsWith("*/"));
}

private static String getFullyQualifiedClassName(String filePath, String moduleName) {
Expand Down Expand Up @@ -199,34 +189,10 @@ private static List<String> readFile(Path filePath) throws CheckstyleException {
}
}

private static void setModuleName(ModuleInputConfiguration.Builder inputConfigBuilder,
String filePath, List<String> lines)
throws CheckstyleException {
if (lines.size() < 2) {
throw new CheckstyleException("Config not specified in " + filePath);
}
final String moduleName = lines.get(1);
private static void setModuleName(ModuleInputConfiguration.Builder moduleInputConfigBuilder,
String filePath, String moduleName) {
final String fullyQualifiedClassName = getFullyQualifiedClassName(filePath, moduleName);
inputConfigBuilder.setModuleName(fullyQualifiedClassName);
}

private static int getFilterConfigLineNo(List<String> lines) {
int lineNo = 1;
while (!lines.get(lineNo - 1).isEmpty() || lines.get(lineNo).isEmpty()) {
lineNo++;
}
return lineNo;
}

private static void setFilterName(ModuleInputConfiguration.Builder inputConfigBuilder,
String filePath, List<String> lines, int lineNo)
throws CheckstyleException {
final String filterName = lines.get(lineNo);
if (!filterName.endsWith("Filter")) {
throw new CheckstyleException("Filter not specified in " + filePath);
}
final String fullyQualifiedClassName = getFullyQualifiedClassName(filePath, filterName);
inputConfigBuilder.setModuleName(fullyQualifiedClassName);
moduleInputConfigBuilder.setModuleName(fullyQualifiedClassName);
}

private static void setProperties(ModuleInputConfiguration.Builder inputConfigBuilder,
Expand Down Expand Up @@ -336,13 +302,13 @@ private static void setFilteredViolation(TestInputConfiguration.Builder inputCon
final Matcher violationBelowMatcher =
FILTERED_VIOLATION_BELOW_PATTERN.matcher(line);
if (violationMatcher.matches()) {
inputConfigBuilder.addViolation(lineNo, violationMatcher.group(1));
inputConfigBuilder.addFilteredViolation(lineNo, violationMatcher.group(1));
}
else if (violationAboveMatcher.matches()) {
inputConfigBuilder.addViolation(lineNo - 1, violationAboveMatcher.group(1));
inputConfigBuilder.addFilteredViolation(lineNo - 1, violationAboveMatcher.group(1));
}
else if (violationBelowMatcher.matches()) {
inputConfigBuilder.addViolation(lineNo + 1, violationBelowMatcher.group(1));
inputConfigBuilder.addFilteredViolation(lineNo + 1, violationBelowMatcher.group(1));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,26 @@ public final class TestInputConfiguration {

private final List<TestInputViolation> violations;

private final List<TestInputViolation> filteredViolations;

private TestInputConfiguration(List<ModuleInputConfiguration> childrenModules,
List<TestInputViolation> violations) {
List<TestInputViolation> violations,
List<TestInputViolation> filteredViolations) {
this.childrenModules = childrenModules;
this.violations = violations;
this.filteredViolations = filteredViolations;
}

public List<ModuleInputConfiguration> getChildrenModules() {
return Collections.unmodifiableList(childrenModules);
}

public List<TestInputViolation> getViolations() {
return Collections.unmodifiableList(violations);
}

public List<ModuleInputConfiguration> getChildrenModules() {
return Collections.unmodifiableList(childrenModules);
public List<TestInputViolation> getFilteredViolations() {
return Collections.unmodifiableList(filteredViolations);
}

public DefaultConfiguration createConfiguration() {
Expand All @@ -93,24 +101,52 @@ public DefaultConfiguration createConfiguration() {
return root;
}

public DefaultConfiguration createConfigurationWithoutFilters() {
final DefaultConfiguration root = new DefaultConfiguration(ROOT_MODULE_NAME);
final DefaultConfiguration treeWalker =
new DefaultConfiguration(TreeWalker.class.getName());
root.addProperty("charset", StandardCharsets.UTF_8.name());
childrenModules
.stream()
.map(ModuleInputConfiguration::createConfiguration)
.filter(moduleConfig -> !moduleConfig.getName().endsWith("Filter"))
.forEach(moduleConfig -> {
if (CHECKER_CHILDREN.contains(moduleConfig.getName())) {
root.addChild(moduleConfig);
}
else {
treeWalker.addChild(moduleConfig);
}
});
root.addChild(treeWalker);
return root;
}

public static final class Builder {

private final List<ModuleInputConfiguration> childrenModules = new ArrayList<>();

private final List<TestInputViolation> violations = new ArrayList<>();

private final List<TestInputViolation> filteredViolations = new ArrayList<>();

public void addChildModule(ModuleInputConfiguration childModule) {
childrenModules.add(childModule);
}

public void addViolation(int violationLine, String violationMessage) {
violations.add(new TestInputViolation(violationLine, violationMessage));
}

public void addChildModule(ModuleInputConfiguration childModule) {
childrenModules.add(childModule);
public void addFilteredViolation(int violationLine, String violationMessage) {
filteredViolations.add(new TestInputViolation(violationLine, violationMessage));
}

public TestInputConfiguration build() {
return new TestInputConfiguration(
childrenModules,
violations
violations,
filteredViolations
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

import java.util.regex.Pattern;

public final class TestInputViolation {
public final class TestInputViolation implements Comparable<TestInputViolation> {

/** Pattern to match the symbol: "{". */
private static final Pattern OPEN_CURLY_PATTERN = Pattern.compile("\\{");
Expand Down Expand Up @@ -83,4 +83,9 @@ public String toRegex() {
}
return regex;
}

@Override
public int compareTo(TestInputViolation testInputViolation) {
return lineNo - testInputViolation.lineNo;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public void testJavaStyleOn()
"55:27: " + getCheckMessage(MSG_KEY),
"55:29: " + getCheckMessage(MSG_KEY),
};
verifyWithInlineConfigParser(checkConfig,
verifyWithInlineConfigParser(
getPath("InputArrayTypeStyle.java"), expected);
}

Expand All @@ -81,7 +81,7 @@ public void testJavaStyleOff()
"55:27: " + getCheckMessage(MSG_KEY),
"55:29: " + getCheckMessage(MSG_KEY),
};
verifyWithInlineConfigParser(checkConfig,
verifyWithInlineConfigParser(
getPath("InputArrayTypeStyleOff.java"), expected);
}

Expand All @@ -96,7 +96,7 @@ public void testNestedGenerics()
"24:76: " + getCheckMessage(MSG_KEY),
"31:16: " + getCheckMessage(MSG_KEY),
};
verifyWithInlineConfigParser(checkConfig,
verifyWithInlineConfigParser(
getPath("InputArrayTypeStyleNestedGenerics.java"), expected);
}

Expand Down

0 comments on commit 525bc1e

Please sign in to comment.