1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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 com.puppycrawl.tools.checkstyle.filters;
21  
22  import static org.junit.Assert.assertFalse;
23  import static org.junit.Assert.assertTrue;
24  import static org.junit.Assert.fail;
25  
26  import java.io.File;
27  import java.nio.charset.StandardCharsets;
28  
29  import org.junit.Before;
30  import org.junit.Test;
31  
32  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
33  import com.puppycrawl.tools.checkstyle.JavaParser;
34  import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
35  import com.puppycrawl.tools.checkstyle.api.FileContents;
36  import com.puppycrawl.tools.checkstyle.api.FileText;
37  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
38  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
39  
40  public class SuppressionXpathSingleFilterTest
41          extends AbstractModuleTestSupport {
42  
43      private File file;
44      private FileContents fileContents;
45  
46      @Before
47      public void setUp() throws Exception {
48          file = new File(getPath("InputSuppressionXpathSingleFilter.java"));
49          fileContents = new FileContents(new FileText(file,
50                  StandardCharsets.UTF_8.name()));
51      }
52  
53      @Override
54      protected String getPackageLocation() {
55          return "com/puppycrawl/tools/checkstyle/filters/suppressionxpathsinglefilter";
56      }
57  
58      @Test
59      public void testMatching() throws Exception {
60          final String xpath = "/CLASS_DEF[./IDENT[@text='InputSuppressionXpathSingleFilter']]";
61          final SuppressionXpathSingleFilter filter =
62                  createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
63                          null, null, xpath);
64          final TreeWalkerAuditEvent ev = createEvent(3, 0,
65                  TokenTypes.CLASS_DEF);
66          assertFalse("Event should be rejected", filter.accept(ev));
67      }
68  
69      @Test
70      public void testNonMatchingTokenType() throws Exception {
71          final String xpath = "//METHOD_DEF[@text='countTokens']";
72          final SuppressionXpathSingleFilter filter =
73                  createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
74                          null, null, xpath);
75          final TreeWalkerAuditEvent ev = createEvent(3, 0,
76                  TokenTypes.CLASS_DEF);
77          assertTrue("Event should be accepted", filter.accept(ev));
78      }
79  
80      @Test
81      public void testNonMatchingLineNumber() throws Exception {
82          final String xpath = "/CLASS_DEF[@text='InputSuppressionXpathSingleFilter']";
83          final SuppressionXpathSingleFilter filter =
84                  createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
85                          null, null, xpath);
86          final TreeWalkerAuditEvent ev = createEvent(100, 0,
87                  TokenTypes.CLASS_DEF);
88          assertTrue("Event should be accepted", filter.accept(ev));
89      }
90  
91      @Test
92      public void testNonMatchingColumnNumber() throws Exception {
93          final String xpath = "/CLASS_DEF[@text='InputSuppressionXpathSingleFilter']";
94          final SuppressionXpathSingleFilter filter =
95                  createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
96                          null, null, xpath);
97          final TreeWalkerAuditEvent ev = createEvent(3, 100,
98                  TokenTypes.CLASS_DEF);
99          assertTrue("Event should be accepted", filter.accept(ev));
100     }
101 
102     @Test
103     public void testComplexQuery() throws Exception {
104         final String xpath = "//VARIABLE_DEF[./IDENT[@text='pi'] and "
105                 + "../../IDENT[@text='countTokens']] "
106                 + "| //VARIABLE_DEF[./IDENT[@text='someVariable'] and ../../IDENT[@text='sum']]";
107         final SuppressionXpathSingleFilter filter =
108                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
109                         null, null, xpath);
110         final TreeWalkerAuditEvent eventOne = createEvent(5, 8,
111                 TokenTypes.VARIABLE_DEF);
112         final TreeWalkerAuditEvent eventTwo = createEvent(10, 4,
113                 TokenTypes.VARIABLE_DEF);
114         final TreeWalkerAuditEvent eventThree = createEvent(15, 8,
115                 TokenTypes.VARIABLE_DEF);
116         assertFalse("Event should be rejected", filter.accept(eventOne));
117         assertTrue("Event should be accepted", filter.accept(eventTwo));
118         assertFalse("Event should be rejected", filter.accept(eventThree));
119     }
120 
121     @Test
122     public void testIncorrectQuery() {
123         final String xpath = "1@#";
124         try {
125             final Object test = createSuppressionXpathSingleFilter(
126                     "InputSuppressionXpathSingleFilter", "Test",
127                     null, null, xpath);
128             fail("Exception was expected but got " + test);
129         }
130         catch (IllegalArgumentException ex) {
131             assertTrue("Message should be: Unexpected xpath query",
132                     ex.getMessage().contains("Incorrect xpath query"));
133         }
134     }
135 
136     @Test
137     public void testNoQuery() throws Exception {
138         final TreeWalkerAuditEvent event = createEvent(15, 8,
139                 TokenTypes.VARIABLE_DEF);
140         final SuppressionXpathSingleFilter filter =
141                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
142                         null, null, null);
143         assertFalse("Event should be accepted", filter.accept(event));
144     }
145 
146     @Test
147     public void testNullFileName() {
148         final String xpath = "NON_MATCHING_QUERY";
149         final SuppressionXpathSingleFilter filter =
150                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
151                         null, null, xpath);
152         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(null,
153                 null, null, null);
154         assertTrue("Event should be accepted", filter.accept(ev));
155     }
156 
157     @Test
158     public void testNonMatchingFileRegexp() throws Exception {
159         final String xpath = "NON_MATCHING_QUERY";
160         final SuppressionXpathSingleFilter filter =
161                 createSuppressionXpathSingleFilter("NonMatchingRegexp", "Test",
162                         null, null, xpath);
163         final TreeWalkerAuditEvent ev = createEvent(3, 0,
164                 TokenTypes.CLASS_DEF);
165         assertTrue("Event should be accepted", filter.accept(ev));
166     }
167 
168     @Test
169     public void testNullLocalizedMessage() {
170         final String xpath = "NON_MATCHING_QUERY";
171         final SuppressionXpathSingleFilter filter =
172                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
173                         null, null, xpath);
174         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(null,
175                 file.getName(), null, null);
176         assertTrue("Event should be accepted", filter.accept(ev));
177     }
178 
179     @Test
180     public void testNonMatchingModuleId() throws Exception {
181         final String xpath = "NON_MATCHING_QUERY";
182         final SuppressionXpathSingleFilter filter =
183                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
184                         null, "id19", xpath);
185         final LocalizedMessage message =
186                 new LocalizedMessage(3, 0, TokenTypes.CLASS_DEF, "", "",
187                         null, null, "id20",
188                         getClass(), null);
189         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(fileContents, file.getName(),
190                 message, JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
191         assertTrue("Event should be accepted", filter.accept(ev));
192     }
193 
194     @Test
195     public void testMatchingModuleId() throws Exception {
196         final String xpath = "/CLASS_DEF[./IDENT[@text='InputSuppressionXpathSingleFilter']]";
197         final SuppressionXpathSingleFilter filter =
198                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter", "Test",
199                         null, "id19", xpath);
200         final LocalizedMessage message =
201                 new LocalizedMessage(3, 0, TokenTypes.CLASS_DEF, "",
202                         "", null, null, "id19",
203                         getClass(), null);
204         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(fileContents, file.getName(),
205                 message, JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
206         assertFalse("Event should be rejected", filter.accept(ev));
207     }
208 
209     @Test
210     public void testNonMatchingChecks() throws Exception {
211         final String xpath = "NON_MATCHING_QUERY";
212         final SuppressionXpathSingleFilter filter = createSuppressionXpathSingleFilter(
213                 "InputSuppressionXpathSingleFilter", "NonMatchingRegexp",
214                 null, "id19", xpath);
215         final LocalizedMessage message =
216                 new LocalizedMessage(3, 0, TokenTypes.CLASS_DEF, "",
217                         "", null, null, "id19",
218                         getClass(), null);
219         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(fileContents, file.getName(),
220                 message, JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
221         assertTrue("Event should be accepted", filter.accept(ev));
222     }
223 
224     @Test
225     public void testNonMatchingFileNameModuleIdAndCheck() throws Exception {
226         final String xpath = "NON_MATCHING_QUERY";
227         final SuppressionXpathSingleFilter filter =
228                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter",
229                         null, null, null, xpath);
230         final TreeWalkerAuditEvent ev = createEvent(3, 0,
231                 TokenTypes.CLASS_DEF);
232         assertTrue("Event should be accepted", filter.accept(ev));
233     }
234 
235     @Test
236     public void testNullModuleIdAndNonMatchingChecks() throws Exception {
237         final String xpath = "NON_MATCHING_QUERY";
238         final SuppressionXpathSingleFilter filter = createSuppressionXpathSingleFilter(
239                 "InputSuppressionXpathSingleFilter", "NonMatchingRegexp", null, null, xpath);
240         final TreeWalkerAuditEvent ev = createEvent(3, 0,
241                 TokenTypes.CLASS_DEF);
242         assertTrue("Event should be accepted", filter.accept(ev));
243     }
244 
245     @Test
246     public void testDecideByMessage() throws Exception {
247         final LocalizedMessage message = new LocalizedMessage(0, 0,
248                 TokenTypes.CLASS_DEF, "", "",
249                 null, null, null, getClass(), "Test");
250         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(fileContents, file.getName(),
251                 message, JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
252         final SuppressionXpathSingleFilter filter1 = createSuppressionXpathSingleFilter(
253                 null, null, "Test", null, null);
254         final SuppressionXpathSingleFilter filter2 = createSuppressionXpathSingleFilter(
255                 null, null, "Bad", null, null);
256         assertFalse("Message match", filter1.accept(ev));
257         assertTrue("Message not match", filter2.accept(ev));
258     }
259 
260     @Test
261     public void testThrowException() {
262         final String xpath = "/CLASS_DEF[@text='InputSuppressionXpathSingleFilter']";
263         final SuppressionXpathSingleFilter filter =
264                 createSuppressionXpathSingleFilter("InputSuppressionXpathSingleFilter",
265                         "Test", null, null, xpath);
266         final LocalizedMessage message =
267                 new LocalizedMessage(3, 0, TokenTypes.CLASS_DEF, "",
268                         "", null, null, "id19",
269                         getClass(), null);
270         final TreeWalkerAuditEvent ev = new TreeWalkerAuditEvent(fileContents,
271                 file.getName(), message, null);
272         try {
273             filter.accept(ev);
274             fail("Exception is expected");
275         }
276         catch (IllegalStateException ex) {
277             assertTrue("Exception message does not match expected one",
278                     ex.getMessage().contains("Cannot initialize context and evaluate query"));
279         }
280     }
281 
282     private static SuppressionXpathSingleFilter createSuppressionXpathSingleFilter(
283             String files, String checks, String message, String moduleId, String query) {
284         final SuppressionXpathSingleFilter filter = new SuppressionXpathSingleFilter();
285         filter.setFiles(files);
286         filter.setChecks(checks);
287         filter.setMessage(message);
288         filter.setId(moduleId);
289         filter.setQuery(query);
290         filter.finishLocalSetup();
291         return filter;
292     }
293 
294     private TreeWalkerAuditEvent createEvent(int line, int column, int tokenType)
295             throws Exception {
296         final LocalizedMessage message =
297                 new LocalizedMessage(line, column, tokenType, "", "", null, null, null,
298                         getClass(), null);
299         return new TreeWalkerAuditEvent(fileContents, file.getName(), message,
300                 JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
301     }
302 
303 }