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