merge from tags

This commit is contained in:
Malcolm Noyes 2013-12-09 16:40:52 +00:00
commit 760eed1ad6
44 changed files with 5023 additions and 648 deletions

6
.gitignore vendored
View File

@ -10,6 +10,12 @@ Debug
Release
ipch
TestResults
projects/VS2010/TestCatch/Visual Lint
projects/VS2010/ManagedTestCatch/Visual Lint
projects/VS2012/ManagedTestCatch/Visual Lint
projects/VS2012/NativeTestCatch/Visual Lint
DebugMbcs
ReleaseMbcs
*.user
*.xcuserstate
*.o

View File

@ -0,0 +1,8 @@
If you've used the Catch command line, you might know that Catch can selectively include and exclude tests using tags. For example, you might want to exclude long running tests from each check-in to your CI server, so you might tag those tests with `[slow]` and run Catch with `example.exe ~[slow]`.
It doesn't look like it's possible to reproduce the flexibility of Catch but it is possible to do some basic filtering using Catch tags.
---
[Home](../../README.md)

View File

@ -20,7 +20,15 @@ We can do the same for VS2012 - [see this page for instructions on how to do thi
# Running tests from the command line
Tests can also be run from the command line. [For VS2010 see these details](VS2010commandline.md) and [for VS2012 see these](VS2012commandline.md)
Tests can also be run from the command line. [For VS2010 see these details](VS2010commandline.md) and [for VS2012 see these](VS2012commandline.md).
# Running tests using Catch tags
If you've used the Catch command line, you'll know that Catch can selectively include and exclude tests using tags. For example, you might want to exclude long running tests from each check-in to your CI server, so you might tag those tests with `[slow]` and run Catch with `example.exe ~[slow]`.
It doesn't look like it's possible to reproduce the flexibility of Catch but it is possible to do some basic filtering using Catch tags.
[This page details how to do this.](VScommandlinetags.md)
# Differences in behaviour
@ -34,7 +42,7 @@ There are some minor differences in behaviour between Catch and Visual Studio pr
You can still use the same names that you would normally use for Catch TEST_CASE names, however we use an internal name for the actual function name that the test lives in. This means that you won't see the Catch names in the Test View (VS2010) unless you 'Group By' Description, or in VS2012 you select the 'Traits' view Test Explorer - see the screen shots above.
## Catch tests always stop on first failure.
## When running from the GUI, Catch tests always stop on first failure.
A Catch test that uses SECTIONS will continue to run further sections if one fails; in VS this doesn't make much sense because in a visual environment we want to capture the context of where the test failed. If we allowed the test to continue then we lose this context, so instead we always stop on each failure. You can still use the CHECK macros if you don't want the test to stop.

View File

@ -19,6 +19,7 @@
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#define INTERNAL_CATCH_VS_MANAGED
#define INTERNAL_CATCH_INLINE inline
#else
#if defined(_WINDLL)
@ -26,6 +27,7 @@
// It's possible that this is not enough for someone so allow it to be overridden...
#if !defined( CATCH_CONFIG_MAIN ) && !defined( CATCH_CONFIG_RUNNER )
#define INTERNAL_CATCH_VS_NATIVE
#define INTERNAL_CATCH_INLINE inline
#endif
#endif
@ -52,7 +54,6 @@
#endif
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#define INTERNAL_CATCH_INLINE inline
#ifdef INTERNAL_CATCH_VS_MANAGED
#include "internal/catch_vs_managed_impl.hpp"
#else // INTERNAL_CATCH_VS_MANAGED
@ -203,6 +204,16 @@
#define THEN( desc ) SECTION( " Then: " desc, "" )
#define AND_THEN( desc ) SECTION( " And: " desc, "" )
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
#define CATCH_CONFIG_SHOW_SUCCESS( v ) CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v )
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v ) CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v )
#else
#define CATCH_MAP_CATEGORY_TO_TAG( Category, Tag )
#define CATCH_CONFIG_SHOW_SUCCESS( v )
#define CATCH_CONFIG_WARN_MISSING_ASSERTIONS( v )
#endif
using Catch::Detail::Approx;
#ifdef __clang__

View File

