added cppunit unit testing framework, using cmake, stripped out the original build systems.

added starting point for Bullet unit tests, with one example unit test
Enable the option BUILD_UNIT_TESTS in cmake to build the test. Note that the test doesn't automatically run.
This commit is contained in:
erwin.coumans
2010-07-23 22:09:57 +00:00
parent 6f823687b5
commit a983353f34
139 changed files with 15575 additions and 0 deletions

View File

@@ -0,0 +1,41 @@
#include <cppunit/AdditionalMessage.h>
CPPUNIT_NS_BEGIN
AdditionalMessage::AdditionalMessage()
{
}
AdditionalMessage::AdditionalMessage( const std::string &detail1 )
{
if ( !detail1.empty() )
addDetail( detail1 );
}
AdditionalMessage::AdditionalMessage( const char *detail1 )
{
if ( detail1 && !std::string( detail1 ).empty() )
addDetail( std::string(detail1) );
}
AdditionalMessage::AdditionalMessage( const Message &other )
: SuperClass( other )
{
}
AdditionalMessage &
AdditionalMessage::operator =( const Message &other )
{
SuperClass::operator =( other );
return *this;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,101 @@
#include <cppunit/Asserter.h>
#include <cppunit/Exception.h>
#include <cppunit/Message.h>
CPPUNIT_NS_BEGIN
void
Asserter::fail( std::string message,
const SourceLine &sourceLine )
{
fail( Message( "assertion failed", message ), sourceLine );
}
void
Asserter::fail( const Message &message,
const SourceLine &sourceLine )
{
throw Exception( message, sourceLine );
}
void
Asserter::failIf( bool shouldFail,
const Message &message,
const SourceLine &sourceLine )
{
if ( shouldFail )
fail( message, sourceLine );
}
void
Asserter::failIf( bool shouldFail,
std::string message,
const SourceLine &sourceLine )
{
failIf( shouldFail, Message( "assertion failed", message ), sourceLine );
}
std::string
Asserter::makeExpected( const std::string &expectedValue )
{
return "Expected: " + expectedValue;
}
std::string
Asserter::makeActual( const std::string &actualValue )
{
return "Actual : " + actualValue;
}
Message
Asserter::makeNotEqualMessage( const std::string &expectedValue,
const std::string &actualValue,
const AdditionalMessage &additionalMessage,
const std::string &shortDescription )
{
Message message( shortDescription,
makeExpected( expectedValue ),
makeActual( actualValue ) );
message.addDetail( additionalMessage );
return message;
}
void
Asserter::failNotEqual( std::string expected,
std::string actual,
const SourceLine &sourceLine,
const AdditionalMessage &additionalMessage,
std::string shortDescription )
{
fail( makeNotEqualMessage( expected,
actual,
additionalMessage,
shortDescription ),
sourceLine );
}
void
Asserter::failNotEqualIf( bool shouldFail,
std::string expected,
std::string actual,
const SourceLine &sourceLine,
const AdditionalMessage &additionalMessage,
std::string shortDescription )
{
if ( shouldFail )
failNotEqual( expected, actual, sourceLine, additionalMessage, shortDescription );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,49 @@
#include <cppunit/Portability.h>
#if defined(CPPUNIT_HAVE_BEOS_DLL_LOADER)
#include <cppunit/plugin/DynamicLibraryManager.h>
#include <kernel/image.h>
CPPUNIT_NS_BEGIN
DynamicLibraryManager::LibraryHandle
DynamicLibraryManager::doLoadLibrary( const std::string &libraryName )
{
return (LibraryHandle)::load_add_on( libraryName.c_str() );
}
void
DynamicLibraryManager::doReleaseLibrary()
{
::unload_add_on( (image_id)m_libraryHandle );
}
DynamicLibraryManager::Symbol
DynamicLibraryManager::doFindSymbol( const std::string &symbol )
{
void *symbolPointer;
if ( ::get_image_symbol( (image_id)m_libraryHandle,
symbol.c_str(),
B_SYMBOL_TYPE_TEXT,
&symbolPointer ) == B_OK )
return symnolPointer;
return NULL;
}
std::string
DynamicLibraryManager::getLastErrorDetail() const
{
return "";
}
CPPUNIT_NS_END
#endif // defined(CPPUNIT_HAVE_BEOS_DLL_LOADER)

View File

@@ -0,0 +1,49 @@
#include <cppunit/BriefTestProgressListener.h>
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/portability/Stream.h>
CPPUNIT_NS_BEGIN
BriefTestProgressListener::BriefTestProgressListener()
: m_lastTestFailed( false )
{
}
BriefTestProgressListener::~BriefTestProgressListener()
{
}
void
BriefTestProgressListener::startTest( Test *test )
{
stdCOut() << test->getName();
stdCOut().flush();
m_lastTestFailed = false;
}
void
BriefTestProgressListener::addFailure( const TestFailure &failure )
{
stdCOut() << " : " << (failure.isError() ? "error" : "assertion");
m_lastTestFailed = true;
}
void
BriefTestProgressListener::endTest( Test * )
{
if ( !m_lastTestFailed )
stdCOut() << " : OK";
stdCOut() << "\n";
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,216 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/Exception.h>
#include <cppunit/SourceLine.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/CompilerOutputter.h>
#include <algorithm>
#include <cppunit/tools/StringTools.h>
CPPUNIT_NS_BEGIN
CompilerOutputter::CompilerOutputter( TestResultCollector *result,
OStream &stream,
const std::string &locationFormat )
: m_result( result )
, m_stream( stream )
, m_locationFormat( locationFormat )
, m_wrapColumn( CPPUNIT_WRAP_COLUMN )
{
}
CompilerOutputter::~CompilerOutputter()
{
}
void
CompilerOutputter::setLocationFormat( const std::string &locationFormat )
{
m_locationFormat = locationFormat;
}
CompilerOutputter *
CompilerOutputter::defaultOutputter( TestResultCollector *result,
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() << ")\n";
}
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 ( unsigned 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 << "\nTest name: " << failure->failedTestName();
}
void
CompilerOutputter::printFailureMessage( TestFailure *failure )
{
m_stream << "\n";
Exception *thrownException = failure->thrownException();
m_stream << thrownException->message().shortDescription() << "\n";
std::string message = thrownException->message().details();
if ( m_wrapColumn > 0 )
message = StringTools::wrap( message, m_wrapColumn );
m_stream << message << "\n";
}
void
CompilerOutputter::printStatistics()
{
m_stream << "Failures !!!\n";
m_stream << "Run: " << m_result->runTests() << " "
<< "Failure total: " << m_result->testFailuresTotal() << " "
<< "Failures: " << m_result->testFailures() << " "
<< "Errors: " << m_result->testErrors()
<< "\n";
}
void
CompilerOutputter::setWrapColumn( int wrapColumn )
{
m_wrapColumn = wrapColumn;
}
void
CompilerOutputter::setNoWrap()
{
m_wrapColumn = 0;
}
int
CompilerOutputter::wrapColumn() const
{
return m_wrapColumn;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,42 @@
#include <cppunit/Exception.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include "DefaultProtector.h"
CPPUNIT_NS_BEGIN
bool
DefaultProtector::protect( const Functor &functor,
const ProtectorContext &context )
{
try
{
return functor();
}
catch ( Exception &failure )
{
reportFailure( context, failure );
}
catch ( std::exception &e )
{
std::string shortDescription( "uncaught exception of type " );
#if CPPUNIT_USE_TYPEINFO_NAME
shortDescription += TypeInfoHelper::getClassName( typeid(e) );
#else
shortDescription += "std::exception (or derived).";
#endif
Message message( shortDescription, e.what() );
reportError( context, message );
}
catch ( ... )
{
reportError( context,
Message( "uncaught exception of unknown type") );
}
return false;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,27 @@
#ifndef CPPUNIT_DEFAULTPROTECTOR_H
#define CPPUNIT_DEFAULTPROTECTOR_H
#include <cppunit/Protector.h>
CPPUNIT_NS_BEGIN
/*! \brief Default protector that catch all exceptions (Implementation).
*
* Implementation detail.
* \internal This protector catch and generate a failure for the following
* exception types:
* - Exception
* - std::exception
* - ...
*/
class DefaultProtector : public Protector
{
public:
bool protect( const Functor &functor,
const ProtectorContext &context );
};
CPPUNIT_NS_END
#endif // CPPUNIT_DEFAULTPROTECTOR_H

View File

@@ -0,0 +1,16 @@
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOUSER
#define NOKERNEL
#define NOSOUND
#define BLENDFUNCTION void // for mingw & gcc
#include <windows.h>
BOOL APIENTRY
DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
return TRUE;
}

View File

@@ -0,0 +1,77 @@
#include <cppunit/plugin/DynamicLibraryManager.h>
#if !defined(CPPUNIT_NO_TESTPLUGIN)
#include <cppunit/plugin/DynamicLibraryManagerException.h>
CPPUNIT_NS_BEGIN
DynamicLibraryManager::DynamicLibraryManager( const std::string &libraryFileName )
: m_libraryHandle( NULL )
, m_libraryName( libraryFileName )
{
loadLibrary( libraryFileName );
}
DynamicLibraryManager::~DynamicLibraryManager()
{
releaseLibrary();
}
DynamicLibraryManager::Symbol
DynamicLibraryManager::findSymbol( const std::string &symbol )
{
try
{
Symbol symbolPointer = doFindSymbol( symbol );
if ( symbolPointer != NULL )
return symbolPointer;
}
catch ( ... )
{
}
throw DynamicLibraryManagerException( m_libraryName,
symbol,
DynamicLibraryManagerException::symbolNotFound );
return NULL; // keep compiler happy
}
void
DynamicLibraryManager::loadLibrary( const std::string &libraryName )
{
try
{
releaseLibrary();
m_libraryHandle = doLoadLibrary( libraryName );
if ( m_libraryHandle != NULL )
return;
}
catch (...)
{
}
throw DynamicLibraryManagerException( m_libraryName,
getLastErrorDetail(),
DynamicLibraryManagerException::loadingFailed );
}
void
DynamicLibraryManager::releaseLibrary()
{
if ( m_libraryHandle != NULL )
{
doReleaseLibrary();
m_libraryHandle = NULL;
}
}
CPPUNIT_NS_END
#endif // !defined(CPPUNIT_NO_TESTPLUGIN)

View File

@@ -0,0 +1,41 @@
#include <cppunit/plugin/DynamicLibraryManagerException.h>
#if !defined(CPPUNIT_NO_TESTPLUGIN)
CPPUNIT_NS_BEGIN
DynamicLibraryManagerException::DynamicLibraryManagerException(
const std::string &libraryName,
const std::string &errorDetail,
Cause cause )
: std::runtime_error( "" ),
m_cause( cause )
{
if ( cause == loadingFailed )
m_message = "Failed to load dynamic library: " + libraryName + "\n" +
errorDetail;
else
m_message = "Symbol [" + errorDetail + "] not found in dynamic libary:" +
libraryName;
}
DynamicLibraryManagerException::Cause
DynamicLibraryManagerException::getCause() const
{
return m_cause;
}
const char *
DynamicLibraryManagerException::what() const throw()
{
return m_message.c_str();
}
CPPUNIT_NS_END
#endif // !defined(CPPUNIT_NO_TESTPLUGIN)

View File

@@ -0,0 +1,126 @@
#include <cppunit/Exception.h>
CPPUNIT_NS_BEGIN
#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED
/*!
* \deprecated Use SourceLine::isValid() instead.
*/
const std::string Exception::UNKNOWNFILENAME = "<unknown>";
/*!
* \deprecated Use SourceLine::isValid() instead.
*/
const long Exception::UNKNOWNLINENUMBER = -1;
#endif
Exception::Exception( const Exception &other )
: std::exception( other )
{
m_message = other.m_message;
m_sourceLine = other.m_sourceLine;
}
Exception::Exception( const Message &message,
const SourceLine &sourceLine )
: m_message( message )
, m_sourceLine( sourceLine )
{
}
#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED
Exception::Exception( std::string message,
long lineNumber,
std::string fileName )
: m_message( message )
, m_sourceLine( fileName, lineNumber )
{
}
#endif
Exception::~Exception() throw()
{
}
Exception &
Exception::operator =( const Exception& other )
{
// Don't call superclass operator =(). VC++ STL implementation
// has a bug. It calls the destructor and copy constructor of
// std::exception() which reset the virtual table to std::exception.
// SuperClass::operator =(other);
if ( &other != this )
{
m_message = other.m_message;
m_sourceLine = other.m_sourceLine;
}
return *this;
}
const char*
Exception::what() const throw()
{
Exception *mutableThis = CPPUNIT_CONST_CAST( Exception *, this );
mutableThis->m_whatMessage = m_message.shortDescription() + "\n" +
m_message.details();
return m_whatMessage.c_str();
}
SourceLine
Exception::sourceLine() const
{
return m_sourceLine;
}
Message
Exception::message() const
{
return m_message;
}
void
Exception::setMessage( const Message &message )
{
m_message = message;
}
#ifdef CPPUNIT_ENABLE_SOURCELINE_DEPRECATED
long
Exception::lineNumber() const
{
return m_sourceLine.isValid() ? m_sourceLine.lineNumber() :
UNKNOWNLINENUMBER;
}
std::string
Exception::fileName() const
{
return m_sourceLine.isValid() ? m_sourceLine.fileName() :
UNKNOWNFILENAME;
}
#endif
Exception *
Exception::clone() const
{
return new Exception( *this );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,170 @@
#include <cppunit/Message.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
Message::Message()
{
}
Message::Message( const Message &other )
{
*this = other;
}
Message::Message( const std::string &shortDescription )
: m_shortDescription( shortDescription )
{
}
Message::Message( const std::string &shortDescription,
const std::string &detail1 )
: m_shortDescription( shortDescription )
{
addDetail( detail1 );
}
Message::Message( const std::string &shortDescription,
const std::string &detail1,
const std::string &detail2 )
: m_shortDescription( shortDescription )
{
addDetail( detail1, detail2 );
}
Message::Message( const std::string &shortDescription,
const std::string &detail1,
const std::string &detail2,
const std::string &detail3 )
: m_shortDescription( shortDescription )
{
addDetail( detail1, detail2, detail3 );
}
Message &
Message::operator =( const Message &other )
{
if ( this != &other )
{
m_shortDescription = other.m_shortDescription.c_str();
m_details.clear();
Details::const_iterator it = other.m_details.begin();
Details::const_iterator itEnd = other.m_details.end();
while ( it != itEnd )
m_details.push_back( (*it++).c_str() );
}
return *this;
}
const std::string &
Message::shortDescription() const
{
return m_shortDescription;
}
int
Message::detailCount() const
{
return m_details.size();
}
std::string
Message::detailAt( int index ) const
{
if ( index < 0 || index >= detailCount() )
throw std::invalid_argument( "Message::detailAt() : invalid index" );
return m_details[ index ];
}
std::string
Message::details() const
{
std::string details;
for ( Details::const_iterator it = m_details.begin(); it != m_details.end(); ++it )
{
details += "- ";
details += *it;
details += '\n';
}
return details;
}
void
Message::clearDetails()
{
m_details.clear();
}
void
Message::addDetail( const std::string &detail )
{
m_details.push_back( detail );
}
void
Message::addDetail( const std::string &detail1,
const std::string &detail2 )
{
addDetail( detail1 );
addDetail( detail2 );
}
void
Message::addDetail( const std::string &detail1,
const std::string &detail2,
const std::string &detail3 )
{
addDetail( detail1, detail2 );
addDetail( detail3 );
}
void
Message::addDetail( const Message &message )
{
m_details.insert( m_details.end(),
message.m_details.begin(),
message.m_details.end() );
}
void
Message::setShortDescription( const std::string &shortDescription )
{
m_shortDescription = shortDescription;
}
bool
Message::operator ==( const Message &other ) const
{
return m_shortDescription == other.m_shortDescription &&
m_details == other.m_details;
}
bool
Message::operator !=( const Message &other ) const
{
return !( *this == other );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,110 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/XmlOutputterHook.h>
#if !defined(CPPUNIT_NO_TESTPLUGIN)
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/plugin/PlugInManager.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <cppunit/plugin/DynamicLibraryManager.h>
CPPUNIT_NS_BEGIN
PlugInManager::PlugInManager()
{
}
PlugInManager::~PlugInManager()
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
unload( *it );
}
void
PlugInManager::load( const std::string &libraryFileName,
const PlugInParameters &parameters )
{
PlugInInfo info;
info.m_fileName = libraryFileName;
info.m_manager = new DynamicLibraryManager( libraryFileName );
TestPlugInSignature plug = (TestPlugInSignature)info.m_manager->findSymbol(
CPPUNIT_STRINGIZE( CPPUNIT_PLUGIN_EXPORTED_NAME ) );
info.m_interface = (*plug)();
m_plugIns.push_back( info );
info.m_interface->initialize( &TestFactoryRegistry::getRegistry(), parameters );
}
void
PlugInManager::unload( const std::string &libraryFileName )
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
{
if ( (*it).m_fileName == libraryFileName )
{
unload( *it );
m_plugIns.erase( it );
break;
}
}
}
void
PlugInManager::addListener( TestResult *eventManager )
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
(*it).m_interface->addListener( eventManager );
}
void
PlugInManager::removeListener( TestResult *eventManager )
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
(*it).m_interface->removeListener( eventManager );
}
void
PlugInManager::unload( PlugInInfo &plugIn )
{
try
{
plugIn.m_interface->uninitialize( &TestFactoryRegistry::getRegistry() );
delete plugIn.m_manager;
}
catch (...)
{
delete plugIn.m_manager;
plugIn.m_manager = NULL;
throw;
}
}
void
PlugInManager::addXmlOutputterHooks( XmlOutputter *outputter )
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
(*it).m_interface->addXmlOutputterHooks( outputter );
}
void
PlugInManager::removeXmlOutputterHooks()
{
for ( PlugIns::iterator it = m_plugIns.begin(); it != m_plugIns.end(); ++it )
(*it).m_interface->removeXmlOutputterHooks();
}
CPPUNIT_NS_END
#endif // !defined(CPPUNIT_NO_TESTPLUGIN)

View File

@@ -0,0 +1,28 @@
#include <cppunit/plugin/PlugInParameters.h>
#if !defined(CPPUNIT_NO_TESTPLUGIN)
CPPUNIT_NS_BEGIN
PlugInParameters::PlugInParameters( const std::string &commandLine )
: m_commandLine( commandLine )
{
}
PlugInParameters::~PlugInParameters()
{
}
std::string
PlugInParameters::getCommandLine() const
{
return m_commandLine;
}
CPPUNIT_NS_END
#endif // !defined(CPPUNIT_NO_TESTPLUGIN)

View File

@@ -0,0 +1,86 @@
#include <cppunit/Exception.h>
#include <cppunit/Message.h>
#include <cppunit/Protector.h>
#include <cppunit/TestResult.h>
#include "ProtectorContext.h"
#include <memory>
CPPUNIT_NS_BEGIN
Functor::~Functor()
{
}
Protector::~Protector()
{
}
void
Protector::reportError( const ProtectorContext &context,
const Exception &error ) const
{
std::auto_ptr<Exception> actualError( error.clone() );
actualError->setMessage( actualMessage( actualError->message(), context ) );
context.m_result->addError( context.m_test,
actualError.release() );
}
void
Protector::reportError( const ProtectorContext &context,
const Message &message,
const SourceLine &sourceLine ) const
{
reportError( context, Exception( message, sourceLine ) );
}
void
Protector::reportFailure( const ProtectorContext &context,
const Exception &failure ) const
{
std::auto_ptr<Exception> actualFailure( failure.clone() );
actualFailure->setMessage( actualMessage( actualFailure->message(), context ) );
context.m_result->addFailure( context.m_test,
actualFailure.release() );
}
Message
Protector::actualMessage( const Message &message,
const ProtectorContext &context ) const
{
Message theActualMessage;
if ( context.m_shortDescription.empty() )
theActualMessage = message;
else
{
theActualMessage = Message( context.m_shortDescription,
message.shortDescription() );
theActualMessage.addDetail( message );
}
return theActualMessage;
}
ProtectorGuard::ProtectorGuard( TestResult *result,
Protector *protector )
: m_result( result )
{
m_result->pushProtector( protector );
}
ProtectorGuard::~ProtectorGuard()
{
m_result->popProtector();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,86 @@
#include "ProtectorChain.h"
CPPUNIT_NS_BEGIN
class ProtectorChain::ProtectFunctor : public Functor
{
public:
ProtectFunctor( Protector *protector,
const Functor &functor,
const ProtectorContext &context )
: m_protector( protector )
, m_functor( functor )
, m_context( context )
{
}
bool operator()() const
{
return m_protector->protect( m_functor, m_context );
}
private:
Protector *m_protector;
const Functor &m_functor;
const ProtectorContext &m_context;
};
ProtectorChain::~ProtectorChain()
{
while ( count() > 0 )
pop();
}
void
ProtectorChain::push( Protector *protector )
{
m_protectors.push_back( protector );
}
void
ProtectorChain::pop()
{
delete m_protectors.back();
m_protectors.pop_back();
}
int
ProtectorChain::count() const
{
return m_protectors.size();
}
bool
ProtectorChain::protect( const Functor &functor,
const ProtectorContext &context )
{
if ( m_protectors.empty() )
return functor();
Functors functors;
for ( int index = m_protectors.size()-1; index >= 0; --index )
{
const Functor &protectedFunctor =
functors.empty() ? functor : *functors.back();
functors.push_back( new ProtectFunctor( m_protectors[index],
protectedFunctor,
context ) );
}
const Functor &outermostFunctor = *functors.back();
bool succeed = outermostFunctor();
for ( unsigned int deletingIndex = 0; deletingIndex < m_protectors.size(); ++deletingIndex )
delete functors[deletingIndex];
return succeed;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,51 @@
#ifndef CPPUNIT_PROTECTORCHAIN_H
#define CPPUNIT_PROTECTORCHAIN_H
#include <cppunit/Protector.h>
#include <cppunit/portability/CppUnitDeque.h>
#if CPPUNIT_NEED_DLL_DECL
#pragma warning( push )
#pragma warning( disable: 4251 ) // X needs to have dll-interface to be used by clients of class Z
#endif
CPPUNIT_NS_BEGIN
/*! \brief Protector chain (Implementation).
* Implementation detail.
* \internal Protector that protect a Functor using a chain of nested Protector.
*/
class CPPUNIT_API ProtectorChain : public Protector
{
public:
~ProtectorChain();
void push( Protector *protector );
void pop();
int count() const;
bool protect( const Functor &functor,
const ProtectorContext &context );
private:
class ProtectFunctor;
private:
typedef CppUnitDeque<Protector *> Protectors;
Protectors m_protectors;
typedef CppUnitDeque<Functor *> Functors;
};
CPPUNIT_NS_END
#if CPPUNIT_NEED_DLL_DECL
#pragma warning( pop )
#endif
#endif // CPPUNIT_PROTECTORCHAIN_H

View File

@@ -0,0 +1,38 @@
#ifndef CPPUNIT_PROTECTORCONTEXT_H
#define CPPUNIT_PROTECTORCONTEXT_H
#include <cppunit/Portability.h>
#include <string>
CPPUNIT_NS_BEGIN
class Test;
class TestResult;
/*! \brief Protector context (Implementation).
* Implementation detail.
* \internal Context use to report failure in Protector.
*/
class CPPUNIT_API ProtectorContext
{
public:
ProtectorContext( Test *test,
TestResult *result,
const std::string &shortDescription )
: m_test( test )
, m_result( result )
, m_shortDescription( shortDescription )
{
}
Test *m_test;
TestResult *m_result;
std::string m_shortDescription;
};
CPPUNIT_NS_END
#endif // CPPUNIT_PROTECTORCONTEXT_H

View File

@@ -0,0 +1,29 @@
#include <cppunit/extensions/RepeatedTest.h>
#include <cppunit/TestResult.h>
CPPUNIT_NS_BEGIN
// Counts the number of test cases that will be run by this test.
int
RepeatedTest::countTestCases() const
{
return TestDecorator::countTestCases() * m_timesRepeat;
}
// Runs a repeated test
void
RepeatedTest::run( TestResult *result )
{
for ( int n = 0; n < m_timesRepeat; n++ )
{
if ( result->shouldStop() )
break;
TestDecorator::run( result );
}
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,53 @@
#include <cppunit/Portability.h>
#if defined(CPPUNIT_HAVE_UNIX_SHL_LOADER)
#include <cppunit/plugin/DynamicLibraryManager.h>
#include <dl.h>
#include <unistd.h>
CPPUNIT_NS_BEGIN
DynamicLibraryManager::LibraryHandle
DynamicLibraryManager::doLoadLibrary( const std::string &libraryName )
{
return ::shl_load(libraryName.c_str(), BIND_IMMEDIATE, 0L);
}
void
DynamicLibraryManager::doReleaseLibrary()
{
::shl_unload( (shl_t)m_libraryHandle);
}
DynamicLibraryManager::Symbol
DynamicLibraryManager::doFindSymbol( const std::string &symbol )
{
DynamicLibraryManager::Symbol L_symaddr = 0;
if ( ::shl_findsym( (shl_t*)(&m_libraryHandle),
symbol.c_str(),
TYPE_UNDEFINED,
&L_symaddr ) == 0 )
{
return L_symaddr;
}
return 0;
}
std::string
DynamicLibraryManager::getLastErrorDetail() const
{
return "";
}
CPPUNIT_NS_END
#endif // defined(CPPUNIT_HAVE_UNIX_SHL_LOADER)

View File

@@ -0,0 +1,81 @@
#include <cppunit/SourceLine.h>
CPPUNIT_NS_BEGIN
SourceLine::SourceLine() :
m_lineNumber( -1 )
{
}
SourceLine::SourceLine( const SourceLine &other )
: m_fileName( other.m_fileName.c_str() )
, m_lineNumber( other.m_lineNumber )
{
}
SourceLine::SourceLine( const std::string &fileName,
int lineNumber )
: m_fileName( fileName.c_str() )
, m_lineNumber( lineNumber )
{
}
SourceLine &
SourceLine::operator =( const SourceLine &other )
{
if ( this != &other )
{
m_fileName = other.m_fileName.c_str();
m_lineNumber = other.m_lineNumber;
}
return *this;
}
SourceLine::~SourceLine()
{
}
bool
SourceLine::isValid() const
{
return !m_fileName.empty();
}
int
SourceLine::lineNumber() const
{
return m_lineNumber;
}
std::string
SourceLine::fileName() const
{
return m_fileName;
}
bool
SourceLine::operator ==( const SourceLine &other ) const
{
return m_fileName == other.m_fileName &&
m_lineNumber == other.m_lineNumber;
}
bool
SourceLine::operator !=( const SourceLine &other ) const
{
return !( *this == other );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,80 @@
#include <cppunit/tools/StringTools.h>
#include <cppunit/portability/Stream.h>
#include <algorithm>
CPPUNIT_NS_BEGIN
std::string
StringTools::toString( int value )
{
OStringStream stream;
stream << value;
return stream.str();
}
std::string
StringTools::toString( double value )
{
OStringStream stream;
stream << value;
return stream.str();
}
StringTools::Strings
StringTools::split( const std::string &text,
char separator )
{
Strings splittedText;
std::string::const_iterator itStart = text.begin();
while ( !text.empty() )
{
std::string::const_iterator itSeparator = std::find( itStart,
text.end(),
separator );
splittedText.push_back( text.substr( itStart - text.begin(),
itSeparator - itStart ) );
if ( itSeparator == text.end() )
break;
itStart = itSeparator +1;
}
return splittedText;
}
std::string
StringTools::wrap( const std::string &text,
int wrapColumn )
{
const char lineBreak = '\n';
Strings lines = split( text, lineBreak );
std::string wrapped;
for ( Strings::const_iterator it = lines.begin(); it != lines.end(); ++it )
{
if ( it != lines.begin() )
wrapped += lineBreak;
const std::string &line = *it;
unsigned int index =0;
while ( index < line.length() )
{
std::string lineSlice( line.substr( index, wrapColumn ) );
wrapped += lineSlice;
index += wrapColumn;
if ( index < line.length() )
wrapped += lineBreak;
}
}
return wrapped;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,32 @@
#include <cppunit/SynchronizedObject.h>
CPPUNIT_NS_BEGIN
SynchronizedObject::SynchronizedObject( SynchronizationObject *syncObject )
: m_syncObject( syncObject == 0 ? new SynchronizationObject() :
syncObject )
{
}
SynchronizedObject::~SynchronizedObject()
{
delete m_syncObject;
}
/** Accept a new synchronization object for protection of this instance
* TestResult assumes ownership of the object
*/
void
SynchronizedObject::setSynchronizationObject( SynchronizationObject *syncObject )
{
delete m_syncObject;
m_syncObject = syncObject;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,97 @@
#include <cppunit/Portability.h>
#include <cppunit/Test.h>
#include <cppunit/TestPath.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
Test *
Test::getChildTestAt( int index ) const
{
checkIsValidIndex( index );
return doGetChildTestAt( index );
}
Test *
Test::findTest( const std::string &testName ) const
{
TestPath path;
Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this );
mutableThis->findTestPath( testName, path );
if ( !path.isValid() )
throw std::invalid_argument( "No test named <" + testName + "> found in test <"
+ getName() + ">." );
return path.getChildTest();
}
bool
Test::findTestPath( const std::string &testName,
TestPath &testPath ) const
{
Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this );
if ( getName() == testName )
{
testPath.add( mutableThis );
return true;
}
int childCount = getChildTestCount();
for ( int childIndex =0; childIndex < childCount; ++childIndex )
{
if ( getChildTestAt( childIndex )->findTestPath( testName, testPath ) )
{
testPath.insert( mutableThis, 0 );
return true;
}
}
return false;
}
bool
Test::findTestPath( const Test *test,
TestPath &testPath ) const
{
Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this );
if ( this == test )
{
testPath.add( mutableThis );
return true;
}
int childCount = getChildTestCount();
for ( int childIndex =0; childIndex < childCount; ++childIndex )
{
if ( getChildTestAt( childIndex )->findTestPath( test, testPath ) )
{
testPath.insert( mutableThis, 0 );
return true;
}
}
return false;
}
TestPath
Test::resolveTestPath( const std::string &testPath ) const
{
Test *mutableThis = CPPUNIT_CONST_CAST( Test *, this );
return TestPath( mutableThis, testPath );
}
void
Test::checkIsValidIndex( int index ) const
{
if ( index < 0 || index >= getChildTestCount() )
throw std::out_of_range( "Test::checkValidIndex(): invalid index" );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,46 @@
#include <cppunit/TestAssert.h>
#include <cppunit/portability/FloatingPoint.h>
CPPUNIT_NS_BEGIN
void
assertDoubleEquals( double expected,
double actual,
double delta,
SourceLine sourceLine,
const std::string &message )
{
AdditionalMessage msg( "Delta : " +
assertion_traits<double>::toString(delta) );
msg.addDetail( AdditionalMessage(message) );
bool equal;
if ( floatingPointIsFinite(expected) && floatingPointIsFinite(actual) )
equal = fabs( expected - actual ) <= delta;
else
{
// If expected or actual is not finite, it may be +inf, -inf or NaN (Not a Number).
// Value of +inf or -inf leads to a true equality regardless of delta if both
// expected and actual have the same value (infinity sign).
// NaN Value should always lead to a failed equality.
if ( floatingPointIsUnordered(expected) || floatingPointIsUnordered(actual) )
{
equal = false; // expected or actual is a NaN
}
else // ordered values, +inf or -inf comparison
{
equal = expected == actual;
}
}
Asserter::failNotEqualIf( !equal,
assertion_traits<double>::toString(expected),
assertion_traits<double>::toString(actual),
sourceLine,
msg,
"double equality assertion failed" );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,137 @@
#include <cppunit/Portability.h>
#include <cppunit/Exception.h>
#include <cppunit/Protector.h>
#include <cppunit/TestCase.h>
#include <cppunit/TestResult.h>
#include <stdexcept>
#if CPPUNIT_USE_TYPEINFO_NAME
# include <typeinfo>
#endif
CPPUNIT_NS_BEGIN
/*! \brief Functor to call test case method (Implementation).
*
* Implementation detail.
*/
class TestCaseMethodFunctor : public Functor
{
public:
typedef void (TestCase::*Method)();
TestCaseMethodFunctor( TestCase *target,
Method method )
: m_target( target )
, m_method( method )
{
}
bool operator()() const
{
(m_target->*m_method)();
return true;
}
private:
TestCase *m_target;
Method m_method;
};
/** Constructs a test case.
* \param name the name of the TestCase.
**/
TestCase::TestCase( const std::string &name )
: m_name(name)
{
}
/// Run the test and catch any exceptions that are triggered by it
void
TestCase::run( TestResult *result )
{
result->startTest(this);
/*
try {
setUp();
try {
runTest();
}
catch ( Exception &e ) {
Exception *copy = e.clone();
result->addFailure( this, copy );
}
catch ( std::exception &e ) {
result->addError( this, new Exception( Message( "uncaught std::exception",
e.what() ) ) );
}
catch (...) {
Exception *e = new Exception( Message( "uncaught unknown exception" ) );
result->addError( this, e );
}
try {
tearDown();
}
catch (...) {
result->addError( this, new Exception( Message( "tearDown() failed" ) ) );
}
}
catch (...) {
result->addError( this, new Exception( Message( "setUp() failed" ) ) );
}
*/
if ( result->protect( TestCaseMethodFunctor( this, &TestCase::setUp ),
this,
"setUp() failed" ) )
{
result->protect( TestCaseMethodFunctor( this, &TestCase::runTest ),
this );
}
result->protect( TestCaseMethodFunctor( this, &TestCase::tearDown ),
this,
"tearDown() failed" );
result->endTest( this );
}
/// All the work for runTest is deferred to subclasses
void
TestCase::runTest()
{
}
/** Constructs a test case for a suite.
* \deprecated This constructor was used by fixture when TestFixture did not exist.
* Have your fixture inherits TestFixture instead of TestCase.
* \internal
* This TestCase was intended for use by the TestCaller and should not
* be used by a test case for which run() is called.
**/
TestCase::TestCase()
: m_name( "" )
{
}
/// Destructs a test case
TestCase::~TestCase()
{
}
/// Returns the name of the test case
std::string
TestCase::getName() const
{
return m_name;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,47 @@
#include <cppunit/extensions/TestCaseDecorator.h>
CPPUNIT_NS_BEGIN
TestCaseDecorator::TestCaseDecorator( TestCase *test )
: TestCase( test->getName() ),
m_test( test )
{
}
TestCaseDecorator::~TestCaseDecorator()
{
delete m_test;
}
std::string
TestCaseDecorator::getName() const
{
return m_test->getName();
}
void
TestCaseDecorator::setUp()
{
m_test->setUp();
}
void
TestCaseDecorator::tearDown()
{
m_test->tearDown();
}
void
TestCaseDecorator::runTest()
{
m_test->runTest();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,77 @@
#include <cppunit/TestComposite.h>
#include <cppunit/TestResult.h>
CPPUNIT_NS_BEGIN
TestComposite::TestComposite( const std::string &name )
: m_name( name )
{
}
TestComposite::~TestComposite()
{
}
void
TestComposite::run( TestResult *result )
{
doStartSuite( result );
doRunChildTests( result );
doEndSuite( result );
}
int
TestComposite::countTestCases() const
{
int count = 0;
int childCount = getChildTestCount();
for ( int index =0; index < childCount; ++index )
count += getChildTestAt( index )->countTestCases();
return count;
}
std::string
TestComposite::getName() const
{
return m_name;
}
void
TestComposite::doStartSuite( TestResult *controller )
{
controller->startSuite( this );
}
void
TestComposite::doRunChildTests( TestResult *controller )
{
int childCount = getChildTestCount();
for ( int index =0; index < childCount; ++index )
{
if ( controller->shouldStop() )
break;
getChildTestAt( index )->run( controller );
}
}
void
TestComposite::doEndSuite( TestResult *controller )
{
controller->endSuite( this );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,53 @@
#include <cppunit/extensions/TestDecorator.h>
CPPUNIT_NS_BEGIN
TestDecorator::TestDecorator( Test *test )
: m_test( test)
{
}
TestDecorator::~TestDecorator()
{
delete m_test;
}
int
TestDecorator::countTestCases() const
{
return m_test->countTestCases();
}
void
TestDecorator::run( TestResult *result )
{
m_test->run(result);
}
std::string
TestDecorator::getName() const
{
return m_test->getName();
}
int
TestDecorator::getChildTestCount() const
{
return m_test->getChildTestCount();
}
Test *
TestDecorator::doGetChildTestAt( int index ) const
{
return m_test->getChildTestAt( index );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,161 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/portability/CppUnitMap.h>
#include <cppunit/TestSuite.h>
#include <assert.h>
CPPUNIT_NS_BEGIN
/*! \brief (INTERNAL) List of all TestFactoryRegistry.
*/
class TestFactoryRegistryList
{
private:
typedef CppUnitMap<std::string, TestFactoryRegistry *, std::less<std::string> > Registries;
Registries m_registries;
enum State {
doNotChange =0,
notCreated,
exist,
destroyed
};
static State stateFlag( State newState = doNotChange )
{
static State state = notCreated;
if ( newState != doNotChange )
state = newState;
return state;
}
static TestFactoryRegistryList *getInstance()
{
static TestFactoryRegistryList list;
return &list;
}
TestFactoryRegistry *getInternalRegistry( const std::string &name )
{
Registries::const_iterator foundIt = m_registries.find( name );
if ( foundIt == m_registries.end() )
{
TestFactoryRegistry *factory = new TestFactoryRegistry( name );
m_registries.insert( std::pair<const std::string, TestFactoryRegistry*>( name, factory ) );
return factory;
}
return (*foundIt).second;
}
public:
TestFactoryRegistryList()
{
stateFlag( exist );
}
~TestFactoryRegistryList()
{
for ( Registries::iterator it = m_registries.begin(); it != m_registries.end(); ++it )
delete (*it).second;
stateFlag( destroyed );
}
static TestFactoryRegistry *getRegistry( const std::string &name )
{
// If the following assertion failed, then TestFactoryRegistry::getRegistry()
// was called during static variable destruction without checking the registry
// validity beforehand using TestFactoryRegistry::isValid() beforehand.
assert( isValid() );
if ( !isValid() ) // release mode
return NULL; // => force CRASH
return getInstance()->getInternalRegistry( name );
}
static bool isValid()
{
return stateFlag() != destroyed;
}
};
TestFactoryRegistry::TestFactoryRegistry( std::string name ) :
m_name( name )
{
}
TestFactoryRegistry::~TestFactoryRegistry()
{
}
TestFactoryRegistry &
TestFactoryRegistry::getRegistry( const std::string &name )
{
return *TestFactoryRegistryList::getRegistry( name );
}
void
TestFactoryRegistry::registerFactory( const std::string &,
TestFactory *factory )
{
registerFactory( factory );
}
void
TestFactoryRegistry::registerFactory( TestFactory *factory )
{
m_factories.insert( factory );
}
void
TestFactoryRegistry::unregisterFactory( TestFactory *factory )
{
m_factories.erase( factory );
}
void
TestFactoryRegistry::addRegistry( const std::string &name )
{
registerFactory( &getRegistry( name ) );
}
Test *
TestFactoryRegistry::makeTest()
{
TestSuite *suite = new TestSuite( m_name );
addTestToSuite( suite );
return suite;
}
void
TestFactoryRegistry::addTestToSuite( TestSuite *suite )
{
for ( Factories::iterator it = m_factories.begin();
it != m_factories.end();
++it )
{
TestFactory *factory = *it;
suite->addTest( factory->makeTest() );
}
}
bool
TestFactoryRegistry::isValid()
{
return TestFactoryRegistryList::isValid();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,71 @@
#include <cppunit/Exception.h>
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
CPPUNIT_NS_BEGIN
/// Constructs a TestFailure with the given test and exception.
TestFailure::TestFailure( Test *failedTest,
Exception *thrownException,
bool isError ) :
m_failedTest( failedTest ),
m_thrownException( thrownException ),
m_isError( isError )
{
}
/// Deletes the owned exception.
TestFailure::~TestFailure()
{
delete m_thrownException;
}
/// Gets the failed test.
Test *
TestFailure::failedTest() const
{
return m_failedTest;
}
/// Gets the thrown exception. Never \c NULL.
Exception *
TestFailure::thrownException() const
{
return m_thrownException;
}
/// Gets the failure location.
SourceLine
TestFailure::sourceLine() const
{
return m_thrownException->sourceLine();
}
/// Indicates if the failure is a failed assertion or an error.
bool
TestFailure::isError() const
{
return m_isError;
}
/// Gets the name of the failed test.
std::string
TestFailure::failedTestName() const
{
return m_failedTest->getName();
}
TestFailure *
TestFailure::clone() const
{
return new TestFailure( m_failedTest, m_thrownException->clone(), m_isError );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,28 @@
#include <cppunit/TestLeaf.h>
CPPUNIT_NS_BEGIN
int
TestLeaf::countTestCases() const
{
return 1;
}
int
TestLeaf::getChildTestCount() const
{
return 0;
}
Test *
TestLeaf::doGetChildTestAt( int index ) const
{
checkIsValidIndex( index );
return NULL; // never called, checkIsValidIndex() always throw.
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,44 @@
#include <cppunit/extensions/TestNamer.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#include <string>
CPPUNIT_NS_BEGIN
#if CPPUNIT_HAVE_RTTI
TestNamer::TestNamer( const std::type_info &typeInfo )
{
m_fixtureName = TypeInfoHelper::getClassName( typeInfo );
}
#endif
TestNamer::TestNamer( const std::string &fixtureName )
: m_fixtureName( fixtureName )
{
}
TestNamer::~TestNamer()
{
}
std::string
TestNamer::getFixtureName() const
{
return m_fixtureName;
}
std::string
TestNamer::getTestNameFor( const std::string &testMethodName ) const
{
return getFixtureName() + "::" + testMethodName;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,254 @@
#include <cppunit/Portability.h>
#include <cppunit/Test.h>
#include <cppunit/TestPath.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
TestPath::TestPath()
{
}
TestPath::TestPath( Test *root )
{
add( root );
}
TestPath::TestPath( const TestPath &other,
int indexFirst,
int count )
{
int countAdjustment = 0;
if ( indexFirst < 0 )
{
countAdjustment = indexFirst;
indexFirst = 0;
}
if ( count < 0 )
count = other.getTestCount();
else
count += countAdjustment;
int index = indexFirst;
while ( count-- > 0 && index < other.getTestCount() )
add( other.getTestAt( index++ ) );
}
TestPath::TestPath( Test *searchRoot,
const std::string &pathAsString )
{
PathTestNames testNames;
Test *parentTest = findActualRoot( searchRoot, pathAsString, testNames );
add( parentTest );
for ( unsigned int index = 1; index < testNames.size(); ++index )
{
bool childFound = false;
for ( int childIndex =0; childIndex < parentTest->getChildTestCount(); ++childIndex )
{
if ( parentTest->getChildTestAt( childIndex )->getName() == testNames[index] )
{
childFound = true;
parentTest = parentTest->getChildTestAt( childIndex );
break;
}
}
if ( !childFound )
throw std::invalid_argument( "TestPath::TestPath(): failed to resolve test name <"+
testNames[index] + "> of path <" + pathAsString + ">" );
add( parentTest );
}
}
TestPath::TestPath( const TestPath &other )
: m_tests( other.m_tests )
{
}
TestPath::~TestPath()
{
}
TestPath &
TestPath::operator =( const TestPath &other )
{
if ( &other != this )
m_tests = other.m_tests;
return *this;
}
bool
TestPath::isValid() const
{
return getTestCount() > 0;
}
void
TestPath::add( Test *test )
{
m_tests.push_back( test );
}
void
TestPath::add( const TestPath &path )
{
for ( int index =0; index < path.getTestCount(); ++index )
add( path.getTestAt( index ) );
}
void
TestPath::insert( Test *test,
int index )
{
if ( index < 0 || index > getTestCount() )
throw std::out_of_range( "TestPath::insert(): index out of range" );
m_tests.insert( m_tests.begin() + index, test );
}
void
TestPath::insert( const TestPath &path,
int index )
{
int itemIndex = path.getTestCount() -1;
while ( itemIndex >= 0 )
insert( path.getTestAt( itemIndex-- ), index );
}
void
TestPath::removeTests()
{
while ( isValid() )
removeTest( 0 );
}
void
TestPath::removeTest( int index )
{
checkIndexValid( index );
m_tests.erase( m_tests.begin() + index );
}
void
TestPath::up()
{
checkIndexValid( 0 );
removeTest( getTestCount() -1 );
}
int
TestPath::getTestCount() const
{
return m_tests.size();
}
Test *
TestPath::getTestAt( int index ) const
{
checkIndexValid( index );
return m_tests[index];
}
Test *
TestPath::getChildTest() const
{
return getTestAt( getTestCount() -1 );
}
void
TestPath::checkIndexValid( int index ) const
{
if ( index < 0 || index >= getTestCount() )
throw std::out_of_range( "TestPath::checkIndexValid(): index out of range" );
}
std::string
TestPath::toString() const
{
std::string asString( "/" );
for ( int index =0; index < getTestCount(); ++index )
{
if ( index > 0 )
asString += '/';
asString += getTestAt(index)->getName();
}
return asString;
}
Test *
TestPath::findActualRoot( Test *searchRoot,
const std::string &pathAsString,
PathTestNames &testNames )
{
bool isRelative = splitPathString( pathAsString, testNames );
if ( isRelative && pathAsString.empty() )
return searchRoot;
if ( testNames.empty() )
throw std::invalid_argument( "TestPath::TestPath(): invalid root or root name in absolute path" );
Test *root = isRelative ? searchRoot->findTest( testNames[0] ) // throw if bad test name
: searchRoot;
if ( root->getName() != testNames[0] )
throw std::invalid_argument( "TestPath::TestPath(): searchRoot does not match path root name" );
return root;
}
bool
TestPath::splitPathString( const std::string &pathAsString,
PathTestNames &testNames )
{
if ( pathAsString.empty() )
return true;
bool isRelative = pathAsString[0] != '/';
int index = (isRelative ? 0 : 1);
while ( true )
{
int separatorIndex = pathAsString.find( '/', index );
if ( separatorIndex >= 0 )
{
testNames.push_back( pathAsString.substr( index, separatorIndex - index ) );
index = separatorIndex + 1;
}
else
{
testNames.push_back( pathAsString.substr( index ) );
break;
}
}
return isRelative;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,63 @@
#include <cppunit/config/SourcePrefix.h>
#if !defined(CPPUNIT_NO_TESTPLUGIN)
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/plugin/TestPlugInDefaultImpl.h>
CPPUNIT_NS_BEGIN
TestPlugInDefaultImpl::TestPlugInDefaultImpl()
{
}
TestPlugInDefaultImpl::~TestPlugInDefaultImpl()
{
}
void
TestPlugInDefaultImpl::initialize( TestFactoryRegistry *,
const PlugInParameters & )
{
}
void
TestPlugInDefaultImpl::addListener( TestResult * )
{
}
void
TestPlugInDefaultImpl::removeListener( TestResult * )
{
}
void
TestPlugInDefaultImpl::addXmlOutputterHooks( XmlOutputter * )
{
}
void
TestPlugInDefaultImpl::removeXmlOutputterHooks()
{
}
void
TestPlugInDefaultImpl::uninitialize( TestFactoryRegistry * )
{
}
CPPUNIT_NS_END
#endif // !defined(CPPUNIT_NO_TESTPLUGIN)

View File

@@ -0,0 +1,199 @@
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TestListener.h>
#include <cppunit/TestResult.h>
#include <cppunit/tools/Algorithm.h>
#include <cppunit/portability/Stream.h>
#include <algorithm>
#include "DefaultProtector.h"
#include "ProtectorChain.h"
#include "ProtectorContext.h"
CPPUNIT_NS_BEGIN
TestResult::TestResult( SynchronizationObject *syncObject )
: SynchronizedObject( syncObject )
, m_protectorChain( new ProtectorChain() )
, m_stop( false )
{
m_protectorChain->push( new DefaultProtector() );
}
TestResult::~TestResult()
{
stdCOut().flush();
stdCErr().flush();
delete m_protectorChain;
}
void
TestResult::reset()
{
ExclusiveZone zone( m_syncObject );
m_stop = false;
}
void
TestResult::addError( Test *test,
Exception *e )
{
TestFailure failure( test, e, true );
addFailure( failure );
}
void
TestResult::addFailure( Test *test, Exception *e )
{
TestFailure failure( test, e, false );
addFailure( failure );
}
void
TestResult::addFailure( const TestFailure &failure )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->addFailure( failure );
}
void
TestResult::startTest( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->startTest( test );
}
void
TestResult::endTest( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->endTest( test );
}
void
TestResult::startSuite( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->startSuite( test );
}
void
TestResult::endSuite( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->endSuite( test );
}
bool
TestResult::shouldStop() const
{
ExclusiveZone zone( m_syncObject );
return m_stop;
}
void
TestResult::stop()
{
ExclusiveZone zone( m_syncObject );
m_stop = true;
}
void
TestResult::addListener( TestListener *listener )
{
ExclusiveZone zone( m_syncObject );
m_listeners.push_back( listener );
}
void
TestResult::removeListener ( TestListener *listener )
{
ExclusiveZone zone( m_syncObject );
removeFromSequence( m_listeners, listener );
}
void
TestResult::runTest( Test *test )
{
startTestRun( test );
test->run( this );
endTestRun( test );
}
void
TestResult::startTestRun( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->startTestRun( test, this );
}
void
TestResult::endTestRun( Test *test )
{
ExclusiveZone zone( m_syncObject );
for ( TestListeners::iterator it = m_listeners.begin();
it != m_listeners.end();
++it )
(*it)->endTestRun( test, this );
}
bool
TestResult::protect( const Functor &functor,
Test *test,
const std::string &shortDescription )
{
ProtectorContext context( test, this, shortDescription );
return m_protectorChain->protect( functor, context );
}
void
TestResult::pushProtector( Protector *protector )
{
m_protectorChain->push( protector );
}
void
TestResult::popProtector()
{
m_protectorChain->pop();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,117 @@
#include <cppunit/TestFailure.h>
#include <cppunit/TestResultCollector.h>
CPPUNIT_NS_BEGIN
TestResultCollector::TestResultCollector( SynchronizationObject *syncObject )
: TestSuccessListener( syncObject )
{
reset();
}
TestResultCollector::~TestResultCollector()
{
freeFailures();
}
void
TestResultCollector::freeFailures()
{
TestFailures::iterator itFailure = m_failures.begin();
while ( itFailure != m_failures.end() )
delete *itFailure++;
m_failures.clear();
}
void
TestResultCollector::reset()
{
TestSuccessListener::reset();
ExclusiveZone zone( m_syncObject );
freeFailures();
m_testErrors = 0;
m_tests.clear();
}
void
TestResultCollector::startTest( Test *test )
{
ExclusiveZone zone (m_syncObject);
m_tests.push_back( test );
}
void
TestResultCollector::addFailure( const TestFailure &failure )
{
TestSuccessListener::addFailure( failure );
ExclusiveZone zone( m_syncObject );
if ( failure.isError() )
++m_testErrors;
m_failures.push_back( failure.clone() );
}
/// Gets the number of run tests.
int
TestResultCollector::runTests() const
{
ExclusiveZone zone( m_syncObject );
return m_tests.size();
}
/// Gets the number of detected errors (uncaught exception).
int
TestResultCollector::testErrors() const
{
ExclusiveZone zone( m_syncObject );
return m_testErrors;
}
/// Gets the number of detected failures (failed assertion).
int
TestResultCollector::testFailures() const
{
ExclusiveZone zone( m_syncObject );
return m_failures.size() - m_testErrors;
}
/// Gets the total number of detected failures.
int
TestResultCollector::testFailuresTotal() const
{
ExclusiveZone zone( m_syncObject );
return m_failures.size();
}
/// Returns a the list failures (random access collection).
const TestResultCollector::TestFailures &
TestResultCollector::failures() const
{
ExclusiveZone zone( m_syncObject );
return m_failures;
}
const TestResultCollector::Tests &
TestResultCollector::tests() const
{
ExclusiveZone zone( m_syncObject );
return m_tests;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,101 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/TestRunner.h>
#include <cppunit/TestPath.h>
#include <cppunit/TestResult.h>
CPPUNIT_NS_BEGIN
TestRunner::WrappingSuite::WrappingSuite( const std::string &name )
: TestSuite( name )
{
}
int
TestRunner::WrappingSuite::getChildTestCount() const
{
if ( hasOnlyOneTest() )
return getUniqueChildTest()->getChildTestCount();
return TestSuite::getChildTestCount();
}
std::string
TestRunner::WrappingSuite::getName() const
{
if ( hasOnlyOneTest() )
return getUniqueChildTest()->getName();
return TestSuite::getName();
}
Test *
TestRunner::WrappingSuite::doGetChildTestAt( int index ) const
{
if ( hasOnlyOneTest() )
return getUniqueChildTest()->getChildTestAt( index );
return TestSuite::doGetChildTestAt( index );
}
void
TestRunner::WrappingSuite::run( TestResult *result )
{
if ( hasOnlyOneTest() )
getUniqueChildTest()->run( result );
else
TestSuite::run( result );
}
bool
TestRunner::WrappingSuite::hasOnlyOneTest() const
{
return TestSuite::getChildTestCount() == 1;
}
Test *
TestRunner::WrappingSuite::getUniqueChildTest() const
{
return TestSuite::doGetChildTestAt( 0 );
}
TestRunner::TestRunner()
: m_suite( new WrappingSuite() )
{
}
TestRunner::~TestRunner()
{
delete m_suite;
}
void
TestRunner::addTest( Test *test )
{
m_suite->addTest( test );
}
void
TestRunner::run( TestResult &controller,
const std::string &testPath )
{
TestPath path = m_suite->resolveTestPath( testPath );
Test *testToRun = path.getChildTest();
controller.runTest( testToRun );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,32 @@
#include <cppunit/extensions/TestSetUp.h>
CPPUNIT_NS_BEGIN
TestSetUp::TestSetUp( Test *test ) : TestDecorator( test )
{
}
void
TestSetUp::setUp()
{
}
void
TestSetUp::tearDown()
{
}
void
TestSetUp::run( TestResult *result )
{
setUp();
TestDecorator::run(result);
tearDown();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,44 @@
#include <cppunit/TestSuccessListener.h>
CPPUNIT_NS_BEGIN
TestSuccessListener::TestSuccessListener( SynchronizationObject *syncObject )
: SynchronizedObject( syncObject )
, m_success( true )
{
}
TestSuccessListener::~TestSuccessListener()
{
}
void
TestSuccessListener::reset()
{
ExclusiveZone zone( m_syncObject );
m_success = true;
}
void
TestSuccessListener::addFailure( const TestFailure & )
{
ExclusiveZone zone( m_syncObject );
m_success = false;
}
bool
TestSuccessListener::wasSuccessful() const
{
ExclusiveZone zone( m_syncObject );
return m_success;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,64 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TestResult.h>
CPPUNIT_NS_BEGIN
/// Default constructor
TestSuite::TestSuite( std::string name )
: TestComposite( name )
{
}
/// Destructor
TestSuite::~TestSuite()
{
deleteContents();
}
/// Deletes all tests in the suite.
void
TestSuite::deleteContents()
{
int childCount = getChildTestCount();
for ( int index =0; index < childCount; ++index )
delete getChildTestAt( index );
m_tests.clear();
}
/// Adds a test to the suite.
void
TestSuite::addTest( Test *test )
{
m_tests.push_back( test );
}
const CppUnitVector<Test *> &
TestSuite::getTests() const
{
return m_tests;
}
int
TestSuite::getChildTestCount() const
{
return m_tests.size();
}
Test *
TestSuite::doGetChildTestAt( int index ) const
{
return m_tests[index];
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,85 @@
#include <cppunit/TestSuite.h>
#include <cppunit/extensions/TestFixtureFactory.h>
#include <cppunit/extensions/TestNamer.h>
#include <cppunit/extensions/TestSuiteBuilderContext.h>
CPPUNIT_NS_BEGIN
TestSuiteBuilderContextBase::TestSuiteBuilderContextBase(
TestSuite &suite,
const TestNamer &namer,
TestFixtureFactory &factory )
: m_suite( suite )
, m_namer( namer )
, m_factory( factory )
{
}
TestSuiteBuilderContextBase::~TestSuiteBuilderContextBase()
{
}
void
TestSuiteBuilderContextBase::addTest( Test *test )
{
m_suite.addTest( test );
}
std::string
TestSuiteBuilderContextBase::getFixtureName() const
{
return m_namer.getFixtureName();
}
std::string
TestSuiteBuilderContextBase::getTestNameFor(
const std::string &testMethodName ) const
{
return m_namer.getTestNameFor( testMethodName );
}
TestFixture *
TestSuiteBuilderContextBase::makeTestFixture() const
{
return m_factory.makeFixture();
}
void
TestSuiteBuilderContextBase::addProperty( const std::string &key,
const std::string &value )
{
Properties::iterator it = m_properties.begin();
for ( ; it != m_properties.end(); ++it )
{
if ( (*it).first == key )
{
(*it).second = value;
return;
}
}
Property property( key, value );
m_properties.push_back( property );
}
const std::string
TestSuiteBuilderContextBase::getStringProperty( const std::string &key ) const
{
Properties::const_iterator it = m_properties.begin();
for ( ; it != m_properties.end(); ++it )
{
if ( (*it).first == key )
return (*it).second;
}
return "";
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,140 @@
#include <cppunit/Exception.h>
#include <cppunit/SourceLine.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/TestResultCollector.h>
CPPUNIT_NS_BEGIN
TextOutputter::TextOutputter( TestResultCollector *result,
OStream &stream )
: m_result( result )
, m_stream( stream )
{
}
TextOutputter::~TextOutputter()
{
}
void
TextOutputter::write()
{
printHeader();
m_stream << "\n";
printFailures();
m_stream << "\n";
}
void
TextOutputter::printFailures()
{
TestResultCollector::TestFailures::const_iterator itFailure = m_result->failures().begin();
int failureNumber = 1;
while ( itFailure != m_result->failures().end() )
{
m_stream << "\n";
printFailure( *itFailure++, failureNumber++ );
}
}
void
TextOutputter::printFailure( TestFailure *failure,
int failureNumber )
{
printFailureListMark( failureNumber );
m_stream << ' ';
printFailureTestName( failure );
m_stream << ' ';
printFailureType( failure );
m_stream << ' ';
printFailureLocation( failure->sourceLine() );
m_stream << "\n";
printFailureDetail( failure->thrownException() );
m_stream << "\n";
}
void
TextOutputter::printFailureListMark( int failureNumber )
{
m_stream << failureNumber << ")";
}
void
TextOutputter::printFailureTestName( TestFailure *failure )
{
m_stream << "test: " << failure->failedTestName();
}
void
TextOutputter::printFailureType( TestFailure *failure )
{
m_stream << "("
<< (failure->isError() ? "E" : "F")
<< ")";
}
void
TextOutputter::printFailureLocation( SourceLine sourceLine )
{
if ( !sourceLine.isValid() )
return;
m_stream << "line: " << sourceLine.lineNumber()
<< ' ' << sourceLine.fileName();
}
void
TextOutputter::printFailureDetail( Exception *thrownException )
{
m_stream << thrownException->message().shortDescription() << "\n";
m_stream << thrownException->message().details();
}
void
TextOutputter::printHeader()
{
if ( m_result->wasSuccessful() )
m_stream << "\nOK (" << m_result->runTests () << " tests)\n" ;
else
{
m_stream << "\n";
printFailureWarning();
printStatistics();
}
}
void
TextOutputter::printFailureWarning()
{
m_stream << "!!!FAILURES!!!\n";
}
void
TextOutputter::printStatistics()
{
m_stream << "Test Results:\n";
m_stream << "Run: " << m_result->runTests()
<< " Failures: " << m_result->testFailures()
<< " Errors: " << m_result->testErrors()
<< "\n";
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,45 @@
#include <cppunit/TestFailure.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/portability/Stream.h>
CPPUNIT_NS_BEGIN
TextTestProgressListener::TextTestProgressListener()
{
}
TextTestProgressListener::~TextTestProgressListener()
{
}
void
TextTestProgressListener::startTest( Test * )
{
stdCOut() << ".";
stdCOut().flush();
}
void
TextTestProgressListener::addFailure( const TestFailure &failure )
{
stdCOut() << ( failure.isError() ? "E" : "F" );
stdCOut().flush();
}
void
TextTestProgressListener::endTestRun( Test *,
TestResult * )
{
stdCOut() << "\n";
stdCOut().flush();
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,50 @@
#include <cppunit/Exception.h>
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TextTestResult.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/portability/Stream.h>
CPPUNIT_NS_BEGIN
TextTestResult::TextTestResult()
{
addListener( this );
}
void
TextTestResult::addFailure( const TestFailure &failure )
{
TestResultCollector::addFailure( failure );
stdCOut() << ( failure.isError() ? "E" : "F" );
}
void
TextTestResult::startTest( Test *test )
{
TestResultCollector::startTest (test);
stdCOut() << ".";
}
void
TextTestResult::print( OStream &stream )
{
TextOutputter outputter( this, stream );
outputter.write();
}
OStream &
operator <<( OStream &stream,
TextTestResult &result )
{
result.print (stream); return stream;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,144 @@
// ==> Implementation of cppunit/ui/text/TestRunner.h
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/TestSuite.h>
#include <cppunit/TextTestResult.h>
#include <cppunit/TextOutputter.h>
#include <cppunit/TextTestProgressListener.h>
#include <cppunit/TestResult.h>
#include <cppunit/ui/text/TextTestRunner.h>
#include <cppunit/portability/Stream.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
/*! Constructs a new text runner.
* \param outputter used to print text result. Owned by the runner.
*/
TextTestRunner::TextTestRunner( Outputter *outputter )
: m_result( new TestResultCollector() )
, m_eventManager( new TestResult() )
, m_outputter( outputter )
{
if ( !m_outputter )
m_outputter = new TextOutputter( m_result, stdCOut() );
m_eventManager->addListener( m_result );
}
TextTestRunner::~TextTestRunner()
{
delete m_eventManager;
delete m_outputter;
delete m_result;
}
/*! Runs the named test case.
*
* \param testName Name of the test case to run. If an empty is given, then
* all added tests are run. The name can be the name of any
* test in the hierarchy.
* \param doWait if \c true then the user must press the RETURN key
* before the run() method exit.
* \param doPrintResult if \c true (default) then the test result are printed
* on the standard output.
* \param doPrintProgress if \c true (default) then TextTestProgressListener is
* used to show the progress.
* \return \c true is the test was successful, \c false if the test
* failed or was not found.
*/
bool
TextTestRunner::run( std::string testName,
bool doWait,
bool doPrintResult,
bool doPrintProgress )
{
TextTestProgressListener progress;
if ( doPrintProgress )
m_eventManager->addListener( &progress );
TestRunner *pThis = this;
pThis->run( *m_eventManager, testName );
if ( doPrintProgress )
m_eventManager->removeListener( &progress );
printResult( doPrintResult );
wait( doWait );
return m_result->wasSuccessful();
}
void
TextTestRunner::wait( bool doWait )
{
#if !defined( CPPUNIT_NO_STREAM )
if ( doWait )
{
stdCOut() << "<RETURN> to continue\n";
stdCOut().flush();
std::cin.get ();
}
#endif
}
void
TextTestRunner::printResult( bool doPrintResult )
{
stdCOut() << "\n";
if ( doPrintResult )
m_outputter->write();
}
/*! Returns the result of the test run.
* Use this after calling run() to access the result of the test run.
*/
TestResultCollector &
TextTestRunner::result() const
{
return *m_result;
}
/*! Returns the event manager.
* The instance of TestResult results returned is the one that is used to run the
* test. Use this to register additional TestListener before running the tests.
*/
TestResult &
TextTestRunner::eventManager() const
{
return *m_eventManager;
}
/*! Specifies an alternate outputter.
*
* Notes that the outputter will be use after the test run only if \a printResult was
* \c true.
* \param outputter New outputter to use. The previous outputter is destroyed.
* The TextTestRunner assumes ownership of the outputter.
* \see CompilerOutputter, XmlOutputter, TextOutputter.
*/
void
TextTestRunner::setOutputter( Outputter *outputter )
{
delete m_outputter;
m_outputter = outputter;
}
void
TextTestRunner::run( TestResult &controller,
const std::string &testPath )
{
TestRunner::run( controller, testPath );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,54 @@
#include <cppunit/Portability.h>
#include <cppunit/extensions/TypeInfoHelper.h>
#if CPPUNIT_HAVE_RTTI
#include <string>
#if CPPUNIT_HAVE_GCC_ABI_DEMANGLE
#include <malloc.h>
#include <cxxabi.h>
#endif
CPPUNIT_NS_BEGIN
std::string
TypeInfoHelper::getClassName( const std::type_info &info )
{
#if defined(CPPUNIT_HAVE_GCC_ABI_DEMANGLE) && CPPUNIT_HAVE_GCC_ABI_DEMANGLE
int status = 0;
char* c_name = 0;
c_name = abi::__cxa_demangle( info.name(), 0, 0, &status );
std::string name( c_name );
free( c_name );
#else // CPPUNIT_HAVE_GCC_ABI_DEMANGLE
static std::string classPrefix( "class " );
std::string name( info.name() );
// Work around gcc 3.0 bug: strip number before type name.
unsigned int firstNotDigitIndex = 0;
while ( firstNotDigitIndex < name.length() &&
name[firstNotDigitIndex] >= '0' &&
name[firstNotDigitIndex] <= '9' )
++firstNotDigitIndex;
name = name.substr( firstNotDigitIndex );
if ( name.substr( 0, classPrefix.length() ) == classPrefix )
return name.substr( classPrefix.length() );
#endif // CPPUNIT_HAVE_GCC_ABI_DEMANGLE
return name;
}
CPPUNIT_NS_END
#endif // CPPUNIT_HAVE_RTTI

View File

@@ -0,0 +1,44 @@
#include <cppunit/Portability.h>
#if defined(CPPUNIT_HAVE_UNIX_DLL_LOADER)
#include <cppunit/plugin/DynamicLibraryManager.h>
#include <dlfcn.h>
#include <unistd.h>
CPPUNIT_NS_BEGIN
DynamicLibraryManager::LibraryHandle
DynamicLibraryManager::doLoadLibrary( const std::string &libraryName )
{
return ::dlopen( libraryName.c_str(), RTLD_NOW | RTLD_GLOBAL );
}
void
DynamicLibraryManager::doReleaseLibrary()
{
::dlclose( m_libraryHandle);
}
DynamicLibraryManager::Symbol
DynamicLibraryManager::doFindSymbol( const std::string &symbol )
{
return ::dlsym ( m_libraryHandle, symbol.c_str() );
}
std::string
DynamicLibraryManager::getLastErrorDetail() const
{
return "";
}
CPPUNIT_NS_END
#endif // defined(CPPUNIT_HAVE_UNIX_DLL_LOADER)

View File

@@ -0,0 +1,73 @@
#include <cppunit/Portability.h>
#if defined(CPPUNIT_HAVE_WIN32_DLL_LOADER)
#include <cppunit/plugin/DynamicLibraryManager.h>
#define WIN32_LEAN_AND_MEAN
#define NOGDI
#define NOUSER
#define NOKERNEL
#define NOSOUND
#define NOMINMAX
#define BLENDFUNCTION void // for mingw & gcc
#include <windows.h>
CPPUNIT_NS_BEGIN
DynamicLibraryManager::LibraryHandle
DynamicLibraryManager::doLoadLibrary( const std::string &libraryName )
{
return ::LoadLibraryA( libraryName.c_str() );
}
void
DynamicLibraryManager::doReleaseLibrary()
{
::FreeLibrary( (HINSTANCE)m_libraryHandle );
}
DynamicLibraryManager::Symbol
DynamicLibraryManager::doFindSymbol( const std::string &symbol )
{
return (DynamicLibraryManager::Symbol)::GetProcAddress(
(HINSTANCE)m_libraryHandle,
symbol.c_str() );
}
std::string
DynamicLibraryManager::getLastErrorDetail() const
{
LPVOID lpMsgBuf;
::FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPSTR) &lpMsgBuf,
0,
NULL
);
std::string message = (LPCSTR)lpMsgBuf;
// Display the string.
// ::MessageBoxA( NULL, (LPCSTR)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION );
// Free the buffer.
::LocalFree( lpMsgBuf );
return message;
}
CPPUNIT_NS_END
#endif // defined(CPPUNIT_HAVE_WIN32_DLL_LOADER)

View File

@@ -0,0 +1,106 @@
#include <cppunit/config/SourcePrefix.h>
#include <cppunit/tools/XmlDocument.h>
#include <cppunit/tools/XmlElement.h>
CPPUNIT_NS_BEGIN
XmlDocument::XmlDocument( const std::string &encoding,
const std::string &styleSheet )
: m_styleSheet( styleSheet )
, m_rootElement( new XmlElement( "DummyRoot" ) )
, m_standalone( true )
{
setEncoding( encoding );
}
XmlDocument::~XmlDocument()
{
delete m_rootElement;
}
std::string
XmlDocument::encoding() const
{
return m_encoding;
}
void
XmlDocument::setEncoding( const std::string &encoding )
{
m_encoding = encoding.empty() ? std::string("ISO-8859-1") : encoding;
}
std::string
XmlDocument::styleSheet() const
{
return m_styleSheet;
}
void
XmlDocument::setStyleSheet( const std::string &styleSheet )
{
m_styleSheet = styleSheet;
}
bool
XmlDocument::standalone() const
{
return m_standalone;
}
void
XmlDocument::setStandalone( bool standalone )
{
m_standalone = standalone;
}
void
XmlDocument::setRootElement( XmlElement *rootElement )
{
if ( rootElement == m_rootElement )
return;
delete m_rootElement;
m_rootElement = rootElement;
}
XmlElement &
XmlDocument::rootElement() const
{
return *m_rootElement;
}
std::string
XmlDocument::toString() const
{
std::string asString = "<?xml version=\"1.0\" "
"encoding='" + m_encoding + "'";
if ( m_standalone )
asString += " standalone='yes'";
asString += " ?>\n";
if ( !m_styleSheet.empty() )
asString += "<?xml-stylesheet type=\"text/xsl\" href=\"" + m_styleSheet + "\"?>\n";
asString += m_rootElement->toString();
return asString;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,226 @@
#include <cppunit/tools/StringTools.h>
#include <cppunit/tools/XmlElement.h>
#include <stdexcept>
CPPUNIT_NS_BEGIN
XmlElement::XmlElement( std::string elementName,
std::string content )
: m_name( elementName )
, m_content( content )
{
}
XmlElement::XmlElement( std::string elementName,
int numericContent )
: m_name( elementName )
{
setContent( numericContent );
}
XmlElement::~XmlElement()
{
Elements::iterator itNode = m_elements.begin();
while ( itNode != m_elements.end() )
{
XmlElement *element = *itNode++;
delete element;
}
}
std::string
XmlElement::name() const
{
return m_name;
}
std::string
XmlElement::content() const
{
return m_content;
}
void
XmlElement::setName( const std::string &name )
{
m_name = name;
}
void
XmlElement::setContent( const std::string &content )
{
m_content = content;
}
void
XmlElement::setContent( int numericContent )
{
m_content = StringTools::toString( numericContent );
}
void
XmlElement::addAttribute( std::string attributeName,
std::string value )
{
m_attributes.push_back( Attribute( attributeName, value ) );
}
void
XmlElement::addAttribute( std::string attributeName,
int numericValue )
{
addAttribute( attributeName, StringTools::toString( numericValue ) );
}
void
XmlElement::addElement( XmlElement *node )
{
m_elements.push_back( node );
}
int
XmlElement::elementCount() const
{
return m_elements.size();
}
XmlElement *
XmlElement::elementAt( int index ) const
{
if ( index < 0 || index >= elementCount() )
throw std::invalid_argument( "XmlElement::elementAt(), out of range index" );
return m_elements[ index ];
}
XmlElement *
XmlElement::elementFor( const std::string &name ) const
{
Elements::const_iterator itElement = m_elements.begin();
for ( ; itElement != m_elements.end(); ++itElement )
{
if ( (*itElement)->name() == name )
return *itElement;
}
throw std::invalid_argument( "XmlElement::elementFor(), not matching child element found" );
return NULL; // make some compilers happy.
}
std::string
XmlElement::toString( const std::string &indent ) const
{
std::string element( indent );
element += "<";
element += m_name;
if ( !m_attributes.empty() )
{
element += " ";
element += attributesAsString();
}
element += ">";
if ( !m_elements.empty() )
{
element += "\n";
std::string subNodeIndent( indent + " " );
Elements::const_iterator itNode = m_elements.begin();
while ( itNode != m_elements.end() )
{
const XmlElement *node = *itNode++;
element += node->toString( subNodeIndent );
}
element += indent;
}
if ( !m_content.empty() )
{
element += escape( m_content );
if ( !m_elements.empty() )
{
element += "\n";
element += indent;
}
}
element += "</";
element += m_name;
element += ">\n";
return element;
}
std::string
XmlElement::attributesAsString() const
{
std::string attributes;
Attributes::const_iterator itAttribute = m_attributes.begin();
while ( itAttribute != m_attributes.end() )
{
if ( !attributes.empty() )
attributes += " ";
const Attribute &attribute = *itAttribute++;
attributes += attribute.first;
attributes += "=\"";
attributes += escape( attribute.second );
attributes += "\"";
}
return attributes;
}
std::string
XmlElement::escape( std::string value ) const
{
std::string escaped;
for ( unsigned int index =0; index < value.length(); ++index )
{
char c = value[index ];
switch ( c ) // escape all predefined XML entity (safe?)
{
case '<':
escaped += "&lt;";
break;
case '>':
escaped += "&gt;";
break;
case '&':
escaped += "&amp;";
break;
case '\'':
escaped += "&apos;";
break;
case '"':
escaped += "&quot;";
break;
default:
escaped += c;
}
}
return escaped;
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,205 @@
#include <cppunit/Exception.h>
#include <cppunit/Test.h>
#include <cppunit/TestFailure.h>
#include <cppunit/TestResultCollector.h>
#include <cppunit/XmlOutputter.h>
#include <cppunit/XmlOutputterHook.h>
#include <cppunit/tools/XmlDocument.h>
#include <cppunit/tools/XmlElement.h>
#include <stdlib.h>
#include <algorithm>
CPPUNIT_NS_BEGIN
XmlOutputter::XmlOutputter( TestResultCollector *result,
OStream &stream,
std::string encoding )
: m_result( result )
, m_stream( stream )
, m_xml( new XmlDocument( encoding ) )
{
}
XmlOutputter::~XmlOutputter()
{
delete m_xml;
}
void
XmlOutputter::addHook( XmlOutputterHook *hook )
{
m_hooks.push_back( hook );
}
void
XmlOutputter::removeHook( XmlOutputterHook *hook )
{
m_hooks.erase( std::find( m_hooks.begin(), m_hooks.end(), hook ) );
}
void
XmlOutputter::write()
{
setRootNode();
m_stream << m_xml->toString();
}
void
XmlOutputter::setStyleSheet( const std::string &styleSheet )
{
m_xml->setStyleSheet( styleSheet );
}
void
XmlOutputter::setStandalone( bool standalone )
{
m_xml->setStandalone( standalone );
}
void
XmlOutputter::setRootNode()
{
XmlElement *rootNode = new XmlElement( "TestRun" );
m_xml->setRootElement( rootNode );
for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it )
(*it)->beginDocument( m_xml );
FailedTests failedTests;
fillFailedTestsMap( failedTests );
addFailedTests( failedTests, rootNode );
addSuccessfulTests( failedTests, rootNode );
addStatistics( rootNode );
for ( Hooks::iterator itEnd = m_hooks.begin(); itEnd != m_hooks.end(); ++itEnd )
(*itEnd)->endDocument( m_xml );
}
void
XmlOutputter::fillFailedTestsMap( FailedTests &failedTests )
{
const TestResultCollector::TestFailures &failures = m_result->failures();
TestResultCollector::TestFailures::const_iterator itFailure = failures.begin();
while ( itFailure != failures.end() )
{
TestFailure *failure = *itFailure++;
failedTests.insert( std::pair<Test* const, TestFailure*>(failure->failedTest(), failure ) );
}
}
void
XmlOutputter::addFailedTests( FailedTests &failedTests,
XmlElement *rootNode )
{
XmlElement *testsNode = new XmlElement( "FailedTests" );
rootNode->addElement( testsNode );
const TestResultCollector::Tests &tests = m_result->tests();
for ( unsigned int testNumber = 0; testNumber < tests.size(); ++testNumber )
{
Test *test = tests[testNumber];
if ( failedTests.find( test ) != failedTests.end() )
addFailedTest( test, failedTests[test], testNumber+1, testsNode );
}
}
void
XmlOutputter::addSuccessfulTests( FailedTests &failedTests,
XmlElement *rootNode )
{
XmlElement *testsNode = new XmlElement( "SuccessfulTests" );
rootNode->addElement( testsNode );
const TestResultCollector::Tests &tests = m_result->tests();
for ( unsigned int testNumber = 0; testNumber < tests.size(); ++testNumber )
{
Test *test = tests[testNumber];
if ( failedTests.find( test ) == failedTests.end() )
addSuccessfulTest( test, testNumber+1, testsNode );
}
}
void
XmlOutputter::addStatistics( XmlElement *rootNode )
{
XmlElement *statisticsElement = new XmlElement( "Statistics" );
rootNode->addElement( statisticsElement );
statisticsElement->addElement( new XmlElement( "Tests", m_result->runTests() ) );
statisticsElement->addElement( new XmlElement( "FailuresTotal",
m_result->testFailuresTotal() ) );
statisticsElement->addElement( new XmlElement( "Errors", m_result->testErrors() ) );
statisticsElement->addElement( new XmlElement( "Failures", m_result->testFailures() ) );
for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it )
(*it)->statisticsAdded( m_xml, statisticsElement );
}
void
XmlOutputter::addFailedTest( Test *test,
TestFailure *failure,
int testNumber,
XmlElement *testsNode )
{
Exception *thrownException = failure->thrownException();
XmlElement *testElement = new XmlElement( "FailedTest" );
testsNode->addElement( testElement );
testElement->addAttribute( "id", testNumber );
testElement->addElement( new XmlElement( "Name", test->getName() ) );
testElement->addElement( new XmlElement( "FailureType",
failure->isError() ? "Error" :
"Assertion" ) );
if ( failure->sourceLine().isValid() )
addFailureLocation( failure, testElement );
testElement->addElement( new XmlElement( "Message", thrownException->what() ) );
for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it )
(*it)->failTestAdded( m_xml, testElement, test, failure );
}
void
XmlOutputter::addFailureLocation( TestFailure *failure,
XmlElement *testElement )
{
XmlElement *locationNode = new XmlElement( "Location" );
testElement->addElement( locationNode );
SourceLine sourceLine = failure->sourceLine();
locationNode->addElement( new XmlElement( "File", sourceLine.fileName() ) );
locationNode->addElement( new XmlElement( "Line", sourceLine.lineNumber() ) );
}
void
XmlOutputter::addSuccessfulTest( Test *test,
int testNumber,
XmlElement *testsNode )
{
XmlElement *testElement = new XmlElement( "Test" );
testsNode->addElement( testElement );
testElement->addAttribute( "id", testNumber );
testElement->addElement( new XmlElement( "Name", test->getName() ) );
for ( Hooks::iterator it = m_hooks.begin(); it != m_hooks.end(); ++it )
(*it)->successfulTestAdded( m_xml, testElement, test );
}
CPPUNIT_NS_END

View File

@@ -0,0 +1,44 @@
#include <cppunit/XmlOutputterHook.h>
CPPUNIT_NS_BEGIN
void
XmlOutputterHook::beginDocument( XmlDocument * )
{
}
void
XmlOutputterHook::endDocument( XmlDocument * )
{
}
void
XmlOutputterHook::failTestAdded( XmlDocument *,
XmlElement *,
Test *,
TestFailure * )
{
}
void
XmlOutputterHook::successfulTestAdded( XmlDocument *,
XmlElement *,
Test * )
{
}
void
XmlOutputterHook::statisticsAdded( XmlDocument *,
XmlElement * )
{
}
CPPUNIT_NS_END