diff --git a/include/internal/catch_runner_impl.hpp b/include/internal/catch_runner_impl.hpp index 9b3d7c43..cf971539 100644 --- a/include/internal/catch_runner_impl.hpp +++ b/include/internal/catch_runner_impl.hpp @@ -269,7 +269,7 @@ namespace Catch { m_reporter->sectionStarting( testCaseSection ); try { m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); - m_testCaseTracker->enter(); + TestCaseTracker::Guard guard( *m_testCaseTracker ); if( m_reporter->getPreferences().shouldRedirectStdOut ) { StreamRedirect coutRedir( std::cout, redirectedCout ); @@ -279,14 +279,11 @@ namespace Catch { else { m_activeTestCase->invoke(); } - m_testCaseTracker->leave(); } catch( TestFailureException& ) { // This just means the test was aborted due to failure - m_testCaseTracker->leave(); // !TBD: RAII } catch(...) { - m_testCaseTracker->leave(); ExpressionResultBuilder exResult( ResultWas::ThrewException ); exResult << translateActiveException(); actOnCurrentResult( exResult.buildResult( m_lastAssertionInfo ) ); diff --git a/include/internal/catch_test_case_tracker.hpp b/include/internal/catch_test_case_tracker.hpp index e0298d4e..f12d8868 100644 --- a/include/internal/catch_test_case_tracker.hpp +++ b/include/internal/catch_test_case_tracker.hpp @@ -69,13 +69,14 @@ namespace SectionTracking { }; - class SectionTracker { + class TestCaseTracker { public: - SectionTracker( TrackedSection& testCase ) - : m_currentSection( &testCase ), + TestCaseTracker( std::string const& testCaseName ) + : m_testCase( testCaseName, NULL ), + m_currentSection( &m_testCase ), m_completedASectionThisRun( false ) {} - + bool enterSection( std::string const& name ) { if( m_completedASectionThisRun ) return false; @@ -93,7 +94,6 @@ namespace SectionTracking { return false; } } - void leaveSection() { m_currentSection->leave(); m_currentSection = m_currentSection->getParent(); @@ -101,49 +101,40 @@ namespace SectionTracking { m_completedASectionThisRun = true; } - bool currentSectinHasChildren() const { + bool currentSectionHasChildren() const { return m_currentSection->hasChildren(); } - - private: - TrackedSection* m_currentSection; - bool m_completedASectionThisRun; - }; - - class TestCaseTracker { - public: - - TestCaseTracker( std::string const& testCaseName ) - : m_testCase( testCaseName, NULL ), - m_sections( m_testCase ) - {} - - void enter() { - m_sections = SectionTracker( m_testCase ); - m_testCase.enter(); - } - void leave() { - m_testCase.leave(); - } - - bool enterSection( std::string const& name ) { - return m_sections.enterSection( name ); - } - void leaveSection() { - m_sections.leaveSection(); - } - bool isCompleted() const { return m_testCase.runState() == TrackedSection::Completed; } - bool currentSectionHasChildren() const { - return m_sections.currentSectinHasChildren(); - } + class Guard { + public: + Guard( TestCaseTracker& tracker ) + : m_tracker( tracker ) + { + m_tracker.enterTestCase(); + } + ~Guard() { + m_tracker.leaveTestCase(); + } + private: + TestCaseTracker& m_tracker; + }; private: + void enterTestCase() { + m_currentSection = &m_testCase; + m_completedASectionThisRun = false; + m_testCase.enter(); + } + void leaveTestCase() { + m_testCase.leave(); + } + TrackedSection m_testCase; - SectionTracker m_sections; + TrackedSection* m_currentSection; + bool m_completedASectionThisRun; }; } // namespace SectionTracking diff --git a/projects/SelfTest/SectionTrackerTests.cpp b/projects/SelfTest/SectionTrackerTests.cpp index 15e5f5d5..eaf3d2a0 100644 --- a/projects/SelfTest/SectionTrackerTests.cpp +++ b/projects/SelfTest/SectionTrackerTests.cpp @@ -26,132 +26,139 @@ TEST_CASE( "section tracking" ) { SECTION( "test case with no sections" ) { - testCaseTracker.enter(); - CHECK_FALSE( testCaseTracker.isCompleted() ); - - testCaseTracker.leave(); + { + TestCaseTracker::Guard guard( testCaseTracker ); + CHECK_FALSE( testCaseTracker.isCompleted() ); + } CHECK( testCaseTracker.isCompleted() ); } SECTION( "test case with one section" ) { - // Enter test case - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - CHECK_FALSE( testCaseTracker.isCompleted() ); + // Enter section? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); + CHECK_FALSE( testCaseTracker.isCompleted() ); - // Leave test case - incomplete (still need to visit section) - testCaseTracker.leave(); + // Leave test case - incomplete (still need to visit section) + } CHECK_FALSE( testCaseTracker.isCompleted() ); // ... // Enter test case again - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); + // Enter section? - yes + CHECK( testCaseTracker.enterSection( section1Name ) ); - // Leave section and test case - now complete - testCaseTracker.leaveSection(); - testCaseTracker.leave(); + // Leave section and test case - now complete + testCaseTracker.leaveSection(); + } CHECK( testCaseTracker.isCompleted() ); } SECTION( "test case with two consecutive sections" ) { // Enter test case - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); + // Enter section 1? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - // Enter section 2? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); + // Enter section 2? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); - // Leave test case - incomplete (still need to visit sections) - testCaseTracker.leave(); + // Leave test case - incomplete (still need to visit sections) + } CHECK_FALSE( testCaseTracker.isCompleted() ); // ... // Enter test case again - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); - testCaseTracker.leaveSection(); + // Enter section 1? - yes + CHECK( testCaseTracker.enterSection( section1Name ) ); + testCaseTracker.leaveSection(); - // Enter section 2? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); + // Enter section 2? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); - // Leave test case - incomplete (still need to visit section 2) - testCaseTracker.leave(); + // Leave test case - incomplete (still need to visit section 2) + } CHECK_FALSE( testCaseTracker.isCompleted() ); // ... // Enter test case again - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - no, already done now - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); + // Enter section 1? - no, already done now + CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - // Enter section 2? - yes - finally - CHECK( testCaseTracker.enterSection( section2Name ) ); - testCaseTracker.leaveSection(); + // Enter section 2? - yes - finally + CHECK( testCaseTracker.enterSection( section2Name ) ); + testCaseTracker.leaveSection(); - // Leave test case - now complete - testCaseTracker.leave(); + // Leave test case - now complete + } CHECK( testCaseTracker.isCompleted() ); } SECTION( "test case with one section within another" ) { // Enter test case - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); + // Enter section 1? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section1Name ) ); - // Leave test case - incomplete (still need to visit sections) - testCaseTracker.leave(); + // Leave test case - incomplete (still need to visit sections) + } CHECK_FALSE( testCaseTracker.isCompleted() ); // ... // Enter test case again - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - yes - CHECK( testCaseTracker.enterSection( section1Name ) ); + // Enter section 1? - yes + CHECK( testCaseTracker.enterSection( section1Name ) ); - // Enter section 2? - no, not yet - CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); + // Enter section 2? - no, not yet + CHECK_FALSE( testCaseTracker.enterSection( section2Name ) ); - testCaseTracker.leaveSection(); // section 1 - incomplete (section 2) + testCaseTracker.leaveSection(); // section 1 - incomplete (section 2) - // Leave test case - incomplete - testCaseTracker.leave(); + // Leave test case - incomplete + } CHECK_FALSE( testCaseTracker.isCompleted() ); // ... // Enter test case again - testCaseTracker.enter(); + { + TestCaseTracker::Guard guard( testCaseTracker ); - // Enter section 1? - yes - so we can execute section 2 - CHECK( testCaseTracker.enterSection( section1Name ) ); + // Enter section 1? - yes - so we can execute section 2 + CHECK( testCaseTracker.enterSection( section1Name ) ); - // Enter section 2? - yes - finally - CHECK( testCaseTracker.enterSection( section2Name ) ); - testCaseTracker.leaveSection(); // section 2 - testCaseTracker.leaveSection(); // section 1 + // Enter section 2? - yes - finally + CHECK( testCaseTracker.enterSection( section2Name ) ); + testCaseTracker.leaveSection(); // section 2 + testCaseTracker.leaveSection(); // section 1 - // Leave test case - now complete - testCaseTracker.leave(); + // Leave test case - now complete + } CHECK( testCaseTracker.isCompleted() ); } }