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