1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.plugin.surefire.report;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStreamReader;
26 import java.io.RandomAccessFile;
27 import java.lang.reflect.Field;
28 import java.lang.reflect.Method;
29 import java.nio.Buffer;
30 import java.nio.ByteBuffer;
31 import java.nio.file.Path;
32 import java.util.Deque;
33 import java.util.HashMap;
34 import java.util.concurrent.ConcurrentHashMap;
35 import java.util.concurrent.atomic.AtomicInteger;
36
37 import org.apache.maven.plugin.surefire.booterclient.output.DeserializedStacktraceWriter;
38 import org.apache.maven.surefire.api.report.ReportEntry;
39 import org.apache.maven.surefire.api.report.SimpleReportEntry;
40 import org.apache.maven.surefire.api.report.StackTraceWriter;
41 import org.apache.maven.surefire.shared.utils.xml.Xpp3Dom;
42 import org.apache.maven.surefire.shared.utils.xml.Xpp3DomBuilder;
43 import org.junit.jupiter.api.AfterEach;
44 import org.junit.jupiter.api.BeforeEach;
45 import org.junit.jupiter.api.Test;
46
47 import static java.nio.charset.StandardCharsets.UTF_8;
48 import static java.nio.file.Files.readAllLines;
49 import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
50 import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
51 import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
52 import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN;
53 import static org.apache.maven.surefire.api.report.RunMode.RERUN_TEST_AFTER_FAILURE;
54 import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps;
55 import static org.apache.maven.surefire.api.util.internal.StringUtils.NL;
56 import static org.apache.maven.surefire.shared.utils.StringUtils.isEmpty;
57 import static org.assertj.core.api.Assertions.assertThat;
58 import static org.junit.jupiter.api.Assertions.assertEquals;
59 import static org.junit.jupiter.api.Assertions.assertFalse;
60 import static org.junit.jupiter.api.Assertions.assertNotNull;
61 import static org.junit.jupiter.api.Assertions.assertNull;
62 import static org.junit.jupiter.api.Assertions.assertTrue;
63 import static org.mockito.Mockito.doThrow;
64 import static org.mockito.Mockito.mock;
65 import static org.mockito.Mockito.times;
66 import static org.mockito.Mockito.verify;
67 import static org.mockito.Mockito.when;
68
69
70
71
72 @SuppressWarnings({"ResultOfMethodCallIgnored", "checkstyle:magicnumber"})
73 public class StatelessXmlReporterTest {
74 private static final String XSD =
75 "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd";
76 private static final String TEST_ONE = "aTestMethod";
77 private static final String TEST_TWO = "bTestMethod";
78 private static final String TEST_THREE = "cTestMethod";
79 private static final AtomicInteger DIRECTORY_PREFIX = new AtomicInteger();
80
81 private TestSetStats stats;
82 private TestSetStats rerunStats;
83 private File expectedReportFile;
84 private File reportDir;
85
86 @SuppressWarnings("unchecked")
87 private static <T> T getInternalState(Object target, String fieldName) {
88 try {
89 Class<?> clazz = target.getClass();
90 while (clazz != null) {
91 try {
92 Field field = clazz.getDeclaredField(fieldName);
93 field.setAccessible(true);
94 return (T) field.get(target);
95 } catch (NoSuchFieldException e) {
96 clazz = clazz.getSuperclass();
97 }
98 }
99 throw new NoSuchFieldException(fieldName);
100 } catch (Exception e) {
101 throw new RuntimeException(e);
102 }
103 }
104
105 private static void setInternalState(Object target, String fieldName, Object value) {
106 try {
107 Class<?> clazz = target.getClass();
108 while (clazz != null) {
109 try {
110 Field field = clazz.getDeclaredField(fieldName);
111 field.setAccessible(true);
112 field.set(target, value);
113 return;
114 } catch (NoSuchFieldException e) {
115 clazz = clazz.getSuperclass();
116 }
117 }
118 throw new NoSuchFieldException(fieldName);
119 } catch (NoSuchFieldException | IllegalAccessException e) {
120 throw new RuntimeException(e);
121 }
122 }
123
124 @SuppressWarnings("unchecked")
125 private static <T> T invokeMethod(Object target, String methodName, Object... args) throws Exception {
126 Class<?> clazz = target.getClass();
127 while (clazz != null) {
128 for (Method method : clazz.getDeclaredMethods()) {
129 if (method.getName().equals(methodName) && method.getParameterCount() == args.length) {
130 method.setAccessible(true);
131 return (T) method.invoke(target, args);
132 }
133 }
134 clazz = clazz.getSuperclass();
135 }
136 throw new NoSuchMethodException(methodName);
137 }
138
139 @BeforeEach
140 protected void setUp() throws Exception {
141 stats = new TestSetStats(false, true);
142 rerunStats = new TestSetStats(false, true);
143
144 File basedir = new File(".");
145 File target = new File(basedir.getCanonicalFile(), "target");
146 target.mkdir();
147 String reportRelDir = getClass().getSimpleName() + "-" + DIRECTORY_PREFIX.incrementAndGet();
148 reportDir = new File(target, reportRelDir);
149 reportDir.mkdir();
150 }
151
152 @AfterEach
153 protected void tearDown() {
154 if (expectedReportFile != null) {
155 expectedReportFile.delete();
156 }
157 }
158
159 @Test
160 public void testFileNameWithoutSuffix() {
161 StatelessXmlReporter reporter = new StatelessXmlReporter(
162 reportDir,
163 null,
164 false,
165 0,
166 new ConcurrentHashMap<String, Deque<WrappedReportEntry>>(),
167 XSD,
168 "3.0.2",
169 false,
170 false,
171 false,
172 false,
173 true,
174 true,
175 false);
176 reporter.cleanTestHistoryMap();
177
178 ReportEntry reportEntry = new SimpleReportEntry(
179 NORMAL_RUN, 0L, getClass().getName(), null, getClass().getName(), null, 12);
180 WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
181 reportEntry, ReportEntryType.SUCCESS, 1771085631L, 12, null, null, systemProps());
182 stats.testSucceeded(testSetReportEntry);
183 reporter.testSetCompleted(testSetReportEntry, stats);
184
185 expectedReportFile = new File(reportDir, "TEST-" + getClass().getName() + ".xml");
186 assertTrue(
187 expectedReportFile.exists(),
188 "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist");
189 }
190
191 @Test
192 public void testAllFieldsSerialized() throws IOException {
193 ReportEntry reportEntry =
194 new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(), null, TEST_ONE, null, 12);
195 WrappedReportEntry testSetReportEntry =
196 new WrappedReportEntry(reportEntry, SUCCESS, 1771085631L, 12, null, null, systemProps());
197 expectedReportFile = new File(reportDir, "TEST-" + getClass().getName() + ".xml");
198
199 stats.testSucceeded(testSetReportEntry);
200 StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter("A fud msg", "trimmed", "fail at foo");
201 Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream("fds");
202 String stdOutPrefix;
203 String stdErrPrefix;
204 if (defaultCharsetSupportsSpecialChar()) {
205 stdErrPrefix = "std-\u0115rr";
206 stdOutPrefix = "st]]>d-o\u00DCt";
207 } else {
208 stdErrPrefix = "std-err";
209 stdOutPrefix = "st]]>d-out";
210 }
211
212 stdOut.write(stdOutPrefix + "<null>!\u0020\u0000\u001F", false, null);
213
214 Utf8RecodingDeferredFileOutputStream stdErr = new Utf8RecodingDeferredFileOutputStream("fds");
215
216 stdErr.write(stdErrPrefix + "?&-&£\u0020\u0000\u001F", false, null);
217 WrappedReportEntry t2 = new WrappedReportEntry(
218 new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(), null, TEST_TWO, null, stackTraceWriter, 13),
219 ReportEntryType.ERROR,
220 1771085631L,
221 13,
222 stdOut,
223 stdErr);
224
225 stats.testSucceeded(t2);
226 StatelessXmlReporter reporter = new StatelessXmlReporter(
227 reportDir,
228 null,
229 false,
230 0,
231 new ConcurrentHashMap<String, Deque<WrappedReportEntry>>(),
232 XSD,
233 "3.0.2",
234 false,
235 false,
236 false,
237 false,
238 true,
239 true,
240 false);
241 reporter.testSetCompleted(testSetReportEntry, stats);
242
243 FileInputStream fileInputStream = new FileInputStream(expectedReportFile);
244
245 Xpp3Dom testSuite = Xpp3DomBuilder.build(new InputStreamReader(fileInputStream, UTF_8));
246 assertEquals("testsuite", testSuite.getName());
247 Xpp3Dom properties = testSuite.getChild("properties");
248 assertEquals(System.getProperties().size(), properties.getChildCount());
249 Xpp3Dom child = properties.getChild(1);
250 assertFalse(isEmpty(child.getAttribute("value")));
251 assertFalse(isEmpty(child.getAttribute("name")));
252
253 Xpp3Dom[] testcase = testSuite.getChildren("testcase");
254 Xpp3Dom tca = testcase[0];
255 assertEquals(TEST_ONE, tca.getAttribute("name"));
256 assertEquals("0.012", tca.getAttribute("time"));
257 assertEquals(getClass().getName(), tca.getAttribute("classname"));
258
259 Xpp3Dom tcb = testcase[1];
260 assertEquals(TEST_TWO, tcb.getAttribute("name"));
261 assertEquals("0.013", tcb.getAttribute("time"));
262 assertEquals(getClass().getName(), tcb.getAttribute("classname"));
263 Xpp3Dom errorNode = tcb.getChild("error");
264 assertNotNull(errorNode);
265 assertEquals("A fud msg", errorNode.getAttribute("message"));
266 assertEquals("fail at foo", errorNode.getAttribute("type"));
267 assertEquals(
268 stdOutPrefix + "<null>! &#0;&#31;",
269 tcb.getChild("system-out").getValue());
270
271 assertEquals(
272 stdErrPrefix + "?&-&£ &#0;&#31;",
273 tcb.getChild("system-err").getValue());
274 }
275
276 @Test
277 public void testOutputRerunFlakyFailure() throws IOException {
278 WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
279 new SimpleReportEntry(NORMAL_RUN, 0L, getClass().getName(), null, TEST_ONE, null, 12),
280 ReportEntryType.SUCCESS,
281 1771085631L,
282 12,
283 null,
284 null,
285 systemProps());
286 expectedReportFile = new File(reportDir, "TEST-" + getClass().getName() + ".xml");
287
288 stats.testSucceeded(testSetReportEntry);
289 StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter("A fud msg", "trimmed", "fail at foo");
290 StackTraceWriter stackTraceWriterTwo =
291 new DeserializedStacktraceWriter("A fud msg two", "trimmed two", "fail at foo two");
292
293 String firstRunOut = "first run out";
294 String firstRunErr = "first run err";
295 String secondRunOut = "second run out";
296 String secondRunErr = "second run err";
297
298 String cls = getClass().getName();
299 WrappedReportEntry testTwoFirstError = new WrappedReportEntry(
300 new SimpleReportEntry(NORMAL_RUN, 0L, cls, null, TEST_TWO, null, stackTraceWriterOne, 5),
301 ReportEntryType.ERROR,
302 1771085631L,
303 5,
304 createStdOutput(firstRunOut),
305 createStdOutput(firstRunErr));
306
307 WrappedReportEntry testTwoSecondError = new WrappedReportEntry(
308 new SimpleReportEntry(RERUN_TEST_AFTER_FAILURE, 1L, cls, null, TEST_TWO, null, stackTraceWriterTwo, 13),
309 ReportEntryType.ERROR,
310 1771085631L,
311 13,
312 createStdOutput(secondRunOut),
313 createStdOutput(secondRunErr));
314
315 WrappedReportEntry testThreeFirstRun = new WrappedReportEntry(
316 new SimpleReportEntry(NORMAL_RUN, 2L, cls, null, TEST_THREE, null, stackTraceWriterOne, 13),
317 ReportEntryType.FAILURE,
318 1771085631L,
319 13,
320 createStdOutput(firstRunOut),
321 createStdOutput(firstRunErr));
322
323 WrappedReportEntry testThreeSecondRun = new WrappedReportEntry(
324 new SimpleReportEntry(
325 RERUN_TEST_AFTER_FAILURE, 3L, cls, null, TEST_THREE, null, stackTraceWriterTwo, 2),
326 ReportEntryType.SUCCESS,
327 1771085631L,
328 2,
329 createStdOutput(secondRunOut),
330 createStdOutput(secondRunErr));
331
332 stats.testSucceeded(testTwoFirstError);
333 stats.testSucceeded(testThreeFirstRun);
334 rerunStats.testSucceeded(testTwoSecondError);
335 rerunStats.testSucceeded(testThreeSecondRun);
336
337 StatelessXmlReporter reporter = new StatelessXmlReporter(
338 reportDir,
339 null,
340 false,
341 1,
342 new HashMap<String, Deque<WrappedReportEntry>>(),
343 XSD,
344 "3.0.2",
345 false,
346 false,
347 false,
348 false,
349 true,
350 true,
351 false);
352
353 reporter.testSetCompleted(testSetReportEntry, stats);
354 reporter.testSetCompleted(testSetReportEntry, rerunStats);
355
356 FileInputStream fileInputStream = new FileInputStream(expectedReportFile);
357
358 Xpp3Dom testSuite = Xpp3DomBuilder.build(new InputStreamReader(fileInputStream, UTF_8));
359 assertEquals("testsuite", testSuite.getName());
360 assertEquals("0.012", testSuite.getAttribute("time"));
361 Xpp3Dom properties = testSuite.getChild("properties");
362 assertEquals(System.getProperties().size(), properties.getChildCount());
363 Xpp3Dom child = properties.getChild(1);
364 assertFalse(isEmpty(child.getAttribute("value")));
365 assertFalse(isEmpty(child.getAttribute("name")));
366
367 Xpp3Dom[] testcase = testSuite.getChildren("testcase");
368 Xpp3Dom testCaseOne = testcase[0];
369 assertEquals(TEST_ONE, testCaseOne.getAttribute("name"));
370 assertEquals("0.012", testCaseOne.getAttribute("time"));
371 assertEquals(getClass().getName(), testCaseOne.getAttribute("classname"));
372
373 Xpp3Dom testCaseTwo = testcase[1];
374 assertEquals(TEST_TWO, testCaseTwo.getAttribute("name"));
375
376 assertEquals("0.005", testCaseTwo.getAttribute("time"));
377 assertEquals(getClass().getName(), testCaseTwo.getAttribute("classname"));
378 Xpp3Dom errorNode = testCaseTwo.getChild("error");
379 Xpp3Dom rerunErrorNode = testCaseTwo.getChild("rerunError");
380 assertNotNull(errorNode);
381 assertNotNull(rerunErrorNode);
382
383 assertEquals("A fud msg", errorNode.getAttribute("message"));
384 assertEquals("fail at foo", errorNode.getAttribute("type"));
385
386
387 assertEquals(firstRunOut, testCaseTwo.getChild("system-out").getValue());
388 assertEquals(firstRunErr, testCaseTwo.getChild("system-err").getValue());
389 assertEquals(secondRunOut, rerunErrorNode.getChild("system-out").getValue());
390 assertEquals(secondRunErr, rerunErrorNode.getChild("system-err").getValue());
391 assertEquals("A fud msg two", rerunErrorNode.getAttribute("message"));
392 assertEquals("fail at foo two", rerunErrorNode.getAttribute("type"));
393
394
395 Xpp3Dom testCaseThree = testcase[2];
396 assertEquals(TEST_THREE, testCaseThree.getAttribute("name"));
397
398 assertEquals("0.002", testCaseThree.getAttribute("time"));
399 assertEquals(getClass().getName(), testCaseThree.getAttribute("classname"));
400 Xpp3Dom flakyFailureNode = testCaseThree.getChild("flakyFailure");
401 assertNotNull(flakyFailureNode);
402 assertEquals(firstRunOut, flakyFailureNode.getChild("system-out").getValue());
403 assertEquals(firstRunErr, flakyFailureNode.getChild("system-err").getValue());
404
405 assertNull(testCaseThree.getChild("system-out"));
406 assertNull(testCaseThree.getChild("system-err"));
407 }
408
409 @Test
410 public void testOutputRerunFlakyAssumption() throws IOException {
411 expectedReportFile = new File(reportDir, "TEST-" + getClass().getName() + ".xml");
412
413 StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter("A fud msg", "trimmed", "fail at foo");
414
415 StackTraceWriter stackTraceWriterTwo =
416 new DeserializedStacktraceWriter("A fud msg two", "trimmed two", "fail at foo two");
417
418 String firstRunOut = "first run out";
419 String firstRunErr = "first run err";
420 String secondRunOut = "second run out";
421 String secondRunErr = "second run err";
422
423 WrappedReportEntry testTwoFirstError = new WrappedReportEntry(
424 new SimpleReportEntry(
425 NORMAL_RUN, 1L, getClass().getName(), null, TEST_TWO, null, stackTraceWriterOne, 5),
426 ERROR,
427 1771085631L,
428 5,
429 createStdOutput(firstRunOut),
430 createStdOutput(firstRunErr));
431
432 stats.testSucceeded(testTwoFirstError);
433
434 WrappedReportEntry testTwoSecondError = new WrappedReportEntry(
435 new SimpleReportEntry(
436 RERUN_TEST_AFTER_FAILURE,
437 1L,
438 getClass().getName(),
439 null,
440 TEST_TWO,
441 null,
442 stackTraceWriterTwo,
443 13),
444 SKIPPED,
445 1771085631L,
446 13,
447 createStdOutput(secondRunOut),
448 createStdOutput(secondRunErr));
449
450 rerunStats.testSucceeded(testTwoSecondError);
451
452 StatelessXmlReporter reporter = new StatelessXmlReporter(
453 reportDir,
454 null,
455 false,
456 1,
457 new HashMap<>(),
458 XSD,
459 "3.0.2",
460 false,
461 false,
462 false,
463 false,
464 true,
465 true,
466 false);
467
468 WrappedReportEntry testSetReportEntry = new WrappedReportEntry(
469 new SimpleReportEntry(
470 RERUN_TEST_AFTER_FAILURE, 1L, getClass().getName(), null, null, null, stackTraceWriterOne, 5),
471 ERROR,
472 1771085631L,
473 20,
474 createStdOutput(firstRunOut),
475 createStdOutput(firstRunErr));
476
477 reporter.testSetCompleted(testSetReportEntry, stats);
478 reporter.testSetCompleted(testSetReportEntry, rerunStats);
479
480 FileInputStream fileInputStream = new FileInputStream(expectedReportFile);
481
482 Xpp3Dom testSuite = Xpp3DomBuilder.build(new InputStreamReader(fileInputStream, UTF_8));
483 assertEquals("testsuite", testSuite.getName());
484 assertEquals("0.02", testSuite.getAttribute("time"));
485
486 Xpp3Dom[] testcase = testSuite.getChildren("testcase");
487 assertEquals(1, testcase.length);
488 Xpp3Dom testCaseOne = testcase[0];
489 assertEquals(getClass().getName(), testCaseOne.getAttribute("classname"));
490 assertEquals(TEST_TWO, testCaseOne.getAttribute("name"));
491 assertEquals("0.005", testCaseOne.getAttribute("time"));
492
493 Xpp3Dom[] testCaseElements = testCaseOne.getChildren();
494 assertEquals(3, testCaseElements.length);
495 assertEquals("error", testCaseElements[0].getName());
496 assertEquals("system-out", testCaseElements[1].getName());
497 assertEquals("system-err", testCaseElements[2].getName());
498 long linesWithComments = readAllLines(expectedReportFile.toPath(), UTF_8).stream()
499 .filter(line -> line.contains("<!-- a skipped test execution in re-run phase -->"))
500 .count();
501 assertEquals(1, linesWithComments);
502 }
503
504 @Test
505 public void testNoWritesOnDeferredFile() throws Exception {
506 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
507 out.free();
508 out.write("a", false, null);
509 assertThat((boolean) getInternalState(out, "isDirty")).isFalse();
510 }
511
512 @Test
513 public void testLengthOnDeferredFile() throws Exception {
514 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
515
516 assertThat(out.getByteCount()).isZero();
517
518 File f = File.createTempFile("test", "tmp");
519 RandomAccessFile storage = new RandomAccessFile(f, "rw");
520 setInternalState(out, "storage", storage);
521 setInternalState(out, "file", f.toPath());
522 storage.writeByte(0);
523 storage.getFD().sync();
524 assertThat(out.getByteCount()).isEqualTo(1);
525
526 storage.close();
527 assertThat(f.delete()).isTrue();
528 assertThat(out.getByteCount()).isZero();
529 out.free();
530 }
531
532 @Test
533 @SuppressWarnings("checkstyle:magicnumber")
534 public void testWritesOnDeferredFile() throws Exception {
535 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
536 for (int i = 0; i < 33_000; i++) {
537 out.write("A", false, null);
538 out.write("B", true, null);
539 }
540 out.write(null, false, null);
541 out.write(null, true, null);
542
543 assertThat(out.getByteCount()).isEqualTo(33_000 * (1 + 1 + NL.length()) + 4 + 4 + NL.length());
544
545 StringBuilder expectedContent = new StringBuilder(150_000);
546 for (int i = 0; i < 33_000; i++) {
547 expectedContent.append('A').append('B').append(NL);
548 }
549 expectedContent.append("null").append("null").append(NL);
550 ByteArrayOutputStream read = new ByteArrayOutputStream(150_000);
551 out.writeTo(read);
552 assertThat(read.toString()).isEqualTo(expectedContent.toString());
553
554 out.free();
555 }
556
557 @Test
558 public void testFreeOnDeferredFile() throws Exception {
559 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
560 setInternalState(out, "cache", ByteBuffer.allocate(0));
561 Path path = mock(Path.class);
562 File file = mock(File.class);
563 when(path.toFile()).thenReturn(file);
564 setInternalState(out, "file", path);
565 RandomAccessFile storage = mock(RandomAccessFile.class);
566 doThrow(IOException.class).when(storage).close();
567 setInternalState(out, "storage", storage);
568 out.free();
569 assertThat((boolean) getInternalState(out, "closed")).isTrue();
570 verify(file, times(1)).deleteOnExit();
571 }
572
573 @Test
574 public void testCacheOnDeferredFile() throws Exception {
575 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
576 byte[] b1 = invokeMethod(out, "getLargeCache", 1);
577 byte[] b2 = invokeMethod(out, "getLargeCache", 1);
578 assertThat(b1).isSameAs(b2);
579 assertThat(b1).hasSize(1);
580
581 byte[] b3 = invokeMethod(out, "getLargeCache", 2);
582 assertThat(b3).isNotSameAs(b1);
583 assertThat(b3).hasSize(2);
584
585 byte[] b4 = invokeMethod(out, "getLargeCache", 1);
586 assertThat(b4).isSameAs(b3);
587 assertThat(b3).hasSize(2);
588 }
589
590 @Test
591 public void testSyncOnDeferredFile() throws Exception {
592 Utf8RecodingDeferredFileOutputStream out = new Utf8RecodingDeferredFileOutputStream("test");
593 Buffer cache = ByteBuffer.wrap(new byte[] {1, 2, 3});
594 cache.position(3);
595 setInternalState(out, "cache", cache);
596 assertThat((boolean) getInternalState(out, "isDirty")).isFalse();
597 setInternalState(out, "isDirty", true);
598 File file = new File(reportDir, "test");
599 setInternalState(out, "file", file.toPath());
600 RandomAccessFile storage = new RandomAccessFile(file, "rw");
601 setInternalState(out, "storage", storage);
602 invokeMethod(out, "sync");
603 assertThat((boolean) getInternalState(out, "isDirty")).isFalse();
604 storage.seek(0L);
605 assertThat(storage.read()).isEqualTo(1);
606 assertThat(storage.read()).isEqualTo(2);
607 assertThat(storage.read()).isEqualTo(3);
608 assertThat(storage.read()).isEqualTo(-1);
609 assertThat(storage.length()).isEqualTo(3L);
610 assertThat(cache.position()).isEqualTo(0);
611 assertThat(cache.limit()).isEqualTo(3);
612 storage.seek(3L);
613 invokeMethod(out, "sync");
614 assertThat((boolean) getInternalState(out, "isDirty")).isFalse();
615 assertThat(storage.length()).isEqualTo(3L);
616 assertThat(out.getByteCount()).isEqualTo(3L);
617 assertThat((boolean) getInternalState(out, "closed")).isFalse();
618 out.free();
619 assertThat((boolean) getInternalState(out, "closed")).isTrue();
620
621 out.free();
622 assertThat((boolean) getInternalState(out, "closed")).isTrue();
623 }
624
625 @Test
626 public void testReporterHandlesATestWithoutMessageAndWithEmptyStackTrace() {
627 StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter(null, null, "");
628
629 WrappedReportEntry testReport = new WrappedReportEntry(
630 new SimpleReportEntry(
631 NORMAL_RUN, 1L, getClass().getName(), null, "a test name", null, stackTraceWriterOne, 5),
632 ERROR,
633 1771085631L,
634 5,
635 null,
636 null);
637
638 StatelessXmlReporter reporter = new StatelessXmlReporter(
639 reportDir,
640 null,
641 false,
642 1,
643 new HashMap<>(),
644 XSD,
645 "3.0.2",
646 false,
647 false,
648 false,
649 false,
650 true,
651 true,
652 false);
653
654 reporter.testSetCompleted(testReport, stats);
655 }
656
657 private boolean defaultCharsetSupportsSpecialChar() {
658
659 return "\u0115\u00DC".equals(new String("\u0115\u00DC".getBytes()));
660 }
661
662 private Utf8RecodingDeferredFileOutputStream createStdOutput(String content) throws IOException {
663 Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream("fds2");
664 stdOut.write(content, false, null);
665 return stdOut;
666 }
667 }