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;
21
22 import static com.google.common.truth.Truth.assertWithMessage;
23
24 import java.io.IOException;
25 import java.io.PrintWriter;
26 import java.io.Serial;
27 import java.util.List;
28
29 import org.junit.jupiter.api.Test;
30
31 import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean.OutputStreamOptions;
32 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
33 import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
34 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
35 import com.puppycrawl.tools.checkstyle.api.Violation;
36 import com.puppycrawl.tools.checkstyle.internal.utils.CloseAndFlushTestByteArrayOutputStream;
37 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
38
39
40
41
42
43 public class XMLLoggerTest extends AbstractXmlTestSupport {
44
45
46
47
48
49
50 private final CloseAndFlushTestByteArrayOutputStream outStream =
51 new CloseAndFlushTestByteArrayOutputStream();
52
53 @Override
54 protected String getPackageLocation() {
55 return "com/puppycrawl/tools/checkstyle/xmllogger";
56 }
57
58 @Test
59 public void testEncode()
60 throws IOException {
61 final XMLLogger test = new XMLLogger(outStream, OutputStreamOptions.NONE);
62 assertWithMessage("should be able to create XMLLogger without issue")
63 .that(test)
64 .isNotNull();
65 final String[][] encodings = {
66 {"<", "<"},
67 {">", ">"},
68 {"'", "'"},
69 {"\"", """},
70 {"&", "&"},
71 {"<", "&lt;"},
72 {"abc;", "abc;"},
73 {"�", "&#0;"},
74 {"�", "&#0"},
75 {"�", "&#X0;"},
76 {"\u0001", "#x1;"},
77 {"\u0080", "#x80;"},
78 };
79 for (String[] encoding : encodings) {
80 final String encoded = XMLLogger.encode(encoding[0]);
81 assertWithMessage("\"" + encoding[0] + "\"")
82 .that(encoded)
83 .isEqualTo(encoding[1]);
84 }
85 outStream.close();
86 }
87
88 @Test
89 public void testIsReference()
90 throws IOException {
91 final XMLLogger test = new XMLLogger(outStream, OutputStreamOptions.NONE);
92 assertWithMessage("should be able to create XMLLogger without issue")
93 .that(test)
94 .isNotNull();
95 final String[] references = {
96 "�",
97 "�",
98 "<",
99 ">",
100 "'",
101 """,
102 "&",
103 };
104 for (String reference : references) {
105 assertWithMessage("reference: " + reference)
106 .that(XMLLogger.isReference(reference))
107 .isTrue();
108 }
109 final String[] noReferences = {
110 "&",
111 "&;",
112 "&#;",
113 "&#a;",
114 "�",
115 "&#x;",
116 "&#xg;",
117 "ramp;",
118 "ref",
119 };
120 for (String noReference : noReferences) {
121 assertWithMessage("no reference: " + noReference)
122 .that(XMLLogger.isReference(noReference))
123 .isFalse();
124 }
125
126 outStream.close();
127 }
128
129 @Test
130 public void testCloseStream()
131 throws Exception {
132 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
133 logger.auditStarted(null);
134 logger.auditFinished(null);
135
136 assertWithMessage("Invalid close count")
137 .that(outStream.getCloseCount())
138 .isEqualTo(1);
139
140 verifyXml(getPath("ExpectedXMLLoggerEmpty.xml"), outStream);
141 }
142
143 @Test
144 public void testNoCloseStream()
145 throws Exception {
146 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.NONE);
147 logger.auditStarted(null);
148 logger.auditFinished(null);
149
150 assertWithMessage("Invalid close count")
151 .that(outStream.getCloseCount())
152 .isEqualTo(0);
153
154 outStream.close();
155 verifyXml(getPath("ExpectedXMLLoggerEmpty.xml"), outStream);
156 }
157
158 @Test
159 public void testFileStarted() throws Exception {
160 verifyWithInlineConfigParserAndXmlLogger(
161 "InputXMLLoggerFileStarted.java",
162 "ExpectedXMLLoggerFileStarted.xml");
163 }
164
165 @Test
166 public void testFileFinished()
167 throws Exception {
168 verifyWithInlineConfigParserAndXmlLogger(
169 "InputXMLLoggerFileFinished.java",
170 "ExpectedXMLLoggerFileFinished.xml");
171 }
172
173 @Test
174 public void testAddError() throws Exception {
175 verifyWithInlineConfigParserAndXmlLogger("InputXMLLoggerAddError.java",
176 "ExpectedXMLLoggerAddError.xml");
177 }
178
179
180
181
182
183 @Test
184 public void testAddErrorWithNullFileName() throws Exception {
185 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
186 logger.auditStarted(null);
187 final Violation violation =
188 new Violation(1, 1,
189 "messages.properties", "key", null, SeverityLevel.ERROR, null,
190 getClass(), null);
191 final AuditEvent ev = new AuditEvent(this, null, violation);
192 logger.addError(ev);
193 logger.auditFinished(null);
194 verifyXml(getPath("ExpectedXMLLoggerErrorNullFileName.xml"), outStream,
195 violation.getViolation());
196 }
197
198 @Test
199 public void testAddErrorModuleId() throws Exception {
200 final String inputFile = "InputXMLLoggerErrorModuleId.java";
201 final String expectedXmlReport = "ExpectedXMLLoggerErrorModuleId.xml";
202 verifyWithInlineConfigParserAndXmlLogger(inputFile, expectedXmlReport);
203 }
204
205 @Test
206 public void testAddErrorWithEncodedMessage() throws Exception {
207 final String inputFileWithConfig = "InputXMLLoggerEncodedMessage.java";
208 final String expectedXmlReport = "ExpectedXMLLoggerEncodedMessage.xml";
209 verifyWithInlineConfigParserAndXmlLogger(inputFileWithConfig, expectedXmlReport);
210 }
211
212 @Test
213 public void testAddErrorOnZeroColumns() throws Exception {
214 verifyWithInlineConfigParserAndXmlLogger("InputXMLLoggerErrorOnZeroColumn.java",
215 "ExpectedXMLLoggerErrorZeroColumn.xml");
216 }
217
218 @Test
219 public void testAddIgnored() throws Exception {
220 final String inputFile = "InputXMLLoggerIgnored.java";
221 final String expectedXmlReport = "ExpectedXMLLoggerIgnored.xml";
222 verifyWithInlineConfigParserAndXmlLogger(inputFile, expectedXmlReport);
223 }
224
225 @Test
226 public void testAddException()
227 throws Exception {
228 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
229 logger.auditStarted(null);
230 final Violation violation =
231 new Violation(1, 1,
232 "messages.properties", null, null, null, getClass(), null);
233 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
234 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
235 logger.auditFinished(null);
236 verifyXml(getPath("ExpectedXMLLoggerException.xml"), outStream);
237 assertWithMessage("Invalid close count")
238 .that(outStream.getCloseCount())
239 .isEqualTo(1);
240 }
241
242 @Test
243 public void testAddExceptionWithNullFileName()
244 throws Exception {
245 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
246 logger.auditStarted(null);
247 final Violation violation =
248 new Violation(1, 1,
249 "messages.properties", null, null, null, getClass(), null);
250 final AuditEvent ev = new AuditEvent(this, null, violation);
251 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
252 logger.auditFinished(null);
253 verifyXml(getPath("ExpectedXMLLoggerExceptionNullFileName.xml"), outStream);
254 assertWithMessage("Invalid close count")
255 .that(outStream.getCloseCount())
256 .isEqualTo(1);
257 }
258
259 @Test
260 public void testAddExceptionAfterFileStarted()
261 throws Exception {
262 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
263 logger.auditStarted(null);
264
265 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
266 logger.fileStarted(fileStartedEvent);
267
268 final Violation violation =
269 new Violation(1, 1,
270 "messages.properties", null, null, null, getClass(), null);
271 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
272 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
273
274 logger.fileFinished(ev);
275 logger.auditFinished(null);
276 verifyXml(getPath("ExpectedXMLLoggerException2.xml"), outStream);
277 assertWithMessage("Invalid close count")
278 .that(outStream.getCloseCount())
279 .isEqualTo(1);
280 }
281
282 @Test
283 public void testAddExceptionBeforeFileFinished()
284 throws Exception {
285 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
286 logger.auditStarted(null);
287 final Violation violation =
288 new Violation(1, 1,
289 "messages.properties", null, null, null, getClass(), null);
290 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
291 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
292 final AuditEvent fileFinishedEvent = new AuditEvent(this, "Test.java");
293 logger.fileFinished(fileFinishedEvent);
294 logger.auditFinished(null);
295 verifyXml(getPath("ExpectedXMLLoggerException3.xml"), outStream);
296 assertWithMessage("Invalid close count")
297 .that(outStream.getCloseCount())
298 .isEqualTo(1);
299 }
300
301 @Test
302 public void testAddExceptionBetweenFileStartedAndFinished()
303 throws Exception {
304 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
305 logger.auditStarted(null);
306 final Violation violation =
307 new Violation(1, 1,
308 "messages.properties", null, null, null, getClass(), null);
309 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
310 logger.fileStarted(fileStartedEvent);
311 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
312 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
313 final AuditEvent fileFinishedEvent = new AuditEvent(this, "Test.java");
314 logger.fileFinished(fileFinishedEvent);
315 logger.auditFinished(null);
316 verifyXml(getPath("ExpectedXMLLoggerException2.xml"), outStream);
317 assertWithMessage("Invalid close count")
318 .that(outStream.getCloseCount())
319 .isEqualTo(1);
320 }
321
322 @Test
323 public void testAuditFinishedWithoutFileFinished() throws Exception {
324 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
325 logger.auditStarted(null);
326 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
327 logger.fileStarted(fileStartedEvent);
328
329 final Violation violation =
330 new Violation(1, 1,
331 "messages.properties", "key", null, SeverityLevel.ERROR, null,
332 getClass(), null);
333 final AuditEvent errorEvent = new AuditEvent(this, "Test.java", violation);
334 logger.addError(errorEvent);
335
336 logger.fileFinished(errorEvent);
337 logger.auditFinished(null);
338 verifyXml(getPath("ExpectedXMLLoggerError.xml"), outStream, violation.getViolation());
339 }
340
341 @Test
342 public void testFileOpenTag()
343 throws Exception {
344 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
345 logger.auditStarted(null);
346 final AuditEvent ev = new AuditEvent(this, "Test&.java");
347 logger.fileFinished(ev);
348 logger.auditFinished(null);
349 verifyXml(getPath("ExpectedXMLLoggerSpecialName.xml"),
350 outStream, "<file name=" + "Test&.java" + ">");
351
352 }
353
354 @Test
355 public void testVerifyLogger()
356 throws Exception {
357 final String inputFileWithConfig = "InputXMLLogger.java";
358 final String xmlReport = "ExpectedXMLLoggerWithChecker.xml";
359 verifyWithInlineConfigParserAndXmlLogger(inputFileWithConfig, xmlReport);
360 }
361
362 @Test
363 public void testVerifyLoggerWithMultipleInput()
364 throws Exception {
365 final String inputFileWithConfig = "InputXMLLogger.java";
366 final String expectedXmlReport = "ExpectedXMLLoggerDuplicatedFile.xml";
367 verifyWithInlineConfigParserAndXmlLogger(
368 inputFileWithConfig,
369 expectedXmlReport,
370 List.of(inputFileWithConfig, inputFileWithConfig));
371 }
372
373 @Test
374 public void testNullOutputStreamOptions() {
375 try {
376 final XMLLogger logger = new XMLLogger(outStream,
377 (OutputStreamOptions) null);
378
379 assertWithMessage("Null instance")
380 .that(logger)
381 .isNotNull();
382 assertWithMessage("Exception was expected").fail();
383 }
384 catch (IllegalArgumentException exception) {
385 assertWithMessage("Invalid error message")
386 .that(exception.getMessage())
387 .isEqualTo("Parameter outputStreamOptions can not be null");
388 }
389 }
390
391 @Test
392 public void testFinishLocalSetup() {
393 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
394 logger.finishLocalSetup();
395 logger.auditStarted(null);
396 logger.auditFinished(null);
397 assertWithMessage("instance should not be null")
398 .that(logger)
399 .isNotNull();
400 }
401
402
403
404
405 @Test
406 public void testCtorWithTwoParametersCloseStreamOptions() {
407 final XMLLogger logger = new XMLLogger(outStream, AutomaticBean.OutputStreamOptions.CLOSE);
408 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream", Boolean.class);
409
410 assertWithMessage("closeStream should be true")
411 .that(closeStream)
412 .isTrue();
413 }
414
415
416
417
418 @Test
419 public void testCtorWithTwoParametersNoneStreamOptions() {
420 final XMLLogger logger = new XMLLogger(outStream, AutomaticBean.OutputStreamOptions.NONE);
421 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream", Boolean.class);
422
423 assertWithMessage("closeStream should be false")
424 .that(closeStream)
425 .isFalse();
426 }
427
428 private static final class TestException extends RuntimeException {
429 @Serial
430 private static final long serialVersionUID = 1L;
431
432 private TestException(String msg, Throwable cause) {
433 super(msg, cause);
434 }
435
436 @Override
437 public void printStackTrace(PrintWriter printWriter) {
438 printWriter.print("stackTrace\r\nexample");
439 }
440
441 }
442
443 }