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.internal.utils.TestUtil.getExpectedThrowable;
24 import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;
25
26 import java.lang.reflect.Field;
27 import java.util.ArrayList;
28 import java.util.Arrays;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Optional;
32 import java.util.TreeMap;
33
34 import org.junit.jupiter.api.Test;
35
36 import com.puppycrawl.tools.checkstyle.DetailAstImpl;
37 import com.puppycrawl.tools.checkstyle.api.DetailAST;
38 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
39
40 public class TokenUtilTest {
41
42 @Test
43 public void testIsProperUtilsClass() throws ReflectiveOperationException {
44 assertWithMessage("Constructor is not private")
45 .that(isUtilsClassHasPrivateConstructor(TokenUtil.class))
46 .isTrue();
47 }
48
49 @Test
50 public void testGetIntFromAccessibleField() throws NoSuchFieldException {
51 final Field field = Integer.class.getField("MAX_VALUE");
52 final int maxValue = TokenUtil.getIntFromField(field, 0);
53
54 assertWithMessage("Invalid getIntFromField result")
55 .that(maxValue)
56 .isEqualTo(Integer.MAX_VALUE);
57 }
58
59 @Test
60 public void testGetIntFromInaccessibleField() throws NoSuchFieldException {
61 final Field field = Integer.class.getDeclaredField("value");
62
63 final IllegalStateException expected =
64 getExpectedThrowable(IllegalStateException.class, () -> {
65 TokenUtil.getIntFromField(field, 0);
66 });
67
68
69
70 final String message = expected.getMessage();
71 assertWithMessage("Invalid exception message: %s", message)
72 .that(message.startsWith("java.lang.IllegalAccessException: ")
73 && message.contains("com.puppycrawl.tools.checkstyle.utils.TokenUtil")
74 && message.contains("access a member of class java.lang.Integer"))
75 .isTrue();
76 }
77
78 @Test
79 public void testNameToValueMapFromPublicIntFields() {
80 final Map<String, Integer> actualMap =
81 TokenUtil.nameToValueMapFromPublicIntFields(Integer.class);
82 final Map<String, Integer> expectedMap = new TreeMap<>();
83 expectedMap.put("BYTES", Integer.BYTES);
84 expectedMap.put("SIZE", Integer.SIZE);
85 expectedMap.put("MAX_VALUE", Integer.MAX_VALUE);
86 expectedMap.put("MIN_VALUE", Integer.MIN_VALUE);
87
88 assertWithMessage("Unexpected name to value map")
89 .that(actualMap)
90 .isEqualTo(expectedMap);
91 }
92
93 @Test
94 public void testInvertMap() {
95 final Map<String, Integer> map = new TreeMap<>();
96 map.put("ZERO", 0);
97 map.put("ONE", 1);
98 map.put("TWO", 2);
99 map.put("NEGATIVE", -1);
100
101 final Map<Integer, String> invertedMap = TokenUtil.invertMap(map);
102
103 assertWithMessage("Key set of 'map' and values of 'invertedMap' should be the same.")
104 .that(invertedMap.values())
105 .containsExactlyElementsIn(map.keySet());
106 assertWithMessage("Values of 'map' and key set of 'invertedMap' should be the same.")
107 .that(invertedMap.keySet())
108 .containsExactlyElementsIn(map.values());
109 }
110
111 @Test
112 public void testTokenValueIncorrect() throws IllegalAccessException {
113 int maxId = 0;
114 final Field[] fields = TokenTypes.class.getDeclaredFields();
115 for (final Field field : fields) {
116 if (field.getType() != Integer.TYPE) {
117 continue;
118 }
119
120 final String name = field.getName();
121 final int id = field.getInt(name);
122 if (id > maxId) {
123 maxId = id;
124 }
125 }
126
127 final int nextAfterMaxId = maxId + 1;
128 final IllegalArgumentException expectedException =
129 getExpectedThrowable(IllegalArgumentException.class, () -> {
130 TokenUtil.getTokenName(nextAfterMaxId);
131 });
132
133 assertWithMessage("Invalid exception message")
134 .that(expectedException.getMessage())
135 .isEqualTo("unknown TokenTypes id '" + nextAfterMaxId + "'");
136 }
137
138 @Test
139 public void testTokenValueCorrect() throws IllegalAccessException {
140 final Field[] fields = TokenTypes.class.getDeclaredFields();
141 for (final Field field : fields) {
142
143 if (field.getType() != Integer.TYPE) {
144 continue;
145 }
146
147 final String name = field.getName();
148 final int id = field.getInt(name);
149
150 assertWithMessage("Invalid token name")
151 .that(TokenUtil.getTokenName(id))
152 .isEqualTo(name);
153 }
154 }
155
156 @Test
157 public void testTokenValueIncorrect2() {
158 final int id = 0;
159 final IllegalArgumentException expected =
160 getExpectedThrowable(IllegalArgumentException.class, () -> {
161 TokenUtil.getTokenName(id);
162 });
163
164 assertWithMessage("Invalid exception message")
165 .that(expected.getMessage())
166 .isEqualTo("unknown TokenTypes id '" + id + "'");
167 }
168
169 @Test
170 public void testTokenIdIncorrect() {
171 final String id = "NON_EXISTENT_VALUE";
172 final IllegalArgumentException expected =
173 getExpectedThrowable(IllegalArgumentException.class, () -> {
174 TokenUtil.getTokenId(id);
175 });
176
177 assertWithMessage("Invalid exception message")
178 .that(expected.getMessage())
179 .isEqualTo("unknown TokenTypes value '" + id + "'");
180 }
181
182 @Test
183 public void testShortDescriptionIncorrect() {
184 final String id = "NON_EXISTENT_VALUE";
185 final IllegalArgumentException expected =
186 getExpectedThrowable(IllegalArgumentException.class, () -> {
187 TokenUtil.getShortDescription(id);
188 });
189
190 assertWithMessage("Invalid exception message")
191 .that(expected.getMessage())
192 .isEqualTo("unknown TokenTypes value '" + id + "'");
193 }
194
195 @Test
196 public void testIsCommentType() {
197 assertWithMessage("Should return true when valid type passed")
198 .that(TokenUtil.isCommentType(TokenTypes.SINGLE_LINE_COMMENT))
199 .isTrue();
200 assertWithMessage("Should return true when valid type passed")
201 .that(TokenUtil.isCommentType(TokenTypes.BLOCK_COMMENT_BEGIN))
202 .isTrue();
203 assertWithMessage("Should return true when valid type passed")
204 .that(TokenUtil.isCommentType(TokenTypes.BLOCK_COMMENT_END))
205 .isTrue();
206 assertWithMessage("Should return true when valid type passed")
207 .that(TokenUtil.isCommentType(TokenTypes.COMMENT_CONTENT))
208 .isTrue();
209 assertWithMessage("Should return true when valid type passed")
210 .that(TokenUtil.isCommentType("COMMENT_CONTENT"))
211 .isTrue();
212 assertWithMessage("Should return false when invalid type passed")
213 .that(TokenUtil.isCommentType(TokenTypes.CLASS_DEF))
214 .isFalse();
215 assertWithMessage("Should return false when invalid type passed")
216 .that(TokenUtil.isCommentType("CLASS_DEF"))
217 .isFalse();
218 }
219
220 @Test
221 public void testGetTokenTypesTotalNumber() {
222 final int tokenTypesTotalNumber = TokenUtil.getTokenTypesTotalNumber();
223
224 assertWithMessage("Invalid token total number")
225 .that(tokenTypesTotalNumber)
226 .isEqualTo(192);
227 }
228
229 @Test
230 public void testGetAllTokenIds() {
231 final int[] allTokenIds = TokenUtil.getAllTokenIds();
232 final int sum = Arrays.stream(allTokenIds).sum();
233
234 assertWithMessage("Invalid token length")
235 .that(allTokenIds.length)
236 .isEqualTo(192);
237 assertWithMessage("invalid sum")
238 .that(sum)
239 .isEqualTo(20501);
240 }
241
242 @Test
243 public void testGetTokenNameWithGreatestPossibleId() {
244 final int id = TokenTypes.COMMENT_CONTENT;
245 final String tokenName = TokenUtil.getTokenName(id);
246
247 assertWithMessage("Invalid token name")
248 .that(tokenName)
249 .isEqualTo("COMMENT_CONTENT");
250 }
251
252 @Test
253 public void testCorrectBehaviourOfGetTokenId() {
254 final String id = "COMPILATION_UNIT";
255
256 assertWithMessage("Invalid token id")
257 .that(TokenUtil.getTokenId(id))
258 .isEqualTo(TokenTypes.COMPILATION_UNIT);
259 }
260
261 @Test
262 public void testCorrectBehaviourOfShortDescription() {
263 final String id = "COMPILATION_UNIT";
264 final String shortDescription = TokenUtil.getShortDescription(id);
265
266 assertWithMessage("Invalid short description")
267 .that(shortDescription)
268 .isEqualTo("This is the root node for the source file.");
269 }
270
271 @Test
272 public void testFindFirstTokenByPredicate() {
273 final DetailAstImpl astForTest = new DetailAstImpl();
274 final DetailAstImpl child = new DetailAstImpl();
275 final DetailAstImpl firstSibling = new DetailAstImpl();
276 final DetailAstImpl secondSibling = new DetailAstImpl();
277 final DetailAstImpl thirdSibling = new DetailAstImpl();
278 firstSibling.setText("first");
279 secondSibling.setText("second");
280 thirdSibling.setText("third");
281 secondSibling.setNextSibling(thirdSibling);
282 firstSibling.setNextSibling(secondSibling);
283 child.setNextSibling(firstSibling);
284 astForTest.setFirstChild(child);
285 final Optional<DetailAST> result = TokenUtil.findFirstTokenByPredicate(astForTest,
286 ast -> "second".equals(ast.getText()));
287
288 assertWithMessage("Invalid second sibling")
289 .that(result.orElseThrow())
290 .isEqualTo(secondSibling);
291 }
292
293 @Test
294 public void testForEachChild() {
295 final DetailAstImpl astForTest = new DetailAstImpl();
296 final DetailAstImpl child = new DetailAstImpl();
297 final DetailAstImpl firstSibling = new DetailAstImpl();
298 final DetailAstImpl secondSibling = new DetailAstImpl();
299 final DetailAstImpl thirdSibling = new DetailAstImpl();
300 firstSibling.setType(TokenTypes.DOT);
301 secondSibling.setType(TokenTypes.CLASS_DEF);
302 thirdSibling.setType(TokenTypes.IDENT);
303 secondSibling.setNextSibling(thirdSibling);
304 firstSibling.setNextSibling(secondSibling);
305 child.setNextSibling(firstSibling);
306 astForTest.setFirstChild(child);
307 final List<DetailAST> children = new ArrayList<>();
308 TokenUtil.forEachChild(astForTest, TokenTypes.CLASS_DEF, children::add);
309 final DetailAST firstChild = children.getFirst();
310
311 assertWithMessage("Must be one match")
312 .that(children)
313 .hasSize(1);
314 assertWithMessage("Mismatched child node")
315 .that(firstChild)
316 .isEqualTo(secondSibling);
317 }
318
319 @Test
320 public void testIsTypeDeclaration() {
321 assertWithMessage("Should return true when valid type passed")
322 .that(TokenUtil.isTypeDeclaration(TokenTypes.CLASS_DEF))
323 .isTrue();
324 assertWithMessage("Should return true when valid type passed")
325 .that(TokenUtil.isTypeDeclaration(TokenTypes.INTERFACE_DEF))
326 .isTrue();
327 assertWithMessage("Should return true when valid type passed")
328 .that(TokenUtil.isTypeDeclaration(TokenTypes.ANNOTATION_DEF))
329 .isTrue();
330 assertWithMessage("Should return true when valid type passed")
331 .that(TokenUtil.isTypeDeclaration(TokenTypes.ENUM_DEF))
332 .isTrue();
333 assertWithMessage("Should return true when valid type passed")
334 .that(TokenUtil.isTypeDeclaration(TokenTypes.RECORD_DEF))
335 .isTrue();
336 }
337
338 @Test
339 public void testIsOfTypeTrue() {
340 final int type = TokenTypes.LITERAL_CATCH;
341 final DetailAstImpl astForTest = new DetailAstImpl();
342 astForTest.setType(type);
343 final boolean result1 = TokenUtil.isOfType(type, TokenTypes.LITERAL_FOR,
344 TokenTypes.LITERAL_IF, TokenTypes.LITERAL_CATCH);
345 final boolean result2 = TokenUtil.isOfType(astForTest, TokenTypes.LITERAL_FOR,
346 TokenTypes.LITERAL_IF, TokenTypes.LITERAL_CATCH);
347
348 assertWithMessage("Token type did not match")
349 .that(result1)
350 .isTrue();
351 assertWithMessage("Token type did not match")
352 .that(result2)
353 .isTrue();
354 }
355
356 @Test
357 public void testIsOfTypeFalse() {
358 final int type = TokenTypes.LITERAL_CATCH;
359 final DetailAstImpl astForTest1 = new DetailAstImpl();
360 final DetailAstImpl astForTest2 = null;
361 astForTest1.setType(type);
362 final boolean result1 = TokenUtil.isOfType(type, TokenTypes.LITERAL_FOR,
363 TokenTypes.LITERAL_IF, TokenTypes.LITERAL_ELSE);
364 final boolean result2 = TokenUtil.isOfType(astForTest1, TokenTypes.LITERAL_FOR,
365 TokenTypes.LITERAL_IF, TokenTypes.LITERAL_ELSE);
366 final boolean result3 = TokenUtil.isOfType(astForTest2, TokenTypes.LITERAL_FOR,
367 TokenTypes.LITERAL_IF, TokenTypes.LITERAL_ELSE);
368
369 assertWithMessage("Token type should not match")
370 .that(result1)
371 .isFalse();
372 assertWithMessage("Token type should not match")
373 .that(result2)
374 .isFalse();
375 assertWithMessage("Token type should not match")
376 .that(result3)
377 .isFalse();
378 }
379
380 @Test
381 public void testIsBooleanLiteralType() {
382 assertWithMessage("Result is not expected")
383 .that(TokenUtil.isBooleanLiteralType(TokenTypes.LITERAL_TRUE))
384 .isTrue();
385 assertWithMessage("Result is not expected")
386 .that(TokenUtil.isBooleanLiteralType(TokenTypes.LITERAL_FALSE))
387 .isTrue();
388 assertWithMessage("Result is not expected")
389 .that(TokenUtil.isBooleanLiteralType(TokenTypes.LOR))
390 .isFalse();
391 }
392
393 }