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