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 Release
ipch ipch
TestResults TestResults
projects/VS2010/TestCatch/Visual Lint
projects/VS2010/ManagedTestCatch/Visual Lint
projects/VS2012/ManagedTestCatch/Visual Lint
projects/VS2012/NativeTestCatch/Visual Lint
DebugMbcs
ReleaseMbcs
*.user *.user
*.xcuserstate *.xcuserstate
*.o *.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 # 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 # 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. 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. 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 #if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR
#define INTERNAL_CATCH_VS_MANAGED #define INTERNAL_CATCH_VS_MANAGED
#define INTERNAL_CATCH_INLINE inline
#else #else
#if defined(_WINDLL) #if defined(_WINDLL)
@ -26,6 +27,7 @@
// It's possible that this is not enough for someone so allow it to be overridden... // 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 ) #if !defined( CATCH_CONFIG_MAIN ) && !defined( CATCH_CONFIG_RUNNER )
#define INTERNAL_CATCH_VS_NATIVE #define INTERNAL_CATCH_VS_NATIVE
#define INTERNAL_CATCH_INLINE inline
#endif #endif
#endif #endif
@ -52,7 +54,6 @@
#endif #endif
#if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE) #if defined(INTERNAL_CATCH_VS_MANAGED) || defined(INTERNAL_CATCH_VS_NATIVE)
#define INTERNAL_CATCH_INLINE inline
#ifdef INTERNAL_CATCH_VS_MANAGED #ifdef INTERNAL_CATCH_VS_MANAGED
#include "internal/catch_vs_managed_impl.hpp" #include "internal/catch_vs_managed_impl.hpp"
#else // INTERNAL_CATCH_VS_MANAGED #else // INTERNAL_CATCH_VS_MANAGED
@ -203,6 +204,16 @@
#define THEN( desc ) SECTION( " Then: " desc, "" ) #define THEN( desc ) SECTION( " Then: " desc, "" )
#define AND_THEN( desc ) SECTION( " And: " 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; using Catch::Detail::Approx;
#ifdef __clang__ #ifdef __clang__

View File

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

View File

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

View File

