1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 package com.qulice.checkstyle;
32
33 import com.puppycrawl.tools.checkstyle.Checker;
34 import com.puppycrawl.tools.checkstyle.ConfigurationLoader;
35 import com.puppycrawl.tools.checkstyle.PropertiesExpander;
36 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
37 import com.puppycrawl.tools.checkstyle.api.AuditListener;
38 import java.io.File;
39 import java.nio.charset.StandardCharsets;
40 import java.util.ArrayList;
41 import java.util.LinkedList;
42 import java.util.List;
43 import java.util.Properties;
44 import java.util.stream.Stream;
45 import org.apache.commons.io.IOUtils;
46 import org.cactoos.text.Joined;
47 import org.hamcrest.MatcherAssert;
48 import org.hamcrest.Matchers;
49 import org.junit.jupiter.params.ParameterizedTest;
50 import org.junit.jupiter.params.provider.MethodSource;
51 import org.mockito.Mockito;
52 import org.mockito.invocation.InvocationOnMock;
53 import org.mockito.stubbing.Answer;
54 import org.xml.sax.InputSource;
55
56
57
58
59
60 final class ChecksTest {
61
62
63
64
65
66
67 @ParameterizedTest
68 @MethodSource("checks")
69 @SuppressWarnings("PMD.JUnitAssertionsShouldIncludeMessage")
70 void testCheckstyleTruePositive(final String dir) throws Exception {
71 final AuditListener listener = Mockito.mock(AuditListener.class);
72 final Collector collector = new ChecksTest.Collector();
73 Mockito.doAnswer(collector).when(listener)
74 .addError(Mockito.any(AuditEvent.class));
75 this.check(dir, "/Invalid.java", listener);
76 final String[] violations = IOUtils.toString(
77 this.getClass().getResourceAsStream(
78 String.format("%s/violations.txt", dir)
79 ),
80 StandardCharsets.UTF_8
81 ).split("\n");
82 for (final String line : violations) {
83 final String[] sectors = line.split(":");
84 final Integer pos = Integer.valueOf(sectors[0]);
85 final String needle = sectors[1].trim();
86 MatcherAssert.assertThat(
87 collector.has(pos, needle),
88 Matchers.describedAs(
89 String.format(
90 "Line no.%d ('%s') not reported by %s: '%s'",
91 pos,
92 needle,
93 dir,
94 collector.summary()
95 ),
96 Matchers.is(true)
97 )
98 );
99 }
100 MatcherAssert.assertThat(
101 collector.eventCount(),
102 Matchers.describedAs(
103 String.format(
104 "Got more violations that expected for directory %s (%s)",
105 dir, collector.summary()
106 ),
107 Matchers.equalTo(violations.length)
108 )
109 );
110 }
111
112
113
114
115
116
117 @ParameterizedTest
118 @MethodSource("checks")
119 void testCheckstyleTrueNegative(final String dir) throws Exception {
120 final AuditListener listener = Mockito.mock(AuditListener.class);
121 final Collector collector = new ChecksTest.Collector();
122 Mockito.doAnswer(collector).when(listener)
123 .addError(Mockito.any(AuditEvent.class));
124 this.check(dir, "/Valid.java", listener);
125 MatcherAssert.assertThat(
126 "Log should be empty for valid files",
127 collector.summary(),
128 Matchers.equalTo("")
129 );
130 Mockito.verify(listener, Mockito.times(0))
131 .addError(Mockito.any(AuditEvent.class));
132 }
133
134
135
136
137
138
139
140
141 private void check(
142 final String dir, final String name, final AuditListener listener
143 ) throws Exception {
144 final Checker checker = new Checker();
145 final InputSource src = new InputSource(
146 this.getClass().getResourceAsStream(
147 String.format("%s/config.xml", dir)
148 )
149 );
150 checker.setModuleClassLoader(
151 Thread.currentThread().getContextClassLoader()
152 );
153 checker.configure(
154 ConfigurationLoader.loadConfiguration(
155 src,
156 new PropertiesExpander(new Properties()),
157 ConfigurationLoader.IgnoredModulesOptions.OMIT
158 )
159 );
160 final List<File> files = new ArrayList<>(0);
161 files.add(
162 new File(
163 this.getClass().getResource(
164 String.format("%s%s", dir, name)
165 ).getFile()
166 )
167 );
168 checker.addListener(listener);
169 checker.process(files);
170 checker.destroy();
171 }
172
173
174
175
176
177 @SuppressWarnings("PMD.UnusedPrivateMethod")
178 private static Stream<String> checks() {
179 return Stream.of(
180 "MethodsOrderCheck",
181 "MultilineJavadocTagsCheck",
182 "StringLiteralsConcatenationCheck",
183 "EmptyLinesCheck",
184 "ImportCohesionCheck",
185 "BracketsStructureCheck",
186 "CurlyBracketsStructureCheck",
187 "JavadocLocationCheck",
188 "JavadocParameterOrderCheck",
189 "MethodBodyCommentsCheck",
190 "RequireThisCheck",
191 "ProtectedMethodInFinalClassCheck",
192 "NoJavadocForOverriddenMethodsCheck",
193 "NonStaticMethodCheck",
194 "ConstantUsageCheck",
195 "JavadocEmptyLineCheck",
196 "JavadocTagsCheck",
197 "ProhibitNonFinalClassesCheck",
198 "QualifyInnerClassCheck",
199 "CommentCheck",
200 "ProhibitUnusedPrivateConstructorCheck"
201 ).map(s -> String.format("ChecksTest/%s", s));
202 }
203
204
205
206
207
208
209 private static final class Collector implements Answer<Object> {
210
211
212
213
214 private final List<AuditEvent> events = new LinkedList<>();
215
216 @Override
217 public Object answer(final InvocationOnMock invocation) {
218 this.events.add((AuditEvent) invocation.getArguments()[0]);
219 return null;
220 }
221
222
223
224
225
226 public int eventCount() {
227 return this.events.size();
228 }
229
230
231
232
233
234
235
236 public boolean has(final Integer line, final String msg) {
237 boolean has = false;
238 for (final AuditEvent event : this.events) {
239 if (event.getLine() == line && event.getMessage().equals(msg)) {
240 has = true;
241 break;
242 }
243 }
244 return has;
245 }
246
247
248
249
250
251 public String summary() {
252 final List<String> msgs = new LinkedList<>();
253 for (final AuditEvent event : this.events) {
254 msgs.add(
255 String.format(
256 "%s:%s",
257 event.getLine(),
258 event.getMessage()
259 )
260 );
261 }
262 return new Joined("; ", msgs).toString();
263 }
264 }
265
266 }