View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package org.checkstyle.suppressionxpathfilter.coding;
21  
22  import java.io.File;
23  import java.util.Arrays;
24  import java.util.Collections;
25  import java.util.List;
26  
27  import org.checkstyle.suppressionxpathfilter.AbstractXpathTestSupport;
28  import org.junit.jupiter.api.Test;
29  
30  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
31  import com.puppycrawl.tools.checkstyle.checks.coding.IllegalTokenCheck;
32  import com.puppycrawl.tools.checkstyle.checks.coding.MatchXpathCheck;
33  
34  public class XpathRegressionMatchXpathTest extends AbstractXpathTestSupport {
35  
36      private final String checkName = MatchXpathCheck.class.getSimpleName();
37  
38      @Override
39      protected String getCheckName() {
40          return checkName;
41      }
42  
43      @Override
44      protected String getPackageLocation() {
45          return "org/checkstyle/suppressionxpathfilter/coding/matchxpath";
46      }
47  
48      @Test
49      public void testOne() throws Exception {
50          final File fileToProcess =
51                  new File(getPath("InputXpathMatchXpathOne.java"));
52  
53          final DefaultConfiguration moduleConfig =
54                  createModuleConfig(MatchXpathCheck.class);
55          moduleConfig.addProperty("query", "//METHOD_DEF[./IDENT[@text='test']]");
56  
57          final String[] expectedViolation = {
58              "4:5: " + getCheckMessage(MatchXpathCheck.class, MatchXpathCheck.MSG_KEY),
59          };
60  
61          final List<String> expectedXpathQueries = Arrays.asList(
62              "/COMPILATION_UNIT/CLASS_DEF[./IDENT[@text='InputXpathMatchXpathOne']]"
63                      + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]",
64              "/COMPILATION_UNIT/CLASS_DEF[./IDENT[@text='InputXpathMatchXpathOne']]"
65                      + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/MODIFIERS",
66              "/COMPILATION_UNIT/CLASS_DEF[./IDENT[@text='InputXpathMatchXpathOne']]"
67                      + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='test']]/MODIFIERS/LITERAL_PUBLIC"
68          );
69  
70          runVerifications(moduleConfig, fileToProcess, expectedViolation,
71                  expectedXpathQueries);
72      }
73  
74      @Test
75      public void testTwo() throws Exception {
76          final File fileToProcess =
77                  new File(getPath("InputXpathMatchXpathTwo.java"));
78  
79          final DefaultConfiguration moduleConfig =
80                  createModuleConfig(MatchXpathCheck.class);
81          moduleConfig.addProperty("query", "//LITERAL_THROWS[./IDENT[@text='Throwable' or "
82                  + "@text='RuntimeException' or ends-with(@text, 'Error')]]");
83  
84          final String[] expectedViolation = {
85              "4:25: " + getCheckMessage(MatchXpathCheck.class, MatchXpathCheck.MSG_KEY),
86          };
87  
88          final List<String> expectedXpathQueries = Collections.singletonList(
89                  "/COMPILATION_UNIT/CLASS_DEF"
90                          + "[./IDENT[@text='InputXpathMatchXpathTwo']]"
91                          + "/OBJBLOCK/METHOD_DEF[./IDENT[@text='func1']]"
92                          + "/LITERAL_THROWS[./IDENT[@text='RuntimeException']]"
93          );
94  
95          runVerifications(moduleConfig, fileToProcess, expectedViolation,
96                  expectedXpathQueries);
97      }
98  
99      @Test
100     public void testEncodedQuoteString() throws Exception {
101         final File fileToProcess =
102                 new File(getPath("InputXpathMatchXpathEncodedQuoteString.java"));
103 
104         final DefaultConfiguration moduleConfig =
105                 createModuleConfig(IllegalTokenCheck.class);
106         moduleConfig.addProperty("tokens", "STRING_LITERAL");
107 
108         final String[] expectedViolation = {
109             "4:24: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
110                     "\"\\\"testOne\\\"\""),
111         };
112 
113         final List<String> expectedXpathQueries = Arrays.asList(
114             "/COMPILATION_UNIT/CLASS_DEF"
115                     + "[./IDENT[@text='InputXpathMatchXpathEncodedQuoteString']]/"
116                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='quoteChar']]/ASSIGN/EXPR"
117                     + "[./STRING_LITERAL[@text='\\&quot;testOne\\&quot;']]",
118             "/COMPILATION_UNIT/CLASS_DEF"
119                     + "[./IDENT[@text='InputXpathMatchXpathEncodedQuoteString']]/"
120                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='quoteChar']]/ASSIGN/EXPR"
121                     + "/STRING_LITERAL[@text='\\&quot;testOne\\&quot;']"
122         );
123 
124         runVerifications(moduleConfig, fileToProcess, expectedViolation,
125                 expectedXpathQueries);
126     }
127 
128     @Test
129     public void testEncodedLessString() throws Exception {
130         final File fileToProcess =
131                 new File(getPath("InputXpathMatchXpathEncodedLessString.java"));
132 
133         final DefaultConfiguration moduleConfig =
134                 createModuleConfig(IllegalTokenCheck.class);
135         moduleConfig.addProperty("tokens", "STRING_LITERAL");
136 
137         final String[] expectedViolation = {
138             "4:23: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
139                     "\"<testTwo\""),
140         };
141 
142         final List<String> expectedXpathQueries = Arrays.asList(
143             "/COMPILATION_UNIT/CLASS_DEF"
144                     + "[./IDENT[@text='InputXpathMatchXpathEncodedLessString']]/"
145                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='lessChar']]/ASSIGN/EXPR"
146                     + "[./STRING_LITERAL[@text='&lt;testTwo']]",
147             "/COMPILATION_UNIT/CLASS_DEF"
148                     + "[./IDENT[@text='InputXpathMatchXpathEncodedLessString']]/"
149                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='lessChar']]/ASSIGN/EXPR/"
150                     + "STRING_LITERAL[@text='&lt;testTwo']"
151         );
152 
153         runVerifications(moduleConfig, fileToProcess, expectedViolation,
154                 expectedXpathQueries);
155     }
156 
157     @Test
158     public void testEncodedNewLineString() throws Exception {
159         final File fileToProcess =
160                 new File(getPath("InputXpathMatchXpathEncodedNewLineString.java"));
161 
162         final DefaultConfiguration moduleConfig =
163                 createModuleConfig(IllegalTokenCheck.class);
164         moduleConfig.addProperty("tokens", "STRING_LITERAL");
165 
166         final String[] expectedViolation = {
167             "4:26: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
168                     "\"testFive\\n\""),
169         };
170 
171         final List<String> expectedXpathQueries = Arrays.asList(
172             "/COMPILATION_UNIT/CLASS_DEF"
173                     + "[./IDENT[@text='InputXpathMatchXpathEncodedNewLineString']]/"
174                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='newLineChar']]/ASSIGN/EXPR"
175                     + "[./STRING_LITERAL[@text='testFive\\n']]",
176             "/COMPILATION_UNIT/CLASS_DEF"
177                     + "[./IDENT[@text='InputXpathMatchXpathEncodedNewLineString']]/"
178                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='newLineChar']]/ASSIGN/EXPR"
179                     + "/STRING_LITERAL[@text='testFive\\n']"
180         );
181 
182         runVerifications(moduleConfig, fileToProcess, expectedViolation,
183                 expectedXpathQueries);
184     }
185 
186     @Test
187     public void testGreaterString() throws Exception {
188         final File fileToProcess =
189                 new File(getPath("InputXpathMatchXpathEncodedGreaterString.java"));
190 
191         final DefaultConfiguration moduleConfig =
192                 createModuleConfig(IllegalTokenCheck.class);
193         moduleConfig.addProperty("tokens", "STRING_LITERAL");
194 
195         final String[] expectedViolation = {
196             "4:26: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
197                     "\">testFour\""),
198         };
199 
200         final List<String> expectedXpathQueries = Arrays.asList(
201             "/COMPILATION_UNIT/CLASS_DEF"
202                     + "[./IDENT[@text='InputXpathMatchXpathEncodedGreaterString']]/"
203                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='greaterChar']]/ASSIGN/EXPR"
204                     + "[./STRING_LITERAL[@text='&gt;testFour']]",
205             "/COMPILATION_UNIT/CLASS_DEF"
206                     + "[./IDENT[@text='InputXpathMatchXpathEncodedGreaterString']]/"
207                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='greaterChar']]/ASSIGN/EXPR"
208                     + "/STRING_LITERAL[@text='&gt;testFour']"
209         );
210 
211         runVerifications(moduleConfig, fileToProcess, expectedViolation,
212                 expectedXpathQueries);
213     }
214 
215     @Test
216     public void testEncodedAmpString() throws Exception {
217         final File fileToProcess =
218                 new File(getPath("InputXpathMatchXpathEncodedAmpString.java"));
219 
220         final DefaultConfiguration moduleConfig =
221                 createModuleConfig(IllegalTokenCheck.class);
222         moduleConfig.addProperty("tokens", "STRING_LITERAL");
223 
224         final String[] expectedViolation = {
225             "4:28: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
226                     "\"&testThree\""),
227         };
228 
229         final List<String> expectedXpathQueries = Arrays.asList(
230             "/COMPILATION_UNIT/CLASS_DEF"
231                     + "[./IDENT[@text='InputXpathMatchXpathEncodedAmpString']]/"
232                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='ampersandChar']]/ASSIGN/EXPR"
233                     + "[./STRING_LITERAL[@text='&amp;testThree']]",
234             "/COMPILATION_UNIT/CLASS_DEF"
235                     + "[./IDENT[@text='InputXpathMatchXpathEncodedAmpString']]/"
236                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='ampersandChar']]/ASSIGN/EXPR"
237                     + "/STRING_LITERAL[@text='&amp;testThree']"
238         );
239 
240         runVerifications(moduleConfig, fileToProcess, expectedViolation,
241                 expectedXpathQueries);
242     }
243 
244     @Test
245     public void testEncodedAposString() throws Exception {
246         final File fileToProcess =
247                 new File(getPath("InputXpathMatchXpathEncodedAposString.java"));
248 
249         final DefaultConfiguration moduleConfig =
250                 createModuleConfig(IllegalTokenCheck.class);
251         moduleConfig.addProperty("tokens", "STRING_LITERAL");
252 
253         final String[] expectedViolation = {
254             "4:23: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
255                     "\"'SingleQuoteOnBothSide'\""),
256         };
257 
258         final List<String> expectedXpathQueries = Arrays.asList(
259             "/COMPILATION_UNIT/CLASS_DEF"
260                     + "[./IDENT[@text='InputXpathMatchXpathEncodedAposString']]/"
261                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='aposChar']]/ASSIGN/EXPR"
262                     + "[./STRING_LITERAL[@text='&apos;&apos;SingleQuoteOnBothSide&apos;&apos;']]",
263             "/COMPILATION_UNIT/CLASS_DEF"
264                     + "[./IDENT[@text='InputXpathMatchXpathEncodedAposString']]/"
265                     + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='aposChar']]/ASSIGN/EXPR"
266                     + "/STRING_LITERAL[@text='&apos;&apos;SingleQuoteOnBothSide&apos;&apos;']"
267         );
268 
269         runVerifications(moduleConfig, fileToProcess, expectedViolation,
270                 expectedXpathQueries);
271     }
272 
273     @Test
274     public void testEncodedCarriageString() throws Exception {
275         final File fileToProcess =
276             new File(getPath("InputXpathMatchXpathEncodedCarriageString.java"));
277 
278         final DefaultConfiguration moduleConfig =
279                 createModuleConfig(IllegalTokenCheck.class);
280         moduleConfig.addProperty("tokens", "STRING_LITERAL");
281 
282         final String[] expectedViolation = {
283             "4:27: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
284                     "\"carriageCharAtEnd\\r\""),
285         };
286 
287         final List<String> expectedXpathQueries = Arrays.asList(
288                 "/COMPILATION_UNIT/CLASS_DEF"
289                         + "[./IDENT[@text='InputXpathMatchXpathEncodedCarriageString"
290                         + "']]/OBJBLOCK/VARIABLE_DEF[./IDENT[@text='carriageChar']]/ASSIGN"
291                         + "/EXPR[./STRING_LITERAL[@text='carriageCharAtEnd\\r']]",
292                 "/COMPILATION_UNIT/CLASS_DEF"
293                         + "[./IDENT[@text='InputXpathMatchXpathEncodedCarriageString"
294                         + "']]/OBJBLOCK/VARIABLE_DEF[./IDENT[@text='carriageChar']]/ASSIGN"
295                         + "/EXPR/STRING_LITERAL[@text='carriageCharAtEnd\\r']"
296         );
297 
298         runVerifications(moduleConfig, fileToProcess, expectedViolation,
299                 expectedXpathQueries);
300     }
301 
302     @Test
303     public void testEncodedAmpersandChars() throws Exception {
304         final File fileToProcess =
305                 new File(getPath("InputXpathMatchXpathEncodedAmpChar.java"));
306 
307         final DefaultConfiguration moduleConfig =
308                 createModuleConfig(IllegalTokenCheck.class);
309         moduleConfig.addProperty("tokens", "CHAR_LITERAL");
310 
311         final String[] expectedViolationForAmpersand = {
312             "4:20: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
313                     "'&'"),
314         };
315 
316         final List<String> expectedXpathQueriesForAmpersand = Arrays.asList(
317                 "/COMPILATION_UNIT/CLASS_DEF"
318                         + "[./IDENT[@text='InputXpathMatchXpathEncodedAmpChar']]/"
319                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='ampChar']]/ASSIGN/EXPR"
320                         + "[./CHAR_LITERAL[@text='&apos;&apos;&amp;&apos;&apos;']]",
321                 "/COMPILATION_UNIT/CLASS_DEF"
322                         + "[./IDENT[@text='InputXpathMatchXpathEncodedAmpChar']]/"
323                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='ampChar']]/ASSIGN/EXPR"
324                         + "/CHAR_LITERAL[@text='&apos;&apos;&amp;&apos;&apos;']"
325         );
326 
327         runVerifications(moduleConfig, fileToProcess, expectedViolationForAmpersand,
328                 expectedXpathQueriesForAmpersand);
329     }
330 
331     @Test
332     public void testEncodedQuoteChar() throws Exception {
333         final File fileToProcess =
334                 new File(getPath("InputXpathMatchXpathEncodedQuoteChar.java"));
335 
336         final DefaultConfiguration moduleConfig =
337                 createModuleConfig(IllegalTokenCheck.class);
338         moduleConfig.addProperty("tokens", "CHAR_LITERAL");
339 
340         final String[] expectedViolationsForQuote = {
341             "4:21: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
342                     "'\\\"'"),
343         };
344 
345         final List<String> expectedXpathQueriesForQuote = Arrays.asList(
346                 "/COMPILATION_UNIT/CLASS_DEF"
347                         + "[./IDENT[@text='InputXpathMatchXpathEncodedQuoteChar']]/"
348                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='quotChar']]/ASSIGN/EXPR"
349                         + "[./CHAR_LITERAL[@text='&apos;&apos;\\&quot;&apos;&apos;']]",
350                 "/COMPILATION_UNIT/CLASS_DEF"
351                         + "[./IDENT[@text='InputXpathMatchXpathEncodedQuoteChar']]/"
352                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='quotChar']]/ASSIGN/EXPR/"
353                         + "CHAR_LITERAL[@text='&apos;&apos;\\&quot;&apos;&apos;']"
354         );
355 
356         runVerifications(moduleConfig, fileToProcess, expectedViolationsForQuote,
357                 expectedXpathQueriesForQuote);
358     }
359 
360     @Test
361     public void testEncodedLessChar() throws Exception {
362         final File fileToProcess =
363                 new File(getPath("InputXpathMatchXpathEncodedLessChar.java"));
364 
365         final DefaultConfiguration moduleConfig =
366                 createModuleConfig(IllegalTokenCheck.class);
367         moduleConfig.addProperty("tokens", "CHAR_LITERAL");
368 
369         final String[] expectedViolationsForLess = {
370             "4:21: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
371                     "'<'"),
372         };
373 
374         final List<String> expectedXpathQueriesForLess = Arrays.asList(
375                 "/COMPILATION_UNIT/CLASS_DEF"
376                         + "[./IDENT[@text='InputXpathMatchXpathEncodedLessChar']]/"
377                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='lessChar']]/ASSIGN/EXPR"
378                         + "[./CHAR_LITERAL[@text='&apos;&apos;&lt;&apos;&apos;']]",
379                 "/COMPILATION_UNIT/CLASS_DEF"
380                         + "[./IDENT[@text='InputXpathMatchXpathEncodedLessChar']]/"
381                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='lessChar']]/ASSIGN/EXPR/"
382                         + "CHAR_LITERAL[@text='&apos;&apos;&lt;&apos;&apos;']"
383         );
384 
385         runVerifications(moduleConfig, fileToProcess, expectedViolationsForLess,
386                 expectedXpathQueriesForLess);
387     }
388 
389     @Test
390     public void testEncodedAposChar() throws Exception {
391         final File fileToProcess =
392                 new File(getPath("InputXpathMatchXpathEncodedAposChar.java"));
393 
394         final DefaultConfiguration moduleConfig =
395                 createModuleConfig(IllegalTokenCheck.class);
396         moduleConfig.addProperty("tokens", "CHAR_LITERAL");
397 
398         final String[] expectedViolationsForApos = {
399             "4:21: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
400                     "'\\''"),
401         };
402 
403         final List<String> expectedXpathQueriesForApos = Arrays.asList(
404                 "/COMPILATION_UNIT/CLASS_DEF"
405                         + "[./IDENT[@text='InputXpathMatchXpathEncodedAposChar']]/"
406                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='aposChar']]/ASSIGN/EXPR"
407                         + "[./CHAR_LITERAL[@text='&apos;&apos;\\&apos;&apos;&apos;&apos;']]",
408                 "/COMPILATION_UNIT/CLASS_DEF"
409                         + "[./IDENT[@text='InputXpathMatchXpathEncodedAposChar']]/"
410                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='aposChar']]/ASSIGN/EXPR/"
411                         + "CHAR_LITERAL[@text='&apos;&apos;\\&apos;&apos;&apos;&apos;']"
412         );
413 
414         runVerifications(moduleConfig, fileToProcess, expectedViolationsForApos,
415                 expectedXpathQueriesForApos);
416     }
417 
418     @Test
419     public void testEncodedGreaterChar() throws Exception {
420         final File fileToProcess =
421                 new File(getPath("InputXpathMatchXpathEncodedGreaterChar.java"));
422 
423         final DefaultConfiguration moduleConfig =
424                 createModuleConfig(IllegalTokenCheck.class);
425         moduleConfig.addProperty("tokens", "CHAR_LITERAL");
426 
427         final String[] expectedViolationsForGreater = {
428             "4:24: " + getCheckMessage(IllegalTokenCheck.class, IllegalTokenCheck.MSG_KEY,
429                     "'>'"),
430         };
431 
432         final List<String> expectedXpathQueriesForGreater = Arrays.asList(
433                 "/COMPILATION_UNIT/CLASS_DEF"
434                         + "[./IDENT[@text='"
435                         + "InputXpathMatchXpathEncodedGreaterChar']]/"
436                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='greaterChar']]/ASSIGN/EXPR"
437                         + "[./CHAR_LITERAL[@text='&apos;&apos;&gt;&apos;&apos;']]",
438                 "/COMPILATION_UNIT/CLASS_DEF"
439                         + "[./IDENT[@text='"
440                         + "InputXpathMatchXpathEncodedGreaterChar']]/"
441                         + "OBJBLOCK/VARIABLE_DEF[./IDENT[@text='greaterChar']]/ASSIGN/EXPR/"
442                         + "CHAR_LITERAL[@text='&apos;&apos;&gt;&apos;&apos;']"
443         );
444 
445         runVerifications(moduleConfig, fileToProcess, expectedViolationsForGreater,
446                 expectedXpathQueriesForGreater);
447     }
448 
449     @Test
450     public void testFollowing() throws Exception {
451         final File fileToProcess =
452                 new File(getPath("InputXpathMatchXpathThree.java"));
453 
454         final DefaultConfiguration moduleConfig =
455                 createModuleConfig(MatchXpathCheck.class);
456         moduleConfig.addProperty("query",
457                 "//METHOD_DEF/following::*[1]");
458 
459         final String[] expectedViolation = {
460             "5:1: " + getCheckMessage(MatchXpathCheck.class, MatchXpathCheck.MSG_KEY),
461         };
462 
463         final List<String> expectedXpathQueries = Collections.singletonList(
464                 "/COMPILATION_UNIT"
465                         + "/CLASS_DEF[./IDENT[@text='InputXpathMatchXpathThree']]"
466                         + "/OBJBLOCK/RCURLY"
467         );
468 
469         runVerifications(moduleConfig, fileToProcess, expectedViolation,
470                 expectedXpathQueries);
471     }
472 }