@ -22,6 +22,138 @@
#define CATCH_CONFIG_CONSOLE_WIDTH 80 #define CATCH_CONFIG_CONSOLE_WIDTH 80
#endif #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 { namespace Catch {
struct ConfigData { struct ConfigData {
@ -41,6 +173,21 @@ namespace Catch {
showDurations( ShowDurations::DefaultForReporter ) 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 listTests;
bool listTags; bool listTags;
bool listReporters; bool listReporters;

View File

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

View File

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

View File

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

View File

@ -41,6 +41,23 @@ namespace Catch {
virtual std::string getCurrentTestName() const = 0; virtual std::string getCurrentTestName() const = 0;
virtual const AssertionResult* getLastResult() 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 #endif // TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED

View File

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

View File

@ -16,64 +16,68 @@
namespace Catch { namespace Catch {
namespace { class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
class RegistryHub : public IRegistryHub, public IMutableRegistryHub { RegistryHub( RegistryHub const& );
void operator=( RegistryHub const& );
RegistryHub( RegistryHub const& ); public: // IRegistryHub
void operator=( RegistryHub const& ); RegistryHub() {
}
virtual IReporterRegistry const& getReporterRegistry() const {
return m_reporterRegistry;
}
virtual ITestCaseRegistry const& getTestCaseRegistry() const {
return m_testCaseRegistry;
}
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() {
return m_exceptionTranslatorRegistry;
}
public: // IRegistryHub public: // IMutableRegistryHub
RegistryHub() { virtual void registerReporter( std::string const& name, IReporterFactory* factory ) {
} m_reporterRegistry.registerReporter( name, factory );
virtual IReporterRegistry const& getReporterRegistry() const { }
return m_reporterRegistry; virtual void registerTest( TestCase const& testInfo ) {
} m_testCaseRegistry.registerTest( testInfo );
virtual ITestCaseRegistry const& getTestCaseRegistry() const { }
return m_testCaseRegistry; virtual void registerTranslator( const IExceptionTranslator* translator ) {
} m_exceptionTranslatorRegistry.registerTranslator( translator );
virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() { }
return m_exceptionTranslatorRegistry;
}
public: // IMutableRegistryHub private:
virtual void registerReporter( std::string const& name, IReporterFactory* factory ) { TestRegistry m_testCaseRegistry;
m_reporterRegistry.registerReporter( name, factory ); ReporterRegistry m_reporterRegistry;
} ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
virtual void registerTest( TestCase const& testInfo ) { };
m_testCaseRegistry.registerTest( testInfo );
}
virtual void registerTranslator( const IExceptionTranslator* translator ) {
m_exceptionTranslatorRegistry.registerTranslator( translator );
}
private: // Single, global, instance
TestRegistry m_testCaseRegistry; template <typename T>
ReporterRegistry m_reporterRegistry; struct GlobalRegistryHub
ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; {
}; static T*& instance()
{
// Single, global, instance
inline RegistryHub*& getTheRegistryHub() {
static RegistryHub* theRegistryHub = NULL;
if( !theRegistryHub ) if( !theRegistryHub )
theRegistryHub = new RegistryHub(); theRegistryHub = new T();
return theRegistryHub; return theRegistryHub;
} }
} static T* theRegistryHub;
};
template <typename T>
T* GlobalRegistryHub<T>::theRegistryHub = NULL;
IRegistryHub& getRegistryHub() { INTERNAL_CATCH_INLINE IRegistryHub& getRegistryHub() {
return *getTheRegistryHub(); return *GlobalRegistryHub<RegistryHub>::instance();
} }
IMutableRegistryHub& getMutableRegistryHub() { INTERNAL_CATCH_INLINE IMutableRegistryHub& getMutableRegistryHub() {
return *getTheRegistryHub(); return *GlobalRegistryHub<RegistryHub>::instance();
} }
void cleanUp() { INTERNAL_CATCH_INLINE void cleanUp() {
delete getTheRegistryHub(); delete GlobalRegistryHub<RegistryHub>::instance();
getTheRegistryHub() = NULL; GlobalRegistryHub<RegistryHub>::instance() = NULL;
cleanUpContext(); cleanUpContext();
} }
std::string translateActiveException() { INTERNAL_CATCH_INLINE std::string translateActiveException() {
return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
} }

View File

@ -48,7 +48,6 @@ namespace Catch {
}; };
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
class RunContext : public IResultCapture, public IRunner { class RunContext : public IResultCapture, public IRunner {
RunContext( RunContext const& ); RunContext( RunContext const& );
@ -105,18 +104,16 @@ namespace Catch {
} }
Totals runTest( TestCase const& testCase ) { Totals runTest( TestCase const& testCase ) {
Totals prevTotals = m_totals;
std::string redirectedCout; std::string redirectedCout;
std::string redirectedCerr; std::string redirectedCerr;
TestCaseInfo testInfo = testCase.getTestCaseInfo(); TestCaseInfo testInfo = testCase.getTestCaseInfo();
m_reporter->testCaseStarting( testInfo ); UnwindTestCaseOnCompletion finaliser(*this, m_totals, m_reporter, testInfo, redirectedCout, redirectedCerr);
m_activeTestCase = &testCase; m_activeTestCase = &testCase;
m_testCaseTracker = TestCaseTracker( testInfo.name ); m_testCaseTracker = TestCaseTracker( testInfo.name );
do { do {
do { do {
runCurrentTest( redirectedCout, redirectedCerr ); runCurrentTest( redirectedCout, redirectedCerr );
@ -125,18 +122,10 @@ namespace Catch {
} }
while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); 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_activeTestCase = NULL;
m_testCaseTracker.reset(); m_testCaseTracker.reset();
return deltaTotals; return finaliser.report();
} }
Ptr<IConfig const> config() const { Ptr<IConfig const> config() const {
@ -194,12 +183,7 @@ namespace Catch {
return true; return true;
} }
virtual void sectionEnded( SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) { void unwindSection(SectionInfo const& info, Counts const& prevAssertions, double _durationInSeconds ) {
if( std::uncaught_exception() ) {
m_unfinishedSections.push_back( UnfinishedSections( info, prevAssertions, _durationInSeconds ) );
return;
}
Counts assertions = m_totals.assertions - prevAssertions; Counts assertions = m_totals.assertions - prevAssertions;
bool missingAssertions = testForMissingAssertions( assertions ); bool missingAssertions = testForMissingAssertions( assertions );
@ -209,6 +193,15 @@ namespace Catch {
m_messages.clear(); 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 ) { virtual void pushScopedMessage( MessageInfo const& message ) {
m_messages.push_back( message ); m_messages.push_back( message );
} }
@ -257,16 +250,13 @@ namespace Catch {
void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo );
m_reporter->sectionStarting( testCaseSection ); UnwindSectionOnCompletion finaliser(*this, m_totals, m_reporter, testCaseInfo, m_unfinishedSections, m_messages);
Counts prevAssertions = m_totals.assertions;
double duration = 0;
try { try {
m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
TestCaseTracker::Guard guard( *m_testCaseTracker ); TestCaseTracker::Guard guard( *m_testCaseTracker );
Timer timer; finaliser.startTimer();
timer.start();
if( m_reporter->getPreferences().shouldRedirectStdOut ) { if( m_reporter->getPreferences().shouldRedirectStdOut ) {
StreamRedirect coutRedir( std::cout, redirectedCout ); StreamRedirect coutRedir( std::cout, redirectedCout );
StreamRedirect cerrRedir( std::cerr, redirectedCerr ); StreamRedirect cerrRedir( std::cerr, redirectedCerr );
@ -275,37 +265,16 @@ namespace Catch {
else { else {
m_activeTestCase->invoke(); m_activeTestCase->invoke();
} }
duration = timer.getElapsedSeconds(); finaliser.stopTimer();
} }
#ifdef INTERNAL_CATCH_VS_MANAGED // detect CLR catch( const Catch::TestFailureException& ) {
catch(AssertFailedException^) {
throw; // CLR always rethrows - stop on first assert
}
#else
catch( INTERNAL_CATCH_TEST_FAILURE_EXCEPTION ) {
// This just means the test was aborted due to failure // This just means the test was aborted due to failure
} }
#endif
catch(...) { catch(...) {
ExpressionResultBuilder exResult( ResultWas::ThrewException ); ExpressionResultBuilder exResult( ResultWas::ThrewException );
exResult << translateActiveException(); exResult << translateActiveException();
actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); 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: private:
@ -319,6 +288,111 @@ namespace Catch {
double durationInSeconds; 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; TestRunInfo m_runInfo;
IMutableContext& m_context; IMutableContext& m_context;
TestCase const* m_activeTestCase; TestCase const* m_activeTestCase;

View File

@ -8,7 +8,11 @@
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED #ifndef TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
#define 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" #include "catch_test_registry.hpp"
#endif
#include "catch_test_case_info.h" #include "catch_test_case_info.h"
#include "catch_test_spec.h" #include "catch_test_spec.h"
#include "catch_context.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, SourceLineInfo const& lineInfo,
NameAndDesc const& nameAndDesc ) { NameAndDesc const& nameAndDesc ) {
registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); 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, char const* classOrQualifiedMethodName,
NameAndDesc const& nameAndDesc, NameAndDesc const& nameAndDesc,
SourceLineInfo const& lineInfo ) { SourceLineInfo const& lineInfo ) {

View File

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

View File

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

View File

@ -18,7 +18,7 @@ using namespace System::Collections::Generic;
using namespace Microsoft::VisualStudio::TestTools::UnitTesting; using namespace Microsoft::VisualStudio::TestTools::UnitTesting;
namespace Catch { 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()); String^ result = gcnew String(s.c_str());
return result; return result;
@ -33,67 +33,50 @@ namespace Catch {
#include "catch_section.hpp" #include "catch_section.hpp"
#include "internal/catch_timer.hpp" #include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp" #include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.hpp" #include "reporters/catch_vs_reporter.hpp"
#include "catch_registry_hub.hpp"
#include "internal/catch_exception_translator_registry.hpp" #include "internal/catch_console_colour_impl.hpp"
#include "catch_runner.hpp"
namespace Catch { 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& ); inline Matchers::Impl::StdString::Equals::~Equals() {}
void operator=( ExceptionRegistryHub const& ); inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
public: // IRegistryHub inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
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 void Config::dummy() {}
} }
#endif #endif
#endif // TWOBLUECUBES_CATCH_VS_MANAGED_HPP_INCLUDED #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::Assert;
using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo; using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#define INTERNAL_CATCH_INLINE inline
#include <cvt/wstring> #include <cvt/wstring>
#include <codecvt> #include <codecvt>
@ -26,66 +24,50 @@ using Microsoft::VisualStudio::CppUnitTestFramework::__LineInfo;
#include "catch_tags.hpp" #include "catch_tags.hpp"
#include "catch_test_spec.hpp" #include "catch_test_spec.hpp"
#include "catch_section.hpp" #include "catch_section.hpp"
#include "internal/catch_timer.hpp"
#include "internal/catch_vs_test_registry.hpp" #include "internal/catch_vs_test_registry.hpp"
#include "internal/catch_reporter_registrars.hpp"
#include "reporters/catch_vs_reporter.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 { 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& ); inline Matchers::Impl::StdString::Equals::~Equals() {}
void operator=( ExceptionRegistryHub const& ); inline Matchers::Impl::StdString::Contains::~Contains() {}
inline Matchers::Impl::StdString::StartsWith::~StartsWith() {}
public: // IRegistryHub inline Matchers::Impl::StdString::EndsWith::~EndsWith() {}
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 void Config::dummy() {}
} }
#endif // INTERNAL_CATCH_VS_NATIVE #endif // INTERNAL_CATCH_VS_NATIVE

View File

@ -16,27 +16,11 @@
#include "catch_common.h" #include "catch_common.h"
#include "catch_interfaces_testcase.h" #include "catch_interfaces_testcase.h"
#include "internal/catch_compiler_capabilities.h" #include "internal/catch_compiler_capabilities.h"
#include "internal/clara.h"
#include <tchar.h> #include <tchar.h>
namespace Catch { 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> { class MethodTestCase : public SharedImpl<ITestCase> {
struct placeholder struct placeholder
@ -79,7 +63,7 @@ private:
typedef void(*TestFunction)(); typedef void(*TestFunction)();
struct NameAndDesc { struct NameAndDesc {
#if (_MANAGED == 1) || (_M_CEE == 1) // detect CLR #ifdef INTERNAL_CATCH_VS_MANAGED
NameAndDesc( const char* _name = "", const char* _description= "" ) NameAndDesc( const char* _name = "", const char* _description= "" )
: name( _name ), description( _description ) : name( _name ), description( _description )
{} {}
@ -90,14 +74,35 @@ struct NameAndDesc {
NameAndDesc( const wchar_t* _name, const char* _description= "" ) NameAndDesc( const wchar_t* _name, const char* _description= "" )
: name(), description( _description ) : name(), description( _description )
{ {
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1; assignName(_name);
name = conv1.to_bytes(_name);
} }
NameAndDesc( const wchar_t* _name, int ) NameAndDesc( const wchar_t* _name, int )
: name(), description( "" ) : name(), description( "" )
{
assignName(_name);
}
void assignName(const wchar_t* _name)
{ {
stdext::cvt::wstring_convert<std::codecvt_utf8<wchar_t> > conv1; 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 #endif
@ -105,9 +110,38 @@ struct NameAndDesc {
std::string description; 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 } // 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_PARAM2( name ) name##""
#define CATCH_INTERNAL_HANDLE_EMPTY_PARAM(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM2( INTERNAL_CATCH_SPLIT_ARGS_2(__VA_ARGS__) ) #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 CATCH_INTERNAL_NAMESPACE( Ext )
#define INTERNAL_CATCH_TEST_METHOD( Method, UniqueExt, Name, Desc ) \ #define INTERNAL_CATCH_TEST_METHOD( Count, UniqueExt, Name, Desc ) \
public: \ public: \
[TestMethod] \ [TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \ [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) () \ 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::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: \ public: \
[TestMethod] \ [TestMethod] \
[Description( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \ [TestCategory( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) )] \
[TestProperty( "Description", CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) )] \ [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) () \ [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) ()
Catch::NameAndDesc name_desc( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name), Desc ); \
CATCH_INTERNAL_RUN_SINGLE_CLASS_TEST( Method ); \
}
#define CHECK_FOR_TEST_CASE_CLASH #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 #else // detect CLR
// Native tests // Native tests
@ -173,99 +209,161 @@ struct NameAndDesc {
#define TEST_IMPL_2(tuple) TEST_IMPL2 tuple #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 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(...) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPLW( (__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_IMPLW(tuple) CATCH_INTERNAL_HANDLE_EMPTY_PARAM_IMPL2W tuple #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 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: \ public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \ 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_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \ TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Name) ) \
END_TEST_METHOD_ATTRIBUTE() \ END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \ 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::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: \ public: \
BEGIN_TEST_METHOD_ATTRIBUTE( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \ 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_OWNER( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAMW(Name) ) \ TEST_DESCRIPTION( CATCH_INTERNAL_HANDLE_EMPTY_PARAM(Tags) ) \
END_TEST_METHOD_ATTRIBUTE() \ END_TEST_METHOD_ATTRIBUTE() \
TEST_METHOD( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H___M_E_T_H_O_D___, UniqueExt) ) \ 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 ); \
}
#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 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 #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 ) \ #define CATCH_INTERNAL_CONFIG_SHOW_SUCCESS2( v, Count ) \
{ Catch::ConfigData cd; \ 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.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::Ptr<Catch::Config> config(new Catch::Config(cd)); \
Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \ Catch::MSTestReporter* rep = new Catch::MSTestReporter(config.get()); \
Catch::RunContext tr(config.get(), rep); \ Catch::RunContext tr(config.get(), rep); \
Catch::TestCase tc = Catch::makeTestCase( new Catch::FreeFunctionTestCase( & Method ), "", name_desc.name, name_desc.description, CATCH_INTERNAL_LINEINFO ); \ std::vector<Catch::TestCase> testCase = Catch::getRegistryHub().getTestCaseRegistry().getMatchingTestCases(name_desc.name); \
tr.runTest(tc); \ 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 ) \ #define INTERNAL_CATCH_TESTCASE2( Count, Name, Desc ) \
{ 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 ) \
CHECK_FOR_TEST_CASE_CLASH \ CHECK_FOR_TEST_CASE_CLASH \
static void INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____, 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( UniqueExt ) { \ namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ 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_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 \ CHECK_FOR_TEST_CASE_CLASH \
namespace CATCH_INTERNAL_NAMESPACE( UniqueExt ) { \ namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ 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_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 \ 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(); \ 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 ) { \ namespace CATCH_INTERNAL_NAMESPACE( INTERNAL_CATCH_CONCAT_LINE_COUNTER( Count ) ) { \
INTERNAL_CATCH_CLASS_DEFINITION( INTERNAL_CATCH_UNIQUE_NAME_LINE( C_A_T_C_H____T_E_S_T____C_L_A_S_S___, UniqueExt ) ) \ 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_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 //#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_SPLIT_TAGS_IMPL_(INTERNAL_CATCH_SPLIT_ARG_1,INTERNAL_CATCH_SPLIT_ARG_2,N,...) INTERNAL_CATCH_SPLIT_ARG_2
#define INTERNAL_CATCH_TESTCASE( ... ) \ #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, ... ) \ #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, ... )\ #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 #else
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
#define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ #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 ) \ #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 )\ #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 #endif
@ -320,51 +418,6 @@ struct NameAndDesc {
#include "catch_exception_translator_registry.hpp" #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__ #ifdef __clang__
#pragma clang diagnostic pop #pragma clang diagnostic pop
#endif #endif

View File

@ -46,15 +46,27 @@ namespace Catch {
#endif // detect CLR #endif // detect CLR
struct MSTestReporter : SharedImpl<IStreamingReporter> { 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 ) MSTestReporter( Ptr<IConfig> const& _fullConfig )
: m_config( _fullConfig ), : m_config( _fullConfig ),
m_headerPrinted( false ), m_headerPrinted( false ),
m_atLeastOneTestCasePrinted( false ) m_atLeastOneTestCasePrinted( false ),
m_failed(0)
{} {}
virtual ~MSTestReporter() { virtual ~MSTestReporter() {
if( m_atLeastOneTestCasePrinted ) { if( m_atLeastOneTestCasePrinted ) {
write_output_message(stream.str()); 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(_testCaseStats.stdErr);
write_output_message(getDoubleDashes()); 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; m_headerPrinted = false;
currentTestCaseInfo.reset(); currentTestCaseInfo.reset();
assert( m_sectionStack.empty() ); assert( m_sectionStack.empty() );
@ -141,6 +150,7 @@ namespace Catch {
printTotalsDivider(); printTotalsDivider();
printTotals( _testRunStats.totals ); printTotals( _testRunStats.totals );
stream << "\r\n" << "\r\n"; stream << "\r\n" << "\r\n";
m_failed = _testRunStats.totals.testCases.failed;
currentTestCaseInfo.reset(); currentTestCaseInfo.reset();
currentGroupInfo.reset(); currentGroupInfo.reset();
currentTestRunInfo.reset(); currentTestRunInfo.reset();
@ -448,6 +458,7 @@ namespace Catch {
std::vector<SectionInfo> m_sectionStack; std::vector<SectionInfo> m_sectionStack;
bool m_headerPrinted; bool m_headerPrinted;
bool m_atLeastOneTestCasePrinted; bool m_atLeastOneTestCasePrinted;
size_t m_failed;
}; };
} // end namespace Catch } // end namespace Catch

View File

@ -15,21 +15,24 @@ namespace Counter {
int g_haveCountedMessages = 0; int g_haveCountedMessages = 0;
} }
// This test works with the equivalent in MessageInstantiationTests2.cpp namespace MI1
// 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
// greedy instantiation (or whatever process it uses) eliminate all other
// references to the globalCount
TEST_CASE("message counting1","")
{ {
if( Counter::g_haveCountedMessages > 0 ) { // This test works with the equivalent in MessageInstantiationTests2.cpp
REQUIRE( Catch::MessageInfoCounter<unsigned int>::globalCount > 0 ); // 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
else // greedy instantiation (or whatever process it uses) eliminate all other
// references to the globalCount
TEST_CASE("message counting1","")
{ {
++Catch::MessageInfoCounter<unsigned int>::globalCount; if( Counter::g_haveCountedMessages > 0 ) {
Counter::g_haveCountedMessages = 1; REQUIRE( Catch::MessageInfoCounter<unsigned int>::globalCount > 0 );
}
else
{
++Catch::MessageInfoCounter<unsigned int>::globalCount;
Counter::g_haveCountedMessages = 1;
}
} }
} }
@ -37,14 +40,17 @@ namespace LongCounter {
int g_haveCountedMessagesLong = 0; int g_haveCountedMessagesLong = 0;
} }
TEST_CASE("long message counting1","") namespace MI1
{ {
if( LongCounter::g_haveCountedMessagesLong > 0 ) { TEST_CASE("long message counting1","")
REQUIRE( Catch::MessageInfoCounter<long>::globalCount > 0 );
}
else
{ {
++Catch::MessageInfoCounter<long>::globalCount; if( LongCounter::g_haveCountedMessagesLong > 0 ) {
LongCounter::g_haveCountedMessagesLong = 1; REQUIRE( Catch::MessageInfoCounter<long>::globalCount > 0 );
}
else
{
++Catch::MessageInfoCounter<long>::globalCount;
LongCounter::g_haveCountedMessagesLong = 1;
}
} }
} }

View File

@ -14,21 +14,24 @@ namespace Counter {
extern int g_haveCountedMessages; extern int g_haveCountedMessages;
} }
// This test works with the equivalent in MessageInstantiationTests1.cpp namespace MI2
// 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
// greedy instantiation (or whatever process it uses) eliminate all other
// references to the globalCount
TEST_CASE("message counting2","")
{ {
if( Counter::g_haveCountedMessages > 0 ) { // This test works with the equivalent in MessageInstantiationTests1.cpp
REQUIRE( Catch::MessageInfoCounter<unsigned int>::globalCount > 0 ); // 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
else // greedy instantiation (or whatever process it uses) eliminate all other
// references to the globalCount
TEST_CASE("message counting2","")
{ {
++Catch::MessageInfoCounter<unsigned int>::globalCount; if( Counter::g_haveCountedMessages > 0 ) {
Counter::g_haveCountedMessages = 1; REQUIRE( Catch::MessageInfoCounter<unsigned int>::globalCount > 0 );
}
else
{
++Catch::MessageInfoCounter<unsigned int>::globalCount;
Counter::g_haveCountedMessages = 1;
}
} }
} }
@ -36,14 +39,17 @@ namespace LongCounter {
extern int g_haveCountedMessagesLong; extern int g_haveCountedMessagesLong;
} }
TEST_CASE("long message counting2","") namespace MI2
{ {
if( LongCounter::g_haveCountedMessagesLong > 0 ) { TEST_CASE("long message counting2","")
REQUIRE( Catch::MessageInfoCounter<long>::globalCount > 0 );
}
else
{ {
++Catch::MessageInfoCounter<long>::globalCount; if( LongCounter::g_haveCountedMessagesLong > 0 ) {
LongCounter::g_haveCountedMessagesLong = 1; REQUIRE( Catch::MessageInfoCounter<long>::globalCount > 0 );
}
else
{
++Catch::MessageInfoCounter<long>::globalCount;
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"; std::string testString = "one two three four";
SECTION( "No wrapping", "" ) { SECTION( "No wrapping", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
} }
SECTION( "Wrapped once", "" ) { SECTION( "Wrapped once", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 17 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 16 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 14 ) ).toString() == "one two three\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 13 ) ).toString() == "one two three\nfour" ); CHECK( Catch::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( 12 ) ).toString() == "one two\nthree four" );
} }
SECTION( "Wrapped twice", "" ) { SECTION( "Wrapped twice", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); CHECK( Catch::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( 7 ) ).toString() == "one two\nthree\nfour" );
} }
SECTION( "Wrapped three times", "" ) { SECTION( "Wrapped three times", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 6 ) ).toString() == "one\ntwo\nthree\nfour" ); CHECK( Catch::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( 5 ) ).toString() == "one\ntwo\nthree\nfour" );
} }
SECTION( "Short wrap", "" ) { SECTION( "Short wrap", "" ) {
CHECK( Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" ); CHECK( Catch::Text( "abcdef", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef" );
CHECK( Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" ); CHECK( Catch::Text( "abcdefg", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndefg" );
CHECK( Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" ); CHECK( Catch::Text( "abcdefgh", TextAttributes().setWidth( 4 ) ).toString() == "abc-\ndef-\ngh" );
CHECK( Text( testString, TextAttributes().setWidth( 4 ) ).toString() == "one\ntwo\nthr-\nee\nfour" ); CHECK( Catch::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( 3 ) ).toString() == "one\ntwo\nth-\nree\nfo-\nur" );
} }
SECTION( "As container", "" ) { SECTION( "As container", "" ) {
Text text( testString, TextAttributes().setWidth( 6 ) ); Catch::Text text( testString, TextAttributes().setWidth( 6 ) );
REQUIRE( text.size() == 4 ); REQUIRE( text.size() == 4 );
CHECK( text[0] == "one" ); CHECK( text[0] == "one" );
CHECK( text[1] == "two" ); CHECK( text[1] == "two" );
@ -382,7 +382,7 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
CHECK( text[3] == "four" ); CHECK( text[3] == "four" );
} }
SECTION( "Indent first line differently", "" ) { SECTION( "Indent first line differently", "" ) {
Text text( testString, TextAttributes() Catch::Text text( testString, TextAttributes()
.setWidth( 10 ) .setWidth( 10 )
.setIndent( 4 ) .setIndent( 4 )
.setInitialIndent( 1 ) ); .setInitialIndent( 1 ) );
@ -397,22 +397,22 @@ TEST_CASE( "Long strings can be wrapped", "[wrap]" ) {
std::string testString = "one two\nthree four"; std::string testString = "one two\nthree four";
SECTION( "No wrapping" , "" ) { SECTION( "No wrapping" , "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 80 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 18 ) ).toString() == testString );
CHECK( Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 10 ) ).toString() == testString );
} }
SECTION( "Trailing newline" , "" ) { SECTION( "Trailing newline" , "" ) {
CHECK( Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" ); CHECK( Catch::Text( "abcdef\n", TextAttributes().setWidth( 10 ) ).toString() == "abcdef\n" );
CHECK( Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" ); CHECK( Catch::Text( "abcdef", TextAttributes().setWidth( 6 ) ).toString() == "abcdef" );
CHECK( Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" ); CHECK( Catch::Text( "abcdef\n", TextAttributes().setWidth( 6 ) ).toString() == "abcdef\n" );
} }
SECTION( "Wrapped once", "" ) { SECTION( "Wrapped once", "" ) {
CHECK( Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" ); CHECK( Catch::Text( testString, TextAttributes().setWidth( 9 ) ).toString() == "one two\nthree\nfour" );
CHECK( Text( testString, TextAttributes().setWidth( 8 ) ).toString() == "one two\nthree\nfour" ); CHECK( Catch::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( 7 ) ).toString() == "one two\nthree\nfour" );
} }
SECTION( "Wrapped twice", "" ) { 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 // guide: 1234567890123456789
std::string testString = "one two \tthree four five six"; 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" ); == "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", "" ) { 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; TextAttributes narrow;
narrow.setWidth( 6 ); 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]" ) { TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) {
@ -537,7 +537,7 @@ TEST_CASE( "Long text is truncted", "[Text][Truncated]" ) {
std::ostringstream oss; std::ostringstream oss;
for(int i = 0; i < 600; ++i ) for(int i = 0; i < 600; ++i )
oss << longLine << longLine << "\n"; oss << longLine << longLine << "\n";
Text t( oss.str() ); Catch::Text t( oss.str() );
CHECK_THAT( t.toString(), EndsWith( "... message truncated due to excessive size" ) ); 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 TEST_CASE
@ -209,177 +209,180 @@ namespace ObjectWithNonConstEqualityOperator
} }
} }
namespace EnumBitFieldTests namespace TrickyTests
{ {
enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006, namespace EnumBitFieldTests
bit30 = 0x40000000, bit31 = 0x80000000,
bit30and31 = 0xc0000000};
TEST_CASE( "Test enum bit values", "[Tricky]" )
{ {
REQUIRE( 0xc0000000 == bit30and31 ); enum Bits {bit0 = 0x0001, bit1 = 0x0002, bit2 = 0x0004, bit3 = 0x0008, bit1and2 = 0x0006,
} bit30 = 0x40000000, bit31 = 0x80000000,
} bit30and31 = 0xc0000000};
struct Obj TEST_CASE( "Test enum bit values", "[Tricky]" )
{ {
Obj():prop(&p){} REQUIRE( 0xc0000000 == bit30and31 );
}
}
struct Obj
{
Obj():prop(&p){}
int p; int p;
int* prop; int* prop;
}; };
TEST_CASE("boolean member", "[Tricky]") TEST_CASE("boolean member", "[Tricky]")
{
Obj obj;
REQUIRE( obj.prop != NULL );
}
// Tests for a problem submitted by Ralph McArdell
//
// The static bool value should not need to be defined outside the
// struct it is declared in - but when evaluating it in a deduced
// context it appears to require the extra definition.
// The issue was fixed by adding bool overloads to bypass the
// templates that were there to deduce it.
template <bool B>
struct is_true
{
static const bool value = B;
};
TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" )
{
SECTION("compare to true","")
{ {
REQUIRE( is_true<true>::value == true ); Obj obj;
REQUIRE( true == is_true<true>::value ); REQUIRE( obj.prop != NULL );
}
SECTION("compare to false","")
{
REQUIRE( is_true<false>::value == false );
REQUIRE( false == is_true<false>::value );
} }
SECTION("negation", "") // Tests for a problem submitted by Ralph McArdell
//
// The static bool value should not need to be defined outside the
// struct it is declared in - but when evaluating it in a deduced
// context it appears to require the extra definition.
// The issue was fixed by adding bool overloads to bypass the
// templates that were there to deduce it.
template <bool B>
struct is_true
{ {
REQUIRE( !is_true<false>::value ); static const bool value = B;
};
TEST_CASE( "(unimplemented) static bools can be evaluated", "[Tricky]" )
{
SECTION("compare to true","")
{
REQUIRE( is_true<true>::value == true );
REQUIRE( true == is_true<true>::value );
}
SECTION("compare to false","")
{
REQUIRE( is_true<false>::value == false );
REQUIRE( false == is_true<false>::value );
}
SECTION("negation", "")
{
REQUIRE( !is_true<false>::value );
}
SECTION("double negation","")
{
REQUIRE( !!is_true<true>::value );
}
SECTION("direct","")
{
REQUIRE( is_true<true>::value );
REQUIRE_FALSE( is_true<false>::value );
}
} }
SECTION("double negation","") // Uncomment these tests to produce an error at test registration time
/*
TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
{ {
REQUIRE( !!is_true<true>::value );
}
SECTION("direct","")
{
REQUIRE( is_true<true>::value );
REQUIRE_FALSE( is_true<false>::value );
}
}
// Uncomment these tests to produce an error at test registration time
/*
TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
{
} }
TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" ) TEST_CASE( "Tests with the same name are not allowed", "[Tricky]" )
{ {
} }
*/ */
struct Boolable struct Boolable
{ {
explicit Boolable( bool value ) : m_value( value ) {} explicit Boolable( bool value ) : m_value( value ) {}
operator Catch::SafeBool::type() const { operator Catch::SafeBool::type() const {
return Catch::SafeBool::makeSafe( m_value ); return Catch::SafeBool::makeSafe( m_value );
}
bool m_value;
};
TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" )
{
Boolable True( true );
Boolable False( false );
CHECK( True );
CHECK( !False );
CHECK_FALSE( False );
} }
bool m_value; TEST_CASE( "Assertions then sections", "[Tricky]" )
};
TEST_CASE( "Objects that evaluated in boolean contexts can be checked", "[Tricky][SafeBool]" )
{
Boolable True( true );
Boolable False( false );
CHECK( True );
CHECK( !False );
CHECK_FALSE( False );
}
TEST_CASE( "Assertions then sections", "[Tricky]" )
{
// This was causing a failure due to the way the console reporter was handling
// the current section
REQUIRE( Catch::isTrue( true ) );
SECTION( "A section", "" )
{ {
// This was causing a failure due to the way the console reporter was handling
// the current section
REQUIRE( Catch::isTrue( true ) ); REQUIRE( Catch::isTrue( true ) );
SECTION( "A section", "" )
{
REQUIRE( Catch::isTrue( true ) );
SECTION( "Another section", "" ) SECTION( "Another section", "" )
{ {
REQUIRE( Catch::isTrue( true ) ); REQUIRE( Catch::isTrue( true ) );
} }
SECTION( "Another other section", "" ) SECTION( "Another other section", "" )
{ {
REQUIRE( Catch::isTrue( true ) ); REQUIRE( Catch::isTrue( true ) );
}
} }
} }
struct Awkward
{
operator int() const { return 7; }
};
TEST_CASE( "non streamable - with conv. op", "[Tricky]" )
{
Awkward awkward;
std::string s = Catch::toString( awkward );
REQUIRE( s == "7" );
}
inline void foo() {}
typedef void (*fooptr_t)();
TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" )
{
// This was giving a warning in VS2010
// #179
fooptr_t a = foo;
REQUIRE( a );
REQUIRE( a == &foo );
}
class ClassName {};
TEST_CASE( "pointer to class", "[Tricky]" )
{
ClassName *p = 0;
REQUIRE( p == 0 );
}
#ifdef CATCH_CONFIG_CPP11_NULLPTR
#include <memory>
TEST_CASE( "null_ptr", "[Tricky]" )
{
std::unique_ptr<int> ptr;
REQUIRE(ptr.get() == nullptr);
}
#endif
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(""); }
} }
struct Awkward
{
operator int() const { return 7; }
};
TEST_CASE( "non streamable - with conv. op", "[Tricky]" )
{
Awkward awkward;
std::string s = Catch::toString( awkward );
REQUIRE( s == "7" );
}
inline void foo() {}
typedef void (*fooptr_t)();
TEST_CASE( "Comparing function pointers", "[Tricky][function pointer]" )
{
// This was giving a warning in VS2010
// #179
fooptr_t a = foo;
REQUIRE( a );
REQUIRE( a == &foo );
}
class ClassName {};
TEST_CASE( "pointer to class", "[Tricky]" )
{
ClassName *p = 0;
REQUIRE( p == 0 );
}
#ifdef CATCH_CONFIG_CPP11_NULLPTR
#include <memory>
TEST_CASE( "null_ptr", "[Tricky]" )
{
std::unique_ptr<int> ptr;
REQUIRE(ptr.get() == nullptr);
}
#endif
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 \ ExceptionTests.cpp \
GeneratorTests.cpp \ GeneratorTests.cpp \
MessageTests.cpp \ MessageTests.cpp \
MessageInstantiationTests1.cpp \
MessageInstantiationTests2.cpp \
MiscTests.cpp \ MiscTests.cpp \
TestMain.cpp \ TestMain.cpp \
TrickyTests.cpp \ TrickyTests.cpp \

View File

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

View File

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

View File

@ -63,6 +63,15 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp"> <ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </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>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">

View File

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

View File

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

View File

@ -63,6 +63,15 @@
<ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp"> <ClCompile Include="..\..\SelfTest\MessageInstantiationTests2.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </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>
<ItemGroup> <ItemGroup>
<ClInclude Include="stdafx.h"> <ClInclude Include="stdafx.h">

View File

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

View File

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

View File

@ -50,12 +50,6 @@
<ClCompile Include="..\..\SelfTest\GeneratorTests.cpp"> <ClCompile Include="..\..\SelfTest\GeneratorTests.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </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"> <ClCompile Include="..\..\SelfTest\MessageTests.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -68,5 +62,20 @@
<ClCompile Include="..\..\SelfTest\TrickyTests.cpp"> <ClCompile Include="..\..\SelfTest\TrickyTests.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </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> </ItemGroup>
</Project> </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()