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.coding;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.coding.IllegalSymbolCheck.MSG_KEY;
24 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.getExpectedThrowable;
25 import static org.junit.Assert.assertEquals;
26 import static org.junit.Assert.assertTrue;
27 import static org.junit.Assert.fail;
28
29 import org.junit.jupiter.api.Test;
30
31 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
32 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
33 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
34
35 public class IllegalSymbolCheckTest extends AbstractModuleTestSupport {
36
37 @Override
38 public String getPackageLocation() {
39 return "com/puppycrawl/tools/checkstyle/checks/coding/illegalsymbol";
40 }
41
42 @Test
43 public void testDefault() throws Exception {
44 final String[] expected = {
45 "12:7: " + getCheckMessage(MSG_KEY, "✅"),
46 };
47 verifyWithInlineConfigParser(
48 getPath("InputIllegalSymbolDefault.java"), expected);
49 }
50
51 @Test
52 public void testEmojiInComment() throws Exception {
53 final String[] expected = {
54 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
55 "13:18: " + getCheckMessage(MSG_KEY, "❌"),
56 };
57 verifyWithInlineConfigParser(
58 getPath("InputIllegalSymbolEmoji.java"), expected);
59 }
60
61 @Test
62 public void testAsciiOnly() throws Exception {
63 final String[] expected = {
64 "12:18: " + getCheckMessage(MSG_KEY, "é"),
65 "13:18: " + getCheckMessage(MSG_KEY, "•"),
66 };
67
68 verifyWithInlineConfigParser(
69 getPath("InputIllegalSymbolAsciiOnly.java"),
70 expected);
71 }
72
73 @Test
74 public void testMultipleRanges() throws Exception {
75 final String[] expected = {
76 "12:19: " + getCheckMessage(MSG_KEY, "✅"),
77 "13:19: " + getCheckMessage(MSG_KEY, "😀"),
78 "14:19: " + getCheckMessage(MSG_KEY, "©"),
79 };
80 verifyWithInlineConfigParser(
81 getPath("InputIllegalSymbolMultipleRanges.java"), expected);
82 }
83
84 @Test
85 public void testMultipleViolationsInSameToken() throws Exception {
86 final String[] expected = {
87 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
88 };
89
90 verifyWithInlineConfigParser(
91 getPath("InputIllegalSymbolMultiple.java"), expected);
92 }
93
94 @Test
95 public void testNoViolationWhenNotConfigured() throws Exception {
96 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
97
98 verifyWithInlineConfigParser(
99 getPath("InputIllegalSymbolNoConfig.java"), expected);
100 }
101
102 @Test
103 public void testSymbolStringLiteral() throws Exception {
104 final String[] expected = {
105 "12:16: " + getCheckMessage(MSG_KEY, "😀"),
106 };
107
108 verifyWithInlineConfigParser(
109 getPath("InputIllegalSymbolStringLiteral.java"), expected);
110 }
111
112 @Test
113 public void testCharLiteral() throws Exception {
114 final String[] expected = {
115 "12:14: " + getCheckMessage(MSG_KEY, "é"),
116 };
117
118 verifyWithInlineConfigParser(
119 getPath("InputIllegalSymbolChar.java"), expected);
120 }
121
122 @Test
123 public void testTextBlock() throws Exception {
124 final String[] expected = {
125 "13:19: " + getCheckMessage(MSG_KEY, "😀"),
126 };
127
128 verifyWithInlineConfigParser(
129 getPath("InputIllegalSymbolTextBlock.java"), expected);
130 }
131
132 @Test
133 public void testLowercasePlusU() throws Exception {
134 final String[] expected = {
135 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
136 };
137
138 verifyWithInlineConfigParser(
139 getPath("InputIllegalSymbolLowercaseU.java"), expected);
140 }
141
142 @Test
143 public void testUppercase0X() throws Exception {
144 final String[] expected = {
145 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
146 };
147
148 verifyWithInlineConfigParser(
149 getPath("InputIllegalSymbolUppercase0X.java"), expected);
150 }
151
152 @Test
153 public void testHexWithoutPrefix() throws Exception {
154 final String[] expected = {
155 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
156 };
157
158 verifyWithInlineConfigParser(
159 getPath("InputIllegalSymbolHexNoPrefix.java"), expected);
160 }
161
162 @Test
163 public void testBackslashFormatU() throws Exception {
164 final String[] expected = {
165 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
166 };
167
168 verifyWithInlineConfigParser(
169 getPath("InputIllegalSymbolBackslashU.java"), expected);
170 }
171
172 @Test
173 public void testUnicodePlusFormat() throws Exception {
174 final String[] expected = {
175 "14:7: " + getCheckMessage(MSG_KEY, "✅"),
176 };
177 verifyWithInlineConfigParser(
178 getPath("InputIllegalSymbolUnicodePlus.java"), expected);
179 }
180
181 @Test
182 public void testInvalidRangeMultipleDashes() throws Exception {
183 try {
184 verifyWithInlineConfigParser(
185 getPath("InputIllegalSymbolMultipleDashes.java"),
186 CommonUtil.EMPTY_STRING_ARRAY);
187 fail("CheckstyleException expected");
188 }
189 catch (CheckstyleException exception) {
190 assertTrue("Exception should indicate initialization failure",
191 exception.getMessage().contains("cannot initialize module"));
192 }
193 }
194
195 @Test
196 public void testSetSymbolCodesNull() throws Exception {
197 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
198 verifyWithInlineConfigParser(
199 getPath("InputIllegalSymbolNullConfig.java"),
200 expected);
201 }
202
203 @Test
204 public void testSetSymbolCodesEmptyViaConfig() throws Exception {
205 verifyWithInlineConfigParser(
206 getPath("InputIllegalSymbolEmptyConfig.java"),
207 CommonUtil.EMPTY_STRING_ARRAY);
208 }
209
210 @Test
211 public void testInitParseSymbolCodesIsCalledAndPopulatesSets() throws Exception {
212 final String[] expected = {
213 "12:7: " + getCheckMessage(MSG_KEY, "😀"),
214 "13:7: " + getCheckMessage(MSG_KEY, "🚀"),
215 };
216 verifyWithInlineConfigParser(
217 getPath("InputIllegalSymbolDefaultStrong.java"), expected);
218 }
219
220 @Test
221 public void testRangeStartEqualsEnd() throws Exception {
222 final String[] expected = {
223 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
224 };
225 verifyWithInlineConfigParser(
226 getPath("InputIllegalSymbolRangeStartEqualsEnd.java"), expected);
227 }
228
229 @Test
230 public void testRangePartsAreTrimmed() throws Exception {
231 final String[] expected = {
232 "12:18: " + getCheckMessage(MSG_KEY, "✈"),
233 };
234 verifyWithInlineConfigParser(
235 getPath("InputIllegalSymbolRangeTrimmed.java"), expected);
236 }
237
238 @Test
239 public void testSymbolCodesWithSpacesAreTrimmed() throws Exception {
240 final String[] expected = {
241 "12:18: " + getCheckMessage(MSG_KEY, "✅"),
242 };
243 verifyWithInlineConfigParser(
244 getPath("InputIllegalSymbolSpacedEntries.java"), expected);
245 }
246
247 @Test
248 public void testInvalidSingleSymbolCode() throws Exception {
249 try {
250 verifyWithInlineConfigParser(
251 getPath("InputIllegalSymbolInvalidCode.java"),
252 CommonUtil.EMPTY_STRING_ARRAY);
253 fail("CheckstyleException expected");
254 }
255 catch (CheckstyleException exception) {
256 final String message = exception.getMessage();
257 assertTrue("Exception should indicate initialization failure, but got: " + message,
258 message.contains("cannot initialize module")
259 || message.contains("Invalid symbol code format")
260 || message.contains("NumberFormatException")
261 || message.contains("Cannot set property"));
262 }
263 }
264
265 @Test
266 public void testInvalidRangeFormat() throws Exception {
267 try {
268 verifyWithInlineConfigParser(
269 getPath("InputIllegalSymbolInvalidRange.java"),
270 CommonUtil.EMPTY_STRING_ARRAY);
271 fail("CheckstyleException expected");
272 }
273 catch (CheckstyleException exception) {
274 final String message = exception.getMessage();
275 assertTrue("Exception should indicate initialization failure, but got: " + message,
276 message.contains("cannot initialize module")
277 || message.contains("Invalid range format")
278 || message.contains("Cannot set property"));
279 }
280 }
281
282 @Test
283 public void testRangeStartGreaterThanEnd() throws Exception {
284 try {
285 verifyWithInlineConfigParser(
286 getPath("InputIllegalSymbolRangeReversed.java"),
287 CommonUtil.EMPTY_STRING_ARRAY);
288 fail("CheckstyleException expected");
289 }
290 catch (CheckstyleException exception) {
291 final String message = exception.getMessage();
292 assertTrue("Exception should indicate initialization failure, but got: " + message,
293 message.contains("cannot initialize module")
294 || message.contains("Range start must be <= end")
295 || message.contains("Cannot set property"));
296 }
297 }
298
299 @Test
300 public void testInvalidShortCodePoint() throws Exception {
301 try {
302 verifyWithInlineConfigParser(
303 getPath("InputIllegalSymbolShortCode.java"),
304 CommonUtil.EMPTY_STRING_ARRAY);
305 fail("CheckstyleException expected");
306 }
307 catch (CheckstyleException exception) {
308 final String message = exception.getMessage();
309 assertTrue("Exception should indicate initialization failure, but got: " + message,
310 message.contains("cannot initialize module")
311 || message.contains("Invalid code point format")
312 || message.contains("NumberFormatException")
313 || message.contains("Cannot set property"));
314 }
315 }
316
317 @Test
318 public void testSetSymbolCodesIgnoresEmptyEntries() throws Exception {
319 final String[] expected = {
320 "12:7: " + getCheckMessage(MSG_KEY, "✅"),
321 };
322 verifyWithInlineConfigParser(
323 getPath("InputIllegalSymbolIgnoreEmpty.java"),
324 expected);
325 }
326
327 @Test
328 public void testSetSymbolCodesEmptyList() throws Exception {
329 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
330
331 verifyWithInlineConfigParser(
332 getPath("InputIllegalSymbolNoConfig.java"),
333 expected);
334
335 assertEquals("Expected should have 0 violations", 0, expected.length);
336 }
337
338 @Test
339 public void testSetSymbolCodesBlankRangeStart() throws Exception {
340 try {
341 verifyWithInlineConfigParser(
342 getPath("InputIllegalSymbolBlankStart.java"),
343 CommonUtil.EMPTY_STRING_ARRAY);
344 fail("CheckstyleException expected");
345 }
346 catch (CheckstyleException exception) {
347 final String message = exception.getMessage();
348 assertTrue("Exception should indicate initialization failure, but got: " + message,
349 message.contains("cannot initialize module")
350 || message.contains("Invalid range format")
351 || message.contains("Cannot set property"));
352 }
353 }
354
355 @Test
356 public void testContainsReturnsFalse() throws Exception {
357 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
358
359 verifyWithInlineConfigParser(
360 getPath("InputIllegalSymbolOutsideRange.java"),
361 expected);
362 }
363
364 @Test
365 public void testSetSymbolCodesEmptyString() throws Exception {
366 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
367
368 verifyWithInlineConfigParser(
369 getPath("InputIllegalSymbolEmptyConfig.java"),
370 expected);
371
372 assertEquals("Expected should have 0 violations", 0, expected.length);
373 }
374
375 @Test
376 public void testRangeStartBoundary() throws Exception {
377 final String[] expected = {
378 "13:18: " + getCheckMessage(MSG_KEY, "😀"),
379 };
380 verifyWithInlineConfigParser(
381 getPath("InputIllegalSymbolRangeStart.java"), expected);
382 }
383
384 @Test
385 public void testRangeEndBoundary() throws Exception {
386 final String[] expected = {
387 "13:18: " + getCheckMessage(MSG_KEY, "🙏"),
388 };
389 verifyWithInlineConfigParser(
390 getPath("InputIllegalSymbolRangeEnd.java"), expected);
391 }
392
393 @Test
394 public void testSetSymbolCodesTwice() throws Exception {
395 final String[] expected = {
396 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
397 };
398 verifyWithInlineConfigParser(
399 getPath("InputIllegalSymbolSetTwice.java"), expected);
400 }
401
402 @Test
403 public void testSymbolNotInRange() throws Exception {
404 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
405 verifyWithInlineConfigParser(
406 getPath("InputIllegalSymbolNotInRange.java"), expected);
407 }
408
409 @Test
410 public void testEmptyConfigDoesNothing() throws Exception {
411 verifyWithInlineConfigParser(
412 getPath("InputIllegalSymbolEmpty.java"),
413 CommonUtil.EMPTY_STRING_ARRAY);
414 }
415
416 @Test
417 public void testJustOutsideRange() throws Exception {
418 verifyWithInlineConfigParser(
419 getPath("InputIllegalSymbolJustOutsideRange.java"),
420 CommonUtil.EMPTY_STRING_ARRAY);
421 }
422
423 @Test
424 public void testSetThenClearConfig() throws Exception {
425 verifyWithInlineConfigParser(
426 getPath("InputIllegalSymbolSetThenClear.java"),
427 CommonUtil.EMPTY_STRING_ARRAY);
428 }
429
430 @Test
431 public void testRangeBoundaries() throws Exception {
432 final String[] expected = {
433 "13:18: " + getCheckMessage(MSG_KEY, "😀"),
434 "14:18: " + getCheckMessage(MSG_KEY, "😁"),
435 "15:18: " + getCheckMessage(MSG_KEY, "🙏"),
436 };
437
438 verifyWithInlineConfigParser(
439 getPath("InputIllegalSymbolRangeBoundaries.java"),
440 expected);
441 }
442
443 @Test
444 public void testMultipleIllegalSymbolsOnlyOneViolation() throws Exception {
445 final String[] expected = {
446 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
447 };
448
449 verifyWithInlineConfigParser(
450 getPath("InputIllegalSymbolMultipleInComment.java"),
451 expected);
452 }
453
454 @Test
455 public void testTrimmedCommaSeparatedValues() throws Exception {
456 final String[] expected = {
457 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
458 };
459
460 verifyWithInlineConfigParser(
461 getPath("InputIllegalSymbolTrimComma.java"),
462 expected);
463 }
464
465 @Test
466 public void testInvalidShortPrefix() {
467 final IllegalSymbolCheck check = new IllegalSymbolCheck();
468
469 final IllegalArgumentException ex0x = getExpectedThrowable(
470 IllegalArgumentException.class,
471 () -> check.setSymbolCodes("0x"));
472 assertWithMessage("Wrong exception message for '0x' prefix")
473 .that(ex0x.getMessage())
474 .contains("Invalid");
475
476 final IllegalArgumentException ex = getExpectedThrowable(
477 IllegalArgumentException.class,
478 () -> check.setSymbolCodes("U+"));
479 assertWithMessage("Wrong exception message for 'U+' prefix")
480 .that(ex.getMessage())
481 .contains("Invalid");
482 }
483
484 @Test
485 public void testInvalidRangeFormats() {
486 final IllegalSymbolCheck check = new IllegalSymbolCheck();
487
488 final IllegalArgumentException exMissingStart = getExpectedThrowable(
489 IllegalArgumentException.class,
490 () -> check.setSymbolCodes("-0x1234"));
491 assertWithMessage("Exception message mismatch for missing range start")
492 .that(exMissingStart.getMessage())
493 .contains("Invalid range");
494
495 final IllegalArgumentException exMissingEnd = getExpectedThrowable(
496 IllegalArgumentException.class,
497 () -> check.setSymbolCodes("0x1234-"));
498 assertWithMessage("Exception message mismatch for missing range end")
499 .that(exMissingEnd.getMessage())
500 .contains("Invalid range");
501 }
502
503 @Test
504 public void testSingleAndRangeOverlap() throws Exception {
505 final String[] expected = {
506 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
507 };
508
509 verifyWithInlineConfigParser(
510 getPath("InputIllegalSymbolSingleAndRange.java"),
511 expected);
512 }
513
514 @Test
515 public void testInvalidRangeOrder() {
516 final IllegalSymbolCheck check = new IllegalSymbolCheck();
517
518 final IllegalArgumentException exception = getExpectedThrowable(
519 IllegalArgumentException.class,
520 () -> check.setSymbolCodes("0x1F601-0x1F600"));
521 assertWithMessage("Wrong message")
522 .that(exception.getMessage())
523 .contains("Range start must be <=");
524 }
525
526 @Test
527 public void testSingleAndRangeOverlapBehaviour() throws Exception {
528 final String[] expected = {
529 "12:18: " + getCheckMessage(MSG_KEY, "😀"),
530 };
531
532 verifyWithInlineConfigParser(
533 getPath("InputIllegalSymbolOverlap.java"),
534 expected);
535 }
536 }