Small fixes and started new section tracking code

This commit is contained in:
Phil Nash 2013-07-23 08:15:34 +01:00
parent f3d1f08c3b
commit 372a6c6fed
8 changed files with 294 additions and 13 deletions

View File

@ -62,8 +62,8 @@ namespace Catch {
std::map<std::string, IGeneratorsForTest*>::const_iterator it =
m_generatorsByTestName.find( testName );
return it != m_generatorsByTestName.end()
? it->second
: NULL;
? it->second
: NULL;
}
IGeneratorsForTest& getGeneratorsForCurrentTest() {

View File

@ -123,7 +123,8 @@ namespace Catch {
Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str isEqualToString:m_substr];
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
virtual std::string toString() const {
@ -135,7 +136,8 @@ namespace Catch {
Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location != NSNotFound;
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
virtual std::string toString() const {
@ -147,7 +149,8 @@ namespace Catch {
StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == 0;
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
virtual std::string toString() const {
@ -158,7 +161,8 @@ namespace Catch {
EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}
virtual std::string toString() const {

View File

@ -286,6 +286,8 @@ namespace Catch {
exResult << translateActiveException();
actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) );
}
// If sections ended prematurely due to an exception we stored their
// infos here so we can tear them down outside the unwind process.
for( std::vector<UnfinishedSections>::const_iterator it = m_unfinishedSections.begin(),
itEnd = m_unfinishedSections.end();
it != itEnd;

View File

@ -188,4 +188,5 @@ TEST_CASE( "cmdline" ) {
}
}
#endif

View File

@ -0,0 +1,265 @@
/*
* Created by Phil on 20/07/2013.
* Copyright 2013 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)
*/
#ifdef __clang__
#pragma clang diagnostic ignored "-Wpadded"
#endif
#include "catch.hpp"
using namespace Catch;
class TrackedSection;
typedef std::map<std::string, TrackedSection> TrackedSections;
class TrackedSection {
public:
enum RunState {
NotStarted,
Executing,
ExecutingChildren,
Completed
};
TrackedSection( std::string const& name, TrackedSection* parent )
: m_name( name ), m_runState( NotStarted ), m_parent( parent )
{}
RunState runState() const { return m_runState; }
void addChild( std::string const& childName ) {
m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
}
TrackedSection* getChild( std::string const& childName ) {
return &m_children.find( childName )->second;
}
void enter() {
if( m_runState == NotStarted )
m_runState = Executing;
}
void leave() {
for( TrackedSections::const_iterator it = m_children.begin(), itEnd = m_children.end();
it != itEnd;
++it )
if( it->second.runState() != Completed ) {
m_runState = ExecutingChildren;
return;
}
m_runState = Completed;
}
TrackedSection* getParent() {
return m_parent;
}
private:
std::string m_name;
RunState m_runState;
TrackedSections m_children;
TrackedSection* m_parent;
};
class SectionTracker {
public:
SectionTracker( std::string const& testCaseName )
: m_testCase( testCaseName, NULL ),
m_currentSection( NULL ),
m_completedASectionThisRun( false )
{}
void enter() {
m_completedASectionThisRun = false;
m_currentSection = &m_testCase;
m_testCase.enter();
}
void leave() {
m_testCase.leave();
}
bool enterSection( std::string const& name ) {
if( m_completedASectionThisRun )
return false;
if( m_currentSection->runState() == TrackedSection::Executing ) {
m_currentSection->addChild( name );
return false;
}
else {
TrackedSection* child = m_currentSection->getChild( name );
if( child->runState() != TrackedSection::Completed ) {
m_currentSection = child;
m_currentSection->enter();
return true;
}
return false;
}
}
void leaveSection() {
m_currentSection->leave();
m_currentSection = m_currentSection->getParent();
assert( m_currentSection != NULL );
m_completedASectionThisRun = true;
}
bool isCompleted() const {
return m_testCase.runState() == TrackedSection::Completed;
}
bool hasCompletedASectionThisRun() const {
return m_completedASectionThisRun;
}
private:
TrackedSection m_testCase;
TrackedSection* m_currentSection;
bool m_completedASectionThisRun;
};
TEST_CASE( "sections" ) {
using namespace Catch;
SectionTracker sectionTracker( "test case" );
const std::string section1Name = "section 1";
const std::string section2Name = "section 2";
CHECK_FALSE( sectionTracker.isCompleted() );
SECTION( "test case with no sections" ) {
sectionTracker.enter();
CHECK_FALSE( sectionTracker.isCompleted() );
sectionTracker.leave();
CHECK( sectionTracker.isCompleted() );
}
SECTION( "test case with one section" ) {
// Enter test case
sectionTracker.enter();
// Enter section? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section1Name ) );
CHECK_FALSE( sectionTracker.isCompleted() );
// Leave test case - incomplete (still need to visit section)
sectionTracker.leave();
CHECK_FALSE( sectionTracker.isCompleted() );
// ...
// Enter test case again
sectionTracker.enter();
// Enter section? - yes
CHECK( sectionTracker.enterSection( section1Name ) );
// Leave section and test case - now complete
sectionTracker.leaveSection();
sectionTracker.leave();
CHECK( sectionTracker.isCompleted() );
}
SECTION( "test case with two consecutive sections" ) {
// Enter test case
sectionTracker.enter();
// Enter section 1? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section1Name ) );
// Enter section 2? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section2Name ) );
// Leave test case - incomplete (still need to visit sections)
sectionTracker.leave();
CHECK_FALSE( sectionTracker.isCompleted() );
// ...
// Enter test case again
sectionTracker.enter();
// Enter section 1? - yes
CHECK( sectionTracker.enterSection( section1Name ) );
sectionTracker.leaveSection();
// Enter section 2? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section2Name ) );
// Leave test case - incomplete (still need to visit section 2)
sectionTracker.leave();
CHECK_FALSE( sectionTracker.isCompleted() );
// ...
// Enter test case again
sectionTracker.enter();
// Enter section 1? - no, already done now
CHECK_FALSE( sectionTracker.enterSection( section1Name ) );
// Enter section 2? - yes - finally
CHECK( sectionTracker.enterSection( section2Name ) );
sectionTracker.leaveSection();
// Leave test case - now complete
sectionTracker.leave();
CHECK( sectionTracker.isCompleted() );
}
SECTION( "test case with one section within another" ) {
// Enter test case
sectionTracker.enter();
// Enter section 1? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section1Name ) );
// Leave test case - incomplete (still need to visit sections)
sectionTracker.leave();
CHECK_FALSE( sectionTracker.isCompleted() );
// ...
// Enter test case again
sectionTracker.enter();
// Enter section 1? - yes
CHECK( sectionTracker.enterSection( section1Name ) );
// Enter section 2? - no, not yet
CHECK_FALSE( sectionTracker.enterSection( section2Name ) );
sectionTracker.leaveSection(); // section 1 - incomplete (section 2)
// Leave test case - incomplete
sectionTracker.leave();
CHECK_FALSE( sectionTracker.isCompleted() );
// ...
// Enter test case again
sectionTracker.enter();
// Enter section 1? - yes - so we can execute section 2
CHECK( sectionTracker.enterSection( section1Name ) );
// Enter section 2? - yes - finally
CHECK( sectionTracker.enterSection( section2Name ) );
sectionTracker.leaveSection(); // section 2
sectionTracker.leaveSection(); // section 1
// Leave test case - now complete
sectionTracker.leave();
CHECK( sectionTracker.isCompleted() );
}
}

View File

@ -11,6 +11,7 @@
266E9AD617290E8E0061DAB2 /* CmdLineTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266E9AD417290E8E0061DAB2 /* CmdLineTests.cpp */; };
266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 266ECD73170F3C620030D735 /* BDDTests.cpp */; };
26847E5F16BBADB40043B9C1 /* catch_message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26847E5D16BBADB40043B9C1 /* catch_message.cpp */; };
26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26948284179A9AB900ED166E /* SectionTrackerTests.cpp */; };
2694A1FD16A0000E004816E3 /* catch_text.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_text.cpp */; };
4A45DA2416161EF9004F8D6B /* catch_console_colour.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2316161EF9004F8D6B /* catch_console_colour.cpp */; };
4A45DA2716161F1F004F8D6B /* catch_ptr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2616161F1F004F8D6B /* catch_ptr.cpp */; };
@ -67,6 +68,7 @@
26847E5B16BBAB790043B9C1 /* catch_message.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_message.h; sourceTree = "<group>"; };
26847E5C16BBACB60043B9C1 /* catch_message.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_message.hpp; sourceTree = "<group>"; };
26847E5D16BBADB40043B9C1 /* catch_message.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = catch_message.cpp; path = ../../../SelfTest/SurrogateCpps/catch_message.cpp; sourceTree = "<group>"; };
26948284179A9AB900ED166E /* SectionTrackerTests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SectionTrackerTests.cpp; path = ../../../SelfTest/SectionTrackerTests.cpp; sourceTree = "<group>"; };
2694A1FB16A0000E004816E3 /* catch_text.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_text.cpp; sourceTree = "<group>"; };
26C5F3EC17514B970056FB3C /* clara.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = clara.h; path = ../../../../include/internal/clara.h; sourceTree = "<group>"; };
26DACF2F17206D3400A21326 /* catch_text.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_text.h; sourceTree = "<group>"; };
@ -142,7 +144,7 @@
4A90B59B15D0F61A00EF71BC /* catch_interfaces_generators.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_interfaces_generators.h; sourceTree = "<group>"; };
4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_assertionresult.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
4A90B59E15D2521E00EF71BC /* catch_expressionresult_builder.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_expressionresult_builder.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
4A9D84B11558FC0400FBB209 /* catch_tostring.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_tostring.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
4A9D84B11558FC0400FBB209 /* catch_tostring.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_tostring.hpp; sourceTree = "<group>"; };
4A9D84B315599AC900FBB209 /* catch_expressionresult_builder.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = catch_expressionresult_builder.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
4AA7B8B4165428BA003155F6 /* catch_version.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; name = catch_version.hpp; path = ../../../../include/internal/catch_version.hpp; sourceTree = "<group>"; };
4AB1C73514F97BDA00F31DF7 /* catch_console_colour_impl.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; lineEnding = 0; path = catch_console_colour_impl.hpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
@ -183,6 +185,7 @@
isa = PBXGroup;
children = (
266E9AD417290E8E0061DAB2 /* CmdLineTests.cpp */,
26948284179A9AB900ED166E /* SectionTrackerTests.cpp */,
);
name = "Introspective Tests";
sourceTree = "<group>";
@ -515,6 +518,7 @@
266B06B816F3A60A004ED264 /* VariadicMacrosTests.cpp in Sources */,
266ECD74170F3C620030D735 /* BDDTests.cpp in Sources */,
266E9AD617290E8E0061DAB2 /* CmdLineTests.cpp in Sources */,
26948286179A9AB900ED166E /* SectionTrackerTests.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -76,7 +76,8 @@ OC_TEST_CASE( "OCTest/matchers", "Matches work with OC types (NSString so far)"
OC_TEST_CASE( "OCTest/matchers/nil", "nil NSString should not crash the test" )
{
REQUIRE_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) );
CHECK_THAT( (NSString*)nil, Equals( @"This should fail, but not crash" ) );
CHECK_THAT( (NSString*)nil, StartsWith( @"anything" ) );
}
@end

View File

@ -1,6 +1,6 @@
/*
* CATCH v1.0 build 5 (master branch)
* Generated: 2013-07-03 08:24:00.747039
* Generated: 2013-07-05 08:38:07.926803
* ----------------------------------------------------------
* This file has been merged from multiple headers. Please don't edit it directly
* Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
@ -3498,7 +3498,8 @@ namespace Catch {
Equals( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str isEqualToString:m_substr];
return (str != nil || m_substr == nil ) &&
[str isEqualToString:m_substr];
}
virtual std::string toString() const {
@ -3510,7 +3511,8 @@ namespace Catch {
Contains( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location != NSNotFound;
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location != NSNotFound;
}
virtual std::string toString() const {
@ -3522,7 +3524,8 @@ namespace Catch {
StartsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == 0;
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == 0;
}
virtual std::string toString() const {
@ -3533,7 +3536,8 @@ namespace Catch {
EndsWith( NSString* substr ) : StringHolder( substr ){}
virtual bool match( ExpressionType const& str ) const {
return [str rangeOfString:m_substr].location == [str length] - [m_substr length];
return (str != nil || m_substr == nil ) &&
[str rangeOfString:m_substr].location == [str length] - [m_substr length];
}
virtual std::string toString() const {