1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.checkstyle.suppressionxpathfilter;
21
22 import static org.junit.Assert.assertEquals;
23
24 import java.io.File;
25 import java.io.Writer;
26 import java.nio.charset.StandardCharsets;
27 import java.nio.file.Files;
28 import java.util.List;
29 import java.util.Locale;
30 import java.util.regex.Matcher;
31 import java.util.regex.Pattern;
32 import java.util.stream.Collectors;
33
34 import org.junit.Rule;
35 import org.junit.rules.TemporaryFolder;
36
37 import com.google.checkstyle.test.base.AbstractModuleTestSupport;
38 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
39 import com.puppycrawl.tools.checkstyle.JavaParser;
40 import com.puppycrawl.tools.checkstyle.TreeWalker;
41 import com.puppycrawl.tools.checkstyle.api.DetailAST;
42 import com.puppycrawl.tools.checkstyle.api.FileText;
43 import com.puppycrawl.tools.checkstyle.filters.SuppressionXpathFilter;
44 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
45 import com.puppycrawl.tools.checkstyle.xpath.XpathQueryGenerator;
46
47 public abstract class AbstractXpathTestSupport extends AbstractModuleTestSupport {
48
49 private static final int DEFAULT_TAB_WIDTH = 4;
50
51 private static final String DELIMITER = " | \n";
52
53 private static final Pattern LINE_COLUMN_NUMBER_REGEX =
54 Pattern.compile("([0-9]+):([0-9]+):");
55
56 @Rule
57 public final TemporaryFolder temporaryFolder = new TemporaryFolder();
58
59 protected abstract String getCheckName();
60
61 @Override
62 protected String getPackageLocation() {
63 final String subpackage = getCheckName().toLowerCase(Locale.ENGLISH)
64 .replace("check", "");
65 return "org/checkstyle/suppressionxpathfilter" + "/" + subpackage;
66 }
67
68 private static List<String> generateXpathQueries(File fileToProcess,
69 ViolationPosition position)
70 throws Exception {
71 final FileText fileText = new FileText(fileToProcess,
72 StandardCharsets.UTF_8.name());
73 final DetailAST rootAst = JavaParser.parseFile(fileToProcess,
74 JavaParser.Options.WITH_COMMENTS);
75 final XpathQueryGenerator queryGenerator = new XpathQueryGenerator(rootAst,
76 position.violationLineNumber, position.violationColumnNumber,
77 fileText, DEFAULT_TAB_WIDTH);
78
79 return queryGenerator.generate();
80 }
81
82 private static void verifyXpathQueries(List<String> generatedXpathQueries,
83 List<String> expectedXpathQueries) {
84 assertEquals("Generated queries do not match expected ones", expectedXpathQueries,
85 generatedXpathQueries);
86 }
87
88 private String createSuppressionsXpathConfigFile(String checkName,
89 List<String> xpathQueries)
90 throws Exception {
91
92 final File suppressionsXpathConfigFile = temporaryFolder.newFile();
93 try (Writer bw = Files.newBufferedWriter(suppressionsXpathConfigFile.toPath(),
94 StandardCharsets.UTF_8)) {
95 bw.write("<?xml version=\"1.0\"?>\n");
96 bw.write("<!DOCTYPE suppressions PUBLIC\n");
97 bw.write(" \"-//Checkstyle//DTD SuppressionXpathFilter ");
98 bw.write("Experimental Configuration 1.2//EN\"\n");
99 bw.write(" \"https://checkstyle.org/dtds/");
100 bw.write("suppressions_1_2_xpath_experimental.dtd\">\n");
101 bw.write("<suppressions>\n");
102 bw.write(" <suppress-xpath\n");
103 bw.write(" checks=\"");
104 bw.write(checkName);
105 bw.write("\"\n");
106 bw.write(" query=\"");
107 bw.write(xpathQueries.stream().collect(Collectors.joining(DELIMITER)));
108 bw.write("\"/>\n");
109 bw.write("</suppressions>");
110 }
111
112 return suppressionsXpathConfigFile.getPath();
113 }
114
115 private DefaultConfiguration createSuppressionXpathFilter(String checkName,
116 List<String> xpathQueries) throws Exception {
117 final DefaultConfiguration suppressionXpathFilterConfig =
118 createModuleConfig(SuppressionXpathFilter.class);
119 suppressionXpathFilterConfig.addAttribute("file",
120 createSuppressionsXpathConfigFile(checkName, xpathQueries));
121
122 return suppressionXpathFilterConfig;
123 }
124
125 private static ViolationPosition extractLineAndColumnNumber(String... expectedViolations) {
126 ViolationPosition violation = null;
127 final Matcher matcher =
128 LINE_COLUMN_NUMBER_REGEX.matcher(expectedViolations[0]);
129 if (matcher.find()) {
130 final int violationLineNumber = Integer.parseInt(matcher.group(1));
131 final int violationColumnNumber = Integer.parseInt(matcher.group(2));
132 violation = new ViolationPosition(violationLineNumber, violationColumnNumber);
133 }
134 return violation;
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151 protected void runVerifications(DefaultConfiguration moduleConfig,
152 File fileToProcess,
153 String[] expectedViolations,
154 List<String> expectedXpathQueries) throws Exception {
155 final ViolationPosition position =
156 extractLineAndColumnNumber(expectedViolations);
157 final List<String> generatedXpathQueries =
158 generateXpathQueries(fileToProcess, position);
159
160 final DefaultConfiguration treeWalkerConfigWithXpath =
161 createModuleConfig(TreeWalker.class);
162 treeWalkerConfigWithXpath.addChild(moduleConfig);
163 treeWalkerConfigWithXpath.addChild(createSuppressionXpathFilter(moduleConfig.getName(),
164 generatedXpathQueries));
165
166 final Integer[] warnList = getLinesWithWarn(fileToProcess.getPath());
167 verify(moduleConfig, fileToProcess.getPath(), expectedViolations, warnList);
168 verifyXpathQueries(generatedXpathQueries, expectedXpathQueries);
169 verify(treeWalkerConfigWithXpath, fileToProcess.getPath(), CommonUtil.EMPTY_STRING_ARRAY);
170 }
171
172 private static final class ViolationPosition {
173 private final int violationLineNumber;
174 private final int violationColumnNumber;
175
176 ViolationPosition(int violationLineNumber,
177 int violationColumnNumber) {
178 this.violationLineNumber = violationLineNumber;
179 this.violationColumnNumber = violationColumnNumber;
180 }
181 }
182 }