1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle.filters;
21
22 import static org.junit.Assert.assertEquals;
23 import static org.junit.Assert.assertTrue;
24 import static org.junit.Assert.fail;
25
26 import java.io.IOException;
27 import java.net.HttpURLConnection;
28 import java.net.URL;
29 import java.util.HashSet;
30 import java.util.Set;
31
32 import org.junit.Test;
33 import org.powermock.reflect.Whitebox;
34 import org.xml.sax.InputSource;
35
36 import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
37 import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
38 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
39 import com.puppycrawl.tools.checkstyle.api.FilterSet;
40
41
42
43
44 public class SuppressionsLoaderTest extends AbstractPathTestSupport {
45
46 @Override
47 protected String getPackageLocation() {
48 return "com/puppycrawl/tools/checkstyle/filters/suppressionsloader";
49 }
50
51 @Test
52 public void testNoSuppressions() throws Exception {
53 final FilterSet fc =
54 SuppressionsLoader.loadSuppressions(getPath("InputSuppressionsLoaderNone.xml"));
55 final FilterSet fc2 = new FilterSet();
56 assertEquals("No suppressions should be loaded, but found: " + fc.getFilters().size(),
57 fc2.getFilters(), fc.getFilters());
58 }
59
60 @Test
61 public void testLoadFromUrl() throws Exception {
62 final String[] urlCandidates = {
63 "https://checkstyle.org/files/suppressions_none.xml",
64 "https://raw.githubusercontent.com/checkstyle/checkstyle/master/src/site/resources/"
65 + "files/suppressions_none.xml",
66 };
67 FilterSet actualFilterSet = null;
68
69 for (String url : urlCandidates) {
70 actualFilterSet = loadFilterSet(url);
71
72 if (actualFilterSet != null) {
73 break;
74 }
75 }
76
77
78 if (actualFilterSet != null) {
79 final FilterSet expectedFilterSet = new FilterSet();
80 assertEquals("Failed to load from url", expectedFilterSet.getFilters(),
81 actualFilterSet.getFilters());
82 }
83 }
84
85 @Test
86 public void testLoadFromMalformedUrl() {
87 try {
88 SuppressionsLoader.loadSuppressions("http");
89 fail("exception expected");
90 }
91 catch (CheckstyleException ex) {
92 assertEquals("Invalid error message", "Unable to find: http", ex.getMessage());
93 }
94 }
95
96 @Test
97 public void testLoadFromNonExistentUrl() {
98 try {
99 SuppressionsLoader.loadSuppressions("http://^%$^* %&% %^&");
100 fail("exception expected");
101 }
102 catch (CheckstyleException ex) {
103 assertEquals("Invalid error message",
104 "Unable to find: http://^%$^* %&% %^&", ex.getMessage());
105 }
106 }
107
108 @Test
109 public void testMultipleSuppression() throws Exception {
110 final FilterSet fc =
111 SuppressionsLoader.loadSuppressions(getPath("InputSuppressionsLoaderMultiple.xml"));
112 final FilterSet fc2 = new FilterSet();
113
114 final SuppressFilterElement se0 =
115 new SuppressFilterElement("file0", "check0", null, null, null, null);
116 fc2.addFilter(se0);
117 final SuppressFilterElement se1 =
118 new SuppressFilterElement("file1", "check1", null, null, "1,2-3", null);
119 fc2.addFilter(se1);
120 final SuppressFilterElement se2 =
121 new SuppressFilterElement("file2", "check2", null, null, null, "1,2-3");
122 fc2.addFilter(se2);
123 final SuppressFilterElement se3 =
124 new SuppressFilterElement("file3", "check3", null, null, "1,2-3", "1,2-3");
125 fc2.addFilter(se3);
126 final SuppressFilterElement se4 =
127 new SuppressFilterElement(null, null, "message0", null, null, null);
128 fc2.addFilter(se4);
129 assertEquals("Multiple suppressions were loaded incorrectly", fc2.getFilters(),
130 fc.getFilters());
131 }
132
133 @Test
134 public void testNoFile() throws IOException {
135 final String fn = getPath("InputSuppressionsLoaderNoFile.xml");
136 try {
137 SuppressionsLoader.loadSuppressions(fn);
138 fail("Exception is expected");
139 }
140 catch (CheckstyleException ex) {
141 final String messageStart = "Unable to parse " + fn;
142 assertTrue("Exception message should start with: " + messageStart,
143 ex.getMessage().startsWith("Unable to parse " + fn));
144 assertTrue("Exception message should contain \"files\"",
145 ex.getMessage().contains("\"files\""));
146 assertTrue("Exception message should contain \"suppress\"",
147 ex.getMessage().contains("\"suppress\""));
148 }
149 }
150
151 @Test
152 public void testNoCheck() throws IOException {
153 final String fn = getPath("InputSuppressionsLoaderNoCheck.xml");
154 try {
155 SuppressionsLoader.loadSuppressions(fn);
156 fail("Exception is expected");
157 }
158 catch (CheckstyleException ex) {
159 final String messageStart = "Unable to parse " + fn;
160 assertTrue("Exception message should start with: " + messageStart,
161 ex.getMessage().startsWith(messageStart));
162 assertTrue("Exception message should contain \"checks\"",
163 ex.getMessage().contains("\"checks\""));
164 assertTrue("Exception message should contain \"suppress\"",
165 ex.getMessage().contains("\"suppress\""));
166 }
167 }
168
169 @Test
170 public void testBadInt() throws IOException {
171 final String fn = getPath("InputSuppressionsLoaderBadInt.xml");
172 try {
173 SuppressionsLoader.loadSuppressions(fn);
174 fail("Exception is expected");
175 }
176 catch (CheckstyleException ex) {
177 assertTrue(
178 ex.getMessage(),
179 ex.getMessage().startsWith("Number format exception " + fn + " - "));
180 }
181 }
182
183 private static FilterSet loadFilterSet(String url) throws Exception {
184 FilterSet filterSet = null;
185
186 if (isUrlReachable(url)) {
187 int attemptCount = 0;
188 final int attemptLimit = 5;
189
190 while (attemptCount <= attemptLimit) {
191 try {
192 filterSet = SuppressionsLoader.loadSuppressions(url);
193 break;
194 }
195 catch (CheckstyleException ex) {
196
197 if (attemptCount < attemptLimit && ex.getMessage().contains("Unable to read")) {
198 attemptCount++;
199
200 Thread.sleep(1000);
201 }
202 else {
203 throw ex;
204 }
205 }
206 }
207 }
208 return filterSet;
209 }
210
211 private static boolean isUrlReachable(String url) {
212 boolean result = true;
213 try {
214 final URL verifiableUrl = new URL(url);
215 final HttpURLConnection urlConnect = (HttpURLConnection) verifiableUrl.openConnection();
216 urlConnect.getContent();
217 }
218 catch (IOException ignored) {
219 result = false;
220 }
221 return result;
222 }
223
224 @Test
225 public void testUnableToFindSuppressions() throws Exception {
226 final String sourceName = "InputSuppressionsLoaderNone.xml";
227
228 try {
229 Whitebox.invokeMethod(SuppressionsLoader.class, "loadSuppressions",
230 new InputSource(sourceName), sourceName);
231 fail("CheckstyleException is expected");
232 }
233 catch (CheckstyleException ex) {
234 assertEquals("Invalid exception message", "Unable to find: " + sourceName,
235 ex.getMessage());
236 }
237 }
238
239 @Test
240 public void testUnableToReadSuppressions() throws Exception {
241 final String sourceName = "InputSuppressionsLoaderNone.xml";
242
243 try {
244 Whitebox.invokeMethod(SuppressionsLoader.class, "loadSuppressions",
245 new InputSource(), sourceName);
246 fail("CheckstyleException is expected");
247 }
248 catch (CheckstyleException ex) {
249 assertEquals("Invalid exception message", "Unable to read " + sourceName,
250 ex.getMessage());
251 }
252 }
253
254 @Test
255 public void testNoCheckNoId() throws IOException {
256 final String fn = getPath("InputSuppressionsLoaderNoCheckAndId.xml");
257 try {
258 SuppressionsLoader.loadSuppressions(fn);
259 fail("Exception is expected");
260 }
261 catch (CheckstyleException ex) {
262 assertEquals("Invalid error message",
263 "Unable to parse " + fn + " - missing checks or id or message attribute",
264 ex.getMessage());
265 }
266 }
267
268 @Test
269 public void testNoCheckYesId() throws Exception {
270 final String fn = getPath("InputSuppressionsLoaderId.xml");
271 final FilterSet set = SuppressionsLoader.loadSuppressions(fn);
272
273 assertEquals("Invalid number of filters", 1, set.getFilters().size());
274 }
275
276 @Test
277 public void testInvalidFileFormat() throws IOException {
278 final String fn = getPath("InputSuppressionsLoaderInvalidFile.xml");
279 try {
280 SuppressionsLoader.loadSuppressions(fn);
281 fail("Exception is expected");
282 }
283 catch (CheckstyleException ex) {
284 assertEquals("Invalid error message",
285 "Unable to parse " + fn + " - invalid files or checks or message format",
286 ex.getMessage());
287 }
288 }
289
290 @Test
291 public void testLoadFromClasspath() throws Exception {
292 final FilterSet fc =
293 SuppressionsLoader.loadSuppressions(getPath("InputSuppressionsLoaderNone.xml"));
294 final FilterSet fc2 = new FilterSet();
295 assertEquals("Suppressions were not loaded", fc2.getFilters(), fc.getFilters());
296 }
297
298 @Test
299 public void testSettingModuleId() throws Exception {
300 final FilterSet fc =
301 SuppressionsLoader.loadSuppressions(getPath("InputSuppressionsLoaderWithId.xml"));
302 final SuppressFilterElement suppressElement = (SuppressFilterElement) fc.getFilters()
303 .toArray()[0];
304
305 final String id = Whitebox.getInternalState(suppressElement, "moduleId");
306 assertEquals("Id has to be defined", "someId", id);
307 }
308
309 @Test
310 public void testXpathSuppressions() throws Exception {
311 final String fn = getPath("InputSuppressionsLoaderXpathCorrect.xml");
312 final Set<TreeWalkerFilter> filterSet = SuppressionsLoader.loadXpathSuppressions(fn);
313
314 final Set<TreeWalkerFilter> expectedFilterSet = new HashSet<>();
315 final XpathFilterElement xf0 =
316 new XpathFilterElement("file1", "test", null, "id1", "/CLASS_DEF");
317 expectedFilterSet.add(xf0);
318 final XpathFilterElement xf1 =
319 new XpathFilterElement(null, null, "message1", null, "/CLASS_DEF");
320 expectedFilterSet.add(xf1);
321 assertEquals("Multiple xpath suppressions were loaded incorrectly", expectedFilterSet,
322 filterSet);
323 }
324
325 @Test
326 public void testXpathInvalidFileFormat() throws IOException {
327 final String fn = getPath("InputSuppressionsLoaderXpathInvalidFile.xml");
328 try {
329 SuppressionsLoader.loadXpathSuppressions(fn);
330 fail("Exception should be thrown");
331 }
332 catch (CheckstyleException ex) {
333 assertEquals("Invalid error message",
334 "Unable to parse " + fn + " - invalid files or checks or message format for "
335 + "suppress-xpath",
336 ex.getMessage());
337 }
338 }
339
340 @Test
341 public void testXpathNoCheckNoId() throws IOException {
342 final String fn =
343 getPath("InputSuppressionsLoaderXpathNoCheckAndId.xml");
344 try {
345 SuppressionsLoader.loadXpathSuppressions(fn);
346 fail("Exception should be thrown");
347 }
348 catch (CheckstyleException ex) {
349 assertEquals("Invalid error message",
350 "Unable to parse " + fn + " - missing checks or id or message attribute for "
351 + "suppress-xpath",
352 ex.getMessage());
353 }
354 }
355
356 @Test
357 public void testXpathNoCheckYesId() throws Exception {
358 final String fn = getPath("InputSuppressionsLoaderXpathId.xml");
359 final Set<TreeWalkerFilter> filterSet = SuppressionsLoader.loadXpathSuppressions(fn);
360
361 assertEquals("Invalid number of filters", 1, filterSet.size());
362 }
363
364 }