1 package org.apache.maven.plugin.surefire.report;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import junit.framework.TestCase;
23 import org.apache.maven.plugin.surefire.booterclient.output.DeserializedStacktraceWriter;
24 import org.apache.maven.shared.utils.StringUtils;
25 import org.apache.maven.shared.utils.xml.Xpp3Dom;
26 import org.apache.maven.shared.utils.xml.Xpp3DomBuilder;
27 import org.apache.maven.surefire.report.ReportEntry;
28 import org.apache.maven.surefire.report.SimpleReportEntry;
29 import org.apache.maven.surefire.report.StackTraceWriter;
30
31 import java.io.File;
32 import java.io.FileInputStream;
33 import java.io.IOException;
34 import java.io.InputStreamReader;
35 import java.util.HashMap;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.concurrent.ConcurrentHashMap;
39 import java.util.concurrent.atomic.AtomicInteger;
40
41 import static java.nio.charset.StandardCharsets.UTF_8;
42 import static org.apache.maven.surefire.util.internal.ObjectUtils.systemProps;
43
44 @SuppressWarnings( "ResultOfMethodCallIgnored" )
45 public class StatelessXmlReporterTest
46 extends TestCase
47 {
48 private static final String XSD =
49 "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd";
50 private final static String TEST_ONE = "aTestMethod";
51 private final static String TEST_TWO = "bTestMethod";
52 private final static String TEST_THREE = "cTestMethod";
53 private static final AtomicInteger FOLDER_POSTFIX = new AtomicInteger();
54
55 private TestSetStats stats;
56 private TestSetStats rerunStats;
57 private File expectedReportFile;
58 private File reportDir;
59
60 @Override
61 protected void setUp()
62 throws Exception
63 {
64 stats = new TestSetStats( false, true );
65 rerunStats = new TestSetStats( false, true );
66
67 File basedir = new File( "." );
68 File target = new File( basedir.getCanonicalFile(), "target" );
69 target.mkdir();
70 String reportRelDir = getClass().getSimpleName() + "-" + FOLDER_POSTFIX.incrementAndGet();
71 reportDir = new File( target, reportRelDir );
72 reportDir.mkdir();
73 }
74
75 @Override
76 protected void tearDown()
77 {
78 if ( expectedReportFile != null )
79 {
80 expectedReportFile.delete();
81 }
82 }
83
84 public void testFileNameWithoutSuffix()
85 {
86 StatelessXmlReporter reporter =
87 new StatelessXmlReporter( reportDir, null, false, 0,
88 new ConcurrentHashMap<String, Map<String, List<WrappedReportEntry>>>(), XSD );
89 reporter.cleanTestHistoryMap();
90
91 ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), getClass().getName(), 12 );
92 WrappedReportEntry testSetReportEntry =
93 new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() );
94 stats.testSucceeded( testSetReportEntry );
95 reporter.testSetCompleted( testSetReportEntry, stats );
96
97 expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" );
98 assertTrue( "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist",
99 expectedReportFile.exists() );
100 }
101
102
103 public void testAllFieldsSerialized()
104 throws IOException
105 {
106 ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), TEST_ONE, 12 );
107 WrappedReportEntry testSetReportEntry =
108 new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() );
109 expectedReportFile = new File( reportDir, "TEST-" + TEST_ONE + ".xml" );
110
111 stats.testSucceeded( testSetReportEntry );
112 StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "A fud msg", "trimmed", "fail at foo" );
113 Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream( "fds" );
114 String stdOutPrefix;
115 String stdErrPrefix;
116 if ( defaultCharsetSupportsSpecialChar() )
117 {
118 stdErrPrefix = "std-\u0115rr";
119 stdOutPrefix = "st]]>d-o\u00DCt";
120 }
121 else
122 {
123 stdErrPrefix = "std-err";
124 stdOutPrefix = "st]]>d-out";
125 }
126
127 byte[] stdOutBytes = (stdOutPrefix + "<null>!\u0020\u0000\u001F").getBytes();
128 stdOut.write( stdOutBytes, 0, stdOutBytes.length );
129
130 Utf8RecodingDeferredFileOutputStream stdErr = new Utf8RecodingDeferredFileOutputStream( "fds" );
131
132
133 byte[] stdErrBytes = (stdErrPrefix + "?&-&£\u0020\u0000\u001F").getBytes();
134 stdErr.write( stdErrBytes, 0, stdErrBytes.length );
135 WrappedReportEntry t2 =
136 new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriter, 13 ),
137 ReportEntryType.ERROR, 13, stdOut, stdErr );
138
139 stats.testSucceeded( t2 );
140 StatelessXmlReporter reporter = new StatelessXmlReporter( reportDir, null, false, 0,
141 new ConcurrentHashMap<String, Map<String, List<WrappedReportEntry>>>(), XSD );
142 reporter.testSetCompleted( testSetReportEntry, stats );
143
144 FileInputStream fileInputStream = new FileInputStream( expectedReportFile );
145
146 Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8) );
147 assertEquals( "testsuite", testSuite.getName() );
148 Xpp3Dom properties = testSuite.getChild( "properties" );
149 assertEquals( System.getProperties().size(), properties.getChildCount() );
150 Xpp3Dom child = properties.getChild( 1 );
151 assertFalse( StringUtils.isEmpty( child.getAttribute( "value" ) ) );
152 assertFalse( StringUtils.isEmpty( child.getAttribute( "name" ) ) );
153
154 Xpp3Dom[] testcase = testSuite.getChildren( "testcase" );
155 Xpp3Dom tca = testcase[0];
156 assertEquals( TEST_ONE, tca.getAttribute( "name" ) );
157 assertEquals( "0.012", tca.getAttribute( "time" ) );
158 assertEquals( getClass().getName(), tca.getAttribute( "classname" ) );
159
160 Xpp3Dom tcb = testcase[1];
161 assertEquals( TEST_TWO, tcb.getAttribute( "name" ) );
162 assertEquals( "0.013", tcb.getAttribute( "time" ) );
163 assertEquals( Inner.class.getName(), tcb.getAttribute( "classname" ) );
164 Xpp3Dom errorNode = tcb.getChild( "error" );
165 assertNotNull( errorNode );
166 assertEquals( "A fud msg", errorNode.getAttribute( "message" ) );
167 assertEquals( "fail at foo", errorNode.getAttribute( "type" ) );
168 assertEquals( stdOutPrefix + "<null>! &#0;&#31;", tcb.getChild( "system-out" ).getValue() );
169
170
171 assertEquals( stdErrPrefix + "?&-&£ &#0;&#31;", tcb.getChild( "system-err" ).getValue() );
172 }
173
174 public void testOutputRerunFlakyFailure()
175 throws IOException
176 {
177 ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), TEST_ONE, 12 );
178
179 WrappedReportEntry testSetReportEntry =
180 new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() );
181 expectedReportFile = new File( reportDir, "TEST-" + TEST_ONE + ".xml" );
182
183 stats.testSucceeded( testSetReportEntry );
184 StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter( "A fud msg", "trimmed",
185 "fail at foo" );
186 StackTraceWriter stackTraceWriterTwo =
187 new DeserializedStacktraceWriter( "A fud msg two", "trimmed two", "fail at foo two" );
188
189 String firstRunOut = "first run out";
190 String firstRunErr = "first run err";
191 String secondRunOut = "second run out";
192 String secondRunErr = "second run err";
193
194 WrappedReportEntry testTwoFirstError =
195 new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriterOne, 5 ),
196 ReportEntryType.ERROR, 5, createStdOutput( firstRunOut ),
197 createStdOutput( firstRunErr ) );
198
199 WrappedReportEntry testTwoSecondError =
200 new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_TWO, stackTraceWriterTwo, 13 ),
201 ReportEntryType.ERROR, 13, createStdOutput( secondRunOut ),
202 createStdOutput( secondRunErr ) );
203
204 WrappedReportEntry testThreeFirstRun =
205 new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_THREE, stackTraceWriterOne, 13 ),
206 ReportEntryType.FAILURE, 13, createStdOutput( firstRunOut ),
207 createStdOutput( firstRunErr ) );
208
209 WrappedReportEntry testThreeSecondRun =
210 new WrappedReportEntry( new SimpleReportEntry( Inner.class.getName(), TEST_THREE, stackTraceWriterTwo, 2 ),
211 ReportEntryType.SUCCESS, 2, createStdOutput( secondRunOut ),
212 createStdOutput( secondRunErr ) );
213
214 stats.testSucceeded( testTwoFirstError );
215 stats.testSucceeded( testThreeFirstRun );
216 rerunStats.testSucceeded( testTwoSecondError );
217 rerunStats.testSucceeded( testThreeSecondRun );
218
219 StatelessXmlReporter reporter =
220 new StatelessXmlReporter( reportDir, null, false, 1,
221 new HashMap<String, Map<String, List<WrappedReportEntry>>>(), XSD );
222
223 reporter.testSetCompleted( testSetReportEntry, stats );
224 reporter.testSetCompleted( testSetReportEntry, rerunStats );
225
226 FileInputStream fileInputStream = new FileInputStream( expectedReportFile );
227
228 Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8 ) );
229 assertEquals( "testsuite", testSuite.getName() );
230 assertEquals( "0.012", testSuite.getAttribute( "time" ) );
231 Xpp3Dom properties = testSuite.getChild( "properties" );
232 assertEquals( System.getProperties().size(), properties.getChildCount() );
233 Xpp3Dom child = properties.getChild( 1 );
234 assertFalse( StringUtils.isEmpty( child.getAttribute( "value" ) ) );
235 assertFalse( StringUtils.isEmpty( child.getAttribute( "name" ) ) );
236
237 Xpp3Dom[] testcase = testSuite.getChildren( "testcase" );
238 Xpp3Dom testCaseOne = testcase[0];
239 assertEquals( TEST_ONE, testCaseOne.getAttribute( "name" ) );
240 assertEquals( "0.012", testCaseOne.getAttribute( "time" ) );
241 assertEquals( getClass().getName(), testCaseOne.getAttribute( "classname" ) );
242
243 Xpp3Dom testCaseTwo = testcase[1];
244 assertEquals( TEST_TWO, testCaseTwo.getAttribute( "name" ) );
245
246 assertEquals( "0.005", testCaseTwo.getAttribute( "time" ) );
247 assertEquals( Inner.class.getName(), testCaseTwo.getAttribute( "classname" ) );
248 Xpp3Dom errorNode = testCaseTwo.getChild( "error" );
249 Xpp3Dom rerunErrorNode = testCaseTwo.getChild( "rerunError" );
250 assertNotNull( errorNode );
251 assertNotNull( rerunErrorNode );
252
253 assertEquals( "A fud msg", errorNode.getAttribute( "message" ) );
254 assertEquals( "fail at foo", errorNode.getAttribute( "type" ) );
255
256
257 assertEquals( firstRunOut, testCaseTwo.getChild( "system-out" ).getValue() );
258 assertEquals( firstRunErr, testCaseTwo.getChild( "system-err" ).getValue() );
259 assertEquals( secondRunOut, rerunErrorNode.getChild( "system-out" ).getValue() );
260 assertEquals( secondRunErr, rerunErrorNode.getChild( "system-err" ).getValue() );
261 assertEquals( "A fud msg two", rerunErrorNode.getAttribute( "message" ) );
262 assertEquals( "fail at foo two", rerunErrorNode.getAttribute( "type" ) );
263
264
265 Xpp3Dom testCaseThree = testcase[2];
266 assertEquals( TEST_THREE, testCaseThree.getAttribute( "name" ) );
267
268 assertEquals( "0.002", testCaseThree.getAttribute( "time" ) );
269 assertEquals( Inner.class.getName(), testCaseThree.getAttribute( "classname" ) );
270 Xpp3Dom flakyFailureNode = testCaseThree.getChild( "flakyFailure" );
271 assertNotNull( flakyFailureNode );
272 assertEquals( firstRunOut, flakyFailureNode.getChild( "system-out" ).getValue() );
273 assertEquals( firstRunErr, flakyFailureNode.getChild( "system-err" ).getValue() );
274
275 assertNull( testCaseThree.getChild( "system-out" ) );
276 assertNull( testCaseThree.getChild( "system-err" ) );
277 }
278
279 private boolean defaultCharsetSupportsSpecialChar()
280 {
281
282 return "\u0115\u00DC".equals( new String( "\u0115\u00DC".getBytes() ) );
283 }
284
285 private Utf8RecodingDeferredFileOutputStream createStdOutput( String content )
286 throws IOException
287 {
288 Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream( "fds2" );
289 stdOut.write( content.getBytes(), 0, content.length() );
290 return stdOut;
291 }
292
293 class Inner
294 {
295
296 }
297 }