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.utils;
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.internal.utils.TestUtil.getExpectedThrowable;
25 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
26 import static org.mockito.Mockito.CALLS_REAL_METHODS;
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.mockStatic;
29 import static org.mockito.Mockito.when;
30
31 import java.io.Closeable;
32 import java.io.File;
33 import java.io.IOException;
34 import java.lang.reflect.Constructor;
35 import java.net.URI;
36 import java.net.URISyntaxException;
37 import java.net.URL;
38 import java.nio.charset.StandardCharsets;
39 import java.util.Dictionary;
40 import java.util.Properties;
41 import java.util.regex.Pattern;
42
43 import org.apache.commons.io.IOUtils;
44 import org.junit.jupiter.api.Test;
45 import org.mockito.MockedStatic;
46
47 import com.puppycrawl.tools.checkstyle.AbstractPathTestSupport;
48 import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
49 import com.puppycrawl.tools.checkstyle.PropertiesExpander;
50 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
51 import com.puppycrawl.tools.checkstyle.api.Configuration;
52
53 public class CommonUtilTest extends AbstractPathTestSupport {
54
55
56 private static final String PATH_DENORMALIZER = "/levelDown/.././";
57
58 @Override
59 protected String getPackageLocation() {
60 return "com/puppycrawl/tools/checkstyle/utils/commonutil";
61 }
62
63 @Test
64 public void testIsProperUtilsClass() throws ReflectiveOperationException {
65 assertWithMessage("Constructor is not private")
66 .that(isUtilsClassHasPrivateConstructor(CommonUtil.class))
67 .isTrue();
68 }
69
70
71
72
73 @Test
74 public void testLengthExpandedTabs() {
75 final String s1 = "\t";
76 assertWithMessage("Invalid expanded tabs length")
77 .that(CommonUtil.lengthExpandedTabs(s1, s1.length(), 8))
78 .isEqualTo(8);
79
80 final String s2 = " \t";
81 assertWithMessage("Invalid expanded tabs length")
82 .that(CommonUtil.lengthExpandedTabs(s2, s2.length(), 8))
83 .isEqualTo(8);
84
85 final String s3 = "\t\t";
86 assertWithMessage("Invalid expanded tabs length")
87 .that(CommonUtil.lengthExpandedTabs(s3, s3.length(), 8))
88 .isEqualTo(16);
89
90 final String s4 = " \t ";
91 assertWithMessage("Invalid expanded tabs length")
92 .that(CommonUtil.lengthExpandedTabs(s4, s4.length(), 8))
93 .isEqualTo(9);
94
95 assertWithMessage("Invalid expanded tabs length")
96 .that(CommonUtil.lengthMinusTrailingWhitespace(""))
97 .isEqualTo(0);
98 assertWithMessage("Invalid expanded tabs length")
99 .that(CommonUtil.lengthMinusTrailingWhitespace(" \t "))
100 .isEqualTo(0);
101 assertWithMessage("Invalid expanded tabs length")
102 .that(CommonUtil.lengthMinusTrailingWhitespace(" 23"))
103 .isEqualTo(3);
104 assertWithMessage("Invalid expanded tabs length")
105 .that(CommonUtil.lengthMinusTrailingWhitespace(" 23 \t "))
106 .isEqualTo(3);
107 }
108
109 @Test
110 public void testCreatePattern() {
111 assertWithMessage("invalid pattern")
112 .that(CommonUtil.createPattern("Test").pattern())
113 .isEqualTo("Test");
114 assertWithMessage("invalid pattern")
115 .that(CommonUtil.createPattern(".*Pattern.*")
116 .pattern())
117 .isEqualTo(".*Pattern.*");
118 }
119
120 @Test
121 public void testBadRegex() {
122 final IllegalArgumentException ex =
123 getExpectedThrowable(IllegalArgumentException.class, () -> {
124 CommonUtil.createPattern("[");
125 });
126 assertWithMessage("Invalid exception message")
127 .that(ex)
128 .hasMessageThat()
129 .isEqualTo("Failed to initialise regular expression [");
130 }
131
132 @Test
133 public void testBadRegex2() {
134 final IllegalArgumentException ex =
135 getExpectedThrowable(IllegalArgumentException.class, () -> {
136 CommonUtil.createPattern("[", Pattern.MULTILINE);
137 });
138 assertWithMessage("Invalid exception message")
139 .that(ex)
140 .hasMessageThat()
141 .isEqualTo("Failed to initialise regular expression [");
142 }
143
144 @Test
145 public void testFileExtensions() {
146 final String[] fileExtensions = {"java"};
147 final File pdfFile = new File("file.pdf");
148 assertWithMessage("Invalid file extension")
149 .that(CommonUtil.matchesFileExtension(pdfFile, fileExtensions))
150 .isFalse();
151 assertWithMessage("Invalid file extension")
152 .that(CommonUtil.matchesFileExtension(pdfFile))
153 .isTrue();
154 assertWithMessage("Invalid file extension")
155 .that(CommonUtil.matchesFileExtension(pdfFile, (String[]) null))
156 .isTrue();
157 final File javaFile = new File("file.java");
158 assertWithMessage("Invalid file extension")
159 .that(CommonUtil.matchesFileExtension(javaFile, fileExtensions))
160 .isTrue();
161 final File invalidJavaFile = new File("file,java");
162 assertWithMessage("Invalid file extension")
163 .that(CommonUtil.matchesFileExtension(invalidJavaFile, fileExtensions))
164 .isFalse();
165 final File emptyExtensionFile = new File("file.");
166 assertWithMessage("Invalid file extension")
167 .that(CommonUtil.matchesFileExtension(emptyExtensionFile, ""))
168 .isTrue();
169 assertWithMessage("Invalid file extension")
170 .that(CommonUtil.matchesFileExtension(pdfFile, ".noMatch"))
171 .isFalse();
172 assertWithMessage("Invalid file extension")
173 .that(CommonUtil.matchesFileExtension(pdfFile, ".pdf"))
174 .isTrue();
175 }
176
177 @Test
178 public void testHasWhitespaceBefore() {
179 assertWithMessage("Invalid result")
180 .that(CommonUtil.hasWhitespaceBefore(0, "a"))
181 .isTrue();
182 assertWithMessage("Invalid result")
183 .that(CommonUtil.hasWhitespaceBefore(4, " a"))
184 .isTrue();
185 assertWithMessage("Invalid result")
186 .that(CommonUtil.hasWhitespaceBefore(5, " a"))
187 .isFalse();
188 }
189
190 @Test
191 public void testBaseClassNameForCanonicalName() {
192 assertWithMessage("Invalid base class name")
193 .that(CommonUtil.baseClassName("java.util.List"))
194 .isEqualTo("List");
195 }
196
197 @Test
198 public void testBaseClassNameForSimpleName() {
199 assertWithMessage("Invalid base class name")
200 .that(CommonUtil.baseClassName("Set"))
201 .isEqualTo("Set");
202 }
203
204 @Test
205 public void testRelativeNormalizedPath() {
206 final String relativePath = CommonUtil.relativizePath("/home", "/home/test");
207
208 assertWithMessage("Invalid relative path")
209 .that(relativePath)
210 .isEqualTo("test");
211 }
212
213 @Test
214 public void testRelativeNormalizedPathWithNullBaseDirectory() {
215 final String relativePath = CommonUtil.relativizePath(null, "/tmp");
216
217 assertWithMessage("Invalid relative path")
218 .that(relativePath)
219 .isEqualTo("/tmp");
220 }
221
222 @Test
223 public void testRelativeNormalizedPathWithDenormalizedBaseDirectory() throws IOException {
224 final String sampleAbsolutePath = new File("src/main/java").getCanonicalPath();
225 final String absoluteFilePath = sampleAbsolutePath + "/SampleFile.java";
226 final String basePath = sampleAbsolutePath + PATH_DENORMALIZER;
227
228 final String relativePath = CommonUtil.relativizePath(basePath,
229 absoluteFilePath);
230
231 assertWithMessage("Invalid relative path")
232 .that(relativePath)
233 .isEqualTo("SampleFile.java");
234 }
235
236 @Test
237 public void testPattern() {
238 final boolean result = CommonUtil.isPatternValid("someValidPattern");
239 assertWithMessage("Should return true when pattern is valid")
240 .that(result)
241 .isTrue();
242 }
243
244 @Test
245 public void testInvalidPattern() {
246 final boolean result = CommonUtil.isPatternValid("some[invalidPattern");
247 assertWithMessage("Should return false when pattern is invalid")
248 .that(result)
249 .isFalse();
250 }
251
252 @Test
253 public void testGetExistingConstructor() throws NoSuchMethodException {
254 final Constructor<?> constructor = CommonUtil.getConstructor(String.class, String.class);
255
256 assertWithMessage("Invalid constructor")
257 .that(constructor)
258 .isEqualTo(String.class.getConstructor(String.class));
259 }
260
261 @Test
262 public void testGetNonExistentConstructor() {
263 final IllegalStateException ex = getExpectedThrowable(IllegalStateException.class, () -> {
264 CommonUtil.getConstructor(Math.class);
265 });
266 assertWithMessage("Invalid exception cause")
267 .that(ex)
268 .hasCauseThat()
269 .isInstanceOf(NoSuchMethodException.class);
270 }
271
272 @Test
273 public void testInvokeConstructor() throws NoSuchMethodException {
274 final Constructor<String> constructor = String.class.getConstructor(String.class);
275
276 final String constructedString = CommonUtil.invokeConstructor(constructor, "string");
277
278 assertWithMessage("Invalid construction result")
279 .that(constructedString)
280 .isEqualTo("string");
281 }
282
283 @SuppressWarnings("rawtypes")
284 @Test
285 public void testInvokeConstructorThatFails() throws NoSuchMethodException {
286 final Constructor<Dictionary> constructor = Dictionary.class.getConstructor();
287 final IllegalStateException ex = getExpectedThrowable(IllegalStateException.class, () -> {
288 CommonUtil.invokeConstructor(constructor);
289 });
290 assertWithMessage("Invalid exception cause")
291 .that(ex)
292 .hasCauseThat()
293 .isInstanceOf(InstantiationException.class);
294 }
295
296 @Test
297 public void testClose() {
298 final TestCloseable closeable = new TestCloseable();
299
300 CommonUtil.close(null);
301 CommonUtil.close(closeable);
302
303 assertWithMessage("Should be closed")
304 .that(closeable.closed)
305 .isTrue();
306 }
307
308 @Test
309 public void testCloseWithException() {
310 final IllegalStateException ex = getExpectedThrowable(IllegalStateException.class, () -> {
311 CommonUtil.close(() -> {
312 throw new IOException("Test IOException");
313 });
314 });
315 assertWithMessage("Invalid exception message")
316 .that(ex)
317 .hasMessageThat()
318 .isEqualTo("Cannot close the stream");
319 }
320
321 @Test
322 public void testFillTemplateWithStringsByRegexp() {
323 assertWithMessage("invalid result")
324 .that(CommonUtil.fillTemplateWithStringsByRegexp("template",
325 "lineToPlaceInTemplate", Pattern.compile("NO MATCH")))
326 .isEqualTo("template");
327 assertWithMessage("invalid result")
328 .that(CommonUtil.fillTemplateWithStringsByRegexp("before $0 after", "word",
329 Pattern.compile("\\w+")))
330 .isEqualTo("before word after");
331 assertWithMessage("invalid result")
332 .that(CommonUtil.fillTemplateWithStringsByRegexp("before $0 after1 $1 after2 $2 after3",
333 "word 123", Pattern.compile("(\\w+) (\\d+)")))
334 .isEqualTo("before word 123 after1 word after2 123 after3");
335 }
336
337 @Test
338 public void testGetFileNameWithoutExtension() {
339 assertWithMessage("invalid result")
340 .that(CommonUtil.getFileNameWithoutExtension("filename"))
341 .isEqualTo("filename");
342 assertWithMessage("invalid result")
343 .that(CommonUtil.getFileNameWithoutExtension("filename.extension"))
344 .isEqualTo("filename");
345 assertWithMessage("invalid result")
346 .that(CommonUtil.getFileNameWithoutExtension("filename.subext.extension"))
347 .isEqualTo("filename.subext");
348 }
349
350 @Test
351 public void testGetFileExtension() {
352 assertWithMessage("Invalid extension")
353 .that(CommonUtil.getFileExtension("filename"))
354 .isEqualTo("");
355 assertWithMessage("Invalid extension")
356 .that(CommonUtil.getFileExtension("filename.extension"))
357 .isEqualTo("extension");
358 assertWithMessage("Invalid extension")
359 .that(CommonUtil.getFileExtension("filename.subext.extension"))
360 .isEqualTo("extension");
361 }
362
363 @Test
364 public void testIsIdentifier() {
365 assertWithMessage("Should return true when valid identifier is passed")
366 .that(CommonUtil.isIdentifier("aValidIdentifier"))
367 .isTrue();
368 }
369
370 @Test
371 public void testIsIdentifierEmptyString() {
372 assertWithMessage("Should return false when empty string is passed")
373 .that(CommonUtil.isIdentifier(""))
374 .isFalse();
375 }
376
377 @Test
378 public void testIsIdentifierInvalidFirstSymbol() {
379 assertWithMessage("Should return false when invalid identifier is passed")
380 .that(CommonUtil.isIdentifier("1InvalidIdentifier"))
381 .isFalse();
382 }
383
384 @Test
385 public void testIsIdentifierInvalidSymbols() {
386 assertWithMessage("Should return false when invalid identifier is passed")
387 .that(CommonUtil.isIdentifier("invalid#Identifier"))
388 .isFalse();
389 }
390
391 @Test
392 public void testIsName() {
393 assertWithMessage("Should return true when valid name is passed")
394 .that(CommonUtil.isName("a.valid.Nam3"))
395 .isTrue();
396 }
397
398 @Test
399 public void testIsNameEmptyString() {
400 assertWithMessage("Should return false when empty string is passed")
401 .that(CommonUtil.isName(""))
402 .isFalse();
403 }
404
405 @Test
406 public void testIsNameInvalidFirstSymbol() {
407 assertWithMessage("Should return false when invalid name is passed")
408 .that(CommonUtil.isName("1.invalid.name"))
409 .isFalse();
410 }
411
412 @Test
413 public void testIsNameEmptyPart() {
414 assertWithMessage("Should return false when name has empty part")
415 .that(CommonUtil.isName("invalid..name"))
416 .isFalse();
417 }
418
419 @Test
420 public void testIsNameEmptyLastPart() {
421 assertWithMessage("Should return false when name has empty part")
422 .that(CommonUtil.isName("invalid.name."))
423 .isFalse();
424 }
425
426 @Test
427 public void testIsNameInvalidSymbol() {
428 assertWithMessage("Should return false when invalid name is passed")
429 .that(CommonUtil.isName("invalid.name#42"))
430 .isFalse();
431 }
432
433 @Test
434 public void testIsBlank() {
435 assertWithMessage("Should return false when string is not empty")
436 .that(CommonUtil.isBlank("string"))
437 .isFalse();
438 }
439
440 @Test
441 public void testIsBlankAheadWhitespace() {
442 assertWithMessage("Should return false when string is not empty")
443 .that(CommonUtil.isBlank(" string"))
444 .isFalse();
445 }
446
447 @Test
448 public void testIsBlankBehindWhitespace() {
449 assertWithMessage("Should return false when string is not empty")
450 .that(CommonUtil.isBlank("string "))
451 .isFalse();
452 }
453
454 @Test
455 public void testIsBlankWithWhitespacesAround() {
456 assertWithMessage("Should return false when string is not empty")
457 .that(CommonUtil.isBlank(" string "))
458 .isFalse();
459 }
460
461 @Test
462 public void testIsBlankWhitespaceInside() {
463 assertWithMessage("Should return false when string is not empty")
464 .that(CommonUtil.isBlank("str ing"))
465 .isFalse();
466 }
467
468 @Test
469 public void testIsBlankNullString() {
470 assertWithMessage("Should return true when string is null")
471 .that(CommonUtil.isBlank(null))
472 .isTrue();
473 }
474
475 @Test
476 public void testIsBlankWithEmptyString() {
477 assertWithMessage("Should return true when string is empty")
478 .that(CommonUtil.isBlank(""))
479 .isTrue();
480 }
481
482 @Test
483 public void testIsBlankWithWhitespacesOnly() {
484 assertWithMessage("Should return true when string contains only spaces")
485 .that(CommonUtil.isBlank(" "))
486 .isTrue();
487 }
488
489 @Test
490 public void testGetUriByFilenameFindsAbsoluteResourceOnClasspath() throws Exception {
491 final String filename =
492 "/" + getPackageLocation() + "/InputCommonUtilTest_empty_checks.xml";
493 final URI uri = CommonUtil.getUriByFilename(filename);
494
495 final Properties properties = System.getProperties();
496 final Configuration config = ConfigurationLoader.loadConfiguration(uri.toASCIIString(),
497 new PropertiesExpander(properties));
498 assertWithMessage("Unexpected config name!")
499 .that(config.getName())
500 .isEqualTo("Checker");
501 }
502
503 @Test
504 public void testGetUriByFilenameFindsRelativeResourceOnClasspath() throws Exception {
505 final String filename =
506 getPackageLocation() + "/InputCommonUtilTest_empty_checks.xml";
507 final URI uri = CommonUtil.getUriByFilename(filename);
508
509 final Properties properties = System.getProperties();
510 final Configuration config = ConfigurationLoader.loadConfiguration(uri.toASCIIString(),
511 new PropertiesExpander(properties));
512 assertWithMessage("Unexpected config name!")
513 .that(config.getName())
514 .isEqualTo("Checker");
515 }
516
517
518
519
520
521
522
523
524 @Test
525 public void testGetUriByFilenameFindsResourceRelativeToRootClasspath() throws Exception {
526 final String filename =
527 getPackageLocation() + "/InputCommonUtilTest_resource.txt";
528 final URI uri = CommonUtil.getUriByFilename(filename);
529 assertWithMessage("URI is null for: " + filename)
530 .that(uri)
531 .isNotNull();
532 final String uriRelativeToPackage =
533 "com/puppycrawl/tools/checkstyle/utils/"
534 + getPackageLocation() + "/InputCommonUtilTest_resource.txt";
535 assertWithMessage("URI is relative to package " + uriRelativeToPackage)
536 .that(uri.toASCIIString())
537 .doesNotContain(uriRelativeToPackage);
538 final String content = IOUtils.toString(uri.toURL(), StandardCharsets.UTF_8);
539 assertWithMessage("Content mismatches for: " + uri.toASCIIString())
540 .that(content)
541 .startsWith("good");
542 }
543
544 @Test
545 public void testGetUriByFilenameClasspathPrefixLoadConfig() throws Exception {
546 final String filename = CommonUtil.CLASSPATH_URL_PROTOCOL
547 + getPackageLocation() + "/InputCommonUtilTestWithChecks.xml";
548 final URI uri = CommonUtil.getUriByFilename(filename);
549
550 final Properties properties = System.getProperties();
551 final Configuration config = ConfigurationLoader.loadConfiguration(uri.toASCIIString(),
552 new PropertiesExpander(properties));
553 assertWithMessage("Unexpected config name!")
554 .that(config.getName())
555 .isEqualTo("Checker");
556 }
557
558 @Test
559 public void testGetUriByFilenameFindsRelativeResourceOnClasspathPrefix() throws Exception {
560 final String filename = CommonUtil.CLASSPATH_URL_PROTOCOL
561 + getPackageLocation() + "/InputCommonUtilTest_empty_checks.xml";
562 final URI uri = CommonUtil.getUriByFilename(filename);
563
564 final Properties properties = System.getProperties();
565 final Configuration config = ConfigurationLoader.loadConfiguration(uri.toASCIIString(),
566 new PropertiesExpander(properties));
567 assertWithMessage("Unexpected config name!")
568 .that(config.getName())
569 .isEqualTo("Checker");
570 }
571
572 @Test
573 public void testIsCodePointWhitespace() {
574 final int[] codePoints = " 123".codePoints().toArray();
575 assertThat(CommonUtil.isCodePointWhitespace(codePoints, 0))
576 .isTrue();
577 assertThat(CommonUtil.isCodePointWhitespace(codePoints, 1))
578 .isFalse();
579 }
580
581 @Test
582 public void testLoadSuppressionsUriSyntaxException() throws Exception {
583 final URL configUrl = mock();
584 when(configUrl.toURI()).thenThrow(URISyntaxException.class);
585 try (MockedStatic<CommonUtil> utilities =
586 mockStatic(CommonUtil.class, CALLS_REAL_METHODS)) {
587 final String fileName = "/suppressions_none.xml";
588 utilities.when(() -> CommonUtil.getCheckstyleResource(fileName))
589 .thenReturn(configUrl);
590
591 final CheckstyleException ex = getExpectedThrowable(CheckstyleException.class, () -> {
592 CommonUtil.getUriByFilename(fileName);
593 });
594 assertWithMessage("Invalid exception cause")
595 .that(ex)
596 .hasCauseThat()
597 .isInstanceOf(URISyntaxException.class);
598 assertWithMessage("Invalid exception message")
599 .that(ex)
600 .hasMessageThat()
601 .isEqualTo("Unable to find: " + fileName);
602 }
603 }
604
605 private static final class TestCloseable implements Closeable {
606
607 private boolean closed;
608
609 @Override
610 public void close() {
611 closed = true;
612 }
613
614 }
615
616 }