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