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.ByteArrayOutputStream;
25 import java.io.IOException;
26 import java.io.OutputStream;
27 import java.io.PrintWriter;
28 import java.nio.charset.StandardCharsets;
29
30 import org.junit.jupiter.api.Test;
31
32 import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean.OutputStreamOptions;
33 import com.puppycrawl.tools.checkstyle.api.AuditEvent;
34 import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
35 import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
36 import com.puppycrawl.tools.checkstyle.api.Violation;
37 import com.puppycrawl.tools.checkstyle.internal.utils.CloseAndFlushTestByteArrayOutputStream;
38 import com.puppycrawl.tools.checkstyle.internal.utils.TestUtil;
39
40 public class SarifLoggerTest extends AbstractModuleTestSupport {
41
42
43
44
45
46
47 private final CloseAndFlushTestByteArrayOutputStream outStream =
48 new CloseAndFlushTestByteArrayOutputStream();
49
50 @Override
51 protected String getPackageLocation() {
52 return "com/puppycrawl/tools/checkstyle/sariflogger";
53 }
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public final void executeLogger(
69 SarifLoggerTest instance, SarifLogger logger, String fileName, Violation violation) {
70 final AuditEvent event = new AuditEvent(this, "Test.java", violation);
71 logger.fileStarted(event);
72 logger.addError(event);
73 logger.fileFinished(event);
74 logger.auditFinished(null);
75 }
76
77 @Test
78 public void testEscape() {
79 final String[][] encodings = {
80 {"\"", "\\\""},
81 {"\\", "\\\\"},
82 {"\b", "\\b"},
83 {"\f", "\\f"},
84 {"\n", "\\n"},
85 {"\r", "\\r"},
86 {"\t", "\\t"},
87 {"/", "\\/"},
88 {"\u0010", "\\u0010"},
89 {"\u001E", "\\u001E"},
90 {"\u001F", "\\u001F"},
91 {" ", " "},
92 {"bar1234", "bar1234"},
93 };
94 for (String[] encoding : encodings) {
95 final String encoded = SarifLogger.escape(encoding[0]);
96 assertWithMessage("\"" + encoding[0] + "\"")
97 .that(encoded)
98 .isEqualTo(encoding[1]);
99 }
100 }
101
102 @Test
103 public void testSingleError() throws Exception {
104 final String inputFile = "InputSarifLoggerSingleError.java";
105 final String expectedReportFile = "ExpectedSarifLoggerSingleError.sarif";
106 final SarifLogger logger = new SarifLogger(outStream,
107 OutputStreamOptions.CLOSE);
108
109 verifyWithInlineConfigParserAndLogger(
110 getPath(inputFile), getPath(expectedReportFile), logger, outStream);
111 }
112
113 @Test
114 public void testAddErrorAtColumn1() throws Exception {
115 final SarifLogger logger = new SarifLogger(outStream,
116 OutputStreamOptions.CLOSE);
117 final String inputFile = "InputSarifLoggerSingleErrorColumn1.java";
118 final String expectedOutput = "ExpectedSarifLoggerSingleErrorColumn1.sarif";
119 verifyWithInlineConfigParserAndLogger(getPath(inputFile),
120 getPath(expectedOutput), logger, outStream);
121 }
122
123 @Test
124 public void testAddErrorAtColumn0() throws Exception {
125 final String inputFile = "InputSarifLoggerErrorColumn0.java";
126 final String expectedReportFile = "ExpectedSarifLoggerSingleErrorColumn0.sarif";
127 final SarifLogger logger = new SarifLogger(outStream,
128 OutputStreamOptions.CLOSE);
129
130 verifyWithInlineConfigParserAndLogger(
131 getPath(inputFile), getPath(expectedReportFile), logger, outStream);
132 }
133
134 @Test
135 public void testAddErrorWithWarningLevel() throws Exception {
136 final SarifLogger logger = new SarifLogger(outStream,
137 OutputStreamOptions.CLOSE);
138 final String inputFile = "InputSarifLoggerSingleWarning.java";
139 final String expectedOutput = "ExpectedSarifLoggerSingleWarning.sarif";
140 verifyWithInlineConfigParserAndLogger(getPath(inputFile),
141 getPath(expectedOutput), logger, outStream);
142 }
143
144 @Test
145 public void testAddErrors() throws IOException {
146 final SarifLogger logger = new SarifLogger(outStream,
147 OutputStreamOptions.CLOSE);
148 logger.auditStarted(null);
149 final Violation violation =
150 new Violation(1, 1,
151 "messages.properties", "ruleId", null, SeverityLevel.INFO, null,
152 getClass(), "found an error");
153 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
154 final Violation violation2 =
155 new Violation(1, 1,
156 "messages.properties", "ruleId2", null, SeverityLevel.IGNORE, null,
157 getClass(), "found another error");
158 final AuditEvent ev2 = new AuditEvent(this, "Test.java", violation2);
159 logger.fileStarted(ev);
160 logger.addError(ev);
161 logger.fileFinished(ev);
162 logger.fileStarted(ev2);
163 logger.addError(ev2);
164 logger.fileFinished(ev2);
165 logger.auditFinished(null);
166 verifyContent(getPath("ExpectedSarifLoggerDoubleError.sarif"), outStream);
167 }
168
169 @Test
170 public void testAddException() throws IOException {
171 final SarifLogger logger = new SarifLogger(outStream,
172 OutputStreamOptions.CLOSE);
173 logger.auditStarted(null);
174 final Violation message =
175 new Violation(1, 1,
176 "messages.properties", "null", null, null,
177 getClass(), "found an error");
178 final AuditEvent ev = new AuditEvent(this, null, message);
179 logger.fileStarted(ev);
180 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
181 logger.fileFinished(ev);
182 logger.auditFinished(null);
183 verifyContent(getPath("ExpectedSarifLoggerSingleException.sarif"), outStream);
184 }
185
186 @Test
187 public void testAddExceptions() throws IOException {
188 final SarifLogger logger = new SarifLogger(outStream,
189 OutputStreamOptions.CLOSE);
190 logger.auditStarted(null);
191 final Violation violation =
192 new Violation(1, 1,
193 "messages.properties", "null", null, null,
194 getClass(), "found an error");
195 final AuditEvent ev = new AuditEvent(this, null, violation);
196 final Violation violation2 =
197 new Violation(1, 1,
198 "messages.properties", "null", null, null,
199 getClass(), "found an error");
200 final AuditEvent ev2 = new AuditEvent(this, "Test.java", violation2);
201 logger.fileStarted(ev);
202 logger.addException(ev, new TestException("msg", new RuntimeException("msg")));
203 logger.fileFinished(ev);
204 logger.fileStarted(ev2);
205 logger.addException(ev2, new TestException("msg2", new RuntimeException("msg2")));
206 logger.fileFinished(ev);
207 logger.auditFinished(null);
208 verifyContent(getPath("ExpectedSarifLoggerDoubleException.sarif"), outStream);
209 }
210
211 @Test
212 public void testLineOnly() throws IOException {
213 final SarifLogger logger = new SarifLogger(outStream,
214 OutputStreamOptions.CLOSE);
215 logger.auditStarted(null);
216 final Violation violation =
217 new Violation(1, 0,
218 "messages.properties", "ruleId", null, null,
219 getClass(), "found an error");
220 final AuditEvent ev = new AuditEvent(this, "Test.java", violation);
221 logger.fileStarted(ev);
222 logger.addError(ev);
223 logger.fileFinished(ev);
224 logger.auditFinished(null);
225 verifyContent(getPath("ExpectedSarifLoggerLineOnly.sarif"), outStream);
226 }
227
228 @Test
229 public void testEmpty() throws IOException {
230 final SarifLogger logger = new SarifLogger(outStream,
231 OutputStreamOptions.CLOSE);
232 logger.auditStarted(null);
233 final Violation violation =
234 new Violation(1, 1,
235 "messages.properties", "null", null, null,
236 getClass(), "found an error");
237 final AuditEvent ev = new AuditEvent(this, null, violation);
238 logger.fileStarted(ev);
239 logger.fileFinished(ev);
240 logger.auditFinished(null);
241 verifyContent(getPath("ExpectedSarifLoggerEmpty.sarif"), outStream);
242 }
243
244 @Test
245 public void testAddErrorWithSpaceInPath() throws IOException {
246 final SarifLogger logger = new SarifLogger(outStream,
247 OutputStreamOptions.CLOSE);
248 logger.auditStarted(null);
249 final Violation violation =
250 new Violation(1, 1,
251 "messages.properties", "ruleId", null, SeverityLevel.ERROR, null,
252 getClass(), "found an error");
253 final AuditEvent ev = new AuditEvent(this, "/home/someuser/Code/Test 2.java", violation);
254 logger.fileStarted(ev);
255 logger.addError(ev);
256 logger.fileFinished(ev);
257 logger.auditFinished(null);
258 verifyContent(getPath("ExpectedSarifLoggerSpaceInPath.sarif"), outStream);
259 }
260
261 @Test
262 public void testAddErrorWithAbsoluteLinuxPath() throws IOException {
263 final SarifLogger logger = new SarifLogger(outStream,
264 OutputStreamOptions.CLOSE);
265 logger.auditStarted(null);
266 final Violation violation =
267 new Violation(1, 1,
268 "messages.properties", "ruleId", null, SeverityLevel.ERROR, null,
269 getClass(), "found an error");
270 final AuditEvent ev = new AuditEvent(this, "/home/someuser/Code/Test.java", violation);
271 logger.fileStarted(ev);
272 logger.addError(ev);
273 logger.fileFinished(ev);
274 logger.auditFinished(null);
275 verifyContent(getPath("ExpectedSarifLoggerAbsoluteLinuxPath.sarif"), outStream);
276 }
277
278 @Test
279 public void testAddErrorWithRelativeLinuxPath() throws IOException {
280 final SarifLogger logger = new SarifLogger(outStream,
281 OutputStreamOptions.CLOSE);
282 logger.auditStarted(null);
283 final Violation violation =
284 new Violation(1, 1,
285 "messages.properties", "ruleId", null, SeverityLevel.ERROR, null,
286 getClass(), "found an error");
287 final AuditEvent ev = new AuditEvent(this, "./Test.java", violation);
288 logger.fileStarted(ev);
289 logger.addError(ev);
290 logger.fileFinished(ev);
291 logger.auditFinished(null);
292 verifyContent(getPath("ExpectedSarifLoggerRelativeLinuxPath.sarif"), outStream);
293 }
294
295 @Test
296 public void testAddErrorWithAbsoluteWindowsPath() throws IOException {
297 final SarifLogger logger = new SarifLogger(outStream,
298 OutputStreamOptions.CLOSE);
299 logger.auditStarted(null);
300 final Violation violation =
301 new Violation(1, 1,
302 "messages.properties", "ruleId", null, SeverityLevel.ERROR, null,
303 getClass(), "found an error");
304 final AuditEvent ev =
305 new AuditEvent(this, "C:\\Users\\SomeUser\\Code\\Test.java", violation);
306 logger.fileStarted(ev);
307 logger.addError(ev);
308 logger.fileFinished(ev);
309 logger.auditFinished(null);
310 verifyContent(getPath("ExpectedSarifLoggerAbsoluteWindowsPath.sarif"), outStream);
311 }
312
313 @Test
314 public void testAddErrorWithRelativeWindowsPath() throws IOException {
315 final SarifLogger logger = new SarifLogger(outStream,
316 OutputStreamOptions.CLOSE);
317 logger.auditStarted(null);
318 final Violation violation =
319 new Violation(1, 1,
320 "messages.properties", "ruleId", null, SeverityLevel.ERROR, null,
321 getClass(), "found an error");
322 final AuditEvent ev = new AuditEvent(this, ".\\Test.java", violation);
323 logger.fileStarted(ev);
324 logger.addError(ev);
325 logger.fileFinished(ev);
326 logger.auditFinished(null);
327 verifyContent(getPath("ExpectedSarifLoggerRelativeWindowsPath.sarif"), outStream);
328 }
329
330
331
332
333 @Test
334 public void testCtorWithTwoParametersCloseStreamOptions() throws IOException {
335 final OutputStream infoStream = new ByteArrayOutputStream();
336 final SarifLogger logger = new SarifLogger(infoStream,
337 AutomaticBean.OutputStreamOptions.CLOSE);
338 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream");
339
340 assertWithMessage("closeStream should be true")
341 .that(closeStream)
342 .isTrue();
343 }
344
345
346
347
348 @Test
349 public void testCtorWithTwoParametersNoneStreamOptions() throws IOException {
350 final OutputStream infoStream = new ByteArrayOutputStream();
351 final SarifLogger logger = new SarifLogger(infoStream,
352 AutomaticBean.OutputStreamOptions.NONE);
353 final boolean closeStream = TestUtil.getInternalState(logger, "closeStream");
354
355 assertWithMessage("closeStream should be false")
356 .that(closeStream)
357 .isFalse();
358 }
359
360 @Test
361 public void testNullOutputStreamOptions() {
362 try {
363 final SarifLogger logger = new SarifLogger(outStream, (OutputStreamOptions) null);
364
365 assertWithMessage("Null instance")
366 .that(logger)
367 .isNotNull();
368 assertWithMessage("Exception was expected").fail();
369 }
370 catch (IllegalArgumentException | IOException exception) {
371 assertWithMessage("Invalid error message")
372 .that(exception.getMessage())
373 .isEqualTo("Parameter outputStreamOptions can not be null");
374 }
375 }
376
377 @Test
378 public void testCloseStream() throws IOException {
379 final SarifLogger logger = new SarifLogger(outStream,
380 OutputStreamOptions.CLOSE);
381 logger.auditStarted(null);
382 logger.auditFinished(null);
383
384 assertWithMessage("Invalid close count")
385 .that(outStream.getCloseCount())
386 .isEqualTo(1);
387
388 verifyContent(getPath("ExpectedSarifLoggerEmpty.sarif"), outStream);
389 }
390
391 @Test
392 public void testNoCloseStream() throws IOException {
393 final SarifLogger logger = new SarifLogger(outStream,
394 OutputStreamOptions.NONE);
395 logger.auditStarted(null);
396 logger.auditFinished(null);
397
398 assertWithMessage("Invalid close count")
399 .that(outStream.getCloseCount())
400 .isEqualTo(0);
401 assertWithMessage("Invalid flush count")
402 .that(outStream.getFlushCount())
403 .isEqualTo(1);
404
405 outStream.close();
406 verifyContent(getPath("ExpectedSarifLoggerEmpty.sarif"), outStream);
407 }
408
409 @Test
410 public void testFinishLocalSetup() throws IOException {
411 final SarifLogger logger = new SarifLogger(outStream,
412 OutputStreamOptions.CLOSE);
413 logger.finishLocalSetup();
414 logger.auditStarted(null);
415 logger.auditFinished(null);
416 assertWithMessage("instance should not be null")
417 .that(logger)
418 .isNotNull();
419 }
420
421 @Test
422 public void testReadResourceWithInvalidName() {
423 try {
424 SarifLogger.readResource("random");
425 assertWithMessage("Exception expected").fail();
426 }
427 catch (IOException exception) {
428 assertWithMessage("Exception message must match")
429 .that(exception.getMessage())
430 .isEqualTo("Cannot find the resource random");
431 }
432 }
433
434 private static void verifyContent(
435 String expectedOutputFile,
436 ByteArrayOutputStream actualOutputStream) throws IOException {
437 final String expectedContent = readFile(expectedOutputFile);
438 final String actualContent =
439 toLfLineEnding(actualOutputStream.toString(StandardCharsets.UTF_8));
440 assertWithMessage("sarif content should match")
441 .that(actualContent)
442 .isEqualTo(expectedContent);
443 }
444
445 private static final class TestException extends RuntimeException {
446
447 private static final long serialVersionUID = 1L;
448
449 private TestException(String msg, Throwable cause) {
450 super(msg, cause);
451 }
452
453 @Override
454 public void printStackTrace(PrintWriter printWriter) {
455 printWriter.print("stackTrace\nexample");
456 }
457 }
458 }