@ -108,6 +108,8 @@ namespace Catch {
std::set<TestCase> m_testsAlreadyRun;
};
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
class Session {
static bool alreadyInstantiated;
@ -232,6 +234,8 @@ namespace Catch {
bool Session::alreadyInstantiated = false;
#endif // !VS_MANAGED && !VS_NATIVE
} // end namespace Catch
#endif // TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED

View File

@ -58,11 +58,7 @@ namespace Catch {
.setResultType( matcher.match( arg ) );
}
#if defined(INTERNAL_CATCH_VS_MANAGED)
// TestFailureException not defined for CLR
#else // detect CLR
struct TestFailureException{};
#endif
} // end namespace Catch
@ -72,7 +68,6 @@ struct TestFailureException{};
#if !defined(INTERNAL_CATCH_VS_MANAGED) && !defined(INTERNAL_CATCH_VS_NATIVE)
// normal Catch
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
#define INTERNAL_CATCH_TEST_THROW_FAILURE throw Catch::TestFailureException();
#else // VS integration
@ -86,10 +81,9 @@ struct TestFailureException{};
std::stringstream _sf; \
_sf << r->getExpressionInMacro().c_str() << ", " << r->getMessage().c_str(); \
std::string fail = _sf.str(); \
Assert::Fail(Catch::convert_string_to_managed(fail)); \
Assert::Fail(Catch::convert_string_for_assert(fail)); \
}
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION AssertFailedException^
#else
#if defined(INTERNAL_CATCH_VS_NATIVE)
@ -108,8 +102,6 @@ struct TestFailureException{};
Assert::Fail(ws2.c_str(), &li); \
}
#define INTERNAL_CATCH_TEST_FAILURE_EXCEPTION const Catch::TestFailureException&
#endif // INTERNAL_CATCH_VS_MANAGED
#endif // detect CLR
@ -121,7 +113,7 @@ struct TestFailureException{};
if( Catch::ResultAction::Value internal_catch_action = Catch::getResultCapture().acceptExpression( evaluatedExpr, INTERNAL_CATCH_ASSERTIONINFO_NAME ) ) { \
if( internal_catch_action & Catch::ResultAction::Debug ) CATCH_BREAK_INTO_DEBUGGER(); \
if( internal_catch_action & Catch::ResultAction::Abort ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { INTERNAL_CATCH_TEST_THROW_FAILURE } \
if( !Catch::shouldContinueOnFailure( resultDisposition ) ) { throw Catch::TestFailureException(); } \
Catch::isTrue( false && originalExpr ); \
}
@ -135,7 +127,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_INFO( #expr, macroName, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionDecomposer()->*expr ).endExpression( resultDisposition ), resultDisposition, expr ); \
} catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
} catch( const Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException(), \
@ -174,7 +166,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_EXPR( Catch::ExpressionResultBuilder( Catch::ResultWas::DidntThrowException ), resultDisposition, false ); \
} \
} \
catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
catch( const Catch::TestFailureException& ) { \
throw; \
} \
catch( exceptionType ) { \
@ -218,7 +210,7 @@ struct TestFailureException{};
INTERNAL_CATCH_ACCEPT_INFO( #arg " " #matcher, macroName, resultDisposition ); \
try { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::expressionResultBuilderFromMatcher( ::Catch::Matchers::matcher, arg, #matcher ) ), resultDisposition, false ); \
} catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) { \
} catch( const Catch::TestFailureException& ) { \
throw; \
} catch( ... ) { \
INTERNAL_CATCH_ACCEPT_EXPR( ( Catch::ExpressionResultBuilder( Catch::ResultWas::ThrewException ) << Catch::translateActiveException() ), \

View File

@ -22,6 +22,138 @@
#define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif
namespace CatchOverrides {
class ConfigGuard
{
public:
ConfigGuard()
: origConfig(Catch::getCurrentContext().getConfig())
{}
~ConfigGuard()
{
Catch::getCurrentMutableContext().setConfig(origConfig);
}
const Catch::Ptr<Catch::IConfig const>& value() const {return origConfig;}
private:
ConfigGuard(const ConfigGuard&);
ConfigGuard& operator=(const ConfigGuard&);
const Catch::Ptr<Catch::IConfig const> origConfig;
};
template <typename T>
class Config
{
typedef std::map<int, bool> LineData;
typedef std::map<std::string, LineData> FileLineData;
public:
bool includeSuccessfulResults(const std::string& file, int c) const
{
bool result(false);
FileLineData::const_iterator it = showSuccessfulTestsData.find(file);
if( it != showSuccessfulTestsData.end() )
{
for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
{
if( c <= lineIt->first )
break;
result = lineIt->second;
}
}
return result;
}
void insertSuccessfulResults(const std::string& file, int c, bool v)
{
FileLineData::iterator it = showSuccessfulTestsData.find(file);
if( it == showSuccessfulTestsData.end() )
{
LineData tmp;
tmp.insert(std::make_pair(c,v));
showSuccessfulTestsData.insert(std::make_pair(file, tmp));
}
else
{
it->second.insert(std::make_pair(c,v));
}
}
bool warnAboutMissingAssertions(const std::string& file, int c) const
{
bool result(false);
FileLineData::const_iterator it = missingAssertionData.find(file);
if( it != missingAssertionData.end() )
{
for( LineData::const_iterator lineIt = it->second.begin(); lineIt != it->second.end(); ++lineIt )
{
if( c <= lineIt->first )
break;
result = lineIt->second;
}
}
return result;
}
void insertMissingAssertions(const std::string& file, int c, bool v)
{
FileLineData::iterator it = missingAssertionData.find(file);
if( it == missingAssertionData.end() )
{
LineData tmp;
tmp.insert(std::make_pair(c,v));
missingAssertionData.insert(std::make_pair(file, tmp));
}
else
{
it->second.insert(std::make_pair(c,v));
}
}
static Config<T>& instance()
{
if( !s_instance )
{
s_instance = new Config<T>();
}
return *s_instance;
}
private:
FileLineData showSuccessfulTestsData;
FileLineData missingAssertionData;
static Config<T>* s_instance;
};
template <typename T>
Config<T>* Config<T>::s_instance = NULL;
template <typename T>
struct ConfigReset
{
ConfigReset( const std::string& file, int c )
{
Config<T>::instance().insertSuccessfulResults(file, c, false);
Config<T>::instance().insertMissingAssertions(file, c, false);
}
};
template <typename T>
struct ConfigShowSuccessfulTests
{
template <typename U>
ConfigShowSuccessfulTests( const std::string& file, int c, U v )
{
Config<T>::instance().insertSuccessfulResults(file, c, v ? true : false);
}
};
template <typename T>
struct ConfigWarnMissingAssertions
{
template <typename U>
ConfigWarnMissingAssertions( const std::string& file, int c, U v )
{
Config<T>::instance().insertMissingAssertions(file, c, v ? true : false);
}
};
}
namespace Catch {
struct ConfigData {
@ -41,6 +173,21 @@ namespace Catch {
showDurations( ShowDurations::DefaultForReporter )
{}
explicit ConfigData(const IConfig* other)
: listTests( false ),
listTags( false ),
listReporters( false ),
showSuccessfulTests( other ? other->includeSuccessfulResults() : false ),
shouldDebugBreak( false ),
noThrow( other ? !other->allowThrows() : false ),
showHelp( false ),
abortAfter( -1 ),
verbosity( Verbosity::Normal ),
warnings( other ? (other->warnAboutMissingAssertions() ? WarnAbout::NoAssertions : WarnAbout::Nothing) : WarnAbout::Nothing ),
showDurations( other ? other->showDurations() : ShowDurations::DefaultForReporter ),
name( other ? other->name() : std::string() )
{}
bool listTests;
bool listTags;
bool listReporters;

View File

@ -12,10 +12,6 @@
namespace Catch {
namespace Detail {
struct IColourImpl;
}
struct Colour {
enum Code {
None = 0,
@ -53,12 +49,6 @@ namespace Catch {
// Use constructed object for RAII guard
Colour( Code _colourCode );
~Colour();
// Use static method for one-shot changes
static void use( Code _colourCode );
private:
static Detail::IColourImpl* impl;
};
} // end namespace Catch

View File

@ -10,13 +10,6 @@
#include "catch_console_colour.hpp"
namespace Catch { namespace Detail {
struct IColourImpl {
virtual ~IColourImpl() {}
virtual void use( Colour::Code _colourCode ) = 0;
};
}}
#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
#ifndef NOMINMAX
@ -32,7 +25,7 @@ namespace Catch { namespace Detail {
namespace Catch {
namespace {
class Win32ColourImpl : public Detail::IColourImpl {
class Win32ColourImpl {
public:
Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
{
@ -41,7 +34,7 @@ namespace {
originalAttributes = csbiInfo.wAttributes;
}
virtual void use( Colour::Code _colourCode ) {
void use( Colour::Code _colourCode ) {
switch( _colourCode ) {
case Colour::None: return setTextAttribute( originalAttributes );
case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
@ -73,7 +66,7 @@ namespace {
return true;
}
Win32ColourImpl platformColourImpl;
typedef Win32ColourImpl PlatformColourImpl;
} // end anon namespace
} // end namespace Catch
@ -89,9 +82,9 @@ namespace {
// Thanks to Adam Strzelecki for original contribution
// (http://github.com/nanoant)
// https://github.com/philsquared/Catch/pull/131
class PosixColourImpl : public Detail::IColourImpl {
class PosixColourImpl {
public:
virtual void use( Colour::Code _colourCode ) {
void use( Colour::Code _colourCode ) {
switch( _colourCode ) {
case Colour::None:
case Colour::White: return setColour( "[0m" );
@ -120,7 +113,7 @@ namespace {
return isatty(STDOUT_FILENO);
}
PosixColourImpl platformColourImpl;
typedef PosixColourImpl PlatformColourImpl;
} // end anon namespace
} // end namespace Catch
@ -129,24 +122,24 @@ namespace {
namespace Catch {
namespace {
struct NoColourImpl : Detail::IColourImpl {
void use( Colour::Code ) {}
template <typename Impl>
struct ColourChange
{
static Impl impl;
static const bool shouldUseColour;
};
NoColourImpl noColourImpl;
static const bool shouldUseColour = shouldUseColourForPlatform() &&
!isDebuggerActive();
}
template <typename Impl>
Impl ColourChange<Impl>::impl;
template <typename Impl>
const bool ColourChange<Impl>::shouldUseColour = shouldUseColourForPlatform() &&
!isDebuggerActive();;
Colour::Colour( Code _colourCode ){ use( _colourCode ); }
Colour::~Colour(){ use( None ); }
void Colour::use( Code _colourCode ) {
impl->use( _colourCode );
INTERNAL_CATCH_INLINE Colour::Colour( Code _colourCode ) {
if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( _colourCode );
}
INTERNAL_CATCH_INLINE Colour::~Colour() {
if( ColourChange<PlatformColourImpl>::shouldUseColour ) ColourChange<PlatformColourImpl>::impl.use( Colour::None );
}
Detail::IColourImpl* Colour::impl = shouldUseColour
? static_cast<Detail::IColourImpl*>( &platformColourImpl )
: static_cast<Detail::IColourImpl*>( &noColourImpl );
} // end namespace Catch

View File

@ -15,9 +15,10 @@
namespace Catch {
template <typename Runner, typename ResultCapture>
class Context : public IMutableContext {
Context() : m_config( NULL ), m_runner( NULL ), m_resultCapture( NULL ) {}
Context() : m_config( NULL ), m_runner( &nullRunner ), m_resultCapture( &nullResultCapture ) {}
Context( Context const& );
void operator=( Context const& );
@ -81,15 +82,28 @@ namespace Catch {
IRunner* m_runner;
IResultCapture* m_resultCapture;
std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
static ResultCapture nullResultCapture;
static Runner nullRunner;
public:
static Context* currentContext;
};
namespace {
template <typename Runner, typename ResultCapture>
ResultCapture Context<Runner, ResultCapture>::nullResultCapture;
template <typename Runner, typename ResultCapture>
Runner Context<Runner, ResultCapture>::nullRunner;
template <typename Runner, typename ResultCapture>
Context<Runner,ResultCapture>* Context<Runner, ResultCapture>::currentContext = NULL;
/*namespace {
Context* currentContext = NULL;
}
}*/
typedef Context<NullRunner, NullResultCapture> DefaultContext;
INTERNAL_CATCH_INLINE IMutableContext& getCurrentMutableContext() {
if( !currentContext )
currentContext = new Context();
return *currentContext;
if( !DefaultContext::currentContext )
DefaultContext::currentContext = new DefaultContext();
return *DefaultContext::currentContext;
}
INTERNAL_CATCH_INLINE IContext& getCurrentContext() {
return getCurrentMutableContext();
@ -104,8 +118,8 @@ namespace Catch {
}
INTERNAL_CATCH_INLINE void cleanUpContext() {
delete currentContext;
currentContext = NULL;
delete DefaultContext::currentContext;
DefaultContext::currentContext = NULL;
}
}

View File

@ -41,6 +41,23 @@ namespace Catch {
virtual std::string getCurrentTestName() const = 0;
virtual const AssertionResult* getLastResult() const = 0;
};
struct NullResultCapture : public IResultCapture {
virtual void assertionEnded( AssertionResult const& ) {}
virtual bool sectionStarted( SectionInfo const& ,
Counts& ) {return false;}
virtual void sectionEnded( SectionInfo const& , Counts const& , double ) {}
virtual void pushScopedMessage( MessageInfo const& ) {}
virtual void popScopedMessage( MessageInfo const& ) {}
virtual bool shouldDebugBreak() const {return false;}
virtual ResultAction::Value acceptExpression( ExpressionResultBuilder const& , AssertionInfo const& ) {return ResultAction::Abort;}
virtual std::string getCurrentTestName() const {return std::string();}
virtual const AssertionResult* getLastResult() const {return NULL;}
};
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED

View File

@ -14,6 +14,10 @@ namespace Catch {
struct IRunner {
virtual ~IRunner();
};
struct NullRunner : public IRunner
{
};
}
#endif // TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED

View File

@ -16,8 +16,6 @@
namespace Catch {
namespace {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
RegistryHub( RegistryHub const& );
@ -54,26 +52,32 @@ namespace Catch {
};
// Single, global, instance
inline RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = NULL;
template <typename T>
struct GlobalRegistryHub
{
static T*& instance()
{
if( !theRegistryHub )
theRegistryHub = new RegistryHub();
theRegistryHub = new T();
return theRegistryHub;
}
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
IRegistryHub& getRegistryHub() {
return *getTheRegistryHub();
INTERNAL_CATCH_INLINE IRegistryHub& getRegistryHub() {
return *GlobalRegistryHub<RegistryHub>::instance();
}
IMutableRegistryHub& getMutableRegistryHub() {
return *getTheRegistryHub();
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return *GlobalRegistryHub<RegistryHub>::instance();
}
void cleanUp() {
delete getTheRegistryHub();
getTheRegistryHub() = NULL;
INTERNAL_CATCH_INLINE void cleanUp() {
delete GlobalRegistryHub<RegistryHub>::instance();
GlobalRegistryHub<RegistryHub>::instance() = NULL;
cleanUpContext();
}
std::string translateActiveException() {
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
}

View File

@ -48,7 +48,6 @@ namespace Catch {
};
///////////////////////////////////////////////////////////////////////////
class RunContext : public IResultCapture, public IRunner {
RunContext( RunContext const& );
@ -105,18 +104,16 @@ namespace Catch {
}
Totals runTest( TestCase const& testCase ) {
Totals prevTotals = m_totals;
std::string redirectedCout;
std::string redirectedCerr;
TestCaseInfo testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting( testInfo );
UnwindTestCaseOnCompletion finaliser(*this, m_totals, m_reporter, testInfo, redirectedCout, redirectedCerr);
m_activeTestCase = &testCase;
m_testCaseTracker = TestCaseTracker( testInfo.name );
do {
do {
runCurrentTest( redirectedCout, redirectedCerr );
@ -125,18 +122,10 @@ namespace Catch {
}
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
Totals deltaTotals = m_totals.delta( prevTotals );
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( testInfo,
deltaTotals,
redirectedCout,
redirectedCerr,
aborting() ) );
m_activeTestCase = NULL;
m_testCaseTracker.reset();
return deltaTotals;
return finaliser.report();
}
Ptr<IConfig const> config() const {
@ -194,12 +183,7 @@ namespace Catch {
return true;
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
void unwindSection(SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
@ -209,6 +193,15 @@ namespace Catch {
m_messages.clear();
}
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
unwindSection(info, prevAssertions, _durationInSeconds);
}
virtual void pushScopedMessage( MessageInfo const& message ) {
m_messages.push_back( message );
}
@ -257,16 +250,13 @@ namespace Catch {
void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
m_reporter->sectionStarting( testCaseSection );
Counts prevAssertions = m_totals.assertions;
double duration = 0;
UnwindSectionOnCompletion finaliser(*this, m_totals, m_reporter, testCaseInfo, m_unfinishedSections, m_messages);
try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
TestCaseTracker::Guard guard( *m_testCaseTracker );
Timer timer;
timer.start();
finaliser.startTimer();
if( m_reporter->getPreferences().shouldRedirectStdOut ) {
StreamRedirect coutRedir( std::cout, redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr );
@ -275,37 +265,16 @@ namespace Catch {
else {
m_activeTestCase->invoke();
}
duration = timer.getElapsedSeconds();
finaliser.stopTimer();
}
#ifdef INTERNAL_CATCH_VS_MANAGED // detect CLR
catch(AssertFailedException^) {
throw; // CLR always rethrows - stop on first assert
}
#else
catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) {
catch( const Catch::TestFailureException& ) {
// This just means the test was aborted due to failure
}
#endif
catch(...) {
ExpressionResultBuilder exResult( ResultWas::ThrewException );
exResult << translateActiveException();
actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
}
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
itEnd = m_unfinishedSections.end();
it != itEnd;
++it )
sectionEnded( it->info, it->prevAssertions, it->durationInSeconds );
m_unfinishedSections.clear();
m_messages.clear();
Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions );
SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
private:
@ -319,6 +288,111 @@ namespace Catch {
double durationInSeconds;
};
class UnwindSectionOnCompletion
{
public:
UnwindSectionOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo const& testCaseInfo,
std::vector<UnfinishedSections>& unfinishedSections, std::vector<MessageInfo>& messages)
: m_context(context)
, m_totals(totals)
, m_reporter(reporter)
, m_testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo )
, m_unfinishedSections(unfinishedSections)
, m_messages(messages)
, m_duration(0.0)
{
m_prevAssertions = m_totals.assertions;
m_reporter->sectionStarting( m_testCaseSection );
}
~UnwindSectionOnCompletion()
{
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down.
for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
itEnd = m_unfinishedSections.end();
it != itEnd;
++it ) {
m_context.unwindSection( it->info, it->prevAssertions, it->durationInSeconds );
}
m_unfinishedSections.clear();
m_messages.clear();
Counts assertions = m_totals.assertions - m_prevAssertions;
bool missingAssertions = m_context.testForMissingAssertions( assertions );
SectionStats testCaseSectionStats( m_testCaseSection, assertions, m_duration, missingAssertions );
m_reporter->sectionEnded( testCaseSectionStats );
}
void startTimer()
{
m_timer.start();
}
void stopTimer()
{
m_duration = m_timer.getElapsedSeconds();
}
private:
// non-copyable
UnwindSectionOnCompletion(const UnwindSectionOnCompletion&);
UnwindSectionOnCompletion& operator=(const UnwindSectionOnCompletion&);
RunContext& m_context;
Totals& m_totals;
Ptr<IStreamingReporter>& m_reporter;
SectionInfo m_testCaseSection;
std::vector<UnfinishedSections>& m_unfinishedSections;
std::vector<MessageInfo>& m_messages;
Timer m_timer;
Counts m_prevAssertions;
double m_duration;
};
class UnwindTestCaseOnCompletion
{
public:
UnwindTestCaseOnCompletion(RunContext& context, Totals& totals, Ptr<IStreamingReporter>& reporter, TestCaseInfo& testInfo,
std::string& redirectedCout, std::string& redirectedCerr)
: m_context(context), m_totals(totals), m_reporter(reporter), m_testInfo(testInfo)
, m_redirectedCout(redirectedCout), m_redirectedCerr(redirectedCerr)
, m_reported(false)
{
m_prevTotals = m_totals;
m_reporter->testCaseStarting( m_testInfo );
}
~UnwindTestCaseOnCompletion()
{
if( !m_reported )
{
report();
}
}
Totals report()
{
m_reported = true;
Totals deltaTotals = m_totals.delta( m_prevTotals );
m_totals.testCases += deltaTotals.testCases;
m_reporter->testCaseEnded( TestCaseStats( m_testInfo,
deltaTotals,
m_redirectedCout,
m_redirectedCerr,
m_context.aborting() ) );
return deltaTotals;
}
private:
// non-copyable
UnwindTestCaseOnCompletion(const UnwindTestCaseOnCompletion&);
UnwindTestCaseOnCompletion& operator=(const UnwindTestCaseOnCompletion&);
RunContext& m_context;
Totals& m_totals;
Ptr<IStreamingReporter>& m_reporter;
TestCaseInfo& m_testInfo;
std::string& m_redirectedCout;
std::string& m_redirectedCerr;
bool m_reported;
Totals m_prevTotals;
};
TestRunInfo m_runInfo;
IMutableContext& m_context;
TestCase const* m_activeTestCase;

View File

@ -8,7 +8,11 @@
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#include "internal/catch_vs_test_registry.hpp"
#else
#include "catch_test_registry.hpp"
#endif
#include "catch_test_case_info.h"
#include "catch_test_spec.h"
#include "catch_context.h"
@ -124,15 +128,15 @@ namespace Catch {
///////////////////////////////////////////////////////////////////////////
AutoReg::AutoReg( TestFunction function,
INTERNAL_CATCH_INLINE AutoReg::AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
}
AutoReg::~AutoReg() {}
INTERNAL_CATCH_INLINE AutoReg::~AutoReg() {}
void AutoReg::registerTestCase( ITestCase* testCase,
INTERNAL_CATCH_INLINE void AutoReg::registerTestCase( ITestCase* testCase,
char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {

View File

@ -24,15 +24,25 @@ namespace Catch {
namespace {
#ifdef CATCH_PLATFORM_WINDOWS
template <typename T>
struct CounterDefaults
{
static T hz;
static T hzo;
};
template <typename T>
T CounterDefaults<T>::hz = 0;
template <typename T>
T CounterDefaults<T>::hzo = 0;
INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {
static uint64_t hz=0, hzo=0;
if (!hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&hz);
QueryPerformanceCounter((LARGE_INTEGER*)&hzo);
if (!CounterDefaults<uint64_t>::hz) {
QueryPerformanceFrequency((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hz);
QueryPerformanceCounter((LARGE_INTEGER*)&CounterDefaults<uint64_t>::hzo);
}
uint64_t t;
QueryPerformanceCounter((LARGE_INTEGER*)&t);
return ((t-hzo)*1000000)/hz;
return ((t-CounterDefaults<uint64_t>::hzo)*1000000)/CounterDefaults<uint64_t>::hz;
}
#else
INTERNAL_CATCH_INLINE uint64_t getCurrentTicks() {

View File

@ -95,7 +95,11 @@ struct StringMaker<T*> {
if( !p )
return INTERNAL_CATCH_STRINGIFY( NULL );
std::ostringstream oss;
#ifdef _MSC_VER
oss << "0x" << p;
#else
oss << p;
#endif
return oss.str();
}
};

View File

@ -18,7 +18,7 @@ using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
namespace Catch {
inline String^ convert_string_to_managed(const std::string& s)
inline String^ convert_string_for_assert(const std::string& s)
{
String^ result = gcnew String(s.c_str());
return result;
@ -33,67 +33,50 @@ namespace Catch {
#include "catch_section.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.hpp"
#include "internal/catch_exception_translator_registry.hpp"
#include "catch_registry_hub.hpp"
#include "internal/catch_console_colour_impl.hpp"
#include "catch_runner.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporter::~IReporter() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
inline TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
ExceptionRegistryHub( ExceptionRegistryHub const& );
void operator=( ExceptionRegistryHub const& );
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
public: // IRegistryHub
ExceptionRegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
inline void Config::dummy() {}
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const&, IReporterFactory* ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTest( TestCase const& ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private:
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
template <typename T>
struct GlobalRegistryHub
{
static T& instance()
{
if( !theRegistryHub )
theRegistryHub = new T();
return *theRegistryHub;
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance();
}
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
}
}
#endif
#endif // TWOBLUECUBES_CATCH_VS_MANAGED_HPP_INCLUDED

View File

@ -16,8 +16,6 @@ using Microsoft::VisualStudio::CppUnitTestFramework::Logger;
using Microsoft::VisualStudio::CppUnitTestFramework::Assert;
using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#define INTERNAL_CATCH_INLINE inline
#include <cvt/wstring>
#include <codecvt>
@ -26,66 +24,50 @@ using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#include "catch_tags.hpp"
#include "catch_test_spec.hpp"
#include "catch_section.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.hpp"
#include "catch_registry_hub.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_console_colour_impl.hpp"
#include "catch_runner.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporter::~IReporter() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
class ExceptionRegistryHub : public IRegistryHub, public IMutableRegistryHub {
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
inline TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
ExceptionRegistryHub( ExceptionRegistryHub const& );
void operator=( ExceptionRegistryHub const& );
public: // IRegistryHub
ExceptionRegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub
virtual void registerReporter( std::string const&, IReporterFactory* ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTest( TestCase const& ) {
throw std::runtime_error("can't do this for Visual Studio tests!");
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private:
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
};
template <typename T>
struct GlobalRegistryHub
{
static T& instance()
{
if( !theRegistryHub )
theRegistryHub = new T();
return *theRegistryHub;
}
static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance();
}
INTERNAL_CATCH_INLINE std::string translateActiveException() {
return GlobalRegistryHub<ExceptionRegistryHub>::instance().getExceptionTranslatorRegistry().translateActiveException();
}
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
inline void Config::dummy() {}
}
#endif // INTERNAL_CATCH_VS_NATIVE

View File

@ -16,27 +16,11 @@
#include "catch_common.h"
#include "catch_interfaces_testcase.h"
#include "internal/catch_compiler_capabilities.h"
#include "internal/clara.h"
#include <tchar.h>
namespace Catch {
typedef void(*TestFunction)();
class FreeFunctionTestCase : public SharedImpl<ITestCase> {
public:
FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
virtual void invoke() const {
m_fun();
}
private:
virtual ~FreeFunctionTestCase();
TestFunction m_fun;
};
class MethodTestCase : public SharedImpl<ITestCase> {
struct placeholder
@ -79,7 +63,7 @@ private:
typedef void(*TestFunction)();
struct NameAndDesc {
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#ifdef INTERNAL_CATCH_VS_MANAGED
NameAndDesc( const char* _name = "", const char* _description= "" )
: name( _name ), description( _description )
{}
@ -90,14 +74,35 @@ struct NameAndDesc {
NameAndDesc( const wchar_t* _name, const char* _description= "" )
: name(), description( _description )
{
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
name = conv1.to_bytes(_name);
assignName(_name);
}
NameAndDesc( const wchar_t* _name, int )
: name(), description( "" )
{
assignName(_name);
}
void assignName(const wchar_t* _name)
{
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1;
name = conv1.to_bytes(_name);
std::string tmp = conv1.to_bytes(_name);
if( tmp.empty() )
{
name = tmp;
}
else
{
std::string::iterator startIter = tmp.begin();
if(*startIter == '\"')
{
++startIter;
}
std::string::reverse_iterator endIter = tmp.rbegin();
if(*endIter == '\"')
{
++endIter;
}
name.assign(startIter, endIter.base());
}
}
#endif
@ -105,9 +110,38 @@ struct NameAndDesc {
std::string description;
};
struct AutoReg {
AutoReg( TestFunction function,
SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc );
template<typename C>
AutoReg( void (C::*method)(),
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) {
registerTestCase( new MethodTestCase( method ),
className,
nameAndDesc,
lineInfo );
}
void registerTestCase( ITestCase* testCase,
char const* className,
NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo );
~AutoReg();
private:
AutoReg( AutoReg const& );
void operator= ( AutoReg const& );
};
} // end namespace Catch
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#ifdef INTERNAL_CATCH_VS_MANAGED
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( name ) name##""
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__) )
@ -134,7 +168,7 @@ struct NameAndDesc {
#define CATCH_INTERNAL_NAMESPACE( Ext )
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
public: \
[TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
@ -142,22 +176,24 @@ struct NameAndDesc {
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
}
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
public: \
[TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
[TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) () \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
}
[TestCategory( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
[TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ()
#define CHECK_FOR_TEST_CASE_CLASH
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( #Category, Tag, __COUNTER__ )
#define FAIL_STRING( str ) _T( str )
#else // detect CLR
// Native tests
@ -173,99 +209,161 @@ struct NameAndDesc {
#define TEST_IMPL_2(tuple) TEST_IMPL2 tuple
#define TEST_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2 tuple
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) #INTERNAL_CATCH_SPLIT_ARG_1
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__VA_ARGS__, 2, 1) )
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W tuple
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W( INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) L#INTERNAL_CATCH_SPLIT_ARG_1
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
{ \
Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST( Method ); \
Catch::NameAndDesc name_desc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_TEST(Count); \
}
#define INTERNAL_CATCH_TEST_CLASS_METHOD( Method, UniqueExt, Name, Desc ) \
#define BEGIN_INTERNAL_CATCH_BATCH_METHOD( Tags, UniqueExt ) \
public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \
TEST_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \
{ \
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
}
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) )
#define CHECK_FOR_TEST_CASE_CLASH void INTERNAL_CATCH_UNIQUE_NAME_LINE( if_you_get_this_error_you_have_a_test_case_name_clash_please_put_a_namespace_around_the_test_case_at_line_, __LINE__ )() {}
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG( Category, Tag ) \
INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, __COUNTER__ )
#define FAIL_STRING( str ) WIDEN( str )
#endif // detect CLR
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), __COUNTER__ )
#define INTERNAL_CATCH_CONCAT_LINE_COUNTER( count ) INTERNAL_CATCH_UNIQUE_NAME_LINE( INTERNAL_CATCH_UNIQUE_NAME_LINE( __LINE__, _ ), count )
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Method ) \
{ Catch::ConfigData cd; \
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, Count ) \
namespace { CatchOverrides::ConfigShowSuccessfulTests<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, Count ) \
namespace { CatchOverrides::ConfigWarnMissingAssertions<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H_____O_V_E_R_R_I_D_E____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count, v); }
#define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS( v ) \
CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, __COUNTER__)
#define CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS( v ) \
CATCH_INTERNAL_CONFIG_WARN_MISSING_ASSERTIONS2( v, __COUNTER__)
#define CATCH_INTERNAL_RUN_SINGLE_TEST( Count ) \
{ CatchOverrides::ConfigGuard cg; \
Catch::ConfigData cd(cg.value().get()); \
cd.name = name_desc.name; \
cd.abortAfter = 1; \
cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
cd.warnings = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
Catch::RunContext tr(config.get(), rep); \
Catch::TestCase tc = Catch::makeTestCase( new Catch::FreeFunctionTestCase( & Method ), "", name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
tr.runTest(tc); \
std::vector<Catch::TestCase> testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \
if( testCase.empty() ) Assert::Fail(FAIL_STRING("No tests match")); \
if( testCase.size() > 1 ) Assert::Fail(FAIL_STRING("More than one test with the same name")); \
Catch::Totals totals = tr.runTest(*testCase.begin()); \
if( totals.assertions.failed > 0 ) { \
INTERNAL_CATCH_TEST_THROW_FAILURE \
} \
}
#define CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( ClassMethod ) \
{ Catch::ConfigData cd; \
cd.name = name_desc.name; \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
Catch::RunContext tr(config.get(), rep); \
Catch::TestCase tc = Catch::makeTestCase( new Catch::MethodTestCase( & ClassMethod ), # ClassMethod, name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \
tr.runTest(tc); \
}
#define INTERNAL_CATCH_TESTCASE2( UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_TESTCASE2( Count, Name, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )(); \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(); \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc) ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ), UniqueExt, Name, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
}; \
} \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )()
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )()
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, UniqueExt, Name, Desc ) \
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, Count, Name, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & QualifiedMethod, "&" # QualifiedMethod, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc), CATCH_INTERNAL_LINEINFO ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_CLASS_METHOD( QualifiedMethod, UniqueExt, Name, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), Name, Desc ) \
}; \
};
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, UniqueExt, TestName, Desc ) \
#define INTERNAL_CATCH_TEST_CASE_METHOD2( ClassName, Count, TestName, Desc ) \
CHECK_FOR_TEST_CASE_CLASH \
struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) : ClassName { \
struct INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) : ClassName { \
void test(); \
static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt ) tmp; tmp.test(); } \
static void invoke() { INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) tmp; tmp.test(); } \
}; \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( & INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::invoke, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc(CATCH_INTERNAL_HANDLE_EMPTY_PARAM(TestName), Desc) ); \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
INTERNAL_CATCH_TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::invoke, UniqueExt, TestName, Desc ) \
INTERNAL_CATCH_TEST_METHOD( Count, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ), TestName, Desc ) \
}; \
} \
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, UniqueExt )::test()
void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )::test()
#if defined(INTERNAL_CATCH_VS_MANAGED)
#define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
{ \
std::stringstream _sf; \
_sf << count << " assertions failed - check output for results."; \
std::string fail = _sf.str(); \
Assert::Fail(Catch::convert_string_for_assert(fail)); \
}
#else
#define INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE( count ) \
{ \
std::wstringstream _s; \
_s << count << " assertions failed - check output for results."; \
std::wstring ws = _s.str(); \
Assert::Fail(ws.c_str()); \
}
#endif
#define INTERNAL_CATCH_MAP_CATEGORY_TO_TAG2( Category, Tag, Count ) \
CHECK_FOR_TEST_CASE_CLASH \
namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
CatchOverrides::ConfigReset<Catch::IConfig const*> INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_O_N_F_I_G___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) )(__FILE__, Count); \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) ) \
{ \
INTERNAL_CATCH_CLASS_CONTEXT \
BEGIN_INTERNAL_CATCH_BATCH_METHOD( Category, INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) \
{ \
Catch::ConfigData cd; \
cd.showSuccessfulTests = CatchOverrides::Config<Catch::IConfig const*>::instance().includeSuccessfulResults(__FILE__, Count ); \
cd.warnings = (CatchOverrides::Config<Catch::IConfig const*>::instance().warnAboutMissingAssertions(__FILE__, Count ) ? Catch::WarnAbout::NoAssertions : Catch::WarnAbout::Nothing); \
cd.reporterName = "vs_reporter"; \
cd.name = "Batch run using tag : " Tag; \
cd.testsOrTags.push_back( Tag ); \
Catch::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::ReporterRegistrar<Catch::MSTestReporter> reporterReg("vs_reporter"); \
Catch::Runner runner(config); \
Catch::Totals totals = runner.runTests(); \
if( totals.assertions.failed > 0 ) { \
INTERNAL_CATCH_TEST_REPORT_BATCH_FAILURE(totals.assertions.failed) \
} \
} \
}; \
}
//#undef CATCH_CONFIG_VARIADIC_MACROS
@ -279,29 +377,29 @@ struct NameAndDesc {
#define INTERNAL_CATCH_SPLIT_TAGS_IMPL_(INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) INTERNAL_CATCH_SPLIT_ARG_2
#define INTERNAL_CATCH_TESTCASE( ... ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_TESTCASE2( __COUNTER__ , INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__), INTERNAL_CATCH_SPLIT_TAGS(__VA_ARGS__) )
#else
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
INTERNAL_CATCH_TESTCASE2( __COUNTER__ , Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, INTERNAL_CATCH_CONCAT_LINE_COUNTER, Name, Desc )
INTERNAL_CATCH_METHOD_AS_TEST_CASE2( QualifiedMethod, __COUNTER__, Name, Desc )
///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, INTERNAL_CATCH_CONCAT_LINE_COUNTER, TestName, Desc )
INTERNAL_CATCH_TEST_CASE_METHOD2(ClassName, __COUNTER__, TestName, Desc )
#endif
@ -320,51 +418,6 @@ struct NameAndDesc {
#include "catch_exception_translator_registry.hpp"
namespace Catch {
inline NonCopyable::~NonCopyable() {}
inline IShared::~IShared() {}
inline StreamBufBase::~StreamBufBase() throw() {}
inline IContext::~IContext() {}
inline IResultCapture::~IResultCapture() {}
inline ITestCase::~ITestCase() {}
inline ITestCaseRegistry::~ITestCaseRegistry() {}
inline IRegistryHub::~IRegistryHub() {}
inline IMutableRegistryHub::~IMutableRegistryHub() {}
inline IExceptionTranslator::~IExceptionTranslator() {}
inline IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
inline IReporterFactory::~IReporterFactory() {}
inline IReporterRegistry::~IReporterRegistry() {}
inline IStreamingReporter::~IStreamingReporter() {}
inline AssertionStats::~AssertionStats() {}
inline SectionStats::~SectionStats() {}
inline TestCaseStats::~TestCaseStats() {}
inline TestGroupStats::~TestGroupStats() {}
inline TestRunStats::~TestRunStats() {}
//CumulativeReporterBase::SectionNode::~SectionNode() {}
//CumulativeReporterBase::~CumulativeReporterBase() {}
//StreamingReporterBase::~StreamingReporterBase() {}
//ConsoleReporter::~ConsoleReporter() {}
inline IRunner::~IRunner() {}
inline IMutableContext::~IMutableContext() {}
inline IConfig::~IConfig() {}
//XmlReporter::~XmlReporter() {}
//JunitReporter::~JunitReporter() {}
//TestRegistry::~TestRegistry() {}
inline FreeFunctionTestCase::~FreeFunctionTestCase() {}
inline IGeneratorInfo::~IGeneratorInfo() {}
inline IGeneratorsForTest::~IGeneratorsForTest() {}
inline Matchers::Impl::StdString::Equals::~Equals() {}
inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
inline void Config::dummy() {}
//INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( "xml", XmlReporter )
}
#ifdef __clang__
#pragma clang diagnostic pop
#endif

View File

@ -46,15 +46,27 @@ namespace Catch {
#endif // detect CLR
struct MSTestReporter : SharedImpl<IStreamingReporter> {
MSTestReporter( ReporterConfig const& _config )
: m_config( _config.fullConfig() ),
m_headerPrinted( false ),
m_atLeastOneTestCasePrinted( false ),
m_failed(0)
{}
MSTestReporter( Ptr<IConfig> const& _fullConfig )
: m_config( _fullConfig ),
m_headerPrinted( false ),
m_atLeastOneTestCasePrinted( false )
m_atLeastOneTestCasePrinted( false ),
m_failed(0)
{}
virtual ~MSTestReporter() {
if( m_atLeastOneTestCasePrinted ) {
write_output_message(stream.str());
/*if( m_failed )
{
Assert::IsTrue(false, L"At least one test failed - examine output for failures.");
}*/
}
}
@ -120,9 +132,6 @@ namespace Catch {
write_output_message(_testCaseStats.stdErr);
write_output_message(getDoubleDashes());
}
if( _testCaseStats.totals.assertions.failed ) {
Assert::IsTrue(false, L"At least one test failed - examine output for CHECK failures.");
}
m_headerPrinted = false;
currentTestCaseInfo.reset();
assert( m_sectionStack.empty() );
@ -141,6 +150,7 @@ namespace Catch {
printTotalsDivider();
printTotals( _testRunStats.totals );
stream << "\r\n" << "\r\n";
m_failed = _testRunStats.totals.testCases.failed;
currentTestCaseInfo.reset();
currentGroupInfo.reset();
currentTestRunInfo.reset();
@ -448,6 +458,7 @@ namespace Catch {
std::vector<SectionInfo> m_sectionStack;
bool m_headerPrinted;
bool m_atLeastOneTestCasePrinted;
size_t m_failed;
};
} // end namespace Catch

View File

@ -15,6 +15,8 @@ namespace Counter {
int g_haveCountedMessages = 0;
}
namespace MI1
{
// This test works with the equivalent in MessageInstantiationTests2.cpp
// The first test to reach this point will increment the MessageInfo counter. Subsequent tests
// just check the value. The purpose of this test is to verify that the compiler's
@ -32,11 +34,14 @@ TEST_CASE("message counting1","")
Counter::g_haveCountedMessages = 1;
}
}
}
namespace LongCounter {
int g_haveCountedMessagesLong = 0;
}
namespace MI1
{
TEST_CASE("long message counting1","")
{
if( LongCounter::g_haveCountedMessagesLong > 0 ) {
@ -48,3 +53,4 @@ TEST_CASE("long message counting1","")
LongCounter::g_haveCountedMessagesLong = 1;
}
}
}

View File

@ -14,6 +14,8 @@ namespace Counter {
extern int g_haveCountedMessages;
}
namespace MI2
{
// This test works with the equivalent in MessageInstantiationTests1.cpp
// The first test to reach this point will increment the MessageInfo counter. Subsequent tests
// just check the value. The purpose of this test is to verify that the compiler's
@ -31,11 +33,14 @@ TEST_CASE("message counting2","")
Counter::g_haveCountedMessages = 1;
}
}
}
namespace LongCounter {
extern int g_haveCountedMessagesLong;
}
namespace MI2
{
TEST_CASE("long message counting2","")
{
if( LongCounter::g_haveCountedMessagesLong > 0 ) {
@ -47,3 +52,4 @@ TEST_CASE("long message counting2","")
LongCounter::g_haveCountedMessagesLong = 1;
}
}
}

View File

@ -0,0 +1,187 @@
/*
* Created by Phil on 22/10/2010.
* Copyright 2010 Two Blue Cubes Ltd
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch.hpp"
#include "internal/catch_text.h"
#include "internal/catch_console_colour.hpp"
namespace AllTestsRunner {
class NullStreamingReporter : public Catch::SharedImpl<Catch::IStreamingReporter> {
public:
virtual ~NullStreamingReporter();
static std::string getDescription() {
return "null reporter";
}
private: // IStreamingReporter
virtual Catch::ReporterPreferences getPreferences() const {
return Catch::ReporterPreferences();
}
virtual void noMatchingTestCases( std::string const& ) {}
virtual void testRunStarting( Catch::TestRunInfo const& ) {}
virtual void testGroupStarting( Catch::GroupInfo const& ) {}
virtual void testCaseStarting( Catch::TestCaseInfo const& ) {}
virtual void sectionStarting( Catch::SectionInfo const& ) {}
virtual void assertionStarting( Catch::AssertionInfo const& ) {}
virtual bool assertionEnded( Catch::AssertionStats const& ) { return false; }
virtual void sectionEnded( Catch::SectionStats const& ) {}
virtual void testCaseEnded( Catch::TestCaseStats const& ) {}
virtual void testGroupEnded( Catch::TestGroupStats const& ) {}
virtual void testRunEnded( Catch::TestRunStats const& ) {}
};
class EmbeddedRunner {
public:
EmbeddedRunner() : m_reporter( new NullStreamingReporter() ) {}
Catch::Totals runMatching( const std::string& rawTestSpec,
std::size_t groupIndex,
std::size_t groupsCount,
const std::string& reporter = "console" );
private:
Catch::Ptr<Catch::IStreamingReporter> m_reporter;
};
class MetaTestRunner {
public:
struct Expected { enum Result {
ToSucceed,
ToFail
}; };
MetaTestRunner( Expected::Result expectedResult, std::size_t groupIndex, std::size_t groupsCount )
: m_expectedResult( expectedResult ),
m_groupIndex( groupIndex ),
m_groupsCount( groupsCount )
{}
static void runMatching( const std::string& testSpec,
Expected::Result expectedResult,
std::size_t groupIndex,
std::size_t groupsCount ) {
forEach( Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec ),
MetaTestRunner( expectedResult, groupIndex, groupsCount ) );
}
void operator()( const Catch::TestCase& testCase ) {
std::string name;
Catch::Totals totals;
{
EmbeddedRunner runner;
name = testCase.getTestCaseInfo().name;
totals = runner.runMatching( name, m_groupIndex, m_groupsCount );
}
switch( m_expectedResult ) {
case Expected::ToSucceed:
if( totals.assertions.failed > 0 ) {
FAIL( "Expected test case '"
<< name
<< "' to succeed but there was/ were "
<< totals.assertions.failed << " failure(s)" );
}
else {
SUCCEED( "Tests passed, as expected" );
}
break;
case Expected::ToFail:
if( totals.assertions.failed == 0 ) {
FAIL( "Expected test case '"
<< name
<< "' to fail but there was/ were "
<< totals.assertions.passed << " success(es)" );
}
else {
SUCCEED( "Tests failed, as expected" );
}
break;
}
}
private:
Expected::Result m_expectedResult;
std::size_t m_groupIndex;
std::size_t m_groupsCount;
};
NullStreamingReporter::~NullStreamingReporter() {}
Catch::Totals EmbeddedRunner::runMatching( const std::string& rawTestSpec, std::size_t groupIndex, std::size_t groupsCount, const std::string& ) {
std::ostringstream oss;
Catch::Ptr<Catch::Config> config = new Catch::Config();
config->setStreamBuf( oss.rdbuf() );
Catch::Totals totals;
// Scoped because RunContext doesn't report EndTesting until its destructor
{
Catch::RunContext runner( config.get(), m_reporter.get() );
totals = runner.runMatching( rawTestSpec, groupIndex, groupsCount );
}
return totals;
}
TEST_CASE( "Run all failing and succeeding tests", "[vsall]" ) {
///////////////////////////////////////////////////////////////////////////
SECTION( "selftest/expected result",
"Tests do what they claim" ) {
#ifdef _UNICODE
std::cout << "using Unicode..." << std::endl;
#else
std::cout << "using Mbcs..." << std::endl;
#endif
SECTION( "selftest/expected result/failing tests",
"Tests in the 'failing' branch fail" ) {
std::cout << "Tests in the 'failing' branch fail" << std::endl;
MetaTestRunner::runMatching( "./failing/*", MetaTestRunner::Expected::ToFail, 0, 2 );
}
SECTION( "selftest/expected result/succeeding tests",
"Tests in the 'succeeding' branch succeed" ) {
std::cout << "Tests in the 'succeeding' branch succeed" << std::endl;
MetaTestRunner::runMatching( "./succeeding/*", MetaTestRunner::Expected::ToSucceed, 1, 2 );
}
}
///////////////////////////////////////////////////////////////////////////
SECTION( "selftest/test counts",
"Number of test cases that run is fixed" ) {
EmbeddedRunner runner;
SECTION( "selftest/test counts/succeeding tests",
"Number of 'succeeding' tests is fixed" ) {
std::cout << "Number of 'succeeding' tests is fixed" << std::endl;
Catch::Totals totals = runner.runMatching( "./succeeding/*", 0, 2 );
CHECK( totals.assertions.passed == 298 );
CHECK( totals.assertions.failed == 0 );
}
SECTION( "selftest/test counts/failing tests",
"Number of 'failing' tests is fixed" ) {
std::cout << "Number of 'failing' tests is fixed" << std::endl;
Catch::Totals totals = runner.runMatching( "./failing/*", 1, 2 );
CHECK( totals.assertions.passed == 2 );
CHECK( totals.assertions.failed == 77 );
}
}
}
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
CATCH_MAP_CATEGORY_TO_TAG(all, "[vsall]");
#endif
}

View File

@ -346,35 +346,35 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
std::string testString = "one two three four";
SECTION( "No wrapping", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
}
SECTION( "Wrapped once", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 12 ) ).toString() == "one two\nthree four" );
}
SECTION( "Wrapped twice", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" );
}
SECTION( "Wrapped three times", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 5 ) ).toString() == "one\ntwo\nthree\nfour" );
}
SECTION( "Short wrap", "" ) {
CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" );
CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" );
CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" );
CHECK( Catch::Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" );
CHECK( Catch::Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" );
CHECK( Catch::Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" );
CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
}
SECTION( "As container", "" ) {
Text text( testString, TextAttributes().setWidth( 6 ) );
Catch::Text text( testString, TextAttributes().setWidth( 6 ) );
REQUIRE( text.size() == 4 );
CHECK( text[0] == "one" );
CHECK( text[1] == "two" );
@ -382,7 +382,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
CHECK( text[3] == "four" );
}
SECTION( "Indent first line differently", "" ) {
Text text( testString, TextAttributes()
Catch::Text text( testString, TextAttributes()
.setWidth( 10 )
.setIndent( 4 )
.setInitialIndent( 1 ) );
@ -397,22 +397,22 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
std::string testString = "one two\nthree four";
SECTION( "No wrapping" , "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString );
}
SECTION( "Trailing newline" , "" ) {
CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" );
CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" );
CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" );
CHECK( Catch::Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" );
CHECK( Catch::Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" );
CHECK( Catch::Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" );
}
SECTION( "Wrapped once", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 7 ) ).toString() == "one two\nthree\nfour" );
}
SECTION( "Wrapped twice", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" );
CHECK( Catch::Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" );
}
}
@ -421,7 +421,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
// guide: 1234567890123456789
std::string testString = "one two \tthree four five six";
CHECK( Text( testString, TextAttributes().setWidth( 15 ) ).toString()
CHECK( Catch::Text( testString, TextAttributes().setWidth( 15 ) ).toString()
== "one two three\n four\n five\n six" );
}
@ -522,12 +522,12 @@ TEST_CASE( "Strings can be rendered with colour", "[colour]" ) {
TEST_CASE( "Text can be formatted using the Text class", "" ) {
CHECK( Text( "hi there" ).toString() == "hi there" );
CHECK( Catch::Text( "hi there" ).toString() == "hi there" );
TextAttributes narrow;
narrow.setWidth( 6 );
CHECK( Text( "hi there", narrow ).toString() == "hi\nthere" );
CHECK( Catch::Text( "hi there", narrow ).toString() == "hi\nthere" );
}
TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) {
@ -537,7 +537,7 @@ TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) {
std::ostringstream oss;
for(int i = 0; i < 600; ++i )
oss << longLine << longLine << "\n";
Text t( oss.str() );
Catch::Text t( oss.str() );
CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) );
}

View File

@ -24,7 +24,7 @@ namespace Catch
}
}
namespace TrickTests
namespace TrickyTests
{
///////////////////////////////////////////////////////////////////////////////
TEST_CASE
@ -209,6 +209,8 @@ namespace ObjectWithNonConstEqualityOperator
}
}
namespace TrickyTests
{
namespace EnumBitFieldTests
{
enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006,
@ -383,3 +385,4 @@ TEST_CASE( "X/level/0/a", "[Tricky]" ) { SUCCEED(""); }
TEST_CASE( "X/level/0/b", "[Tricky][fizz]" ){ SUCCEED(""); }
TEST_CASE( "X/level/1/a", "[Tricky]" ) { SUCCEED(""); }
TEST_CASE( "X/level/1/b", "[Tricky]" ) { SUCCEED(""); }
}

View File

@ -0,0 +1,110 @@
/*
* Created by Phil on 22/10/2010.
* Copyright 2010 Two Blue Cubes Ltd
*
* Distributed under the Boost Software License, Version 1.0. (See accompanying
* file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
*/
#include "catch.hpp"
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
namespace VisualStudioTests
{
class UniqueTestsFixture {
private:
static int uniqueID;
public:
UniqueTestsFixture() { }
protected:
int getID() {
return ++uniqueID;
}
};
int UniqueTestsFixture::uniqueID = 0;
TEST_CASE("M00", "[m_off]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
}
CATCH_CONFIG_SHOW_SUCCESS(true)
TEST_CASE("M01", "[m_on]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(show);
}
TEST_CASE("M02", "[m_off]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
}
TEST_CASE_METHOD(UniqueTestsFixture, "M10", "[m_off]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
getID();
}
CATCH_CONFIG_WARN_MISSING_ASSERTIONS(true)
CATCH_CONFIG_SHOW_SUCCESS(true)
TEST_CASE_METHOD(UniqueTestsFixture, "M11", "[m_on]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(show);
getID();
}
CATCH_CONFIG_WARN_MISSING_ASSERTIONS(true)
CATCH_CONFIG_SHOW_SUCCESS(true)
TEST_CASE_METHOD(UniqueTestsFixture, "M99", "[m_on]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(show);
WARN("Warning message");
getID();
}
TEST_CASE_METHOD(UniqueTestsFixture, "M12", "[m_off]")
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
getID();
}
class ConfigTest
{
public:
void run1()
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
}
void run2()
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(show);
}
void run3()
{
bool show = Catch::getCurrentContext().getConfig()->includeSuccessfulResults();
REQUIRE(!show);
}
};
METHOD_AS_TEST_CASE(ConfigTest::run1,"M20", "[m_off]");
CATCH_CONFIG_SHOW_SUCCESS(true)
METHOD_AS_TEST_CASE(ConfigTest::run2,"M21", "[m_on]");
METHOD_AS_TEST_CASE(ConfigTest::run3,"M22", "[m_off]");
CATCH_MAP_CATEGORY_TO_TAG(vstestsCheckOutputOff, "[m_off]");
CATCH_CONFIG_SHOW_SUCCESS(true)
CATCH_MAP_CATEGORY_TO_TAG(vstestsCheckOutputOn, "[m_on]");
CATCH_MAP_CATEGORY_TO_TAG(vstestsCheckOutputOff2, "[m_off]");
}
#endif

View File

@ -4,8 +4,6 @@ SOURCES = ApproxTests.cpp \
ExceptionTests.cpp \
GeneratorTests.cpp \
MessageTests.cpp \
MessageInstantiationTests1.cpp \
MessageInstantiationTests2.cpp \
MiscTests.cpp \
TestMain.cpp \
TrickyTests.cpp \

View File

@ -16,13 +16,19 @@ Global
EndGlobalSection
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
DebugMbcs|Win32 = DebugMbcs|Win32
Release|Win32 = Release|Win32
ReleaseMbcs|Win32 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.Debug|Win32.ActiveCfg = Debug|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.Debug|Win32.Build.0 = Debug|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.DebugMbcs|Win32.ActiveCfg = DebugMbcs|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.DebugMbcs|Win32.Build.0 = DebugMbcs|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.Release|Win32.ActiveCfg = Release|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.Release|Win32.Build.0 = Release|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.ReleaseMbcs|Win32.ActiveCfg = ReleaseMbcs|Win32
{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}.ReleaseMbcs|Win32.Build.0 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,17 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugMbcs|Win32">
<Configuration>DebugMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseMbcs|Win32">
<Configuration>ReleaseMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<TargetName>DefaultTest</TargetName>
<TargetName>$(ProjectName)</TargetName>
<ProjectTypes>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}</ProjectTypes>
<ProjectGUID>{7CC06A6B-763E-42B3-AF6C-8F1E340372A1}</ProjectGUID>
<Keyword>ManagedCProj</Keyword>
@ -23,24 +31,42 @@
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CLRSupport>true</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CLRSupport>Safe</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<CLRSupport>Safe</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="PropertySheets">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="PropertySheets">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\10.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<PostBuildEventCommand>if exist app.config copy app.config "$(OutDir)app.config"</PostBuildEventCommand>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">true</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</LinkIncremental>
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -58,6 +84,22 @@
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>..\..\..\include</AdditionalIncludeDirectories>
<CompileAsManaged>true</CompileAsManaged>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -72,6 +114,20 @@
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<CompileAsManaged>true</CompileAsManaged>
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework" />
<Reference Include="System" />
@ -90,13 +146,18 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp" />
<ClCompile Include="..\..\SelfTest\MessageTests.cpp" />
<ClCompile Include="..\..\SelfTest\MiscTests.cpp" />
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp" />
<ClCompile Include="..\..\SelfTest\SectionTrackerTests.cpp" />
<ClCompile Include="..\..\SelfTest\TestMain.cpp" />
<ClCompile Include="..\..\SelfTest\TrickyTests.cpp" />
<ClCompile Include="..\..\SelfTest\VariadicMacrosTests.cpp" />
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp" />
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>

View File

@ -63,6 +63,15 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\TestMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">

View File

@ -6,13 +6,19 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
DebugMbcs|Win32 = DebugMbcs|Win32
Release|Win32 = Release|Win32
ReleaseMbcs|Win32 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9757CB21-B840-49A6-B057-9F322E543DD6}.Debug|Win32.ActiveCfg = Debug|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.Debug|Win32.Build.0 = Debug|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.DebugMbcs|Win32.ActiveCfg = DebugMbcs|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.DebugMbcs|Win32.Build.0 = DebugMbcs|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.Release|Win32.ActiveCfg = Release|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.Release|Win32.Build.0 = Release|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.ReleaseMbcs|Win32.ActiveCfg = ReleaseMbcs|Win32
{9757CB21-B840-49A6-B057-9F322E543DD6}.ReleaseMbcs|Win32.Build.0 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,17 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugMbcs|Win32">
<Configuration>DebugMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseMbcs|Win32">
<Configuration>ReleaseMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<TargetName>DefaultTest</TargetName>
<TargetName>$(ProjectName)</TargetName>
<ProjectTypes>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}</ProjectTypes>
<ProjectGUID>{9757CB21-B840-49A6-B057-9F322E543DD6}</ProjectGUID>
<Keyword>ManagedCProj</Keyword>
@ -24,30 +32,54 @@
<CLRSupport>Safe</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CLRSupport>Safe</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v110</PlatformToolset>
<CLRSupport>true</CLRSupport>
<CharacterSet>MultiByte</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="PropertySheets">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="PropertySheets">
<Import Project="$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(LocalAppData)\Microsoft\VisualStudio\11.0\Microsoft.Cpp.$(Platform).user.props')" />
</ImportGroup>
<PropertyGroup>
<PostBuildEventCommand>if exist app.config copy app.config "$(OutDir)app.config"</PostBuildEventCommand>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -66,6 +98,25 @@
<Command>taskkill /F /IM vstest.executionengine.x86.exe /FI "MEMUSAGE gt 1"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
<CompileAsManaged>true</CompileAsManaged>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
<PreBuildEvent>
<Command>taskkill /F /IM vstest.executionengine.x86.exe /FI "MEMUSAGE gt 1"</Command>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -79,6 +130,20 @@
<AdditionalDependencies />
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<AdditionalIncludeDirectories>../../../include</AdditionalIncludeDirectories>
<CompileAsManaged>true</CompileAsManaged>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>
</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework">
<HintPath>..\..\..\..\..\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll</HintPath>
@ -100,13 +165,18 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp" />
<ClCompile Include="..\..\SelfTest\MessageTests.cpp" />
<ClCompile Include="..\..\SelfTest\MiscTests.cpp" />
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp" />
<ClCompile Include="..\..\SelfTest\SectionTrackerTests.cpp" />
<ClCompile Include="..\..\SelfTest\TestMain.cpp" />
<ClCompile Include="..\..\SelfTest\TrickyTests.cpp" />
<ClCompile Include="..\..\SelfTest\VariadicMacrosTests.cpp" />
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp" />
<ClCompile Include="AssemblyInfo.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>
<ItemGroup>

View File

@ -63,6 +63,15 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\TestMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">

View File

@ -6,13 +6,19 @@ EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
DebugMbcs|Win32 = DebugMbcs|Win32
Release|Win32 = Release|Win32
ReleaseMbcs|Win32 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.Debug|Win32.ActiveCfg = Debug|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.Debug|Win32.Build.0 = Debug|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.DebugMbcs|Win32.ActiveCfg = DebugMbcs|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.DebugMbcs|Win32.Build.0 = DebugMbcs|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.Release|Win32.ActiveCfg = Release|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.Release|Win32.Build.0 = Release|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.ReleaseMbcs|Win32.ActiveCfg = ReleaseMbcs|Win32
{977CE524-3FC7-4281-9C1B-77C210F24A9B}.ReleaseMbcs|Win32.Build.0 = ReleaseMbcs|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,10 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="DebugMbcs|Win32">
<Configuration>DebugMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="ReleaseMbcs|Win32">
<Configuration>ReleaseMbcs</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
@ -23,6 +31,20 @@
<CharacterSet>Unicode</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v110</PlatformToolset>
<CharacterSet>MultiByte</CharacterSet>
<UseOfMfc>false</UseOfMfc>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
@ -37,6 +59,12 @@
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
@ -44,6 +72,12 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
@ -62,6 +96,36 @@
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>../../../include;$(VCInstallDir)UnitTest\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<UseFullPaths>true</UseFullPaths>
</ClCompile>
<Link>
<SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalLibraryDirectories>$(VCInstallDir)UnitTest\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
@ -97,11 +161,16 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp" />
<ClCompile Include="..\..\SelfTest\MessageTests.cpp" />
<ClCompile Include="..\..\SelfTest\MiscTests.cpp" />
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp" />
<ClCompile Include="..\..\SelfTest\SectionTrackerTests.cpp" />
<ClCompile Include="..\..\SelfTest\TestMain.cpp" />
<ClCompile Include="..\..\SelfTest\TrickyTests.cpp" />
<ClCompile Include="..\..\SelfTest\VariadicMacrosTests.cpp" />
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='DebugMbcs|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='ReleaseMbcs|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
</ItemGroup>

View File

@ -50,12 +50,6 @@
<ClCompile Include="..\..\SelfTest\GeneratorTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\MessageTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -68,5 +62,20 @@
<ClCompile Include="..\..\SelfTest\TrickyTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\RunAllTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\TestMain.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\VisualStudioTests.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests1.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

716
scripts/approvalVSTests.py Normal file
View File

@ -0,0 +1,716 @@
#!/c/Python27/python
import os
import sys
import subprocess
import re
import xml.etree.cElementTree as etree
from scriptCommon import catchPath
#from rawfile import writeRawFile
#from rawfile import parseRawFileIntoTree
from catch_test_run import TestRunApprovedHandler
from catch_test_run import TestRunData
from catch_test_run import TestRunResultHandler
from catch_test_case import TestCaseResultParser
from catch_test_case import TestCaseData
rootPath = os.path.join(os.path.join(os.path.join( catchPath, 'projects'), 'SelfTest'), 'Baselines' )
if len(sys.argv) == 2:
cmdPath = sys.argv[1]
else:
if sys.platform == 'win32':
cmdPath = os.path.join( catchPath, 'projects\\VS2010\\TestCatch\\Release\\TestCatch.exe' )
dllPath = os.path.join( catchPath, 'projects\\VS2010\\ManagedTestCatch\\Release\\ManagedTestCatch.dll' )
else:
cmdPath = os.path.join( catchPath, 'projects/XCode4/CatchSelfTest/DerivedData/CatchSelfTest/Build/Products/Debug/CatchSelfTest' )
print cmdPath
overallResult = 0
def approve( baseName, args ):
global overallResult
args[0:0] = [cmdPath]
baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) )
baselinesSortedPath = os.path.join( rootPath, '{0}.sorted.approved.txt'.format( baseName ) )
rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) )
if os.path.exists( baselinesPath ):
approvedFileHandler = TestRunApprovedHandler(baselinesPath)
baselinesPathNew = os.path.join( rootPath, '{0}.approved.new.txt'.format( baseName ) )
approvedFileHandler.writeRawFile(baselinesPathNew)
approvedFileHandler.writeSortedRawFile(baselinesSortedPath)
else:
raise Exception("Base file does not exist: '" + baselinesPath + "'")
if not(os.path.exists( args[0] )):
raise Exception("Executable does not exist: '" + args[0] + "'")
f = open( rawResultsPath, 'w' )
subprocess.call( args, stdout=f, stderr=f )
f.close()
if os.path.exists( rawResultsPath ):
resultFileHandler = TestRunResultHandler(rawResultsPath)
rawPathNew = os.path.join( rootPath, '{0}.rewrite.txt'.format( baseName ) )
#print "F:",rawPathNew,",",approvedFileHandler.current.outputLine
resultFileHandler.writeRawFile(rawPathNew)
rawPathNewSorted = os.path.join( rootPath, '{0}.sorted.unapproved.txt'.format( baseName ) )
resultFileHandler.writeSortedUnapprovedFile(rawPathNewSorted, approvedFileHandler.current.outputLine)
else:
raise Exception("Results file does not exist: '" + rawResultsPath + "'")
#os.remove( rawResultsPath )
print
print baseName + ":"
if os.path.exists( baselinesSortedPath ) and os.path.exists( rawPathNewSorted ):
diffResult = subprocess.call([ "diff", "--ignore-all-space", baselinesSortedPath, rawPathNewSorted ] )
if diffResult == 0:
#os.remove( filteredResultsPath )
if not(sys.platform == 'win32'):
print " \033[92mResults matched"
else:
print " Results matched"
else:
if not(sys.platform == 'win32'):
print " \n****************************\n \033[91mResults differed"
else:
print " \n****************************\n Results differed"
if diffResult > overallResult:
overallResult = diffResult
if not(sys.platform == 'win32'):
print "\033[0m"
def approveJunit( baseName, args ):
global overallResult
args[0:0] = [cmdPath]
baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) )
baselinesSortedPath = os.path.join( rootPath, '{0}.sorted.approved.txt'.format( baseName ) )
#baselinesFixedPath = os.path.join( rootPath, '{0}.rewrite.approved.txt'.format( baseName ) )
rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) )
if os.path.exists( baselinesPath ):
xml = ""
f = open( baselinesPath, 'r' )
for line in f:
xml += line
xml = xml.replace("<line number>", "&lt;line number&gt;")
xml = xml.replace("<hex digits>", "&lt;hex digits&gt;")
#f2 = open( baselinesFixedPath, 'wb' )
#f2.write(xml)
#f2.close()
# ClassTests.cpp:<line number>
otherApprovedTestParser = re.compile( r'(.*\..pp).*:<(.*).*>' )
testRun = TestRunData()
testcase = None
root = etree.fromstring(xml)
for testsuites in root:
if testsuites.tag == "testsuite":
testRun = TestRunData()
testRun.appname = testsuites.get("name")
testRun.errors = testsuites.get("errors")
testRun.failures = testsuites.get("failures")
testRun.tests = testsuites.get("tests")
for tc in testsuites:
if tc.tag == "testcase":
cls = tc.get("classname")
#print "C:",cls,tc
if len(cls):
testcase = testRun.addClassTestCase(cls, tc.get("name"))
else:
testcase = testRun.addTestCase(tc.get("name"))
for prop in tc:
if prop.tag == "failure":
text = prop.text.strip()
lines = text.splitlines()
filename = ""
lineNumber = ""
output = []
for l in lines:
m = otherApprovedTestParser.match(l)
if m:
filename = m.group(1)
lineNumber = m.group(2)
else:
output.append(l)
testcase.addFailure(filename, lineNumber, output, prop.get("message"), prop.get("type"))
elif prop.tag == "error":
text = prop.text.strip()
lines = text.splitlines()
filename = ""
lineNumber = ""
output = []
for l in lines:
m = otherApprovedTestParser.match(l)
if m:
filename = m.group(1)
lineNumber = m.group(2)
else:
output.append(l)
testcase.addError(filename, lineNumber, output, prop.get("message"), prop.get("type"))
elif prop.tag == "system-out":
text = prop.text.strip()
lines = text.splitlines()
testcase.addSysout(lines)
elif prop.tag == "system-err":
text = prop.text.strip()
lines = text.splitlines()
testcase.addSyserr(lines)
elif tc.tag == "system-out":
text = tc.text.strip()
lines = text.splitlines()
testRun.addSysout(lines)
elif tc.tag == "system-err":
text = tc.text.strip()
lines = text.splitlines()
testRun.addSyserr(lines)
else:
print tc.tag
lines = testRun.generateSortedUnapprovedJunit()
rawWriteFile = open( baselinesSortedPath, 'wb' )
for line in lines:
#print "L:",line
rawWriteFile.write(line + "\n")
rawWriteFile.close()
if not(os.path.exists( args[0] )):
raise Exception("Executable does not exist: '" + args[0] + "'")
f = open( rawResultsPath, 'w' )
subprocess.call( args, stdout=f, stderr=f )
f.close()
rawSortedPath = os.path.join( rootPath, '{0}.sorted.unapproved.txt'.format( baseName ) )
if os.path.exists( rawResultsPath ):
xml = ""
f = open( rawResultsPath, 'r' )
for line in f:
xml += line
#xml = xml.replace("<line number>", "&lt;line number&gt;")
#xml = xml.replace("<hex digits>", "&lt;hex digits&gt;")
# ClassTests.cpp:<line number>
otherResultsTestParser = re.compile( r'(.*\\)(.*\..pp).*\((.*).*\)' )
testRun = TestRunData()
testcase = None
root = etree.fromstring(xml)
for testsuites in root:
if testsuites.tag == "testsuite":
testRun = TestRunData()
testRun.appname = testsuites.get("name")
testRun.errors = testsuites.get("errors")
testRun.failures = testsuites.get("failures")
testRun.tests = testsuites.get("tests")
for tc in testsuites:
if tc.tag == "testcase":
cls = tc.get("classname")
#print "C:",cls,tc
if len(cls):
if cls.startswith("::"):
cls = cls[2:]
testcase = testRun.addClassTestCase(cls, tc.get("name"))
else:
testcase = testRun.addTestCase(tc.get("name"))
for prop in tc:
if prop.tag == "failure":
text = prop.text.strip()
lines = text.splitlines()
filename = ""
lineNumber = ""
output = []
for l in lines:
m = otherResultsTestParser.match(l)
if m:
filename = m.group(2)
lineNumber = "line number"
else:
output.append(l)
testcase.addFailure(filename, lineNumber, output, prop.get("message"), prop.get("type"))
elif prop.tag == "error":
text = prop.text.strip()
lines = text.splitlines()
filename = ""
lineNumber = ""
output = []
for l in lines:
m = otherResultsTestParser.match(l)
if m:
filename = m.group(2)
lineNumber = "line number"
else:
output.append(l)
testcase.addError(filename, lineNumber, output, prop.get("message"), prop.get("type"))
elif prop.tag == "system-out":
text = prop.text.strip()
lines = text.splitlines()
testcase.addSysout(lines)
elif prop.tag == "system-err":
text = prop.text.strip()
lines = text.splitlines()
testcase.addSyserr(lines)
elif tc.tag == "system-out":
text = tc.text.strip()
lines = text.splitlines()
testRun.addSysout(lines)
elif tc.tag == "system-err":
text = tc.text.strip()
lines = text.splitlines()
testRun.addSyserr(lines)
else:
print tc.tag
lines = testRun.generateSortedUnapprovedJunit()
rawWriteFile = open( rawSortedPath, 'wb' )
for line in lines:
#print "L:",line
rawWriteFile.write(line + "\n")
rawWriteFile.close()
def addSubSection(testcase, section, exp):
r = exp.find("OverallResults")
if r != None:
ores = []
ores.append(r.get("successes"))
ores.append(r.get("failures"))
if section == None:
section = testcase.addSection(exp.get("name"), exp.get("description"), ores)
else:
section = testcase.addSubSection(section, exp.get("name"), exp.get("description"), ores)
e1 = False
for tmp in exp:
if tmp.tag == "OverallResults":
pass
elif tmp.tag == "Exception":
filename = tmp.get("filename")
text = tmp.text
ls = text.splitlines()
testcase.addSubException(section, filename, ls)
elif tmp.tag == "Section":
addSubSection(testcase, section, tmp)
elif tmp.tag == "Failure":
text = tmp.text
ls = text.splitlines()
testcase.addSubFailure(section, ls)
elif tmp.tag == "Expression":
#print "Exp:",tmp
e1 = True
result = tmp.get("success")
filename = tmp.get("filename")
subSection = testcase.addSubExpression(section,result,filename)
subExp = []
for cond in tmp:
if cond.tag == "Original":
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Expanded" and len(subExp) == 1:
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Exception" and len(subExp) == 2:
subExp.append(cond.get("filename"))
text = cond.text
ls = text.splitlines()
subExp.append(ls)
else:
print "SX:",cond.tag
if len(subExp) >= 2:
testcase.addExpressionDetails(subSection, subExp)
else:
print "Z:",tmp.tag
#if e1:
# print "Section:",section
def addResultsSubSection(otherResultsTestParser, testcase, section, exp):
r = exp.find("OverallResults")
if r != None:
ores = []
ores.append(r.get("successes"))
ores.append(r.get("failures"))
if section == None:
section = testcase.addSection(exp.get("name"), exp.get("description"), ores)
else:
section = testcase.addSubSection(section, exp.get("name"), exp.get("description"), ores)
e1 = False
for tmp in exp:
if tmp.tag == "OverallResults":
pass
elif tmp.tag == "Exception":
filename = tmp.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
text = tmp.text
ls = text.splitlines()
testcase.addSubException(section, filename, ls)
elif tmp.tag == "Section":
addResultsSubSection(otherResultsTestParser, testcase, section, tmp)
elif tmp.tag == "Failure":
text = tmp.text
ls = text.splitlines()
testcase.addSubFailure(section, ls)
elif tmp.tag == "Expression":
#print "Exp:",tmp
e1 = True
result = tmp.get("success")
filename = tmp.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
subSection = testcase.addSubExpression(section,result,filename)
subExp = []
for cond in tmp:
if cond.tag == "Original":
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Expanded" and len(subExp) == 1:
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Exception" and len(subExp) == 2:
filename = cond.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
subExp.append(filename)
text = cond.text
ls = text.splitlines()
subExp.append(ls)
else:
print "SX:",cond.tag
if len(subExp) >= 2:
testcase.addExpressionDetails(subSection, subExp)
else:
print "Z:",tmp.tag
#if e1:
# print "Section:",section
def approveXml( baseName, args ):
global overallResult
args[0:0] = [cmdPath]
baselinesPath = os.path.join( rootPath, '{0}.approved.txt'.format( baseName ) )
baselinesSortedPath = os.path.join( rootPath, '{0}.sorted.approved.txt'.format( baseName ) )
#baselinesFixedPath = os.path.join( rootPath, '{0}.rewrite.approved.txt'.format( baseName ) )
rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) )
if os.path.exists( baselinesPath ):
xml = ""
f = open( baselinesPath, 'r' )
for line in f:
xml += line
xml = xml.replace("<hex digits>", "&lt;hex digits&gt;")
#otherApprovedTestParser = re.compile( r'(.*\..pp).*:<(.*).*>' )
testRun = TestRunData()
testcase = None
root = etree.fromstring(xml)
testRun.appname = root.get("name")
for ts in root:
#print ts.tag
for tc in ts:
if tc.tag == "TestCase":
testcase = testRun.addTestCase(tc.get("name"))
for exp in tc:
if exp.tag == "Expression":
result = exp.get("success")
filename = exp.get("filename")
section = testcase.addExpression(result,filename)
subExp = []
for cond in exp:
if cond.tag == "Original":
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Expanded" and len(subExp) == 1:
text = cond.text
ls = text.splitlines()
subExp.append(ls)
elif cond.tag == "Exception" and len(subExp) == 2:
subExp.append(cond.get("filename"))
text = cond.text
ls = text.splitlines()
subExp.append(ls)
else:
print "X:",cond.tag
if len(subExp) >= 2:
testcase.addExpressionDetails(section, subExp)
elif exp.tag == "Exception":
filename = exp.get("filename")
text = exp.text
ls = text.splitlines()
section = testcase.addException(filename,ls)
elif exp.tag == "Section":
addSubSection(testcase, None, exp)
elif exp.tag == "Info":
text = exp.text
ls = text.splitlines()
section = testcase.addInfo(ls)
elif exp.tag == "Warning":
text = exp.text
ls = text.splitlines()
section = testcase.addWarning(ls)
elif exp.tag == "Failure":
text = exp.text
ls = text.splitlines()
section = testcase.addSimpleFailure(ls)
elif exp.tag == "OverallResult":
testcase.addOverallResult(exp.get("success"))
else:
print "E:",exp.tag
elif tc.tag == "OverallResults":
testRun.tests = tc.get("successes")
testRun.failures = tc.get("failures")
else:
print "U:",tc.tag
lines = testRun.generateSortedUnapprovedXml()
rawWriteFile = open( baselinesSortedPath, 'wb' )
for line in lines:
#print "L:",line
rawWriteFile.write(line + "\n")
rawWriteFile.close()
if not(os.path.exists( args[0] )):
raise Exception("Executable does not exist: '" + args[0] + "'")
f = open( rawResultsPath, 'w' )
subprocess.call( args, stdout=f, stderr=f )
f.close()
rawSortedPath = os.path.join( rootPath, '{0}.sorted.unapproved.txt'.format( baseName ) )
if os.path.exists( rawResultsPath ):
xml = ""
f = open( rawResultsPath, 'r' )
for line in f:
xml += line
#xml = xml.replace("<hex digits>", "&lt;hex digits&gt;")
otherResultsTestParser = re.compile( r'(.*\\)(.*\..pp)' )
hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' )
testRun = TestRunData()
testcase = None
root = etree.fromstring(xml)
testRun.appname = root.get("name")
if testRun.appname == "TestCatch.exe":
testRun.appname = "CatchSelfTest"
for ts in root:
#print ts.tag
for tc in ts:
if tc.tag == "TestCase":
testcase = testRun.addTestCase(tc.get("name"))
for exp in tc:
if exp.tag == "Expression":
result = exp.get("success")
filename = exp.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
section = testcase.addExpression(result,filename)
subExp = []
for cond in exp:
if cond.tag == "Original":
text = cond.text
tmp = text.splitlines()
ls = []
for li in tmp:
m = hexParser.match(li)
if m:
while m:
#print li, m.group(1), m.group(3)
li = m.group(1) + "0x<hex digits>" + m.group(3)
m = hexParser.match(li)
ls.append(li)
subExp.append(ls)
elif cond.tag == "Expanded" and len(subExp) == 1:
text = cond.text
tmp = text.splitlines()
ls = []
for li in tmp:
m = hexParser.match(li)
if m:
while m:
#print li, m.group(1), m.group(3)
li = m.group(1) + "0x<hex digits>" + m.group(3)
m = hexParser.match(li)
ls.append(li)
subExp.append(ls)
elif cond.tag == "Exception" and len(subExp) == 2:
filename = cond.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
subExp.append(filename)
text = cond.text
ls = text.splitlines()
subExp.append(ls)
else:
print "X:",cond.tag
if len(subExp) >= 2:
testcase.addExpressionDetails(section, subExp)
elif exp.tag == "Exception":
filename = exp.get("filename")
m = otherResultsTestParser.match(filename)
if m:
filename = "/Users/philnash/Dev/OSS/Catch/projects/SelfTest/" + m.group(2)
text = exp.text
ls = text.splitlines()
section = testcase.addException(filename,ls)
elif exp.tag == "Section":
addResultsSubSection(otherResultsTestParser, testcase, None, exp)
elif exp.tag == "Info":
text = exp.text
ls = text.splitlines()
section = testcase.addInfo(ls)
elif exp.tag == "Warning":
text = exp.text
ls = text.splitlines()
section = testcase.addWarning(ls)
elif exp.tag == "Failure":
text = exp.text
ls = text.splitlines()
section = testcase.addSimpleFailure(ls)
elif exp.tag == "OverallResult":
testcase.addOverallResult(exp.get("success"))
else:
print "E:",exp.tag
elif tc.tag == "OverallResults":
testRun.tests = tc.get("successes")
testRun.failures = tc.get("failures")
else:
print "U:",tc.tag
lines = testRun.generateSortedUnapprovedXml()
rawWriteFile = open( rawSortedPath, 'wb' )
for line in lines:
#print "L:",line
rawWriteFile.write(line + "\n")
rawWriteFile.close()
def parseTrxFile(trxFile):
print "TRX file:" ,trxFile
if os.path.exists( trxFile ):
xml = ""
f = open( trxFile, 'r' )
for line in f:
xml += line
#otherResultsTestParser = re.compile( r'(.*\\)(.*\..pp)' )
#hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' )
testRun = TestRunData()
testRun.appname = "CatchSelfTest"
root = etree.fromstring(xml)
if testRun.appname == "TestCatch.exe":
testRun.appname = "CatchSelfTest"
qname=re.compile("{(?P<ns>.*)}(?P<element>.*)")
ids = []
for ts in root:
m = qname.match(ts.tag)
if m:
tag = m.group(2)
print tag
if tag != None:
if tag == "TestDefinitions":
for tc in ts:
m = qname.match(tc.tag)
if m:
tag = m.group(2)
if tag != None and tag == "UnitTest":
name = tc.get("name")
id = tc.get("id")
for item in tc:
m = qname.match(item.tag)
if m:
tag = m.group(2)
if tag != None and tag == "Description":
desc = item.text
#print desc, id
ids.append([id,desc])
elif tag == "Results":
#print ids
ids = dict(ids)
#print ids["87ec526a-e414-1a3f-ba0f-e210b204bb42"]
resultParser = TestCaseResultParser()
for tc in ts:
m = qname.match(tc.tag)
if m:
tag = m.group(2)
if tag != None and tag == "UnitTestResult":
outcome = tc.get("outcome")
id = tc.get("testId")
if len(id) > 0:
for item in tc:
m = qname.match(item.tag)
if m:
tag = m.group(2)
if tag != None and tag == "Output":
for sub in item:
m = qname.match(sub.tag)
if m:
tag = m.group(2)
if tag != None and tag == "StdOut":
desc = sub.text
lines = desc.splitlines()
if (len(lines) > 2 and
lines[0].startswith("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") and
lines[1].startswith("Using Catch v") ):
lines = lines[2:-1]
#print "*******",desc
#print lines
for line in lines:
testcase = resultParser.parseResultLine(line)
if isinstance(testcase, TestCaseData):
testRun.testcases.append(testcase)
lines = testRun.generateSortedUnapprovedLines(0)
rawSortedPath = os.path.join( rootPath, 'mstest.trx.sorted.unapproved.txt' )
rawWriteFile = open( rawSortedPath, 'wb' )
for line in lines:
#print "L:",line
rawWriteFile.write(line + "\n")
rawWriteFile.close()
def approveMsTest( baseName ):
rawResultsPath = os.path.join( rootPath, '_{0}.tmp'.format( baseName ) )
if not(os.path.exists( dllPath )):
raise Exception("Managed DLL does not exist: '" + dllPath + "'")
args = []
args.append("MSTest.exe")
args.append("/testcontainer:" + dllPath)
#f = open( rawResultsPath, 'w' )
#subprocess.call( args, stdout=f, stderr=f )
#f.close()
#if os.path.exists( rawResultsPath ):
# f = open( rawResultsPath, 'r' )
# for line in f:
line = "Results file: c:\Projects\Catch\TestResults\NoyesMa_SACHDEW7 2013-12-09 11_43_57.trx"
if line.startswith("Results file:"):
trxFile = line[13:].strip()
parseTrxFile(trxFile)
# Standard console reporter
#approve( "console.std", ["~_"] )
# console reporter, include passes, warn about No Assertions
#approve( "console.sw", ["~_", "-s", "-w", "NoAssertions"] )
# console reporter, include passes, warn about No Assertions, limit failures to first 4
#approve( "console.swa4", ["~_", "-s", "-w", "NoAssertions", "-x", "4"] )
# junit reporter, include passes, warn about No Assertions
#approveJunit( "junit.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "junit"] )
# xml reporter, include passes, warn about No Assertions
#approveXml( "xml.sw", ["~_", "-s", "-w", "NoAssertions", "-r", "xml"] )
#mstest runner, xml output
approveMsTest( "mstest.sw")
if overallResult <> 0:
print "run approve.py to approve new baselines"
exit( overallResult)

398
scripts/catch_conditions.py Normal file
View File

@ -0,0 +1,398 @@
import re
class RandomOutput:
def __init__(self):
output = []
class TestConditionData:
NONE = 0
CONDITION = 1
EXPANSION = 2
MESSAGES = 3
hexParser = re.compile( r'(.*)\b(0[xX][0-9a-fA-F]+)\b(.*)' )
def __init__(self):
self.state = self.NONE
self.filenamePrefix = ""
self.filename = ""
self.lineNumber = ""
self.reason = ""
self.condition = ""
self.expansionPrefix = ""
self.expansion = []
self.messagePrefix = ""
self.messages = []
self.output = []
self.noAssertions = ""
def __eq__(self, other):
return (self.filenamePrefix == other.filenamePrefix and
self.filename == other.filename and self.lineNumber == other.lineNumber and
self.reason == other.reason and self.condition == other.condition and
self.expansion == other.expansion and self.messagePrefix == other.messagePrefix and
self.output == other.output and self.noAssertions == other.noAssertions)
def empty(self):
if self.state == self.NONE:
return True
return False
def __repr__(self):
result = ("[" + self.reason + ", " + self.filename + ", " + self.lineNumber + ", " + self.condition +
", " + self.expansionPrefix + ", [ ")
suffix = ""
for msg in self.expansion:
result += suffix
result += repr(msg)
suffix = ", "
result += "], " + self.messagePrefix + ", [ "
suffix = ""
for msg in self.messages:
result += suffix
result += repr(msg)
suffix = ", "
result += " ], [ "
suffix = ""
for msg in self.output:
result += suffix
result += repr(msg)
suffix = ", "
result += " ] ]"
return result
def parseCondition(self,line):
if len(line):
if self.state == self.CONDITION and line.startswith(" "):
self.condition = line.strip()
elif self.state == self.CONDITION:
if len(self.reason) == 0 and line.startswith("PASSED:"):
self.reason = line.strip()
elif line.startswith("warning:") or line.startswith("with message"):
self.messagePrefix = line.strip()
self.state = self.MESSAGES
elif not(line.startswith(" ")):
self.expansionPrefix = line.strip()
self.state = self.EXPANSION
else:
raise Exception("Unknown condition parse line: '" + line + "'")
elif self.state == self.EXPANSION:
if line.startswith("with message"):
self.messagePrefix = line.strip()
self.state = self.MESSAGES
elif line.startswith(" "):
#print "***LINE: ", line
self.expansion.append(line[2:].rstrip())
elif line.startswith("... message truncated due"):
#print "***MSG: ", line
self.messagePrefix = line.strip()
else:
#print "***OUTPUT: ", line
self.output.append(line.strip())
elif self.state == self.MESSAGES:
if line.startswith(" "):
#print "***MESSAGE: ", line
self.messages.append(line.strip())
else:
#print "***OUTPUT: ", line
self.output.append(line.strip())
else:
raise Exception("Unknown parse line: '" + line + "'")
if len(self.output) == 10:
if (self.output[0] == "Message from section one" and self.output[1] == "Message from section two" and
self.output[2] == "Some information" and self.output[3] == "An error" and
self.output[4] == "Message from section one" and self.output[5] == "Message from section two" and
self.output[6] == "Some information" and self.output[7] == "An error" and
self.output[8] == "hello" and self.output[9] == "hello" ):
obj = RandomOutput()
obj.output = self.output
self.output = []
raise obj
elif len(self.output) == 2:
if (self.output[0] == "hello" and self.output[1] == "hello" ):
obj = RandomOutput()
obj.output = self.output
self.output = []
raise obj
def generateApprovedLines(self):
if self.empty():
raise Exception("Empty condition..." + repr(self))
lines = []
extraLine = False
if len(self.filename):
line = self.filename + ":<" + self.lineNumber + ">:"
reasonOnSameLine = False
if self.reason == "FAILED":
line += " " + "FAILED:"
reasonOnSameLine = True
lines.append(line)
if not(reasonOnSameLine) and len(self.reason):
lines.append(self.reason)
if len(self.condition):
lines.append(" " + self.condition)
if len(self.expansionPrefix):
lines.append(self.expansionPrefix)
extraLine = True
if len(self.expansion):
for line in self.expansion:
m = self.hexParser.match(line)
if m:
while m:
line = m.group(1) + "0x<hex digits>" + m.group(3)
m = self.hexParser.match(line)
lines.append(" " + line)
if len(self.messagePrefix):
lines.append(self.messagePrefix)
extraLine = True
if len(self.messages):
for msg in self.messages:
lines.append(" " + msg)
lines.append("")
if len(self.noAssertions) > 0:
if extraLine:
lines.append("")
lines.append(self.noAssertions)
lines.append("")
if len(self.output):
for msg in self.output:
lines.append(msg)
return lines
def generateResultLines(self):
if self.empty():
raise Exception("Empty condition..." + repr(self))
lines = []
extraLine = False
if len(self.filename):
if len(self.filenamePrefix):
line = self.filenamePrefix + self.filename + "(" + self.lineNumber + "):"
else:
line = self.filename + "(" + self.lineNumber + "):"
reasonOnSameLine = False
if self.reason == "FAILED":
line += " " + "FAILED:"
reasonOnSameLine = True
if (len(self.messagePrefix) > 0 and self.messagePrefix == "warning:" or
self.reason == "PASSED:" or self.expansionPrefix.startswith("FAILED - but was ok") ):
line += " "
lines.append(line)
if not(reasonOnSameLine) and len(self.reason):
lines.append(self.reason)
if len(self.condition):
lines.append(" " + self.condition)
if len(self.expansionPrefix):
lines.append(self.expansionPrefix)
extraLine = True
if len(self.expansion):
for line in self.expansion:
lines.append(" " + line)
if len(self.messagePrefix):
lines.append(self.messagePrefix)
extraLine = True
if len(self.messages):
for msg in self.messages:
lines.append(" " + msg)
lines.append("")
if len(self.noAssertions) > 0:
if extraLine:
lines.append("")
lines.append(self.noAssertions)
lines.append("")
if len(self.output):
for msg in self.output:
lines.append(msg)
return lines
def generateUnapprovedLines(self):
if self.empty():
raise Exception("Empty condition..." + repr(self))
lines = []
extraLine = False
if len(self.filename):
line = self.filename + ":<" + "line number" + ">:"
reasonOnSameLine = False
if self.reason == "FAILED":
line += " " + "FAILED:"
reasonOnSameLine = True
lines.append(line)
if not(reasonOnSameLine) and len(self.reason):
lines.append(self.reason)
if len(self.condition):
lines.append(" " + self.condition)
if len(self.expansionPrefix):
lines.append(self.expansionPrefix)
extraLine = True
if len(self.expansion):
for line in self.expansion:
m = self.hexParser.match(line)
if m:
while m:
line = m.group(1) + "0x<hex digits>" + m.group(3)
m = self.hexParser.match(line)
lines.append(" " + line)
if len(self.messagePrefix):
lines.append(self.messagePrefix)
extraLine = True
if len(self.messages):
for msg in self.messages:
lines.append(" " + msg)
lines.append("")
if len(self.noAssertions) > 0:
if extraLine:
lines.append("")
lines.append(self.noAssertions)
lines.append("")
if len(self.output):
for msg in self.output:
lines.append(msg)
return lines
def addFailure(self, filename, lineNumber, output, message, type):
self.reason = "failure"
self.filename = filename
self.lineNumber = lineNumber
self.condition = type
if message != None:
self.expansion.append(message)
self.output = output
def addError(self, filename, lineNumber, output, message, type):
self.reason = "error"
self.filename = filename
self.lineNumber = lineNumber
self.condition = type
if message != None:
self.expansion.append(message)
self.output = output
def generateUnapprovedJunit(self):
lines = []
msg = ""
for m in self.expansion:
msg += m
msg = msg.replace("\"", "&quot;")
msg = msg.replace("<", "&lt;")
msg = msg.replace("&lt;hex digits>", "<hex digits>")
#msg = msg.replace(">", "&gt;")
#print "R:",self.reason,msg,self.condition
if len(self.reason) > 0:
l = " <" + self.reason
if len(msg) > 0:
m = self.hexParser.match(msg)
if m:
while m:
msg = m.group(1) + "0x<hex digits>" + m.group(3)
m = self.hexParser.match(msg)
l += " message=\"" + msg + "\""
if self.condition != None:
l += " type=\"" + self.condition + "\""
l += ">"
lines.append(l)
if len(self.output) > 0:
for o in self.output:
lines.append(o)
if len(self.filename) > 0:
lines.append(self.filename + ":<" + self.lineNumber + ">")
lines.append(" </" + self.reason + ">")
return lines
class TestConditionApprovedParser:
failedApprovedTestParser = re.compile( r'(.*\..pp).*:<(.*).*>:(.*FAILED)' )
otherApprovedTestParser = re.compile( r'(.*\..pp).*:<(.*).*>:' )
def __init__(self):
self.current = TestConditionData()
def parseApprovedLine(self,line):
result = None
if line.startswith("==============================================================================="):
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
elif line.startswith("-------------------------------------------------------------------------------"):
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
else:
if line.startswith("No assertions in"):
self.current.noAssertions = line.strip()
self.current.state = self.current.MESSAGES
else:
m = self.failedApprovedTestParser.match(line)
if m:
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
self.current.filename = m.group(1).strip()
self.current.lineNumber = m.group(2).strip()
self.current.reason = m.group(3).strip()
self.current.state = self.current.CONDITION
else:
m = self.otherApprovedTestParser.match(line)
if m:
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
self.current.filename = m.group(1).strip()
self.current.lineNumber = m.group(2).strip()
self.current.state = self.current.CONDITION
elif not(self.current.empty()):
self.current.parseCondition(line)
return result
class TestConditionResultParser:
failedResultsTestParser = re.compile( r'(.*\\)(.*\..pp).*\((.*).*\):(.*FAILED)' )
otherResultsTestParser = re.compile( r'(.*\\)(.*\..pp).*\((.*).*\):' )
def __init__(self):
self.current = TestConditionData()
def parseResultLine(self,line):
result = None
if line.startswith("==============================================================================="):
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
elif line.startswith("-------------------------------------------------------------------------------"):
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
else:
if line.startswith("No assertions in"):
self.current.noAssertions = line.strip()
self.current.state = self.current.MESSAGES
else:
m = self.failedResultsTestParser.match(line)
if m:
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
self.current.filenamePrefix = m.group(1).strip()
self.current.filename = m.group(2).strip()
self.current.lineNumber = m.group(3).strip()
self.current.reason = m.group(4).strip()
self.current.state = self.current.CONDITION
else:
m = self.otherResultsTestParser.match(line)
if m:
if not(self.current.empty()):
result = self.current
self.current = TestConditionData()
self.current.filenamePrefix = m.group(1).strip()
self.current.filename = m.group(2).strip()
self.current.lineNumber = m.group(3).strip()
self.current.state = self.current.CONDITION
elif not(self.current.empty()):
self.current.parseCondition(line)
return result

584
scripts/catch_test_case.py Normal file
View File

@ -0,0 +1,584 @@
import re
from catch_conditions import TestConditionData
from catch_conditions import TestConditionApprovedParser
from catch_conditions import TestConditionResultParser
class EndOfClassName:
@staticmethod
def parseRawLine(line):
if line.startswith("..............................................................................."):
return ParseResult.END_OF_CLASS_NAME
return ParseResult.NONE
class TestCaseData:
def __init__(self):
self.name = ""
self.nameParts = []
self.classname = "global"
self.sections = []
self.filenamePrefix = ""
self.filename = ""
self.lineNumber = ""
self.conditions = []
self.sysout = []
self.syserr = []
self.result = ""
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __repr__(self):
result = "[" + self.name + ", [ "
suffix = ""
for section in self.sections:
result += suffix
result += repr(section)
suffix = ", "
result + " ] "
result += self.filename + ", " + self.lineNumber + " [ "
suffix = ""
for cond in self.conditions:
result += suffix
result += repr(cond)
suffix = ", "
result + " ] ]"
return result
def empty(self):
if len(self.name):
return False
return True
def generateApprovedLines(self):
if self.empty():
raise Exception("Empty test case..." + repr(self))
lines = []
if len(self.name):
lines.append("-------------------------------------------------------------------------------")
for n in self.nameParts:
lines.append(n)
if len(self.sections) > 0:
for section in self.sections:
lines.append(" " + section)
lines.append("-------------------------------------------------------------------------------")
if len(self.filename):
lines.append(self.filename + ":<" + self.lineNumber + ">")
lines.append("...............................................................................")
lines.append("")
for cond in self.conditions:
lines += cond.generateApprovedLines()
return lines
def generateResultLines(self):
if self.empty():
raise Exception("Empty test case..." + repr(self))
lines = []
if len(self.name):
lines.append("-------------------------------------------------------------------------------")
for n in self.nameParts:
lines.append(n)
if len(self.sections) > 0:
for section in self.sections:
lines.append(" " + section)
lines.append("-------------------------------------------------------------------------------")
if len(self.filename):
lines.append(self.filenamePrefix + self.filename + "(" + self.lineNumber + ")")
lines.append("...............................................................................")
lines.append("")
for cond in self.conditions:
lines += cond.generateResultLines()
return lines
def generateUnapprovedLines(self):
if self.empty():
raise Exception("Empty test case..." + repr(self))
lines = []
if len(self.name):
lines.append("-------------------------------------------------------------------------------")
for n in self.nameParts:
lines.append(n)
if len(self.sections) > 0:
for section in self.sections:
lines.append(" " + section)
lines.append("-------------------------------------------------------------------------------")
if len(self.filename):
lines.append(self.filename + ":<" + "line number" + ">")
lines.append("...............................................................................")
lines.append("")
for cond in self.conditions:
lines += cond.generateUnapprovedLines()
return lines
def generateUnapprovedJunit(self):
lines = []
condLines = []
for cond in self.conditions:
condLines += cond.generateUnapprovedJunit()
if len(self.name):
l = " <testcase classname=\"" + self.classname + "\" name=\"" + self.name + "\" time=\"{duration}\""
if len(condLines) > 0 or len(self.sysout) > 0 or len(self.syserr) > 0:
l += ">"
else:
l += "/>"
lines.append(l)
#if len(self.sections) > 0:
# for section in self.sections:
# lines.append(" " + section)
#if len(self.filename):
# lines.append(self.filename + ":<" + "line number" + ">")
# lines.append("...............................................................................")
lines += condLines
if len(self.sysout) > 0:
lines.append(" <system-out>")
for l in self.sysout:
lines.append(l)
lines.append(" </system-out>")
if len(self.syserr) > 0:
lines.append(" <system-err>")
for l in self.syserr:
lines.append(l)
lines.append(" </system-err>")
if len(condLines) > 0 or len(self.sysout) > 0 or len(self.syserr) > 0:
lines.append(" </testcase>")
return lines
def generateRecursiveSection(self, prefix, section):
lines = []
#print "S:",section
if section[0] == "S":
l = " " + prefix + "<Section name=\"" + section[1] + "\""
if section[2] != None:
li = section[2]
li = li.replace("&","&amp;")
li = li.replace("<","&lt;")
li = li.replace("&lt;hex digits>","<hex digits>")
li = li.replace("\"","&quot;")
l += " description=\"" + li + "\""
l += ">"
lines.append(l)
if len(section) > 4:
index = 4
while index < len(section):
tmp = section[index]
if len(tmp) > 0:
if tmp[0] == "E":
l = " " + prefix + "<Expression success=\"" + tmp[1] + "\""
if tmp[2] != None:
l += " filename=\"" + tmp[2] + "\""
l += " >"
lines.append(l)
if len(tmp) > 3:
cond = tmp[3]
if len(cond[0]) > 0:
lines.append(" " + prefix + "<Original>")
for li in cond[0]:
if len(li.strip()) > 0:
li = li.replace("<","&lt;")
li = li.replace("&lt;hex digits>","<hex digits>")
li = li.replace("\"","&quot;")
lines.append(li)
lines.append(" " + prefix + "</Original>")
if len(cond[1]) > 0:
lines.append(" " + prefix + "<Expanded>")
for li in cond[1]:
if len(li.strip()) > 0:
li = li.replace("<","&lt;")
li = li.replace("&lt;hex digits>","<hex digits>")
li = li.replace("\"","&quot;")
lines.append(li)
lines.append(" " + prefix + "</Expanded>")
if len(cond) > 2:
filename = cond[2]
lines.append(" " + prefix + "<Exception filename=\"" + filename + "\" >")
if len(cond) > 3:
tmp = cond[3]
for li in tmp:
if len(li.strip()) > 0:
lines.append(li)
lines.append(" " + prefix + "</Exception>")
elif len(tmp) > 4:
print "RE:",tmp[4]
l = " " + prefix + "</Expression>"
lines.append(l)
elif tmp[0] == "X":
l = " " + prefix + "<Exception filename=\"" + tmp[1] + "\" >"
lines.append(l)
for li in tmp[2]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Exception>"
lines.append(l)
elif tmp[0] == "F":
l = " " + prefix + "<Failure>"
lines.append(l)
for li in tmp[1]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Failure>"
lines.append(l)
elif tmp[0] == "S":
lines += self.generateRecursiveSection(prefix + " ", tmp)
else:
print "RS2:",tmp[0]
else:
print "RS:",section[index]
index += 1
lines.append(" " + prefix + "<OverallResults successes=\"" + section[3][0] + "\" failures=\"" + section[3][1] + "\"/>")
l = " " + prefix + "</Section>"
lines.append(l)
return lines
def generateSection(self, prefix, sections):
lines = []
for section in sections:
#print "S:",section
if section[0] == "S":
lines += self.generateRecursiveSection(prefix, section)
elif section[0] == "E":
l = " " + prefix + "<Expression success=\"" + section[1] + "\""
if section[2] != None:
l += " filename=\"" + section[2] + "\""
l += " >"
lines.append(l)
if len(section) > 3:
cond = section[3]
if len(cond[0]) > 0:
lines.append(" " + prefix + "<Original>")
for li in cond[0]:
if len(li.strip()) > 0:
li = li.replace("&","&amp;")
li = li.replace("<","&lt;")
li = li.replace("&lt;hex digits>","<hex digits>")
li = li.replace("\"","&quot;")
lines.append(li)
lines.append(" " + prefix + "</Original>")
if len(cond[1]) > 0:
lines.append(" " + prefix + "<Expanded>")
for li in cond[1]:
if len(li.strip()) > 0:
li = li.replace("<","&lt;")
li = li.replace("&lt;hex digits>","<hex digits>")
li = li.replace("\"","&quot;")
lines.append(li)
lines.append(" " + prefix + "</Expanded>")
if len(cond) > 2:
filename = cond[2]
lines.append(" " + prefix + "<Exception filename=\"" + filename + "\" >")
if len(cond) > 3:
tmp = cond[3]
for li in tmp:
if len(li.strip()) > 0:
lines.append(li)
lines.append(" " + prefix + "</Exception>")
elif len(section) > 4:
print "RE:",section[4]
l = " " + prefix + "</Expression>"
lines.append(l)
elif section[0] == "X":
l = " " + prefix + "<Exception filename=\"" + section[1] + "\" >"
lines.append(l)
for li in section[2]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Exception>"
lines.append(l)
elif section[0] == "I":
l = " " + prefix + "<Info>"
lines.append(l)
for li in section[1]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Info>"
lines.append(l)
elif section[0] == "W":
l = " " + prefix + "<Warning>"
lines.append(l)
for li in section[1]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Warning>"
lines.append(l)
elif section[0] == "F":
l = " " + prefix + "<Failure>"
lines.append(l)
for li in section[1]:
if len(li.strip()) > 0:
lines.append(li)
l = " " + prefix + "</Failure>"
lines.append(l)
return lines
def generateUnapprovedXml(self):
lines = []
if len(self.name):
l = " <TestCase name=\"" + self.name + "\">"
lines.append(l)
if len(self.sections) > 0:
prefix = " "
lines += self.generateSection(prefix, self.sections)
if len(self.result) > 0:
lines.append(" <OverallResult success=\"" + self.result + "\"/>")
if len(self.name):
l = " </TestCase>"
lines.append(l)
return lines
def addFailure(self, filename, lineNumber, output, message, type):
self.filename = filename
self.lineNumber = lineNumber
condition = TestConditionData()
condition.addFailure(filename, lineNumber, output, message, type)
self.conditions.append(condition)
def addError(self, filename, lineNumber, output, message, type):
self.filename = filename
self.lineNumber = lineNumber
condition = TestConditionData()
condition.addError(filename, lineNumber, output, message, type)
self.conditions.append(condition)
def addSysout(self, output):
self.sysout = output
def addSyserr(self, output):
self.syserr = output
def addOverallResult(self,r):
self.result = r
def addSection(self,name,desc, results):
section = []
section.append("S")
section.append(name)
section.append(desc)
section.append(results)
self.sections.append(section)
return section
def addExpression(self,result,filename):
section = []
section.append("E")
section.append(result)
section.append(filename)
self.sections.append(section)
return section
def addException(self,filename,text):
section = []
section.append("X")
section.append(filename)
section.append(text)
#print section
self.sections.append(section)
return section
def addInfo(self,text):
section = []
section.append("I")
section.append(text)
self.sections.append(section)
return section
def addWarning(self,text):
section = []
section.append("W")
section.append(text)
self.sections.append(section)
return section
def addSimpleFailure(self,text):
section = []
section.append("F")
section.append(text)
self.sections.append(section)
return section
def addExpressionDetails(self, section, subExp):
section.append(subExp)
def addSubException(self, section, filename, text):
tmp = []
tmp.append("X")
tmp.append(filename)
tmp.append(text)
section.append(tmp)
def addSubFailure(self, section, text):
tmp = []
tmp.append("F")
tmp.append(text)
section.append(tmp)
def addSubExpression(self,section,result,filename):
tmp = []
tmp.append("E")
tmp.append(result)
tmp.append(filename)
section.append(tmp)
#print "Section:",section
return tmp
def addSubSection(self,section,name,desc,results):
tmp = []
tmp.append("S")
tmp.append(name)
tmp.append(desc)
tmp.append(results)
section.append(tmp)
#print "Section:",section
return tmp
class TestCaseApprovedParser:
NONE = 0
TEST_CASE_NAME_EXPECTED = 1
TEST_CASE_NAME = 2
TEST_CLASS_EXPECTED = 3
END_OF_CLASS_NAME_EXPECTED = 4
TEST_CONDITION_EXPECTED = 5
testFilenameParser = re.compile( r'(.*\..pp).*:<(.*).*>' )
def __init__(self):
self.state = self.NONE
self.current = TestCaseData()
self.conditionParser = TestConditionApprovedParser()
def parseApprovedLine(self,line):
result = None
if self.state == self.NONE:
if line.startswith("-------------------------------------------------------------------------------"):
self.state = self.TEST_CASE_NAME_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_NAME_EXPECTED:
if len(line):
self.current.name = line.strip()
self.current.nameParts.append(line.strip())
self.state = self.TEST_CASE_NAME
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_NAME:
if line.startswith("-------------------------------------------------------------------------------"):
self.state = self.TEST_CLASS_EXPECTED
elif line.startswith(" "):
#print "***SECTION: ",line
self.current.sections.append(line[2:])
elif len(line):
if len(self.current.name) > 0:
self.current.name += line.strip()
else:
self.current.name = line.strip()
self.current.nameParts.append(line.strip())
elif self.state == self.TEST_CLASS_EXPECTED:
m = self.testFilenameParser.match(line)
if m:
self.current.filename = m.group(1).strip()
self.current.lineNumber = m.group(2).strip()
self.state = self.END_OF_CLASS_NAME_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.END_OF_CLASS_NAME_EXPECTED:
if line.startswith("..............................................................................."):
self.state = self.TEST_CONDITION_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CONDITION_EXPECTED:
#print "**** LINE " + line
condition = self.conditionParser.parseApprovedLine(line)
if isinstance(condition, TestConditionData):
#print "**** CASE " + repr(condition)
self.current.conditions.append(condition)
if line.startswith("-------------------------------------------------------------------------------"):
result = self.current
self.current = TestCaseData()
self.state = self.TEST_CASE_NAME_EXPECTED
elif line.startswith("==============================================================================="):
result = self.current
self.current = TestCaseData()
self.state = self.NONE
return result
class TestCaseResultParser:
NONE = 0
TEST_CASE_NAME_EXPECTED = 1
TEST_CASE_NAME = 2
TEST_CLASS_EXPECTED = 3
END_OF_CLASS_NAME_EXPECTED = 4
TEST_CONDITION_EXPECTED = 5
testFilenameParser = re.compile( r'(.*\\)(.*\..pp).*\((.*).*\)' )
def __init__(self):
self.state = self.NONE
self.current = TestCaseData()
self.conditionParser = TestConditionResultParser()
def parseResultLine(self,line):
result = None
if self.state == self.NONE:
if line.startswith("-------------------------------------------------------------------------------"):
self.state = self.TEST_CASE_NAME_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_NAME_EXPECTED:
if len(line):
self.current.name = line.strip()
self.current.nameParts.append(line.strip())
self.state = self.TEST_CASE_NAME
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_NAME:
if line.startswith("-------------------------------------------------------------------------------"):
self.state = self.TEST_CLASS_EXPECTED
elif line.startswith(" "):
#print "***SECTION: ",line
self.current.sections.append(line[2:])
elif len(line):
if len(self.current.name) > 0:
self.current.name += line.strip()
else:
self.current.name = line.strip()
self.current.nameParts.append(line.strip())
elif self.state == self.TEST_CLASS_EXPECTED:
m = self.testFilenameParser.match(line)
if m:
self.current.filenamePrefix = m.group(1).strip()
self.current.filename = m.group(2).strip()
self.current.lineNumber = m.group(3).strip()
self.state = self.END_OF_CLASS_NAME_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.END_OF_CLASS_NAME_EXPECTED:
if line.startswith("..............................................................................."):
self.state = self.TEST_CONDITION_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CONDITION_EXPECTED:
#print "**** LINE " + line
condition = self.conditionParser.parseResultLine(line)
if isinstance(condition, TestConditionData):
#print "**** CASE " + repr(condition)
self.current.conditions.append(condition)
if line.startswith("-------------------------------------------------------------------------------"):
result = self.current
self.current = TestCaseData()
self.state = self.TEST_CASE_NAME_EXPECTED
elif line.startswith("==============================================================================="):
result = self.current
self.current = TestCaseData()
self.state = self.NONE
return result

430
scripts/catch_test_run.py Normal file
View File

@ -0,0 +1,430 @@
import re
import os
from catch_test_case import TestCaseApprovedParser
from catch_test_case import TestCaseResultParser
from catch_test_case import TestCaseData
from catch_conditions import RandomOutput
class TestRunData:
def __init__(self):
self.appname = ""
self.version = ""
self.testcases = []
self.results = ""
self.output = []
self.outputLine = 0
self.writtenOutput = False
self.sysout = []
self.syserr = []
self.errors = ""
self.failures = ""
self.tests = ""
def __eq__(self, other):
return self.__dict__ == other.__dict__
def __repr__(self):
result = "[" + self.appname + ", " + self.version + " [ "
suffix = ""
for case in self.testcases:
result += suffix
result += repr(case)
suffix = ", "
result += " ]"
result += self.results
result += " ]"
return result
def empty(self):
if len(self.appname):
return False
return True
def generateApprovedLines(self):
if self.empty():
raise Exception("Empty test run..." + repr(self))
lines = []
self.writtenOutput = False
if not(self.writtenOutput) and len(self.output) > 0 and self.outputLine == 0:
lines += self.output
self.writtenOutput = True
if len(self.appname):
lines.append("")
lines.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
lines.append(self.appname + " is a " + self.version + " host application.")
lines.append("Run with -? for options")
lines.append("")
for case in self.testcases:
lines += case.generateApprovedLines()
if not(self.writtenOutput) and len(self.output) > 0 and len(lines) >= self.outputLine:
lines += self.output
self.writtenOutput = True
lines.append("===============================================================================")
lines.append(self.results)
lines.append("")
return lines
def generateSortedApprovedLines(self):
if self.empty():
raise Exception("Empty test run..." + repr(self))
lines = []
self.writtenOutput = False
if not(self.writtenOutput) and len(self.output) > 0 and self.outputLine == 0:
lines += self.output
self.writtenOutput = True
if len(self.appname):
lines.append("")
lines.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
lines.append(self.appname + " is a " + self.version + " host application.")
lines.append("Run with -? for options")
lines.append("")
sortedTestcases = sorted(self.testcases, key=lambda x: x.name, reverse=False)
for case in sortedTestcases:
lines += case.generateApprovedLines()
if not(self.writtenOutput) and len(self.output) > 0 and len(lines) >= self.outputLine:
lines += self.output
self.writtenOutput = True
lines.append("===============================================================================")
lines.append(self.results)
lines.append("")
return lines
def generateResultLines(self):
if self.empty():
raise Exception("Empty test run..." + repr(self))
lines = []
self.writtenOutput = False
if not(self.writtenOutput) and len(self.output) > 0 and self.outputLine == 0:
lines += self.output
self.writtenOutput = True
if len(self.appname):
lines.append("")
lines.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
lines.append(self.appname + " is a " + self.version + " host application.")
lines.append("Run with -? for options")
lines.append("")
for case in self.testcases:
lines += case.generateResultLines()
if not(self.writtenOutput) and len(self.output) > 0 and len(lines) >= self.outputLine:
lines += self.output
self.writtenOutput = True
lines.append("===============================================================================")
lines.append(self.results)
lines.append("")
return lines
def generateUnapprovedLines(self, outputLine):
if self.empty():
raise Exception("Empty test run..." + repr(self))
lines = []
self.writtenOutput = False
#print "U:",outputLine,",",self.output
if not(self.writtenOutput) and len(self.output) > 0 and outputLine == 0:
lines += self.output
self.writtenOutput = True
if len(self.appname):
lines.append("")
lines.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
lines.append("CatchSelfTest" + " is a " + "<version>" + " host application.")
lines.append("Run with -? for options")
lines.append("")
for case in self.testcases:
lines += case.generateUnapprovedLines()
if not(self.writtenOutput) and len(self.output) > 0 and len(lines) >= outputLine:
lines += self.output
self.writtenOutput = True
lines.append("===============================================================================")
lines.append(self.results)
lines.append("")
return lines
def generateSortedUnapprovedLines(self, outputLine):
if self.empty():
raise Exception("Empty test run..." + repr(self))
lines = []
self.writtenOutput = False
#print "U:",outputLine,",",self.output
if not(self.writtenOutput) and len(self.output) > 0 and outputLine == 0:
lines += self.output
self.writtenOutput = True
if len(self.appname):
lines.append("")
lines.append("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
lines.append("CatchSelfTest" + " is a " + "<version>" + " host application.")
lines.append("Run with -? for options")
lines.append("")
sortedTestcases = sorted(self.testcases, key=lambda x: x.name, reverse=False)
for case in sortedTestcases:
lines += case.generateUnapprovedLines()
if not(self.writtenOutput) and len(self.output) > 0 and len(lines) >= outputLine:
lines += self.output
self.writtenOutput = True
lines.append("===============================================================================")
lines.append(self.results)
lines.append("")
return lines
def generateSortedUnapprovedJunit(self):
lines = []
#print "U:",outputLine,",",self.output
lines.append("<testsuites>")
l = " <testsuite name=\""
l += self.appname
l += "\" errors=\""
l += self.errors
l += "\" failures=\""
l += self.failures
l += "\" tests=\""
l += self.tests
l += "\" hostname=\"tbd\" time=\"{duration}\" timestamp=\"tbd\">"
lines.append(l)
sortedTestcases = sorted(self.testcases, key=lambda x: x.classname, reverse=False)
sortedTestcases = sorted(sortedTestcases, key=lambda x: x.name, reverse=False)
#sortedTestcases = self.testcases
for case in sortedTestcases:
lines += case.generateUnapprovedJunit()
if len(self.sysout) > 0:
lines.append(" <system-out>")
for l in self.sysout:
lines.append(l)
lines.append(" </system-out>")
if len(self.syserr) > 0:
lines.append(" <system-err>")
for l in self.syserr:
lines.append(l)
lines.append(" </system-err>")
lines.append(" </testsuite>")
lines.append("</testsuites>")
return lines
def generateSortedUnapprovedXml(self):
lines = []
#print "U:",outputLine,",",self.output
lines.append("<Catch name=\"" + self.appname + "\">")
lines.append(" <Group name=\"~_\">")
sortedTestcases = sorted(self.testcases, key=lambda x: x.classname, reverse=False)
sortedTestcases = sorted(sortedTestcases, key=lambda x: x.name, reverse=False)
#sortedTestcases = self.testcases
for case in sortedTestcases:
lines += case.generateUnapprovedXml()
l = "<OverallResults successes=\""
# successes="663" failures="109"
l += self.tests
l += "\" failures=\""
l += self.failures
l += "\"/>"
lines.append(" " + l)
lines.append(" </Group>")
lines.append(" " + l)
lines.append("</Catch>")
return lines
def addTestCase(self, name):
testcase = TestCaseData()
testcase.name = name
testcase.nameParts.append(name)
self.testcases.append(testcase)
return testcase
def addClassTestCase(self, cls, name):
testcase = TestCaseData()
testcase.classname = cls
testcase.name = name
testcase.nameParts.append(name)
self.testcases.append(testcase)
return testcase
def addSysout(self, output):
self.sysout = output
def addSyserr(self, output):
self.syserr = output
class TestRunApprovedParser:
NONE = 0
VERSION_EXPECTED = 1
TEST_CASE_EXPECTED = 2
END_RUN_INFO = 3
versionParser = re.compile( r'(.*)is a (<version>*).*' )
def __init__(self):
self.state = self.NONE
self.current = TestRunData()
self.testcaseParser = TestCaseApprovedParser()
self.lineNumber = 0
def parseApprovedLine(self,line):
result = None
if self.state == self.NONE:
if line.startswith("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"):
self.state = self.VERSION_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.VERSION_EXPECTED:
m = self.versionParser.match(line)
if m:
self.current.appname = m.group(1).strip()
self.current.version = m.group(2).strip()
self.state = self.TEST_CASE_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_EXPECTED:
if line == "Run with -? for options":
pass
else:
testcase = None
try:
testcase = self.testcaseParser.parseApprovedLine(line)
except RandomOutput as e:
#print "E:", self.lineNumber, ", ",e.output
self.current.output = e.output
self.current.outputLine = self.lineNumber - 10
if isinstance(testcase, TestCaseData):
self.current.testcases.append(testcase)
if line.startswith("==============================================================================="):
self.state = self.END_RUN_INFO
elif self.state == self.END_RUN_INFO:
if len(line):
self.current.results = line.strip()
result = self.current
self.lineNumber += 1
return result
class TestRunApprovedHandler:
def __init__(self, filePath):
rawFile = open( filePath, 'r' )
parser = TestRunApprovedParser()
lineNumber = 0
self.current = None
for line in rawFile:
line = line.rstrip()
#print "L:", lineNumber, "'",line,"'"
result = parser.parseApprovedLine(line)
if isinstance(result, TestRunData):
self.current = result
lineNumber += 1
if not(isinstance(self.current, TestRunData) ):
raise Exception("File could not be parsed: '" + filePath + "'")
def writeRawFile(self,filePath):
rawWriteFile = open( filePath, 'wb' )
lines = self.current.generateApprovedLines()
for line in lines:
rawWriteFile.write(line + "\n")
def writeSortedRawFile(self,filePath):
rawWriteFile = open( filePath, 'wb' )
lines = self.current.generateSortedApprovedLines()
for line in lines:
rawWriteFile.write(line + "\n")
class TestRunResultParser:
NONE = 0
VERSION_EXPECTED = 1
TEST_CASE_EXPECTED = 2
END_RUN_INFO = 3
versionParser = re.compile( r'(.*)is a (Catch v[0-9]*.[0-9]* b[0-9]*).*' )
def __init__(self):
self.state = self.NONE
self.current = TestRunData()
self.testcaseParser = TestCaseResultParser()
self.lineNumber = 0
def parseResultLine(self,line):
result = None
if self.state == self.NONE:
if line.startswith("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"):
self.state = self.VERSION_EXPECTED
elif len(line):
self.current.output.append(line.strip())
if len(self.current.output) == 10:
if (self.current.output[0] == "Message from section one" and self.current.output[1] == "Message from section two" and
self.current.output[2] == "Some information" and self.current.output[3] == "An error" and
self.current.output[4] == "Message from section one" and self.current.output[5] == "Message from section two" and
self.current.output[6] == "Some information" and self.current.output[7] == "An error" and
self.current.output[8] == "hello" and self.current.output[9] == "hello" ):
self.current.outputLine = self.lineNumber - 9
elif self.state == self.VERSION_EXPECTED:
m = self.versionParser.match(line)
if m:
self.current.appname = m.group(1).strip()
self.current.version = m.group(2).strip()
self.state = self.TEST_CASE_EXPECTED
elif len(line):
raise Exception("Unknown parse line: '" + line + "'")
elif self.state == self.TEST_CASE_EXPECTED:
if line == "Run with -? for options":
pass
else:
testcase = None
try:
testcase = self.testcaseParser.parseResultLine(line)
except RandomOutput as e:
#print "E:", self.lineNumber, ", ",e.output
self.current.output = e.output
self.current.outputLine = self.lineNumber - 10
if isinstance(testcase, TestCaseData):
self.current.testcases.append(testcase)
if line.startswith("==============================================================================="):
self.state = self.END_RUN_INFO
elif self.state == self.END_RUN_INFO:
if len(line):
self.current.results = line.strip()
result = self.current
self.lineNumber += 1
return result
class TestRunResultHandler:
def __init__(self, filePath):
rawFile = open( filePath, 'r' )
parser = TestRunResultParser()
lineNumber = 0
self.current = None
for line in rawFile:
line = line.rstrip()
#print "L:", lineNumber, "'",line,"'"
result = parser.parseResultLine(line)
if isinstance(result, TestRunData):
self.current = result
lineNumber += 1
if not(isinstance(self.current, TestRunData) ):
raise Exception("File could not be parsed: '" + filePath + "'")
def writeRawFile(self,filePath):
rawWriteFile = open( filePath, 'wb' )
lines = self.current.generateResultLines()
for line in lines:
rawWriteFile.write(line + os.linesep)
def writeUnapprovedFile(self,filePath,outputLine):
rawWriteFile = open( filePath, 'wb' )
lines = self.current.generateUnapprovedLines(outputLine)
for line in lines:
rawWriteFile.write(line + "\n")
def writeSortedUnapprovedFile(self,filePath,outputLine):
rawWriteFile = open( filePath, 'wb' )
lines = self.current.generateSortedUnapprovedLines(outputLine)
for line in lines:
rawWriteFile.write(line + "\n")

698
scripts/test_conditions.py Normal file
View File

@ -0,0 +1,698 @@
import unittest
import catch_conditions
from catch_conditions import TestConditionApprovedParser
from catch_conditions import TestConditionResultParser
from catch_conditions import TestConditionData
from catch_conditions import RandomOutput
class ConditionTest(unittest.TestCase):
def testConditionEquality(self):
c1 = TestConditionData()
c2 = TestConditionData()
c1.state = TestConditionData.CONDITION
c2.state = TestConditionData.EXPANSION
c1.filenamePrefix = "..\\..\\Test"
c2.filenamePrefix = "..\\..\\Test"
self.assertTrue(c1 == c2)
c2.filenamePrefix = "..\\..\\Junk"
self.assertFalse(c1 == c2)
self.assertTrue(c1 != c2)
def testEndOfTestRunIsFound(self):
obj = TestConditionApprovedParser()
line = "==============================================================================="
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.empty())
def testEndOfTestCaseIsFound(self):
obj = TestConditionApprovedParser()
line = "-------------------------------------------------------------------------------"
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.empty())
def testFailedConditionIsFound(self):
obj = TestConditionApprovedParser()
line = "ClassTests.cpp:<line number>: FAILED:"
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue( not(obj.current.empty()) )
def testOtherConditionIsFound(self):
obj = TestConditionApprovedParser()
line = "ClassTests.cpp:<line number>:"
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue( not(obj.current.empty()) )
def testFailedConditionSetsReason(self):
obj = TestConditionApprovedParser()
line = "ClassTests.cpp:<line number>: FAILED:"
result = obj.parseApprovedLine(line)
self.assertTrue(obj.current.reason == "FAILED")
self.assertTrue(obj.current.filename == "ClassTests.cpp")
self.assertTrue(obj.current.lineNumber == "line number")
def testOtherConditionSetsFileNameAndLine(self):
obj = TestConditionApprovedParser()
line = "MessageTests.cpp:<line number>:"
result = obj.parseApprovedLine(line)
self.assertTrue(obj.current.filename == "MessageTests.cpp")
self.assertTrue(obj.current.lineNumber == "line number")
def testFailedConditionSetsCondition(self):
obj = TestConditionApprovedParser()
lines = ["ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
""]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.condition == "REQUIRE( s == \"world\" )")
newLines = obj.current.generateApprovedLines()
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testExpansionConditionReturnsExpansion(self):
obj = TestConditionApprovedParser()
lines = ["ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:" ]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
def testExpansionSetsExpansion(self):
obj = TestConditionApprovedParser()
lines = [ "ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" 1 == 2",
"",
"-------------------------------------------------------------------------------"
]
for line in lines:
result = obj.parseApprovedLine(line)
#print lines
self.assertTrue(isinstance(result, TestConditionData))
self.assertTrue(len(result.expansion) == 1)
self.assertTrue(result.expansion[0] == "1 == 2")
newLines = result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testTwoConditions(self):
obj = TestConditionApprovedParser()
lines = [ "ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.int_seven == 6 )",
"with expansion:",
" 7 == 6",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.int_seven == 8 )",
"with expansion:",
" 7 == 8",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testSuccessConditions(self):
obj = TestConditionApprovedParser()
lines = [ "ApproxTests.cpp:<line number>:",
"PASSED:",
" REQUIRE( d == Approx( 1.23 ) )",
"with expansion:",
" 1.23 == Approx( 1.23 )",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print result
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testConditionsWithoutExpansion(self):
obj = TestConditionApprovedParser()
lines = [ "ConditionTests.cpp:<line number>: FAILED:",
" CHECK( false != false )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( true != true )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( !true )",
"with expansion:",
" false",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testExceptionsExplicit(self):
obj = TestConditionApprovedParser()
lines = [ "ExceptionTests.cpp:<line number>: FAILED:",
" CHECK_THROWS_AS( thisThrows() )",
"due to unexpected exception with message:",
" expected exception",
"",
"ExceptionTests.cpp:<line number>: FAILED:",
" CHECK_THROWS_AS( thisDoesntThrow() )",
"because no exception was thrown where one was expected:",
"",
"ExceptionTests.cpp:<line number>: FAILED:",
" CHECK_NOTHROW( thisThrows() )",
"due to unexpected exception with message:",
" expected exception",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testExceptionsImplicit(self):
obj = TestConditionApprovedParser()
lines = [ "ExceptionTests.cpp:<line number>: FAILED:",
"due to unexpected exception with message:",
" unexpected exception",
"",
"ExceptionTests.cpp:<line number>: FAILED:",
" {Unknown expression after the reported line}",
"due to unexpected exception with message:",
" unexpected exception",
"",
"ExceptionTests.cpp:<line number>: FAILED:",
"due to unexpected exception with message:",
" 3.14",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testWarning(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>:",
"warning:",
" this is a warning",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMessages1(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>: FAILED:",
" REQUIRE( a == 1 )",
"with expansion:",
" 2 == 1",
"with messages:",
" this message should be logged",
" so should this",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMessagesExplicitFail(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>: FAILED:",
"explicitly with message:",
" This is a failure",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMessagesOutput(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>: FAILED:",
"explicitly with message:",
" Message from section two",
"",
"Message from section one",
"Message from section two",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiMessages(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>: FAILED:",
" REQUIRE( i < 10 )",
"with expansion:",
" 10 < 10",
"with messages:",
" current counter 10",
" i := 10",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMiscMessages(self):
obj = TestConditionApprovedParser()
lines = [ "MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[0] (1) is even",
"",
"MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[1] (1) is even",
"",
"MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[3] (3) is even",
"",
"MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[4] (5) is even",
"",
"MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[6] (13) is even",
"",
"MiscTests.cpp:<line number>: FAILED:",
" CHECK( ( fib[i] % 2 ) == 0 )",
"with expansion:",
" 1 == 0",
"with message:",
" Testing if fib[7] (21) is even",
"",
"Some information",
"An error",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testRandomOutput(self):
obj = TestConditionApprovedParser()
lines = [ "MiscTests.cpp:<line number>: FAILED:",
"explicitly with message:",
" to infinity and beyond",
"",
"Message from section one",
"Message from section two",
"Some information",
"An error",
"Message from section one",
"Message from section two",
"Some information",
"An error",
"hello",
"hello",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
try:
result = obj.parseApprovedLine(line)
except RandomOutput as e:
randomOutput = e.output
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
self.assertTrue( len(randomOutput) == 10)
newLines += randomOutput
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiLineWarning(self):
obj = TestConditionApprovedParser()
lines = [ "TrickyTests.cpp:<line number>:",
"warning:",
" Uncomment the code in this test to check that it gives a sensible compiler",
" error",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiMessagesAfterCondition(self):
obj = TestConditionApprovedParser()
lines = [ "MiscTests.cpp:<line number>: FAILED:",
" REQUIRE( false )",
"with messages:",
" hi",
" i := 7",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testNoAssertions(self):
obj = TestConditionApprovedParser()
lines = [ "",
"No assertions in test case './succeeding/exceptions/implicit'",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testNoAssertionsWithOutput(self):
obj = TestConditionApprovedParser()
lines = [ "",
"No assertions in section 'one'",
"",
"Message from section two",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testFailedButOk(self):
obj = TestConditionApprovedParser()
lines = [ "MessageTests.cpp:<line number>:",
"FAILED - but was ok:",
" CHECK_NOFAIL( 1 == 2 )",
"",
"",
"No assertions in test case './succeeding/nofail'",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiLineExpansion(self):
obj = TestConditionApprovedParser()
lines = [ "MiscTests.cpp:<line number>:",
"PASSED:",
" CHECK_THAT( testStringForMatching() AllOf( Catch::Contains( \"string\" ), Catch::Contains( \"abc\" ) ) )",
"with expansion:",
" \"this string contains 'abc' as a substring\" ( contains: \"string\" and",
" contains: \"abc\" )",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiLineExpansionWithWrap(self):
obj = TestConditionApprovedParser()
lines = [ "TestMain.cpp:<line number>:",
"PASSED:",
" CHECK( text.toString() == \" one two\n three\n four\" )",
"with expansion:",
" \" one two",
" three",
" four\"",
" ==",
" \" one two",
" three",
" four\"",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
randomOutput = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testMultiLineExpansionWithTruncation(self):
obj = TestConditionApprovedParser()
lines = [ "TestMain.cpp:<line number>:",
"PASSED:",
" CHECK_THAT( t.toString() EndsWith( \"... message truncated due to excessive size\" ) )",
"with expansion:",
" \"***************************************************************************-",
" ***-",
" ****************************************************************************-",
" **-",
"... message truncated due to excessive size",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testBasicResultsParser(self):
obj = TestConditionResultParser()
lines = [ "..\..\..\SelfTest\ClassTests.cpp(28): FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseResultLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateResultLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testBasicResultsWarning(self):
obj = TestConditionResultParser()
lines = [ "..\..\..\SelfTest\MessageTests.cpp(17): ",
"warning:",
" this is a warning",
"",
"-------------------------------------------------------------------------------"
]
newLines = []
for line in lines:
result = obj.parseResultLine(line)
if isinstance(result, TestConditionData):
#print result
newLines += result.generateResultLines()
newLines.append("-------------------------------------------------------------------------------")
#print lines
#print newLines
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
if __name__ == '__main__':
unittest.main()

341
scripts/test_test_case.py Normal file
View File

@ -0,0 +1,341 @@
import unittest
from catch_test_case import TestCaseApprovedParser
from catch_test_case import TestCaseResultParser
from catch_test_case import TestCaseData
from catch_conditions import TestConditionData
class TestCaseTest(unittest.TestCase):
def testTestCaseEquality(self):
c1 = TestConditionData()
c2 = TestConditionData()
c1.filenamePrefix = "..\\..\\Test"
c2.filenamePrefix = "..\\..\\Junk"
t1 = TestCaseData()
t2 = TestCaseData()
t1.name = "Test 1"
t2.name = "Test 1"
t1.conditions.append(c1)
t1.conditions.append(c2)
t2.conditions.append(c1)
t2.conditions.append(c2)
self.assertTrue(t1 == t2)
c3 = TestConditionData()
c3.filenamePrefix = "..\\..\\Fail"
t2.conditions.append(c3)
self.assertFalse(t1 == t2)
t1.conditions.append(c3)
self.assertTrue(t1 == t2)
t2.name = "Test 2"
self.assertFalse(t1 == t2)
def testEndOfTestCaseIsFound(self):
obj = TestCaseApprovedParser()
line = "-------------------------------------------------------------------------------"
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.empty())
def testTestCaseNameIsFound(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------" ]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.name == "./failing/TestClass/failingCase")
self.assertTrue( not(obj.current.empty()) )
def testTestCaseClassIsFound(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"..............................................................................." ]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(obj.current.filename == "ClassTests.cpp")
self.assertTrue(obj.current.lineNumber == "line number")
def testPartialConditionRequiresMoreData(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"ClassTests.cpp:<line number>: FAILED:" ]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(len(obj.current.conditions) == 0)
def testTestCaseConditionIsFound(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\""]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
self.assertTrue(not(obj.conditionParser.current.empty()))
self.assertTrue(obj.conditionParser.current.reason == "FAILED")
def testTestCaseConditionIsInsertedIntoList(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------"]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(isinstance(result, TestCaseData))
self.assertTrue(len(result.conditions) > 0)
self.assertTrue(result.conditions[0].filename == "ClassTests.cpp" )
self.assertTrue(result.conditions[0].lineNumber == "line number" )
self.assertTrue(result.conditions[0].reason == "FAILED" )
newLines = result.generateApprovedLines()
newLines.append("-------------------------------------------------------------------------------")
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testTwoTestCases(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------",
"./failing/Fixture/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( m_a == 2 )",
"with expansion:",
" 1 == 2",
"",
"==============================================================================="
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestCaseData):
newLines += result.generateApprovedLines()
newLines.append("===============================================================================")
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testTestCaseMultiConditionMatches(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/conditions/equality",
"-------------------------------------------------------------------------------",
"ConditionTests.cpp:<line number>",
"...............................................................................",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.int_seven == 6 )",
"with expansion:",
" 7 == 6",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.int_seven == 8 )",
"with expansion:",
" 7 == 8",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.int_seven == 0 )",
"with expansion:",
" 7 == 0",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.float_nine_point_one == Approx( 9.11f ) )",
"with expansion:",
" 9.1 == Approx( 9.11 )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.float_nine_point_one == Approx( 9.0f ) )",
"with expansion:",
" 9.1 == Approx( 9 )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.float_nine_point_one == Approx( 1 ) )",
"with expansion:",
" 9.1 == Approx( 1 )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.float_nine_point_one == Approx( 0 ) )",
"with expansion:",
" 9.1 == Approx( 0 )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.double_pi == Approx( 3.1415 ) )",
"with expansion:",
" 3.1415926535 == Approx( 3.1415 )",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.str_hello == \"goodbye\" )",
"with expansion:",
" \"hello\" == \"goodbye\"",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.str_hello == \"hell\" )",
"with expansion:",
" \"hello\" == \"hell\"",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.str_hello == \"hello1\" )",
"with expansion:",
" \"hello\" == \"hello1\"",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( data.str_hello.size() == 6 )",
"with expansion:",
" 5 == 6",
"",
"ConditionTests.cpp:<line number>: FAILED:",
" CHECK( x == Approx( 1.301 ) )",
"with expansion:",
" 1.3 == Approx( 1.301 )",
"",
"==============================================================================="
]
for line in lines:
result = obj.parseApprovedLine(line)
self.assertTrue(isinstance(result, TestCaseData))
newLines = result.generateApprovedLines()
newLines.append("===============================================================================")
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testOneSection(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/message/sections",
" one",
"-------------------------------------------------------------------------------",
"MessageTests.cpp:<line number>",
"...............................................................................",
"",
"MessageTests.cpp:<line number>: FAILED:",
"explicitly with message:",
" Message from section one",
"",
"==============================================================================="
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestCaseData):
newLines += result.generateApprovedLines()
newLines.append("===============================================================================")
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testOneSection(self):
obj = TestCaseApprovedParser()
lines = [ "-------------------------------------------------------------------------------",
"Comparisons between unsigned ints and negative signed ints match c++ standard",
"behaviour",
"-------------------------------------------------------------------------------",
"ConditionTests.cpp:<line number>",
"...............................................................................",
"",
"ConditionTests.cpp:<line number>:",
"PASSED:",
" CHECK( ( -1 > 2u ) )",
"with expansion:",
" true",
"",
"ConditionTests.cpp:<line number>:",
"PASSED:",
" CHECK( -1 > 2u )",
"with expansion:",
" -1 > 2",
"",
"==============================================================================="
]
newLines = []
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestCaseData):
newLines += result.generateApprovedLines()
newLines.append("===============================================================================")
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testCaseBasicResults(self):
obj = TestCaseResultParser()
lines = [ "-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"..\..\..\SelfTest\ClassTests.cpp(34)",
"...............................................................................",
"",
"..\..\..\SelfTest\ClassTests.cpp(28): FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"==============================================================================="
]
newLines = []
for line in lines:
result = obj.parseResultLine(line)
if isinstance(result, TestCaseData):
newLines += result.generateResultLines()
newLines.append("===============================================================================")
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
if __name__ == '__main__':
unittest.main()

334
scripts/test_test_run.py Normal file
View File

@ -0,0 +1,334 @@
import unittest
import catch_test_case
from catch_test_run import TestRunData
from catch_test_run import TestRunApprovedParser
from catch_test_run import TestRunResultParser
from catch_test_case import TestCaseData
from catch_conditions import TestConditionData
class TestCaseTest(unittest.TestCase):
def testTestRunEquality(self):
c1 = TestConditionData()
c2 = TestConditionData()
c1.filenamePrefix = "..\\..\\Test"
c2.filenamePrefix = "..\\..\\Junk"
t1 = TestCaseData()
t2 = TestCaseData()
t1.name = "Test 1"
t2.name = "Test 1"
t1.conditions.append(c1)
t1.conditions.append(c2)
t2.conditions.append(c1)
t2.conditions.append(c2)
r1 = TestRunData()
r2 = TestRunData()
r1.appname = "One"
r2.appname = "One"
self.assertTrue(r1 == r2)
r1.testcases.append(t1)
self.assertFalse(r1 == r2)
r2.testcases.append(t2)
self.assertTrue(r1 == r2)
c3 = TestConditionData()
c3.filenamePrefix = "..\\..\\Fail"
t2.conditions.append(c3)
self.assertFalse(r1 == r2)
def testStartOfTestRunIsFound(self):
obj = TestRunApprovedParser()
line = "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
result = obj.parseApprovedLine(line)
self.assertTrue(result == None)
def testTestRunVersionIsSet(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options" ]
for line in lines:
result = obj.parseApprovedLine(line)
#print obj
self.assertTrue(result == None)
self.assertTrue(obj.current.appname == "CatchSelfTest")
self.assertTrue(obj.current.version == "<version>")
def testTestRunParsesTestCase(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:"
" \"hello\" == \"world\""]
for line in lines:
result = obj.parseApprovedLine(line)
#print obj
self.assertTrue(obj.testcaseParser.conditionParser.current.filename == "ClassTests.cpp" )
self.assertTrue(obj.testcaseParser.conditionParser.current.lineNumber == "line number" )
self.assertTrue(obj.testcaseParser.conditionParser.current.reason == "FAILED" )
def testTestRunAddsTestCase(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:"
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------"
]
for line in lines:
result = obj.parseApprovedLine(line)
#print obj
self.assertTrue( result == None )
self.assertTrue( len(obj.current.testcases) == 1 )
self.assertTrue(obj.current.testcases[0].filename == "ClassTests.cpp" )
self.assertTrue(obj.current.testcases[0].lineNumber == "line number" )
self.assertTrue( len(obj.current.testcases[0].conditions) == 1 )
self.assertTrue(obj.current.testcases[0].conditions[0].filename == "ClassTests.cpp" )
self.assertTrue(obj.current.testcases[0].conditions[0].lineNumber == "line number" )
self.assertTrue(obj.current.testcases[0].conditions[0].reason == "FAILED" )
def testTestRunParsesTwoTestCases(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------",
"./failing/Fixture/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( m_a == 2 )",
"with expansion:",
" 1 == 2",
"",
"===============================================================================",
"122 test cases - 35 failed (753 assertions - 90 failed)",
""
]
testRun = None
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestRunData):
testRun = result
self.assertTrue( isinstance(testRun, TestRunData) )
newLines = testRun.generateApprovedLines()
#for line in newLines:
# print "L:",line
#print len(lines),",",len(newLines)
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testTestRunWithRandomOutput(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"MiscTests.cpp:<line number>: FAILED:",
"explicitly with message:",
" to infinity and beyond",
"",
"Message from section one",
"Message from section two",
"Some information",
"An error",
"Message from section one",
"Message from section two",
"Some information",
"An error",
"hello",
"hello",
"===============================================================================",
"122 test cases - 35 failed (753 assertions - 90 failed)",
""
]
testRun = None
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestRunData):
testRun = result
self.assertTrue( isinstance(testRun, TestRunData) )
#print "O:",result.outputLine
self.assertTrue( testRun.outputLine == 14 )
newLines = testRun.generateApprovedLines()
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testRunBasicResult(self):
obj = TestRunResultParser()
lines = [ "Message from section one",
"Message from section two",
"Some information",
"An error",
"Message from section one",
"Message from section two",
"Some information",
"An error",
"hello",
"hello",
"",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"TestCatch.exe is a Catch v1.0 b13 host application.",
"Run with -? for options",
"",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"..\..\..\SelfTest\ClassTests.cpp(34)",
"...............................................................................",
"",
"..\..\..\SelfTest\ClassTests.cpp(28): FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"===============================================================================",
"122 test cases - 35 failed (753 assertions - 90 failed)",
""
]
testRun = None
for line in lines:
result = obj.parseResultLine(line)
if isinstance(result, TestRunData):
testRun = result
self.assertTrue( isinstance(testRun, TestRunData) )
#print "O:",testRun.outputLine
self.assertTrue( testRun.outputLine == 0 )
newLines = testRun.generateResultLines()
#for line in newLines:
# print line
self.assertTrue( len(lines) == len(newLines) )
self.assertTrue( lines == newLines )
def testTestRunSorted(self):
obj = TestRunApprovedParser()
lines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"-------------------------------------------------------------------------------",
"./failing/Fixture/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( m_a == 2 )",
"with expansion:",
" 1 == 2",
"",
"===============================================================================",
"122 test cases - 35 failed (753 assertions - 90 failed)",
""
]
testRun = None
for line in lines:
result = obj.parseApprovedLine(line)
if isinstance(result, TestRunData):
testRun = result
self.assertTrue( isinstance(testRun, TestRunData) )
newLines = testRun.generateSortedApprovedLines()
#for line in newLines:
# print "L:",line
#print len(lines),",",len(newLines)
expectedLines = [ "",
"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",
"CatchSelfTest is a <version> host application.",
"Run with -? for options",
"",
"-------------------------------------------------------------------------------",
"./failing/Fixture/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( m_a == 2 )",
"with expansion:",
" 1 == 2",
"",
"-------------------------------------------------------------------------------",
"./failing/TestClass/failingCase",
"-------------------------------------------------------------------------------",
"ClassTests.cpp:<line number>",
"...............................................................................",
"",
"ClassTests.cpp:<line number>: FAILED:",
" REQUIRE( s == \"world\" )",
"with expansion:",
" \"hello\" == \"world\"",
"",
"===============================================================================",
"122 test cases - 35 failed (753 assertions - 90 failed)",
""
]
self.assertTrue( len(expectedLines) == len(newLines) )
self.assertTrue( expectedLines == newLines )
if __name__ == '__main__':
unittest.main()