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.assertFalse;
24 import static org.junit.Assert.assertTrue;
25 import static org.junit.Assert.fail;
26
27 import java.io.File;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.net.HttpURLConnection;
31 import java.net.URL;
32
33 import org.junit.Rule;
34 import org.junit.Test;
35 import org.junit.rules.TemporaryFolder;
36
37 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
38 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
39 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
40 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
41 import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
42 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
43 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
44
45 public class SuppressionFilterTest extends AbstractModuleTestSupport {
46
47 @Rule
48 public final TemporaryFolder temporaryFolder = new TemporaryFolder();
49
50 @Override
51 protected String getPackageLocation() {
52 return "com/puppycrawl/tools/checkstyle/filters/suppressionfilter";
53 }
54
55 @Test
56 public void testAccept() throws Exception {
57 final String fileName = getPath("InputSuppressionFilterNone.xml");
58 final boolean optional = false;
59 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
60
61 final AuditEvent ev = new AuditEvent(this, "ATest.java", null);
62
63 assertTrue("Audit event should be excepted when there are no suppressions",
64 filter.accept(ev));
65 }
66
67 @Test
68 public void testAcceptFalse() throws Exception {
69 final String fileName = getPath("InputSuppressionFilterSuppress.xml");
70 final boolean optional = false;
71 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
72
73 final LocalizedMessage message = new LocalizedMessage(1, 1, null, "msg", null,
74 SeverityLevel.ERROR, null, getClass(), null);
75 final AuditEvent ev = new AuditEvent(this, "ATest.java", message);
76
77 assertFalse("Audit event should be rejected when there is a matching suppression",
78 filter.accept(ev));
79 }
80
81 @Test
82 public void testAcceptOnNullFile() throws CheckstyleException {
83 final String fileName = null;
84 final boolean optional = false;
85 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
86
87 final AuditEvent ev = new AuditEvent(this, "AnyJava.java", null);
88 assertTrue("Audit event on null file should be excepted, but was not", filter.accept(ev));
89 }
90
91 @Test
92 public void testNonExistentSuppressionFileWithFalseOptional() {
93 final String fileName = "non_existent_suppression_file.xml";
94 try {
95 final boolean optional = false;
96 createSuppressionFilter(fileName, optional);
97 fail("Exception is expected");
98 }
99 catch (CheckstyleException ex) {
100 assertEquals("Invalid error message",
101 "Unable to find: " + fileName, ex.getMessage());
102 }
103 }
104
105 @Test
106 public void testExistingInvalidSuppressionFileWithTrueOptional() throws IOException {
107 final String fileName = getPath("InputSuppressionFilterInvalidFile.xml");
108 try {
109 final boolean optional = true;
110 createSuppressionFilter(fileName, optional);
111 fail("Exception is expected");
112 }
113 catch (CheckstyleException ex) {
114 assertEquals("Invalid error message",
115 "Unable to parse " + fileName + " - invalid files or checks or message format",
116 ex.getMessage());
117 }
118 }
119
120 @Test
121 public void testExistingSuppressionFileWithTrueOptional() throws Exception {
122 final String fileName = getPath("InputSuppressionFilterNone.xml");
123 final boolean optional = true;
124 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
125
126 final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
127
128 assertTrue("Suppression file with true optional was not accepted",
129 filter.accept(ev));
130 }
131
132 @Test
133 public void testNonExistentSuppressionFileWithTrueOptional() throws Exception {
134 final String fileName = "non_existent_suppression_file.xml";
135 final boolean optional = true;
136 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
137
138 final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
139
140 assertTrue("Should except event when suppression file does not exist",
141 filter.accept(ev));
142 }
143
144 @Test
145 public void testNonExistentSuppressionUrlWithTrueOptional() throws Exception {
146 final String fileName =
147 "https://checkstyle.org/non_existent_suppression.xml";
148 final boolean optional = true;
149 final SuppressionFilter filter = createSuppressionFilter(fileName, optional);
150
151 final AuditEvent ev = new AuditEvent(this, "AnyFile.java", null);
152
153 assertTrue("Should except event when suppression file url does not exist",
154 filter.accept(ev));
155 }
156
157 @Test
158 public void testLocalFileExternalResourceContentDoesNotChange() throws Exception {
159 final DefaultConfiguration filterConfig = createModuleConfig(SuppressionFilter.class);
160 filterConfig.addAttribute("file", getPath("InputSuppressionFilterNone.xml"));
161
162 final DefaultConfiguration checkerConfig = createRootConfig(filterConfig);
163 final File cacheFile = temporaryFolder.newFile();
164 checkerConfig.addAttribute("cacheFile", cacheFile.getPath());
165
166 final String filePath = temporaryFolder.newFile("file.java").getPath();
167 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
168
169 verify(checkerConfig, filePath, expected);
170
171 verify(checkerConfig, filePath, expected);
172 }
173
174 @Test
175 public void testRemoteFileExternalResourceContentDoesNotChange() throws Exception {
176 final String[] urlCandidates = {
177 "https://checkstyle.org/files/suppressions_none.xml",
178 "https://raw.githubusercontent.com/checkstyle/checkstyle/master/src/site/resources/"
179 + "files/suppressions_none.xml",
180 };
181
182 String urlForTest = null;
183 for (String url : urlCandidates) {
184 if (isConnectionAvailableAndStable(url)) {
185 urlForTest = url;
186 break;
187 }
188 }
189
190
191
192
193
194 if (urlForTest != null) {
195 final DefaultConfiguration firstFilterConfig =
196 createModuleConfig(SuppressionFilter.class);
197
198 firstFilterConfig.addAttribute("file", urlForTest);
199
200 final DefaultConfiguration firstCheckerConfig = createRootConfig(firstFilterConfig);
201 final File cacheFile = temporaryFolder.newFile();
202 firstCheckerConfig.addAttribute("cacheFile", cacheFile.getPath());
203
204 final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath();
205 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
206
207 verify(firstCheckerConfig, pathToEmptyFile, expected);
208
209
210 final DefaultConfiguration secondFilterConfig =
211 createModuleConfig(SuppressionFilter.class);
212
213 secondFilterConfig.addAttribute("file", urlForTest);
214
215 final DefaultConfiguration secondCheckerConfig = createRootConfig(secondFilterConfig);
216 secondCheckerConfig.addAttribute("cacheFile", cacheFile.getPath());
217
218 verify(secondCheckerConfig, pathToEmptyFile, expected);
219 }
220 }
221
222 private static boolean isConnectionAvailableAndStable(String url) throws Exception {
223 boolean available = false;
224
225 if (isUrlReachable(url)) {
226 final int attemptLimit = 5;
227 int attemptCount = 0;
228
229 while (attemptCount <= attemptLimit) {
230 try (InputStream stream = new URL(url).openStream()) {
231
232 available = stream.read() != -1;
233 break;
234 }
235 catch (IOException ex) {
236
237 if (attemptCount < attemptLimit && ex.getMessage().contains("Unable to read")) {
238 attemptCount++;
239 available = false;
240
241 Thread.sleep(1000);
242 }
243 else {
244 throw ex;
245 }
246 }
247 }
248 }
249 return available;
250 }
251
252 private static boolean isUrlReachable(String url) {
253 boolean result = true;
254 try {
255 final URL verifiableUrl = new URL(url);
256 final HttpURLConnection urlConnect = (HttpURLConnection) verifiableUrl.openConnection();
257 urlConnect.getContent();
258 }
259 catch (IOException ignored) {
260 result = false;
261 }
262 return result;
263 }
264
265 private static SuppressionFilter createSuppressionFilter(String fileName, boolean optional)
266 throws CheckstyleException {
267 final SuppressionFilter suppressionFilter = new SuppressionFilter();
268 suppressionFilter.setFile(fileName);
269 suppressionFilter.setOptional(optional);
270 suppressionFilter.finishLocalSetup();
271 return suppressionFilter;
272 }
273
274 }