2013-07-23 19:48:36 +02:00
|
|
|
/*
|
|
|
|
* Created by Phil Nash on 23/7/2013
|
|
|
|
* Copyright 2013 Two Blue Cubes Ltd. All rights reserved.
|
|
|
|
*
|
|
|
|
* 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)
|
|
|
|
*/
|
|
|
|
#ifndef TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|
|
|
|
#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|
|
|
|
|
|
|
|
#include <map>
|
|
|
|
#include <string>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
namespace Catch {
|
|
|
|
namespace SectionTracking {
|
|
|
|
|
|
|
|
class TrackedSection {
|
|
|
|
|
|
|
|
typedef std::map<std::string, TrackedSection> TrackedSections;
|
|
|
|
|
|
|
|
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; }
|
|
|
|
|
2014-04-21 20:02:38 +02:00
|
|
|
TrackedSection* findChild( std::string const& childName ) {
|
|
|
|
TrackedSections::iterator it = m_children.find( childName );
|
|
|
|
return it != m_children.end()
|
|
|
|
? &it->second
|
|
|
|
: NULL;
|
2013-07-23 19:48:36 +02:00
|
|
|
}
|
2014-04-21 20:02:38 +02:00
|
|
|
TrackedSection* acquireChild( std::string const& childName ) {
|
|
|
|
if( TrackedSection* child = findChild( childName ) )
|
|
|
|
return child;
|
|
|
|
m_children.insert( std::make_pair( childName, TrackedSection( childName, this ) ) );
|
|
|
|
return findChild( childName );
|
2013-07-23 19:48:36 +02:00
|
|
|
}
|
|
|
|
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;
|
|
|
|
}
|
2013-07-24 20:13:08 +02:00
|
|
|
bool hasChildren() const {
|
|
|
|
return !m_children.empty();
|
|
|
|
}
|
2013-07-23 19:48:36 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::string m_name;
|
|
|
|
RunState m_runState;
|
|
|
|
TrackedSections m_children;
|
|
|
|
TrackedSection* m_parent;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
2013-07-25 09:07:55 +02:00
|
|
|
class TestCaseTracker {
|
2013-07-23 19:48:36 +02:00
|
|
|
public:
|
2013-07-25 09:07:55 +02:00
|
|
|
TestCaseTracker( std::string const& testCaseName )
|
|
|
|
: m_testCase( testCaseName, NULL ),
|
|
|
|
m_currentSection( &m_testCase ),
|
2013-07-23 19:48:36 +02:00
|
|
|
m_completedASectionThisRun( false )
|
|
|
|
{}
|
2013-07-25 09:07:55 +02:00
|
|
|
|
2013-07-23 19:48:36 +02:00
|
|
|
bool enterSection( std::string const& name ) {
|
2014-04-21 20:02:38 +02:00
|
|
|
TrackedSection* child = m_currentSection->acquireChild( name );
|
|
|
|
if( m_completedASectionThisRun || child->runState() == TrackedSection::Completed )
|
2013-07-23 19:48:36 +02:00
|
|
|
return false;
|
2014-04-21 20:02:38 +02:00
|
|
|
|
|
|
|
m_currentSection = child;
|
|
|
|
m_currentSection->enter();
|
|
|
|
return true;
|
2013-07-23 19:48:36 +02:00
|
|
|
}
|
|
|
|
void leaveSection() {
|
|
|
|
m_currentSection->leave();
|
|
|
|
m_currentSection = m_currentSection->getParent();
|
|
|
|
assert( m_currentSection != NULL );
|
|
|
|
m_completedASectionThisRun = true;
|
|
|
|
}
|
|
|
|
|
2013-07-25 09:07:55 +02:00
|
|
|
bool currentSectionHasChildren() const {
|
2013-07-24 20:13:08 +02:00
|
|
|
return m_currentSection->hasChildren();
|
|
|
|
}
|
2013-07-25 09:07:55 +02:00
|
|
|
bool isCompleted() const {
|
|
|
|
return m_testCase.runState() == TrackedSection::Completed;
|
|
|
|
}
|
2013-07-23 19:48:36 +02:00
|
|
|
|
2013-07-25 09:07:55 +02:00
|
|
|
class Guard {
|
|
|
|
public:
|
2014-04-21 20:02:38 +02:00
|
|
|
Guard( TestCaseTracker& tracker ) : m_tracker( tracker ) {
|
2013-07-25 09:07:55 +02:00
|
|
|
m_tracker.enterTestCase();
|
|
|
|
}
|
|
|
|
~Guard() {
|
|
|
|
m_tracker.leaveTestCase();
|
|
|
|
}
|
|
|
|
private:
|
2013-07-25 09:18:09 +02:00
|
|
|
Guard( Guard const& );
|
|
|
|
void operator = ( Guard const& );
|
2013-07-25 09:07:55 +02:00
|
|
|
TestCaseTracker& m_tracker;
|
|
|
|
};
|
2013-07-23 19:48:36 +02:00
|
|
|
|
2013-07-25 09:07:55 +02:00
|
|
|
private:
|
|
|
|
void enterTestCase() {
|
|
|
|
m_currentSection = &m_testCase;
|
|
|
|
m_completedASectionThisRun = false;
|
2013-07-23 19:48:36 +02:00
|
|
|
m_testCase.enter();
|
|
|
|
}
|
2013-07-25 09:07:55 +02:00
|
|
|
void leaveTestCase() {
|
2013-07-23 19:48:36 +02:00
|
|
|
m_testCase.leave();
|
|
|
|
}
|
|
|
|
|
|
|
|
TrackedSection m_testCase;
|
2013-07-25 09:07:55 +02:00
|
|
|
TrackedSection* m_currentSection;
|
|
|
|
bool m_completedASectionThisRun;
|
2013-07-23 19:48:36 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace SectionTracking
|
|
|
|
|
|
|
|
using SectionTracking::TestCaseTracker;
|
|
|
|
|
|
|
|
} // namespace Catch
|
|
|
|
|
|
|
|
#endif // TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
|