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