#include #include #include #include #include #include namespace CppUnit { CompilerOutputter::CompilerOutputter( TestResultCollector *result, std::ostream &stream, const std::string &locationFormat ) : m_result( result ) , m_stream( stream ) , m_locationFormat( locationFormat ) { } CompilerOutputter::~CompilerOutputter() { } void CompilerOutputter::setLocationFormat( const std::string &locationFormat ) { m_locationFormat = locationFormat; } CompilerOutputter * CompilerOutputter::defaultOutputter( TestResultCollector *result, std::ostream &stream ) { return new CompilerOutputter( result, stream ); } void CompilerOutputter::write() { if ( m_result->wasSuccessful() ) printSuccess(); else printFailureReport(); } void CompilerOutputter::printSuccess() { m_stream << "OK (" << m_result->runTests() << ")" << std::endl; } void CompilerOutputter::printFailureReport() { printFailuresList(); printStatistics(); } void CompilerOutputter::printFailuresList() { for ( int index =0; index < m_result->testFailuresTotal(); ++index) { printFailureDetail( m_result->failures()[ index ] ); } } void CompilerOutputter::printFailureDetail( TestFailure *failure ) { printFailureLocation( failure->sourceLine() ); printFailureType( failure ); printFailedTestName( failure ); printFailureMessage( failure ); } void CompilerOutputter::printFailureLocation( SourceLine sourceLine ) { if ( !sourceLine.isValid() ) { m_stream << "##Failure Location unknown## : "; return; } std::string location; for ( int index = 0; index < m_locationFormat.length(); ++index ) { char c = m_locationFormat[ index ]; if ( c == '%' && ( index+1 < m_locationFormat.length() ) ) { char command = m_locationFormat[index+1]; if ( processLocationFormatCommand( command, sourceLine ) ) { ++index; continue; } } m_stream << c; } } bool CompilerOutputter::processLocationFormatCommand( char command, const SourceLine &sourceLine ) { switch ( command ) { case 'p': m_stream << sourceLine.fileName(); return true; case 'l': m_stream << sourceLine.lineNumber(); return true; case 'f': m_stream << extractBaseName( sourceLine.fileName() ); return true; } return false; } std::string CompilerOutputter::extractBaseName( const std::string &fileName ) const { int indexLastDirectorySeparator = fileName.find_last_of( '/' ); if ( indexLastDirectorySeparator < 0 ) indexLastDirectorySeparator = fileName.find_last_of( '\\' ); if ( indexLastDirectorySeparator < 0 ) return fileName; return fileName.substr( indexLastDirectorySeparator +1 ); } void CompilerOutputter::printFailureType( TestFailure *failure ) { m_stream << (failure->isError() ? "Error" : "Assertion"); } void CompilerOutputter::printFailedTestName( TestFailure *failure ) { m_stream << std::endl; m_stream << "Test name: " << failure->failedTestName(); } void CompilerOutputter::printFailureMessage( TestFailure *failure ) { m_stream << std::endl; Exception *thrownException = failure->thrownException(); if ( thrownException->isInstanceOf( NotEqualException::type() ) ) printNotEqualMessage( thrownException ); else printDefaultMessage( thrownException ); m_stream << std::endl; } void CompilerOutputter::printNotEqualMessage( Exception *thrownException ) { NotEqualException *e = (NotEqualException *)thrownException; m_stream << wrap( "- Expected : " + e->expectedValue() ); m_stream << std::endl; m_stream << wrap( "- Actual : " + e->actualValue() ); m_stream << std::endl; if ( !e->additionalMessage().empty() ) { m_stream << wrap( e->additionalMessage() ); m_stream << std::endl; } } void CompilerOutputter::printDefaultMessage( Exception *thrownException ) { std::string wrappedMessage = wrap( thrownException->what() ); m_stream << wrappedMessage << std::endl; } void CompilerOutputter::printStatistics() { m_stream << "Failures !!!" << std::endl; m_stream << "Run: " << m_result->runTests() << " " << "Failure total: " << m_result->testFailuresTotal() << " " << "Failures: " << m_result->testFailures() << " " << "Errors: " << m_result->testErrors() << std::endl; } std::string CompilerOutputter::wrap( std::string message ) { Lines lines = splitMessageIntoLines( message ); std::string wrapped; for ( Lines::iterator it = lines.begin(); it != lines.end(); ++it ) { std::string line( *it ); const int maxLineLength = 80; int index =0; while ( index < line.length() ) { std::string line( line.substr( index, maxLineLength ) ); wrapped += line; index += maxLineLength; if ( index < line.length() ) wrapped += "\n"; } wrapped += '\n'; } return wrapped; } CompilerOutputter::Lines CompilerOutputter::splitMessageIntoLines( std::string message ) { Lines lines; std::string::iterator itStart = message.begin(); while ( true ) { std::string::iterator itEol = std::find( itStart, message.end(), '\n' ); lines.push_back( message.substr( itStart - message.begin(), itEol - itStart ) ); if ( itEol == message.end() ) break; itStart = itEol +1; } return lines; } } // namespace CppUnit