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.checks.imports;
21
22 import static com.google.common.truth.Truth.assertThat;
23 import static com.google.common.truth.Truth.assertWithMessage;
24 import static com.puppycrawl.tools.checkstyle.checks.imports.ImportControlCheck.MSG_DISALLOWED;
25 import static com.puppycrawl.tools.checkstyle.checks.imports.ImportControlCheck.MSG_MISSING_FILE;
26 import static com.puppycrawl.tools.checkstyle.checks.imports.ImportControlCheck.MSG_UNKNOWN_PKG;
27 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
28
29 import java.io.File;
30 import java.nio.file.Files;
31 import java.util.Arrays;
32 import java.util.List;
33 import java.util.UUID;
34
35 import org.junit.jupiter.api.Test;
36 import org.junit.jupiter.api.io.TempDir;
37
38 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
39 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
40 import com.puppycrawl.tools.checkstyle.TreeWalker;
41 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
42 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
43 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
44
45 public class ImportControlCheckTest extends AbstractModuleTestSupport {
46
47 @TempDir
48 public File temporaryFolder;
49
50 @Override
51 protected String getPackageLocation() {
52 return "com/puppycrawl/tools/checkstyle/checks/imports/importcontrol";
53 }
54
55 @Test
56 public void testGetRequiredTokens() {
57 final ImportControlCheck checkObj = new ImportControlCheck();
58 final int[] expected = {
59 TokenTypes.PACKAGE_DEF,
60 TokenTypes.IMPORT,
61 TokenTypes.STATIC_IMPORT,
62 };
63 assertWithMessage("Default required tokens are invalid")
64 .that(checkObj.getRequiredTokens())
65 .isEqualTo(expected);
66 }
67
68 @Test
69 public void testOne() throws Exception {
70 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
71
72 verifyWithInlineConfigParser(
73 getPath("InputImportControl.java"), expected);
74 }
75
76 @Test
77 public void testTwo() throws Exception {
78 final String[] expected = {
79 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
80 "12:1: " + getCheckMessage(MSG_DISALLOWED, "javax.swing.border.*"),
81 "14:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Button.ABORT"),
82 };
83
84 verifyWithInlineConfigParser(
85 getPath("InputImportControl2.java"), expected);
86 }
87
88 @Test
89 public void testWrong() throws Exception {
90 final String[] expected = {"9:1: " + getCheckMessage(MSG_UNKNOWN_PKG)};
91 verifyWithInlineConfigParser(
92 getPath("InputImportControl3.java"), expected);
93 }
94
95 @Test
96 public void testMissing() throws Exception {
97 final String[] expected = {"9:1: " + getCheckMessage(MSG_MISSING_FILE)};
98 verifyWithInlineConfigParser(
99 getPath("InputImportControl4.java"), expected);
100 }
101
102 @Test
103 public void testEmpty() throws Exception {
104 final String[] expected = {"9:1: " + getCheckMessage(MSG_MISSING_FILE)};
105 verifyWithInlineConfigParser(
106 getPath("InputImportControl5.java"), expected);
107 }
108
109 @Test
110 public void testNull() throws Exception {
111 final String[] expected = {"9:1: " + getCheckMessage(MSG_MISSING_FILE)};
112 verifyWithInlineConfigParser(
113 getPath("InputImportControl6.java"), expected);
114 }
115
116 @Test
117 public void testUnknown() throws Exception {
118 try {
119 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
120 verifyWithInlineConfigParser(
121 getPath("InputImportControl7.java"), expected);
122 assertWithMessage("Test should fail if exception was not thrown").fail();
123 }
124 catch (CheckstyleException ex) {
125 final String message = getCheckstyleExceptionMessage(ex);
126 final String messageStart = "Unable to find: ";
127
128 assertWithMessage("Invalid message, should start with: %s", messageStart)
129 .that(message)
130 .startsWith(messageStart);
131 }
132 }
133
134 @Test
135 public void testBroken() throws Exception {
136 try {
137 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
138 verifyWithInlineConfigParser(getPath("InputImportControl8.java"), expected);
139 assertWithMessage("Test should fail if exception was not thrown").fail();
140 }
141 catch (CheckstyleException ex) {
142 final String message = getCheckstyleExceptionMessage(ex);
143 final String messageStart = "Unable to load ";
144
145 assertWithMessage("Invalid message, should start with: %s", messageStart)
146 .that(message)
147 .startsWith(messageStart);
148 }
149 }
150
151 @Test
152 public void testOneRegExp() throws Exception {
153 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
154
155 verifyWithInlineConfigParser(
156 getPath("InputImportControl9.java"), expected);
157 }
158
159 @Test
160 public void testTwoRegExp() throws Exception {
161 final String[] expected = {
162 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
163 "12:1: " + getCheckMessage(MSG_DISALLOWED, "javax.swing.border.*"),
164 "14:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Button.ABORT"),
165 };
166
167 verifyWithInlineConfigParser(
168 getPath("InputImportControl10.java"), expected);
169 }
170
171 @Test
172 public void testNotRegExpNoMatch() throws Exception {
173
174 verifyWithInlineConfigParser(
175 getPath("InputImportControl11.java"), CommonUtil.EMPTY_STRING_ARRAY);
176 }
177
178 @Test
179 public void testBlacklist() throws Exception {
180 final String[] expected = {
181 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.stream.Stream"),
182 "12:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.Date"),
183 "14:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.stream.Collectors"),
184 "15:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.stream.IntStream"),
185 };
186
187 verifyWithInlineConfigParser(
188 getPath("InputImportControl_Blacklist.java"), expected);
189 }
190
191 @Test
192 public void testStrategyOnMismatchOne() throws Exception {
193 final String[] expected = {
194 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
195 "12:1: " + getCheckMessage(MSG_DISALLOWED, "javax.swing.border.*"),
196 "14:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Button.ABORT"),
197 };
198
199 verifyWithInlineConfigParser(
200 getPath("InputImportControl12.java"), expected);
201 }
202
203 @Test
204 public void testStrategyOnMismatchTwo() throws Exception {
205 final String[] expected = {
206 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
207 "14:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Button.ABORT"),
208 };
209
210 verifyWithInlineConfigParser(
211 getPath("InputImportControl13.java"), expected);
212 }
213
214 @Test
215 public void testStrategyOnMismatchThree() throws Exception {
216 final String[] expected = {
217 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
218 };
219
220 verifyWithInlineConfigParser(
221 getPath("InputImportControl14.java"), expected);
222 }
223
224 @Test
225 public void testStrategyOnMismatchFour() throws Exception {
226 final String[] expected = {
227 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
228 "12:1: " + getCheckMessage(MSG_DISALLOWED, "javax.swing.border.*"),
229 };
230
231 verifyWithInlineConfigParser(
232 getPath("InputImportControl15.java"), expected);
233 }
234
235 @Test
236 public void testWithoutRegexAndWithStrategyOnMismatch() throws Exception {
237 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
238
239 verifyWithInlineConfigParser(
240 getPath("InputImportControlWithoutRegexAndWithStrategyOnMismatch.java"),
241 expected);
242 }
243
244 @Test
245 public void testPkgRegExpInParent() throws Exception {
246 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
247
248 verifyWithInlineConfigParser(
249 getPath("InputImportControl16.java"), expected);
250 }
251
252 @Test
253 public void testPkgRegExpInChild() throws Exception {
254 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
255
256 verifyWithInlineConfigParser(
257 getPath("InputImportControl162.java"), expected);
258 }
259
260 @Test
261 public void testPkgRegExpInBoth() throws Exception {
262 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
263
264 verifyWithInlineConfigParser(
265 getPath("InputImportControl163.java"), expected);
266 }
267
268 @Test
269 public void testGetAcceptableTokens() {
270 final ImportControlCheck testCheckObject =
271 new ImportControlCheck();
272 final int[] actual = testCheckObject.getAcceptableTokens();
273 final int[] expected = {
274 TokenTypes.PACKAGE_DEF,
275 TokenTypes.IMPORT,
276 TokenTypes.STATIC_IMPORT,
277 };
278
279 assertWithMessage("Default acceptable tokens are invalid")
280 .that(actual)
281 .isEqualTo(expected);
282 }
283
284 @Test
285 public void testResource() throws Exception {
286 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
287
288 verifyWithInlineConfigParser(
289 getPath("InputImportControl17.java"), expected);
290 }
291
292 @Test
293 public void testResourceUnableToLoad() throws Exception {
294 try {
295 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
296 verifyWithInlineConfigParser(getPath("InputImportControl18.java"), expected);
297 assertWithMessage("Test should fail if exception was not thrown").fail();
298 }
299 catch (CheckstyleException ex) {
300 final String message = getCheckstyleExceptionMessage(ex);
301 final String messageStart = "Unable to find: ";
302
303 assertWithMessage("Invalid message, should start with: %s", messageStart)
304 .that(message)
305 .startsWith(messageStart);
306 }
307 }
308
309 @Test
310 public void testUrlInFileProperty() throws Exception {
311 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
312
313 verifyWithInlineConfigParser(
314 getPath("InputImportControl19.java"), expected);
315 }
316
317 @Test
318 public void testUrlInFilePropertyUnableToLoad() throws Exception {
319
320 try {
321 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
322 verifyWithInlineConfigParser(
323 getPath("InputImportControl20.java"), expected);
324 assertWithMessage("Test should fail if exception was not thrown").fail();
325 }
326 catch (CheckstyleException ex) {
327 final String message = getCheckstyleExceptionMessage(ex);
328 final String messageStart = "Unable to load ";
329
330 assertWithMessage("Invalid message, should start with: %s", messageStart)
331 .that(message)
332 .startsWith(messageStart);
333 }
334 }
335
336 @Test
337 public void testCacheWhenFileExternalResourceContentDoesNotChange() throws Exception {
338 final DefaultConfiguration checkConfig = createModuleConfig(ImportControlCheck.class);
339 checkConfig.addProperty("file", getPath("InputImportControlOneRegExp.xml"));
340
341 final DefaultConfiguration treeWalkerConfig = createModuleConfig(TreeWalker.class);
342 treeWalkerConfig.addChild(checkConfig);
343
344 final DefaultConfiguration checkerConfig = createRootConfig(treeWalkerConfig);
345 final String uniqueFileName1 = "junit_" + UUID.randomUUID() + ".java";
346 final File cacheFile = new File(temporaryFolder, uniqueFileName1);
347 checkerConfig.addProperty("cacheFile", cacheFile.getPath());
348
349 final String uniqueFileName2 = "empty_" + UUID.randomUUID() + ".java";
350 final File filePath = new File(temporaryFolder, uniqueFileName2);
351
352 execute(checkerConfig, filePath.toString());
353
354 execute(checkerConfig, filePath.toString());
355
356 final String contents = Files.readString(cacheFile.toPath());
357 assertWithMessage("External resource is not present in cache")
358 .that(contents)
359 .contains("InputImportControlOneRegExp.xml");
360 }
361
362 @Test
363 public void testPathRegexMatches() throws Exception {
364 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
365
366 verifyWithInlineConfigParser(
367 getPath("InputImportControl21.java"), expected);
368 }
369
370 @Test
371 public void testPathRegexMatchesPartially() throws Exception {
372 final String[] expected = {"13:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
373
374 verifyWithInlineConfigParser(
375 getPath("InputImportControl22.java"), expected);
376 }
377
378 @Test
379 public void testPathRegexDoesntMatch() throws Exception {
380 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
381
382 verifyWithInlineConfigParser(
383 getPath("InputImportControl23.java"), expected);
384 }
385
386 @Test
387 public void testPathRegexDoesntMatchPartially() throws Exception {
388 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
389
390 verifyWithInlineConfigParser(
391 getPath("InputImportControl24.java"), expected);
392 }
393
394 @Test
395 public void testDisallowClassOfAllowPackage() throws Exception {
396 final String[] expected = {
397 "12:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.Date"),
398 };
399
400 verifyWithInlineConfigParser(
401 getPath("InputImportControlDisallowClassOfAllowPackage.java"),
402 expected);
403 }
404
405 @Test
406 public void testFileName() throws Exception {
407 final String[] expected = {
408 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
409 };
410
411 verifyWithInlineConfigParser(
412 getPath("InputImportControlFileName.java"), expected);
413 }
414
415 @Test
416 public void testWithRegex() throws Exception {
417 final String[] expected = {
418 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File"),
419 };
420
421 verifyWithInlineConfigParser(
422 getPath("InputImportControlWithRegex.java"), expected);
423 }
424
425 @Test
426 public void testFileNameNoExtension() throws Exception {
427 final String[] expected = {
428 "13:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
429 };
430
431 verifyWithInlineConfigParser(
432 getPath("InputImportControlFileNameNoExtension"), expected);
433 }
434
435 @Test
436 public void testBeginTreeCurrentImportControl() throws Exception {
437 final String file1 = getPath("InputImportControlBeginTree1.java");
438 final String file2 = getPath("InputImportControlBeginTree2.java");
439 final List<String> expectedFirstInput = Arrays.asList(
440 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.stream.Stream"),
441 "12:1: " + getCheckMessage(MSG_DISALLOWED, "java.util.stream.Collectors")
442 );
443 final List<String> expectedSecondInput = Arrays.asList(CommonUtil.EMPTY_STRING_ARRAY);
444 verifyWithInlineConfigParser(file1, file2, expectedFirstInput, expectedSecondInput);
445 }
446
447 @Test
448 public void testImportControlFileName() throws Exception {
449 final String[] expected = {
450 "11:1: " + getCheckMessage(MSG_DISALLOWED, "java.awt.Image"),
451 };
452
453 verifyWithInlineConfigParser(
454 getPath("InputImportControlTestRegexpInFile.java"), expected);
455 }
456
457 @Test
458 public void testImportControlFileName2() throws Exception {
459 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
460
461 verifyWithInlineConfigParser(
462 getPath("InputImportControlTestRegexpInFile2.java"), expected);
463 }
464
465 @Test
466 public void testImportControlTestException() {
467 final CheckstyleException ex = getExpectedThrowable(CheckstyleException.class,
468 () -> {
469 verifyWithInlineConfigParser(getPath("InputImportControlTestException.java"));
470 });
471
472 assertThat(ex.getCause().getCause().getCause().getCause().getCause().getMessage())
473 .startsWith("unable to parse file:");
474 assertThat(ex.getCause().getCause().getCause().getCause().getCause().getMessage())
475 .endsWith("- Document root element \"import-control\", must match DOCTYPE"
476 + " root \"null\".");
477 }
478
479
480
481
482
483
484
485
486
487
488
489 private static String getCheckstyleExceptionMessage(CheckstyleException exception) {
490 return exception.getCause().getCause().getCause().getCause().getMessage();
491 }
492
493 }