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