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()
160 throws Exception {
161 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
162 logger.auditStarted(null);
163 final AuditEvent ev = new AuditEvent(this, "Test.java");
164 logger.fileStarted(ev);
165 logger.fileFinished(ev);
166 logger.auditFinished(null);
167 verifyXml(getPath("ExpectedXMLLogger.xml"), outStream);
168 }
169
170 @Test
171 public void testFileFinished()
172 throws Exception {
173 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
174 logger.auditStarted(null);
175 final AuditEvent ev = new AuditEvent(this, "Test.java");
176 logger.fileFinished(ev);
177 logger.auditFinished(null);
178 verifyXml(getPath("ExpectedXMLLogger.xml"), outStream);
179 }
180
181 @Test
182 public void testAddError() throws Exception {
183 verifyWithInlineConfigParserAndXmlLogger("InputXMLLoggerAddError.java",
184 "ExpectedXMLLoggerAddError.xml");
185 }
186
187 @Test
188 public void testAddErrorWithNullFileName() throws Exception {
189 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
190 logger.auditStarted(null);
191 final Violation violation =
192 new Violation(1, 1,
193 "messages.properties", "key", null, SeverityLevel.ERROR, null,
194 getClass(), null);
195 final AuditEvent ev = new AuditEvent(this, null, violation);
196 logger.addError(ev);
197 logger.auditFinished(null);
198 verifyXml(getPath("ExpectedXMLLoggerErrorNullFileName.xml"), outStream,
199 violation.getViolation());
200 }
201
202 @Test
203 public void testAddErrorModuleId() throws Exception {
204 final String inputFile = "InputXMLLoggerErrorModuleId.java";
205 final String expectedXmlReport = "ExpectedXMLLoggerErrorModuleId.xml";
206 verifyWithInlineConfigParserAndXmlLogger(inputFile, expectedXmlReport);
207 }
208
209 @Test
210 public void testAddErrorWithEncodedMessage() throws Exception {
211 final String inputFileWithConfig = "InputXMLLoggerEncodedMessage.java";
212 final String expectedXmlReport = "ExpectedXMLLoggerEncodedMessage.xml";
213 verifyWithInlineConfigParserAndXmlLogger(inputFileWithConfig, expectedXmlReport);
214 }
215
216 @Test
217 public void testAddErrorOnZeroColumns() throws Exception {
218 verifyWithInlineConfigParserAndXmlLogger("InputXMLLoggerErrorOnZeroColumn.java",
219 "ExpectedXMLLoggerErrorZeroColumn.xml");
220 }
221
222 @Test
223 public void testAddIgnored() throws Exception {
224 final String inputFile = "InputXMLLoggerIgnored.java";
225 final String expectedXmlReport = "ExpectedXMLLoggerIgnored.xml";
226 verifyWithInlineConfigParserAndXmlLogger(inputFile, expectedXmlReport);
227 }
228
229 @Test
230 public void testAddException()
231 throws Exception {
232 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
233 logger.auditStarted(null);
234 final Violation violation =
235 new Violation(1, 1,
236 "messages.properties", null, null, null, getClass(), null);
237 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
238 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
239 logger.auditFinished(null);
240 verifyXml(getPath("ExpectedXMLLoggerException.xml"), outStream);
241 assertWithMessage("Invalid close count")
242 .that(outStream.getCloseCount())
243 .isEqualTo(1);
244 }
245
246 @Test
247 public void testAddExceptionWithNullFileName()
248 throws Exception {
249 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
250 logger.auditStarted(null);
251 final Violation violation =
252 new Violation(1, 1,
253 "messages.properties", null, null, null, getClass(), null);
254 final AuditEvent ev = new AuditEvent(this, null, violation);
255 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
256 logger.auditFinished(null);
257 verifyXml(getPath("ExpectedXMLLoggerExceptionNullFileName.xml"), outStream);
258 assertWithMessage("Invalid close count")
259 .that(outStream.getCloseCount())
260 .isEqualTo(1);
261 }
262
263 @Test
264 public void testAddExceptionAfterFileStarted()
265 throws Exception {
266 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
267 logger.auditStarted(null);
268
269 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
270 logger.fileStarted(fileStartedEvent);
271
272 final Violation violation =
273 new Violation(1, 1,
274 "messages.properties", null, null, null, getClass(), null);
275 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
276 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
277
278 logger.fileFinished(ev);
279 logger.auditFinished(null);
280 verifyXml(getPath("ExpectedXMLLoggerException2.xml"), outStream);
281 assertWithMessage("Invalid close count")
282 .that(outStream.getCloseCount())
283 .isEqualTo(1);
284 }
285
286 @Test
287 public void testAddExceptionBeforeFileFinished()
288 throws Exception {
289 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
290 logger.auditStarted(null);
291 final Violation violation =
292 new Violation(1, 1,
293 "messages.properties", null, null, null, getClass(), null);
294 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
295 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
296 final AuditEvent fileFinishedEvent = new AuditEvent(this, "Test.java");
297 logger.fileFinished(fileFinishedEvent);
298 logger.auditFinished(null);
299 verifyXml(getPath("ExpectedXMLLoggerException3.xml"), outStream);
300 assertWithMessage("Invalid close count")
301 .that(outStream.getCloseCount())
302 .isEqualTo(1);
303 }
304
305 @Test
306 public void testAddExceptionBetweenFileStartedAndFinished()
307 throws Exception {
308 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
309 logger.auditStarted(null);
310 final Violation violation =
311 new Violation(1, 1,
312 "messages.properties", null, null, null, getClass(), null);
313 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
314 logger.fileStarted(fileStartedEvent);
315 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
316 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
317 final AuditEvent fileFinishedEvent = new AuditEvent(this, "Test.java");
318 logger.fileFinished(fileFinishedEvent);
319 logger.auditFinished(null);
320 verifyXml(getPath("ExpectedXMLLoggerException2.xml"), outStream);
321 assertWithMessage("Invalid close count")
322 .that(outStream.getCloseCount())
323 .isEqualTo(1);
324 }
325
326 @Test
327 public void testAuditFinishedWithoutFileFinished() throws Exception {
328 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
329 logger.auditStarted(null);
330 final AuditEvent fileStartedEvent = new AuditEvent(this, "Test.java");
331 logger.fileStarted(fileStartedEvent);
332
333 final Violation violation =
334 new Violation(1, 1,
335 "messages.properties", "key", null, SeverityLevel.ERROR, null,
336 getClass(), null);
337 final AuditEvent errorEvent = new AuditEvent(this, "Test.java", violation);
338 logger.addError(errorEvent);
339
340 logger.fileFinished(errorEvent);
341 logger.auditFinished(null);
342 verifyXml(getPath("ExpectedXMLLoggerError.xml"), outStream, violation.getViolation());
343 }
344
345 @Test
346 public void testFileOpenTag()
347 throws Exception {
348 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
349 logger.auditStarted(null);
350 final AuditEvent ev = new AuditEvent(this, "Test&.java");
351 logger.fileFinished(ev);
352 logger.auditFinished(null);
353 verifyXml(getPath("ExpectedXMLLoggerSpecialName.xml"),
354 outStream, "<file name=" + "Test&.java" + ">");
355
356 }
357
358 @Test
359 public void testVerifyLogger()
360 throws Exception {
361 final String inputFileWithConfig = "InputXMLLogger.java";
362 final String xmlReport = "ExpectedXMLLoggerWithChecker.xml";
363 verifyWithInlineConfigParserAndXmlLogger(inputFileWithConfig, xmlReport);
364 }
365
366 @Test
367 public void testVerifyLoggerWithMultipleInput()
368 throws Exception {
369 final String inputFileWithConfig = "InputXMLLogger.java";
370 final String expectedXmlReport = "ExpectedXMLLoggerDuplicatedFile.xml";
371 verifyWithInlineConfigParserAndXmlLogger(
372 inputFileWithConfig,
373 expectedXmlReport,
374 List.of(inputFileWithConfig, inputFileWithConfig));
375 }
376
377 @Test
378 public void testNullOutputStreamOptions() {
379 try {
380 final XMLLogger logger = new XMLLogger(outStream,
381 (OutputStreamOptions) null);
382
383 assertWithMessage("Null instance")
384 .that(logger)
385 .isNotNull();
386 assertWithMessage("Exception was expected").fail();
387 }
388 catch (IllegalArgumentException exception) {
389 assertWithMessage("Invalid error message")
390 .that(exception.getMessage())
391 .isEqualTo("Parameter outputStreamOptions can not be null");
392 }
393 }
394
395 @Test
396 public void testFinishLocalSetup() {
397 final XMLLogger logger = new XMLLogger(outStream, OutputStreamOptions.CLOSE);
398 logger.finishLocalSetup();
399 logger.auditStarted(null);
400 logger.auditFinished(null);
401 assertWithMessage("instance should not be null")
402 .that(logger)
403 .isNotNull();
404 }
405
406
407
408
409 @Test
410 public void testCtorWithTwoParametersCloseStreamOptions() {
411 final XMLLogger logger = new XMLLogger(outStream, AutomaticBean.OutputStreamOptions.CLOSE);
412 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream");
413
414 assertWithMessage("closeStream should be true")
415 .that(closeStream)
416 .isTrue();
417 }
418
419
420
421
422 @Test
423 public void testCtorWithTwoParametersNoneStreamOptions() {
424 final XMLLogger logger = new XMLLogger(outStream, AutomaticBean.OutputStreamOptions.NONE);
425 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream");
426
427 assertWithMessage("closeStream should be false")
428 .that(closeStream)
429 .isFalse();
430 }
431
432 private static final class TestException extends RuntimeException {
433 @Serial
434 private static final long serialVersionUID = 1L;
435
436 private TestException(String msg, Throwable cause) {
437 super(msg, cause);
438 }
439
440 @Override
441 public void printStackTrace(PrintWriter printWriter) {
442 printWriter.print("stackTrace\r\nexample");
443 }
444
445 }
446
447 }