| package org.apache.maven.plugin.surefire.report; |
| |
| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| |
| import junit.framework.TestCase; |
| import org.apache.maven.plugin.surefire.booterclient.output.DeserializedStacktraceWriter; |
| import org.apache.maven.surefire.shared.utils.StringUtils; |
| import org.apache.maven.surefire.shared.utils.xml.Xpp3Dom; |
| import org.apache.maven.surefire.shared.utils.xml.Xpp3DomBuilder; |
| import org.apache.maven.surefire.api.report.ReportEntry; |
| import org.apache.maven.surefire.api.report.SimpleReportEntry; |
| import org.apache.maven.surefire.api.report.StackTraceWriter; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.util.Deque; |
| import java.util.HashMap; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.atomic.AtomicInteger; |
| |
| import static java.nio.charset.StandardCharsets.UTF_8; |
| import static org.apache.maven.surefire.api.util.internal.ObjectUtils.systemProps; |
| |
| /** |
| * |
| */ |
| @SuppressWarnings( "ResultOfMethodCallIgnored" ) |
| public class StatelessXmlReporterTest |
| extends TestCase |
| { |
| private static final String XSD = |
| "https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report-3.0.xsd"; |
| private static final String TEST_ONE = "aTestMethod"; |
| private static final String TEST_TWO = "bTestMethod"; |
| private static final String TEST_THREE = "cTestMethod"; |
| private static final AtomicInteger FOLDER_POSTFIX = new AtomicInteger(); |
| |
| private TestSetStats stats; |
| private TestSetStats rerunStats; |
| private File expectedReportFile; |
| private File reportDir; |
| |
| @Override |
| protected void setUp() |
| throws Exception |
| { |
| stats = new TestSetStats( false, true ); |
| rerunStats = new TestSetStats( false, true ); |
| |
| File basedir = new File( "." ); |
| File target = new File( basedir.getCanonicalFile(), "target" ); |
| target.mkdir(); |
| String reportRelDir = getClass().getSimpleName() + "-" + FOLDER_POSTFIX.incrementAndGet(); |
| reportDir = new File( target, reportRelDir ); |
| reportDir.mkdir(); |
| } |
| |
| @Override |
| protected void tearDown() |
| { |
| if ( expectedReportFile != null ) |
| { |
| expectedReportFile.delete(); |
| } |
| } |
| |
| public void testFileNameWithoutSuffix() |
| { |
| StatelessXmlReporter reporter = |
| new StatelessXmlReporter( reportDir, null, false, 0, |
| new ConcurrentHashMap<String, Deque<WrappedReportEntry>>(), XSD, "3.0", |
| false, false, false, false ); |
| reporter.cleanTestHistoryMap(); |
| |
| ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), null, getClass().getName(), null, 12 ); |
| WrappedReportEntry testSetReportEntry = new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, |
| 12, null, null, systemProps() ); |
| stats.testSucceeded( testSetReportEntry ); |
| reporter.testSetCompleted( testSetReportEntry, stats ); |
| |
| expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); |
| assertTrue( "Report file (" + expectedReportFile.getAbsolutePath() + ") doesn't exist", |
| expectedReportFile.exists() ); |
| } |
| |
| |
| public void testAllFieldsSerialized() |
| throws IOException |
| { |
| ReportEntry reportEntry = new SimpleReportEntry( getClass().getName(), null, TEST_ONE, null, 12 ); |
| WrappedReportEntry testSetReportEntry = |
| new WrappedReportEntry( reportEntry, ReportEntryType.SUCCESS, 12, null, null, systemProps() ); |
| expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); |
| |
| stats.testSucceeded( testSetReportEntry ); |
| StackTraceWriter stackTraceWriter = new DeserializedStacktraceWriter( "A fud msg", "trimmed", "fail at foo" ); |
| Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream( "fds" ); |
| String stdOutPrefix; |
| String stdErrPrefix; |
| if ( defaultCharsetSupportsSpecialChar() ) |
| { |
| stdErrPrefix = "std-\u0115rr"; |
| stdOutPrefix = "st]]>d-o\u00DCt"; |
| } |
| else |
| { |
| stdErrPrefix = "std-err"; |
| stdOutPrefix = "st]]>d-out"; |
| } |
| |
| stdOut.write( stdOutPrefix + "<null>!\u0020\u0000\u001F", false ); |
| |
| Utf8RecodingDeferredFileOutputStream stdErr = new Utf8RecodingDeferredFileOutputStream( "fds" ); |
| |
| stdErr.write( stdErrPrefix + "?&-&£\u0020\u0000\u001F", false ); |
| WrappedReportEntry t2 = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, |
| stackTraceWriter, 13 ), ReportEntryType.ERROR, 13, stdOut, stdErr ); |
| |
| stats.testSucceeded( t2 ); |
| StatelessXmlReporter reporter = new StatelessXmlReporter( reportDir, null, false, 0, |
| new ConcurrentHashMap<String, Deque<WrappedReportEntry>>(), XSD, "3.0", false, false, false, false ); |
| reporter.testSetCompleted( testSetReportEntry, stats ); |
| |
| FileInputStream fileInputStream = new FileInputStream( expectedReportFile ); |
| |
| Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8 ) ); |
| assertEquals( "testsuite", testSuite.getName() ); |
| Xpp3Dom properties = testSuite.getChild( "properties" ); |
| assertEquals( System.getProperties().size(), properties.getChildCount() ); |
| Xpp3Dom child = properties.getChild( 1 ); |
| assertFalse( StringUtils.isEmpty( child.getAttribute( "value" ) ) ); |
| assertFalse( StringUtils.isEmpty( child.getAttribute( "name" ) ) ); |
| |
| Xpp3Dom[] testcase = testSuite.getChildren( "testcase" ); |
| Xpp3Dom tca = testcase[0]; |
| assertEquals( TEST_ONE, tca.getAttribute( "name" ) ); |
| assertEquals( "0.012", tca.getAttribute( "time" ) ); |
| assertEquals( getClass().getName(), tca.getAttribute( "classname" ) ); |
| |
| Xpp3Dom tcb = testcase[1]; |
| assertEquals( TEST_TWO, tcb.getAttribute( "name" ) ); |
| assertEquals( "0.013", tcb.getAttribute( "time" ) ); |
| assertEquals( getClass().getName(), tcb.getAttribute( "classname" ) ); |
| Xpp3Dom errorNode = tcb.getChild( "error" ); |
| assertNotNull( errorNode ); |
| assertEquals( "A fud msg", errorNode.getAttribute( "message" ) ); |
| assertEquals( "fail at foo", errorNode.getAttribute( "type" ) ); |
| assertEquals( stdOutPrefix + "<null>! &#0;&#31;", tcb.getChild( "system-out" ).getValue() ); |
| |
| |
| assertEquals( stdErrPrefix + "?&-&£ &#0;&#31;", tcb.getChild( "system-err" ).getValue() ); |
| } |
| |
| public void testOutputRerunFlakyFailure() |
| throws IOException |
| { |
| WrappedReportEntry testSetReportEntry = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_ONE, null, 12 ), |
| ReportEntryType.SUCCESS, 12, null, null, systemProps() ); |
| expectedReportFile = new File( reportDir, "TEST-" + getClass().getName() + ".xml" ); |
| |
| stats.testSucceeded( testSetReportEntry ); |
| StackTraceWriter stackTraceWriterOne = new DeserializedStacktraceWriter( "A fud msg", "trimmed", |
| "fail at foo" ); |
| StackTraceWriter stackTraceWriterTwo = |
| new DeserializedStacktraceWriter( "A fud msg two", "trimmed two", "fail at foo two" ); |
| |
| String firstRunOut = "first run out"; |
| String firstRunErr = "first run err"; |
| String secondRunOut = "second run out"; |
| String secondRunErr = "second run err"; |
| |
| WrappedReportEntry testTwoFirstError = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, |
| stackTraceWriterOne, 5 ), ReportEntryType.ERROR, 5, createStdOutput( firstRunOut ), |
| createStdOutput( firstRunErr ) ); |
| |
| WrappedReportEntry testTwoSecondError = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_TWO, null, |
| stackTraceWriterTwo, 13 ), ReportEntryType.ERROR, 13, createStdOutput( secondRunOut ), |
| createStdOutput( secondRunErr ) ); |
| |
| WrappedReportEntry testThreeFirstRun = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_THREE, null, |
| stackTraceWriterOne, 13 ), ReportEntryType.FAILURE, 13, createStdOutput( firstRunOut ), |
| createStdOutput( firstRunErr ) ); |
| |
| WrappedReportEntry testThreeSecondRun = |
| new WrappedReportEntry( new SimpleReportEntry( getClass().getName(), null, TEST_THREE, null, |
| stackTraceWriterTwo, 2 ), ReportEntryType.SUCCESS, 2, createStdOutput( secondRunOut ), |
| createStdOutput( secondRunErr ) ); |
| |
| stats.testSucceeded( testTwoFirstError ); |
| stats.testSucceeded( testThreeFirstRun ); |
| rerunStats.testSucceeded( testTwoSecondError ); |
| rerunStats.testSucceeded( testThreeSecondRun ); |
| |
| StatelessXmlReporter reporter = |
| new StatelessXmlReporter( reportDir, null, false, 1, |
| new HashMap<String, Deque<WrappedReportEntry>>(), XSD, "3.0", false, false, false, false ); |
| |
| reporter.testSetCompleted( testSetReportEntry, stats ); |
| reporter.testSetCompleted( testSetReportEntry, rerunStats ); |
| |
| FileInputStream fileInputStream = new FileInputStream( expectedReportFile ); |
| |
| Xpp3Dom testSuite = Xpp3DomBuilder.build( new InputStreamReader( fileInputStream, UTF_8 ) ); |
| assertEquals( "testsuite", testSuite.getName() ); |
| assertEquals( "0.012", testSuite.getAttribute( "time" ) ); |
| Xpp3Dom properties = testSuite.getChild( "properties" ); |
| assertEquals( System.getProperties().size(), properties.getChildCount() ); |
| Xpp3Dom child = properties.getChild( 1 ); |
| assertFalse( StringUtils.isEmpty( child.getAttribute( "value" ) ) ); |
| assertFalse( StringUtils.isEmpty( child.getAttribute( "name" ) ) ); |
| |
| Xpp3Dom[] testcase = testSuite.getChildren( "testcase" ); |
| Xpp3Dom testCaseOne = testcase[0]; |
| assertEquals( TEST_ONE, testCaseOne.getAttribute( "name" ) ); |
| assertEquals( "0.012", testCaseOne.getAttribute( "time" ) ); |
| assertEquals( getClass().getName(), testCaseOne.getAttribute( "classname" ) ); |
| |
| Xpp3Dom testCaseTwo = testcase[1]; |
| assertEquals( TEST_TWO, testCaseTwo.getAttribute( "name" ) ); |
| // Run time for a rerun failing test is the run time of the first run |
| assertEquals( "0.005", testCaseTwo.getAttribute( "time" ) ); |
| assertEquals( getClass().getName(), testCaseTwo.getAttribute( "classname" ) ); |
| Xpp3Dom errorNode = testCaseTwo.getChild( "error" ); |
| Xpp3Dom rerunErrorNode = testCaseTwo.getChild( "rerunError" ); |
| assertNotNull( errorNode ); |
| assertNotNull( rerunErrorNode ); |
| |
| assertEquals( "A fud msg", errorNode.getAttribute( "message" ) ); |
| assertEquals( "fail at foo", errorNode.getAttribute( "type" ) ); |
| |
| // Check rerun error node contains all the information |
| assertEquals( firstRunOut, testCaseTwo.getChild( "system-out" ).getValue() ); |
| assertEquals( firstRunErr, testCaseTwo.getChild( "system-err" ).getValue() ); |
| assertEquals( secondRunOut, rerunErrorNode.getChild( "system-out" ).getValue() ); |
| assertEquals( secondRunErr, rerunErrorNode.getChild( "system-err" ).getValue() ); |
| assertEquals( "A fud msg two", rerunErrorNode.getAttribute( "message" ) ); |
| assertEquals( "fail at foo two", rerunErrorNode.getAttribute( "type" ) ); |
| |
| // Check flaky failure node |
| Xpp3Dom testCaseThree = testcase[2]; |
| assertEquals( TEST_THREE, testCaseThree.getAttribute( "name" ) ); |
| // Run time for a flaky test is the run time of the first successful run |
| assertEquals( "0.002", testCaseThree.getAttribute( "time" ) ); |
| assertEquals( getClass().getName(), testCaseThree.getAttribute( "classname" ) ); |
| Xpp3Dom flakyFailureNode = testCaseThree.getChild( "flakyFailure" ); |
| assertNotNull( flakyFailureNode ); |
| assertEquals( firstRunOut, flakyFailureNode.getChild( "system-out" ).getValue() ); |
| assertEquals( firstRunErr, flakyFailureNode.getChild( "system-err" ).getValue() ); |
| // system-out and system-err should not be present for flaky failures |
| assertNull( testCaseThree.getChild( "system-out" ) ); |
| assertNull( testCaseThree.getChild( "system-err" ) ); |
| } |
| |
| private boolean defaultCharsetSupportsSpecialChar() |
| { |
| // some charsets are not able to deal with \u0115 on both ways of the conversion |
| return "\u0115\u00DC".equals( new String( "\u0115\u00DC".getBytes() ) ); |
| } |
| |
| private Utf8RecodingDeferredFileOutputStream createStdOutput( String content ) |
| throws IOException |
| { |
| Utf8RecodingDeferredFileOutputStream stdOut = new Utf8RecodingDeferredFileOutputStream( "fds2" ); |
| stdOut.write( content, false ); |
| return stdOut; |
| } |
| } |