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.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck.MSG_EQUALS_AVOID_NULL;
24 import static com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck.MSG_MULTIPLE;
25 import static com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck.MSG_KEY;
26 import static com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck.MSG_EXPECTED_TAG;
27 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.findTokenInAstByPredicate;
28 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
29
30 import java.io.File;
31 import java.util.Arrays;
32 import java.util.HashSet;
33 import java.util.List;
34 import java.util.Optional;
35 import java.util.Set;
36
37 import org.junit.jupiter.api.Test;
38
39 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
40 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
41 import com.puppycrawl.tools.checkstyle.JavaParser;
42 import com.puppycrawl.tools.checkstyle.api.DetailAST;
43 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
44 import com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck;
45 import com.puppycrawl.tools.checkstyle.checks.coding.MultipleVariableDeclarationsCheck;
46 import com.puppycrawl.tools.checkstyle.checks.coding.NestedIfDepthCheck;
47 import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocMethodCheck;
48 import com.puppycrawl.tools.checkstyle.checks.naming.AccessModifierOption;
49
50 public class CheckUtilTest extends AbstractModuleTestSupport {
51
52 @Override
53 protected String getPackageLocation() {
54 return "com/puppycrawl/tools/checkstyle/utils/checkutil";
55 }
56
57 @Test
58 public void testIsProperUtilsClass() throws ReflectiveOperationException {
59 assertWithMessage("Constructor is not private")
60 .that(isUtilsClassHasPrivateConstructor(CheckUtil.class))
61 .isTrue();
62 }
63
64 @Test
65 public void testParseDoubleWithIncorrectToken() {
66 final double parsedDouble = CheckUtil.parseDouble("1_02", TokenTypes.ASSIGN);
67 assertWithMessage("Invalid parse result")
68 .that(parsedDouble)
69 .isEqualTo(Double.NaN);
70 }
71
72 @Test
73 public void testEquals() {
74 final DetailAstImpl litStatic = new DetailAstImpl();
75 litStatic.setType(TokenTypes.LITERAL_STATIC);
76
77 final DetailAstImpl modifiers = new DetailAstImpl();
78 modifiers.setType(TokenTypes.MODIFIERS);
79 modifiers.addChild(litStatic);
80
81 final DetailAstImpl metDef = new DetailAstImpl();
82 metDef.setType(TokenTypes.METHOD_DEF);
83 metDef.addChild(modifiers);
84
85 assertWithMessage("Invalid result: ast is not equals method")
86 .that(CheckUtil.isEqualsMethod(metDef))
87 .isFalse();
88
89 metDef.removeChildren();
90
91 final DetailAstImpl metName = new DetailAstImpl();
92 metName.setType(TokenTypes.IDENT);
93 metName.setText("equals");
94 metDef.addChild(metName);
95
96 final DetailAstImpl modifiers2 = new DetailAstImpl();
97 modifiers2.setType(TokenTypes.MODIFIERS);
98 metDef.addChild(modifiers2);
99
100 final DetailAstImpl parameter1 = new DetailAstImpl();
101 final DetailAstImpl parameter2 = new DetailAstImpl();
102
103 final DetailAstImpl parameters = new DetailAstImpl();
104 parameters.setType(TokenTypes.PARAMETERS);
105
106 parameters.addChild(parameter2);
107
108 parameters.addChild(parameter1);
109 metDef.addChild(parameters);
110
111 assertWithMessage("Invalid result: ast is not equals method")
112 .that(CheckUtil.isEqualsMethod(metDef))
113 .isFalse();
114 }
115
116 @Test
117 public void testGetAccessModifierFromModifiersTokenWrongTokenType() {
118 final DetailAstImpl modifiers = new DetailAstImpl();
119 modifiers.setType(TokenTypes.METHOD_DEF);
120
121 try {
122 CheckUtil.getAccessModifierFromModifiersToken(modifiers);
123 assertWithMessage("%s was expected.", IllegalArgumentException.class.getSimpleName())
124 .fail();
125 }
126 catch (IllegalArgumentException exc) {
127 final String expectedExceptionMsg = "expected non-null AST-token with type 'MODIFIERS'";
128 final String actualExceptionMsg = exc.getMessage();
129 assertWithMessage("Invalid exception message")
130 .that(actualExceptionMsg)
131 .isEqualTo(expectedExceptionMsg);
132 }
133 }
134
135 @Test
136 public void testGetTypeParameterNames() throws Exception {
137 final DetailAST parameterizedClassNode = getNodeFromFile(TokenTypes.CLASS_DEF);
138 final List<String> expected = Arrays.asList("V", "C");
139 final List<String> actual = CheckUtil.getTypeParameterNames(parameterizedClassNode);
140
141 assertWithMessage("Invalid type parameters")
142 .that(actual)
143 .isEqualTo(expected);
144 }
145
146 @Test
147 public void testGetTypeParameters() throws Exception {
148 final DetailAST parameterizedClassNode = getNodeFromFile(TokenTypes.CLASS_DEF);
149 final DetailAST firstTypeParameter =
150 getNode(parameterizedClassNode, TokenTypes.TYPE_PARAMETER);
151 final List<DetailAST> expected = Arrays.asList(firstTypeParameter,
152 firstTypeParameter.getNextSibling().getNextSibling());
153 final List<DetailAST> actual = CheckUtil.getTypeParameters(parameterizedClassNode);
154
155 assertWithMessage("Invalid type parameters")
156 .that(actual)
157 .isEqualTo(expected);
158 }
159
160 @Test
161 public void testIsEqualsMethod() throws Exception {
162 final DetailAST equalsMethodNode = getNodeFromFile(TokenTypes.METHOD_DEF);
163 final DetailAST someOtherMethod = equalsMethodNode.getNextSibling();
164
165 assertWithMessage("Invalid result: AST provided is not equals method")
166 .that(CheckUtil.isEqualsMethod(equalsMethodNode))
167 .isTrue();
168 assertWithMessage("Invalid result: AST provided is equals method")
169 .that(CheckUtil.isEqualsMethod(someOtherMethod))
170 .isFalse();
171 }
172
173 @Test
174 public void testIsNonVoidMethod() throws Exception {
175 final DetailAST nonVoidMethod = getNodeFromFile(TokenTypes.METHOD_DEF);
176 final DetailAST voidMethod = nonVoidMethod.getNextSibling();
177
178 assertWithMessage("Invalid result: AST provided is void method")
179 .that(CheckUtil.isNonVoidMethod(nonVoidMethod))
180 .isTrue();
181 assertWithMessage("Invalid result: AST provided is non void method")
182 .that(CheckUtil.isNonVoidMethod(voidMethod))
183 .isFalse();
184 }
185
186 @Test
187 public void testGetAccessModifierFromModifiersToken() throws Exception {
188 final DetailAST interfaceDef = getNodeFromFile(TokenTypes.INTERFACE_DEF);
189 final AccessModifierOption modifierInterface = CheckUtil
190 .getAccessModifierFromModifiersToken(interfaceDef
191 .findFirstToken(TokenTypes.OBJBLOCK)
192 .findFirstToken(TokenTypes.METHOD_DEF));
193 assertWithMessage("Invalid access modifier")
194 .that(modifierInterface)
195 .isEqualTo(AccessModifierOption.PUBLIC);
196
197 final DetailAST privateVariable = getNodeFromFile(TokenTypes.VARIABLE_DEF);
198 final AccessModifierOption modifierPrivate =
199 CheckUtil.getAccessModifierFromModifiersToken(privateVariable);
200 assertWithMessage("Invalid access modifier")
201 .that(modifierPrivate)
202 .isEqualTo(AccessModifierOption.PRIVATE);
203
204 final DetailAST protectedVariable = privateVariable.getNextSibling();
205 final AccessModifierOption modifierProtected =
206 CheckUtil.getAccessModifierFromModifiersToken(protectedVariable);
207 assertWithMessage("Invalid access modifier")
208 .that(modifierProtected)
209 .isEqualTo(AccessModifierOption.PROTECTED);
210
211 final DetailAST publicVariable = protectedVariable.getNextSibling();
212 final AccessModifierOption modifierPublic =
213 CheckUtil.getAccessModifierFromModifiersToken(publicVariable);
214 assertWithMessage("Invalid access modifier")
215 .that(modifierPublic)
216 .isEqualTo(AccessModifierOption.PUBLIC);
217
218 final DetailAST packageVariable = publicVariable.getNextSibling();
219 final AccessModifierOption modifierPackage =
220 CheckUtil.getAccessModifierFromModifiersToken(packageVariable);
221 assertWithMessage("Invalid access modifier")
222 .that(modifierPackage)
223 .isEqualTo(AccessModifierOption.PACKAGE);
224 }
225
226 @Test
227 public void testGetFirstNode() throws Exception {
228 final DetailAST classDef = getNodeFromFile(TokenTypes.CLASS_DEF);
229
230 final DetailAST firstChild = classDef.getFirstChild().getFirstChild();
231 final DetailAST firstNode = CheckUtil.getFirstNode(classDef);
232 assertWithMessage("Invalid first node")
233 .that(firstNode)
234 .isEqualTo(firstChild);
235 }
236
237 @Test
238 public void testGetFirstNode1() {
239 final DetailAstImpl child = new DetailAstImpl();
240 child.setLineNo(5);
241 child.setColumnNo(6);
242
243 final DetailAstImpl root = new DetailAstImpl();
244 root.setLineNo(5);
245 root.setColumnNo(6);
246
247 root.addChild(child);
248
249 final DetailAST firstNode = CheckUtil.getFirstNode(root);
250 assertWithMessage("Unexpected node")
251 .that(firstNode)
252 .isEqualTo(root);
253 }
254
255 @Test
256 public void testGetFirstNode2() {
257 final DetailAstImpl child = new DetailAstImpl();
258 child.setLineNo(6);
259 child.setColumnNo(5);
260
261 final DetailAstImpl root = new DetailAstImpl();
262 root.setLineNo(5);
263 root.setColumnNo(6);
264
265 root.addChild(child);
266
267 final DetailAST firstNode = CheckUtil.getFirstNode(root);
268 assertWithMessage("Unexpected node")
269 .that(firstNode)
270 .isEqualTo(root);
271 }
272
273 @Test
274 public void testParseDoubleFloatingPointValues() {
275 assertWithMessage("Invalid parse result")
276 .that(CheckUtil.parseDouble("-0.05f", TokenTypes.NUM_FLOAT))
277 .isEqualTo(-0.05);
278 assertWithMessage("Invalid parse result")
279 .that(CheckUtil.parseDouble("10.0", TokenTypes.NUM_DOUBLE))
280 .isEqualTo(10.0);
281 assertWithMessage("Invalid parse result")
282 .that(CheckUtil.parseDouble("1.23e3", TokenTypes.NUM_DOUBLE))
283 .isEqualTo(1230);
284 assertWithMessage("Invalid parse result")
285 .that(CheckUtil.parseDouble("-3.21E2", TokenTypes.NUM_DOUBLE))
286 .isEqualTo(-321);
287 assertWithMessage("Invalid parse result")
288 .that(CheckUtil.parseDouble("-0.0", TokenTypes.NUM_DOUBLE))
289 .isEqualTo(-0.0);
290 assertWithMessage("Invalid parse result")
291 .that(CheckUtil.parseDouble("NaN", TokenTypes.NUM_DOUBLE))
292 .isEqualTo(Double.NaN);
293 }
294
295 @Test
296 public void testParseDoubleIntegerValues() {
297 assertWithMessage("Invalid parse result")
298 .that(CheckUtil.parseDouble("0L", TokenTypes.NUM_LONG))
299 .isEqualTo(0.0);
300 assertWithMessage("Invalid parse result")
301 .that(CheckUtil.parseDouble("0B101", TokenTypes.NUM_INT))
302 .isEqualTo(0b101);
303 assertWithMessage("Invalid parse result")
304 .that(CheckUtil.parseDouble("0b10001010001011010000101000101L", TokenTypes.NUM_LONG))
305 .isEqualTo(289_775_941);
306 assertWithMessage("Invalid parse result")
307 .that(CheckUtil.parseDouble("1", TokenTypes.NUM_INT))
308 .isEqualTo(1.0);
309 assertWithMessage("Invalid parse result")
310 .that(CheckUtil.parseDouble("8L", TokenTypes.NUM_LONG))
311 .isEqualTo(8.0);
312 assertWithMessage("Invalid parse result")
313 .that(CheckUtil.parseDouble("-21474836480", TokenTypes.NUM_LONG))
314 .isEqualTo(-2.147_483_648E10);
315 assertWithMessage("Invalid parse result")
316 .that(CheckUtil.parseDouble("-2", TokenTypes.NUM_INT))
317 .isEqualTo(-2);
318 assertWithMessage("Invalid parse result")
319 .that(CheckUtil.parseDouble("0xffffffff", TokenTypes.NUM_INT))
320 .isEqualTo(-1);
321 assertWithMessage("Invalid parse result")
322 .that(CheckUtil.parseDouble("0x0B63", TokenTypes.NUM_INT))
323 .isEqualTo(2915.0);
324 assertWithMessage("Invalid parse result")
325 .that(CheckUtil.parseDouble("21474836470", TokenTypes.NUM_LONG))
326 .isEqualTo(2.147_483_647E10);
327 assertWithMessage("Invalid parse result")
328 .that(CheckUtil.parseDouble("073l", TokenTypes.NUM_LONG))
329 .isEqualTo(59.0);
330 }
331
332 @Test
333 public void testParseClassNames() {
334 final Set<String> actual = CheckUtil.parseClassNames(
335 "I.am.class.name.with.dot.in.the.end.", "ClassOnly", "my.Class");
336 final Set<String> expected = new HashSet<>();
337 expected.add("I.am.class.name.with.dot.in.the.end.");
338 expected.add("ClassOnly");
339 expected.add("my.Class");
340 expected.add("Class");
341 assertWithMessage("Result is not expected")
342 .that(actual)
343 .isEqualTo(expected);
344 }
345
346 @Test
347 public void testEqualsAvoidNullCheck() throws Exception {
348
349 final String[] expected = {
350 "14:28: " + getCheckMessage(EqualsAvoidNullCheck.class, MSG_EQUALS_AVOID_NULL),
351 "21:17: " + getCheckMessage(EqualsAvoidNullCheck.class, MSG_EQUALS_AVOID_NULL),
352 };
353 verifyWithInlineConfigParser(
354 getPath("InputCheckUtil1.java"), expected);
355 }
356
357 @Test
358 public void testMultipleVariableDeclarationsCheck() throws Exception {
359 final String[] expected = {
360 "11:5: " + getCheckMessage(MultipleVariableDeclarationsCheck.class, MSG_MULTIPLE),
361 "14:5: " + getCheckMessage(MultipleVariableDeclarationsCheck.class, MSG_MULTIPLE),
362 };
363 verifyWithInlineConfigParser(
364 getPath("InputCheckUtil2.java"),
365 expected);
366 }
367
368 @Test
369 public void testNestedIfDepth() throws Exception {
370 final String[] expected = {
371 "26:17: " + getCheckMessage(NestedIfDepthCheck.class, MSG_KEY, 2, 1),
372 "52:17: " + getCheckMessage(NestedIfDepthCheck.class, MSG_KEY, 2, 1),
373 };
374 verifyWithInlineConfigParser(
375 getPath("InputCheckUtil3.java"), expected);
376 }
377
378 @Test
379 public void testJavaDocMethod() throws Exception {
380 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
381 verifyWithInlineConfigParser(
382 getPath("InputCheckUtil4.java"), expected);
383 }
384
385 @Test
386 public void testJavaDocMethod2() throws Exception {
387 final String[] expected = {
388 "14:25: " + getCheckMessage(JavadocMethodCheck.class,
389 MSG_EXPECTED_TAG, "@param", "i"),
390 };
391 verifyWithInlineConfigParser(
392 getPath("InputCheckUtil5.java"), expected);
393 }
394
395 @Test
396 public void testJavadoc() throws Exception {
397 final String[] expected = {
398 "25:39: " + getCheckMessage(JavadocMethodCheck.class,
399 MSG_EXPECTED_TAG, "@param", "i"),
400 };
401 verifyWithInlineConfigParser(
402 getPath("InputCheckUtil7.java"), expected);
403 }
404
405 private DetailAST getNodeFromFile(int type) throws Exception {
406 return getNode(JavaParser.parseFile(new File(getPath("InputCheckUtilTest.java")),
407 JavaParser.Options.WITH_COMMENTS), type);
408 }
409
410
411
412
413
414
415
416
417
418
419 public static DetailAST getNode(File file, int type) throws Exception {
420 return getNode(JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS), type);
421 }
422
423
424
425
426
427
428
429
430 private static DetailAST getNode(DetailAST root, int type) {
431 final Optional<DetailAST> node = findTokenInAstByPredicate(root,
432 ast -> ast.getType() == type);
433
434 assertWithMessage("Cannot find node of specified type: %s", type)
435 .that(node.isPresent())
436 .isTrue();
437
438 return node.orElseThrow();
439 }
440 }