blob: 15b7ed8c5e0b48d8e52ee2a5fbf2dfab9b6317db [file] [log] [blame]
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 java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import org.apache.maven.plugin.surefire.log.api.ConsoleLogger;
import org.apache.maven.plugin.surefire.runorder.StatisticsReporter;
import org.apache.maven.surefire.extensions.ConsoleOutputReportEventListener;
import org.apache.maven.surefire.extensions.StatelessReportEventListener;
import org.apache.maven.surefire.extensions.StatelessTestsetInfoConsoleReportEventListener;
import org.apache.maven.surefire.extensions.StatelessTestsetInfoFileReportEventListener;
import org.apache.maven.surefire.api.report.ConsoleOutputReceiver;
import org.apache.maven.surefire.api.report.ReportEntry;
import org.apache.maven.surefire.api.report.RunListener;
import org.apache.maven.surefire.api.report.RunMode;
import org.apache.maven.surefire.api.report.TestSetReportEntry;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.ERROR;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.FAILURE;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.SKIPPED;
import static org.apache.maven.plugin.surefire.report.ReportEntryType.SUCCESS;
import static org.apache.maven.surefire.api.report.RunMode.NORMAL_RUN;
import static java.util.Objects.requireNonNull;
/**
* Reports data for a single test set.
* <br>
*
* @author Kristian Rosenvold
*/
public class TestSetRunListener
implements RunListener, ConsoleOutputReceiver, ConsoleLogger
{
private final Queue<TestMethodStats> testMethodStats = new ConcurrentLinkedQueue<>();
private final TestSetStats detailsForThis;
private final ConsoleOutputReportEventListener consoleOutputReceiver;
private final boolean briefOrPlainFormat;
private final StatelessReportEventListener<WrappedReportEntry, TestSetStats> simpleXMLReporter;
private final StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats> consoleReporter;
private final StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats> fileReporter;
private final StatisticsReporter statisticsReporter;
private Utf8RecodingDeferredFileOutputStream testStdOut = initDeferred( "stdout" );
private Utf8RecodingDeferredFileOutputStream testStdErr = initDeferred( "stderr" );
private volatile RunMode runMode = NORMAL_RUN;
@SuppressWarnings( "checkstyle:parameternumber" )
public TestSetRunListener( StatelessTestsetInfoConsoleReportEventListener<WrappedReportEntry, TestSetStats>
consoleReporter,
StatelessTestsetInfoFileReportEventListener<WrappedReportEntry, TestSetStats>
fileReporter,
StatelessReportEventListener<WrappedReportEntry, TestSetStats> simpleXMLReporter,
ConsoleOutputReportEventListener consoleOutputReceiver,
StatisticsReporter statisticsReporter, boolean trimStackTrace,
boolean isPlainFormat, boolean briefOrPlainFormat )
{
this.consoleReporter = consoleReporter;
this.fileReporter = fileReporter;
this.statisticsReporter = statisticsReporter;
this.simpleXMLReporter = simpleXMLReporter;
this.consoleOutputReceiver = consoleOutputReceiver;
this.briefOrPlainFormat = briefOrPlainFormat;
detailsForThis = new TestSetStats( trimStackTrace, isPlainFormat );
}
@Override
public boolean isDebugEnabled()
{
return consoleReporter.getConsoleLogger().isDebugEnabled();
}
@Override
public void debug( String message )
{
consoleReporter.getConsoleLogger().debug( trimTrailingNewLine( message ) );
}
@Override
public boolean isInfoEnabled()
{
return consoleReporter.getConsoleLogger().isInfoEnabled();
}
@Override
public void info( String message )
{
consoleReporter.getConsoleLogger().info( trimTrailingNewLine( message ) );
}
@Override
public boolean isWarnEnabled()
{
return consoleReporter.getConsoleLogger().isWarnEnabled();
}
@Override
public void warning( String message )
{
consoleReporter.getConsoleLogger().warning( trimTrailingNewLine( message ) );
}
@Override
public boolean isErrorEnabled()
{
return consoleReporter.getConsoleLogger().isErrorEnabled();
}
@Override
public void error( String message )
{
consoleReporter.getConsoleLogger().error( trimTrailingNewLine( message ) );
}
@Override
public void error( String message, Throwable t )
{
consoleReporter.getConsoleLogger().error( trimTrailingNewLine( message ), t );
}
@Override
public void error( Throwable t )
{
consoleReporter.getConsoleLogger().error( t );
}
@Override
public void writeTestOutput( String output, boolean newLine, boolean stdout )
{
try
{
Utf8RecodingDeferredFileOutputStream stream = stdout ? testStdOut : testStdErr;
stream.write( output, newLine );
consoleOutputReceiver.writeTestOutput( output, newLine, stdout );
}
catch ( IOException e )
{
throw new RuntimeException( e );
}
}
@Override
public void testSetStarting( TestSetReportEntry report )
{
detailsForThis.testSetStart();
consoleReporter.testSetStarting( report );
consoleOutputReceiver.testSetStarting( report );
}
private void clearCapture()
{
testStdOut = initDeferred( "stdout" );
testStdErr = initDeferred( "stderr" );
}
@Override
public void testSetCompleted( TestSetReportEntry report )
{
final WrappedReportEntry wrap = wrapTestSet( report );
final List<String> testResults =
briefOrPlainFormat ? detailsForThis.getTestResults() : Collections.<String>emptyList();
fileReporter.testSetCompleted( wrap, detailsForThis, testResults );
simpleXMLReporter.testSetCompleted( wrap, detailsForThis );
statisticsReporter.testSetCompleted();
consoleReporter.testSetCompleted( wrap, detailsForThis, testResults );
consoleOutputReceiver.testSetCompleted( wrap );
consoleReporter.reset();
wrap.getStdout().free();
wrap.getStdErr().free();
addTestMethodStats();
detailsForThis.reset();
clearCapture();
}
// ----------------------------------------------------------------------
// Test callback methods:
// ----------------------------------------------------------------------
@Override
public void testStarting( ReportEntry report )
{
detailsForThis.testStart();
}
@Override
public void testSucceeded( ReportEntry reportEntry )
{
WrappedReportEntry wrapped = wrap( reportEntry, SUCCESS );
detailsForThis.testSucceeded( wrapped );
statisticsReporter.testSucceeded( reportEntry );
clearCapture();
}
@Override
public void testError( ReportEntry reportEntry )
{
WrappedReportEntry wrapped = wrap( reportEntry, ERROR );
detailsForThis.testError( wrapped );
statisticsReporter.testError( reportEntry );
clearCapture();
}
@Override
public void testFailed( ReportEntry reportEntry )
{
WrappedReportEntry wrapped = wrap( reportEntry, FAILURE );
detailsForThis.testFailure( wrapped );
statisticsReporter.testFailed( reportEntry );
clearCapture();
}
// ----------------------------------------------------------------------
// Counters
// ----------------------------------------------------------------------
@Override
public void testSkipped( ReportEntry reportEntry )
{
WrappedReportEntry wrapped = wrap( reportEntry, SKIPPED );
detailsForThis.testSkipped( wrapped );
statisticsReporter.testSkipped( reportEntry );
clearCapture();
}
@Override
public void testExecutionSkippedByUser()
{
}
public RunMode markAs( RunMode currentRunMode )
{
RunMode runMode = this.runMode;
this.runMode = requireNonNull( currentRunMode );
return runMode;
}
@Override
public void testAssumptionFailure( ReportEntry report )
{
testSkipped( report );
}
private WrappedReportEntry wrap( ReportEntry other, ReportEntryType reportEntryType )
{
int estimatedElapsed = 0;
if ( reportEntryType != SKIPPED )
{
Integer etime = other.getElapsed();
estimatedElapsed = etime == null ? detailsForThis.getElapsedSinceLastStart() : etime;
}
return new WrappedReportEntry( other, reportEntryType, estimatedElapsed, testStdOut, testStdErr );
}
private WrappedReportEntry wrapTestSet( TestSetReportEntry other )
{
return new WrappedReportEntry( other, null, other.getElapsed() != null
? other.getElapsed()
: detailsForThis.getElapsedSinceTestSetStart(), testStdOut, testStdErr, other.getSystemProperties() );
}
public void close()
{
consoleOutputReceiver.close();
}
private void addTestMethodStats()
{
for ( WrappedReportEntry reportEntry : detailsForThis.getReportEntries() )
{
TestMethodStats methodStats =
new TestMethodStats( reportEntry.getClassMethodName(), reportEntry.getReportEntryType(),
reportEntry.getStackTraceWriter() );
testMethodStats.add( methodStats );
}
}
public Queue<TestMethodStats> getTestMethodStats()
{
return testMethodStats;
}
private static String trimTrailingNewLine( final String message )
{
final int e = message == null ? 0 : lineBoundSymbolWidth( message );
return message != null && e != 0 ? message.substring( 0, message.length() - e ) : message;
}
private static int lineBoundSymbolWidth( String message )
{
return message.endsWith( "\r\n" ) ? 2 : ( message.endsWith( "\n" ) || message.endsWith( "\r" ) ? 1 : 0 );
}
private static Utf8RecodingDeferredFileOutputStream initDeferred( String channel )
{
return new Utf8RecodingDeferredFileOutputStream( channel );
}
}