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.metrics;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23 import static com.puppycrawl.tools.checkstyle.checks.metrics.ClassFanOutComplexityCheck.MSG_KEY;
24
25 import java.io.File;
26 import java.util.Collection;
27 import java.util.Map;
28 import java.util.Optional;
29
30 import org.junit.jupiter.api.Test;
31
32 import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
33 import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
34 import com.puppycrawl.tools.checkstyle.JavaParser;
35 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
36 import com.puppycrawl.tools.checkstyle.api.DetailAST;
37 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
38 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
39 import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
40
41 public class ClassFanOutComplexityCheckTest extends AbstractModuleTestSupport {
42
43 @Override
44 protected String getPackageLocation() {
45 return "com/puppycrawl/tools/checkstyle/checks/metrics/classfanoutcomplexity";
46 }
47
48 @Test
49 public void test() throws Exception {
50
51 final String[] expected = {
52 "27:1: " + getCheckMessage(MSG_KEY, 3, 0),
53 "59:1: " + getCheckMessage(MSG_KEY, 1, 0),
54 };
55
56 verifyWithInlineConfigParser(
57 getPath("InputClassFanOutComplexity.java"), expected);
58 }
59
60 @Test
61 public void testExcludedPackagesDirectPackages() throws Exception {
62 final String[] expected = {
63 "29:1: " + getCheckMessage(MSG_KEY, 2, 0),
64 };
65
66 verifyWithInlineConfigParser(
67 getPath("InputClassFanOutComplexityExcludedPackagesDirectPackages.java"), expected);
68 }
69
70 @Test
71 public void testExcludedPackagesCommonPackages() throws Exception {
72 final String[] expected = {
73 "28:1: " + getCheckMessage(MSG_KEY, 2, 0),
74 "32:5: " + getCheckMessage(MSG_KEY, 2, 0),
75 "38:1: " + getCheckMessage(MSG_KEY, 1, 0),
76 };
77 verifyWithInlineConfigParser(
78 getPath("InputClassFanOutComplexityExcludedPackagesCommonPackage.java"), expected);
79 }
80
81 @Test
82 public void testExcludedPackagesCommonPackagesWithEndingDot() throws Exception {
83 final DefaultConfiguration checkConfig =
84 createModuleConfig(ClassFanOutComplexityCheck.class);
85
86 checkConfig.addProperty("max", "0");
87 checkConfig.addProperty("excludedPackages",
88 "com.puppycrawl.tools.checkstyle.checks.metrics.inputs.a.");
89
90 try {
91 createChecker(checkConfig);
92 assertWithMessage("exception expected").fail();
93 }
94 catch (CheckstyleException exc) {
95 assertWithMessage("Invalid exception message")
96 .that(exc.getMessage())
97 .isEqualTo("cannot initialize module com.puppycrawl.tools.checkstyle.TreeWalker - "
98 + "cannot initialize module com.puppycrawl.tools.checkstyle.checks."
99 + "metrics.ClassFanOutComplexityCheck - "
100 + "Cannot set property 'excludedPackages' to "
101 + "'com.puppycrawl.tools.checkstyle.checks.metrics.inputs.a.'");
102 assertWithMessage("Invalid exception message,")
103 .that(exc.getCause().getCause().getCause().getCause().getMessage())
104 .isEqualTo("the following values are not valid identifiers: ["
105 + "com.puppycrawl.tools.checkstyle.checks.metrics.inputs.a.]");
106 }
107 }
108
109 @Test
110 public void testExcludedPackagesAllIgnored() throws Exception {
111 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
112 verifyWithInlineConfigParser(
113 getPath("InputClassFanOutComplexityExcludedPackagesAllIgnored.java"), expected);
114 }
115
116 @Test
117 public void test15() throws Exception {
118
119 final String[] expected = {
120 "29:1: " + getCheckMessage(MSG_KEY, 1, 0),
121 };
122
123 verifyWithInlineConfigParser(
124 getPath("InputClassFanOutComplexity15Extensions.java"), expected);
125 }
126
127 @Test
128 public void testDefaultConfiguration() throws Exception {
129 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
130 verifyWithInlineConfigParser(
131 getPath("InputClassFanOutComplexity2.java"), expected);
132 }
133
134 @Test
135 public void testGetAcceptableTokens() {
136 final ClassFanOutComplexityCheck classFanOutComplexityCheckObj =
137 new ClassFanOutComplexityCheck();
138 final int[] actual = classFanOutComplexityCheckObj.getAcceptableTokens();
139 final int[] expected = {
140 TokenTypes.PACKAGE_DEF,
141 TokenTypes.IMPORT,
142 TokenTypes.CLASS_DEF,
143 TokenTypes.EXTENDS_CLAUSE,
144 TokenTypes.IMPLEMENTS_CLAUSE,
145 TokenTypes.ANNOTATION,
146 TokenTypes.INTERFACE_DEF,
147 TokenTypes.ENUM_DEF,
148 TokenTypes.TYPE,
149 TokenTypes.LITERAL_NEW,
150 TokenTypes.LITERAL_THROWS,
151 TokenTypes.ANNOTATION_DEF,
152 TokenTypes.RECORD_DEF,
153 };
154 assertWithMessage("Acceptable tokens should not be null")
155 .that(actual)
156 .isNotNull();
157 assertWithMessage("Invalid acceptable tokens")
158 .that(actual)
159 .isEqualTo(expected);
160 }
161
162 @Test
163 public void testRegularExpression() throws Exception {
164
165 final String[] expected = {
166 "44:1: " + getCheckMessage(MSG_KEY, 2, 0),
167 "76:1: " + getCheckMessage(MSG_KEY, 1, 0),
168 };
169
170 verifyWithInlineConfigParser(
171 getPath("InputClassFanOutComplexity3.java"), expected);
172 }
173
174 @Test
175 public void testEmptyRegularExpression() throws Exception {
176
177 final String[] expected = {
178 "44:1: " + getCheckMessage(MSG_KEY, 3, 0),
179 "76:1: " + getCheckMessage(MSG_KEY, 1, 0),
180 };
181
182 verifyWithInlineConfigParser(
183 getPath("InputClassFanOutComplexity4.java"), expected);
184 }
185
186 @Test
187 public void testWithMultiDimensionalArray() throws Exception {
188
189 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
190 verifyWithInlineConfigParser(
191 getPath("InputClassFanOutComplexityMultiDimensionalArray.java"), expected);
192 }
193
194 @Test
195 public void testPackageName() throws Exception {
196
197 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
198 verifyWithInlineConfigParser(
199 getPath("InputClassFanOutComplexityPackageName.java"), expected);
200 }
201
202 @Test
203 public void testExtends() throws Exception {
204 final String[] expected = {
205 "23:1: " + getCheckMessage(MSG_KEY, 1, 0),
206 };
207 verifyWithInlineConfigParser(
208 getPath("InputClassFanOutComplexityExtends.java"), expected);
209 }
210
211 @Test
212 public void testImplements() throws Exception {
213 final String[] expected = {
214 "23:1: " + getCheckMessage(MSG_KEY, 1, 0),
215 };
216 verifyWithInlineConfigParser(
217 getPath("InputClassFanOutComplexityImplements.java"), expected);
218 }
219
220 @Test
221 public void testAnnotation() throws Exception {
222 final String[] expected = {
223 "29:1: " + getCheckMessage(MSG_KEY, 2, 0),
224 "45:5: " + getCheckMessage(MSG_KEY, 2, 0),
225 "54:5: " + getCheckMessage(MSG_KEY, 3, 0),
226 "64:5: " + getCheckMessage(MSG_KEY, 2, 0),
227 "79:1: " + getCheckMessage(MSG_KEY, 1, 0),
228 "99:1: " + getCheckMessage(MSG_KEY, 1, 0),
229 "102:1: " + getCheckMessage(MSG_KEY, 1, 0),
230 };
231 verifyWithInlineConfigParser(
232 getPath("InputClassFanOutComplexityAnnotations.java"), expected);
233 }
234
235 @Test
236 public void testImplementsAndNestedCount() throws Exception {
237 final String[] expected = {
238 "26:1: " + getCheckMessage(MSG_KEY, 3, 0),
239 };
240 verifyWithInlineConfigParser(
241 getPath("InputClassFanOutComplexityImplementsAndNestedCount.java"), expected);
242 }
243
244 @Test
245 public void testClassFanOutComplexityRecords() throws Exception {
246 final String[] expected = {
247 "32:1: " + getCheckMessage(MSG_KEY, 4, 2),
248 "53:1: " + getCheckMessage(MSG_KEY, 4, 2),
249 };
250 verifyWithInlineConfigParser(
251 getPath("InputClassFanOutComplexityRecords.java"), expected);
252 }
253
254 @Test
255 public void testClassFanOutComplexityIgnoreVar() throws Exception {
256 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
257 verifyWithInlineConfigParser(
258 getPath("InputClassFanOutComplexityVar.java"), expected);
259 }
260
261 @Test
262 public void testClassFanOutComplexityRemoveIncorrectAnnotationToken() throws Exception {
263 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
264 verifyWithInlineConfigParser(
265 getNonCompilablePath(
266 "InputClassFanOutComplexityRemoveIncorrectAnnotationToken.java"), expected);
267 }
268
269 @Test
270 public void testClassFanOutComplexityRemoveIncorrectTypeParameter() throws Exception {
271 final String[] expected = CommonUtil.EMPTY_STRING_ARRAY;
272 verifyWithInlineConfigParser(
273 getPath("InputClassFanOutComplexityRemoveIncorrectTypeParameter.java"), expected);
274 }
275
276 @Test
277 public void testClassFanOutComplexityMultiCatchBitwiseOr() throws Exception {
278 final String[] expected = {
279 "27:1: " + getCheckMessage(MSG_KEY, 5, 4),
280 };
281
282 verifyWithInlineConfigParser(
283 getPath("InputClassFanOutComplexityMultiCatchBitwiseOr.java"), expected);
284 }
285
286 @Test
287 public void testThrows() throws Exception {
288 final String[] expected = {
289 "25:1: " + getCheckMessage(MSG_KEY, 2, 0),
290 };
291
292 verifyWithInlineConfigParser(
293 getPath("InputClassFanOutComplexityThrows.java"), expected);
294 }
295
296 @Test
297 public void testSealedClasses() throws Exception {
298 final String[] expected = {
299 "25:1: " + getCheckMessage(MSG_KEY, 2, 0),
300 "32:1: " + getCheckMessage(MSG_KEY, 1, 0),
301 };
302
303 verifyWithInlineConfigParser(
304 getPath("InputClassFanOutComplexitySealedClasses.java"),
305 expected);
306 }
307
308
309
310
311
312
313
314
315 @Test
316 @SuppressWarnings("unchecked")
317 public void testClearStateImportedClassPackages() throws Exception {
318 final ClassFanOutComplexityCheck check = new ClassFanOutComplexityCheck();
319 final DetailAST root = JavaParser.parseFile(
320 new File(getPath("InputClassFanOutComplexity.java")),
321 JavaParser.Options.WITHOUT_COMMENTS);
322 final Optional<DetailAST> importAst = TestUtil.findTokenInAstByPredicate(root,
323 ast -> ast.getType() == TokenTypes.IMPORT);
324
325 assertWithMessage("Ast should contain IMPORT")
326 .that(importAst.isPresent())
327 .isTrue();
328 assertWithMessage("State is not cleared on beginTree")
329 .that(TestUtil.isStatefulFieldClearedDuringBeginTree(check,
330 importAst.orElseThrow(), "importedClassPackages",
331 importedClssPackage -> ((Map<String, String>) importedClssPackage).isEmpty()))
332 .isTrue();
333 }
334
335
336
337
338
339
340
341
342 @Test
343 public void testClearStateClassContexts() throws Exception {
344 final ClassFanOutComplexityCheck check = new ClassFanOutComplexityCheck();
345 final DetailAST root = JavaParser.parseFile(
346 new File(getPath("InputClassFanOutComplexity.java")),
347 JavaParser.Options.WITHOUT_COMMENTS);
348 final Optional<DetailAST> classDef = TestUtil.findTokenInAstByPredicate(root,
349 ast -> ast.getType() == TokenTypes.CLASS_DEF);
350
351 assertWithMessage("Ast should contain CLASS_DEF")
352 .that(classDef.isPresent())
353 .isTrue();
354 assertWithMessage("State is not cleared on beginTree")
355 .that(TestUtil.isStatefulFieldClearedDuringBeginTree(check, classDef.orElseThrow(),
356 "classesContexts",
357 classContexts -> ((Collection<?>) classContexts).size() == 1))
358 .isTrue();
359 }
360
361
362
363
364
365
366
367
368 @Test
369 public void testClearStatePackageName() throws Exception {
370 final ClassFanOutComplexityCheck check = new ClassFanOutComplexityCheck();
371 final DetailAST root = JavaParser.parseFile(
372 new File(getPath("InputClassFanOutComplexity.java")),
373 JavaParser.Options.WITHOUT_COMMENTS);
374 final Optional<DetailAST> packageDef = TestUtil.findTokenInAstByPredicate(root,
375 ast -> ast.getType() == TokenTypes.PACKAGE_DEF);
376
377 assertWithMessage("Ast should contain PACKAGE_DEF")
378 .that(packageDef.isPresent())
379 .isTrue();
380 assertWithMessage("State is not cleared on beginTree")
381 .that(TestUtil.isStatefulFieldClearedDuringBeginTree(check,
382 packageDef.orElseThrow(), "packageName",
383 packageName -> ((CharSequence) packageName).isEmpty()))
384 .isTrue();
385 }
386
387
388
389
390
391
392
393 @Test
394 public void testLambdaNew() throws Exception {
395 final String[] expected = {
396 "28:1: " + getCheckMessage(MSG_KEY, 2, 0),
397 };
398 verifyWithInlineConfigParser(
399 getPath("InputClassFanOutComplexityLambdaNew.java"), expected);
400 }
401
402 }