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