mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 04:07:10 +01:00 
			
		
		
		
	Integrated new section tracker.
- also pass extra section to reporter - one for each test case - ignore it in headers (this is so we know a test case has restarted) - significant effect on regression test due to change of ordering of sections - fixes infinite loop issue
This commit is contained in:
		| @@ -34,12 +34,18 @@ namespace Catch { | ||||
|                 nullableValue = new( storage ) T( *_other ); | ||||
|             return *this; | ||||
|         } | ||||
|         Option& operator = ( T const& _value ) { | ||||
|             reset(); | ||||
|             nullableValue = new( storage ) T( _value ); | ||||
|             return *this; | ||||
|         } | ||||
|  | ||||
|         void reset() { | ||||
|             if( nullableValue ) | ||||
|                 nullableValue->~T(); | ||||
|             nullableValue = NULL; | ||||
|         } | ||||
|  | ||||
|         T& operator*() { return *nullableValue; } | ||||
|         T const& operator*() const { return *nullableValue; } | ||||
|         T* operator->() { return nullableValue; } | ||||
|   | ||||
| @@ -18,6 +18,7 @@ | ||||
| #include "catch_totals.hpp" | ||||
| #include "catch_running_test.hpp" | ||||
| #include "catch_test_spec.h" | ||||
| #include "catch_test_case_tracker.hpp" | ||||
|  | ||||
| #include <set> | ||||
| #include <string> | ||||
| @@ -114,13 +115,15 @@ namespace Catch { | ||||
|  | ||||
|             m_reporter->testCaseStarting( testInfo ); | ||||
|  | ||||
|             m_runningTest = new RunningTest( testCase ); | ||||
|             m_runningTest = new RunningTest( testCase ); // deprecated | ||||
|             m_testCaseTracker = TestCaseTracker( testInfo.name ); | ||||
|  | ||||
|             do { | ||||
|                 do { | ||||
|                     runCurrentTest( redirectedCout, redirectedCerr ); | ||||
|                 } | ||||
|                 while( m_runningTest->hasUntestedSections() && !aborting() ); | ||||
| //                while( m_runningTest->hasUntestedSections() && !aborting() ); | ||||
|                 while( !m_testCaseTracker->isCompleted() && !aborting() ); | ||||
|             } | ||||
|             while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); | ||||
|  | ||||
| @@ -144,6 +147,7 @@ namespace Catch { | ||||
|  | ||||
|             delete m_runningTest; | ||||
|             m_runningTest = NULL; | ||||
|             m_testCaseTracker.reset(); | ||||
|  | ||||
|             return deltaTotals; | ||||
|         } | ||||
| @@ -182,10 +186,12 @@ namespace Catch { | ||||
|             std::ostringstream oss; | ||||
|             oss << sectionInfo.name << "@" << sectionInfo.lineInfo; | ||||
|  | ||||
|  | ||||
|             if( !m_runningTest->addSection( oss.str() ) ) | ||||
|             if( !m_testCaseTracker->enterSection( oss.str() ) ) | ||||
|                 return false; | ||||
|  | ||||
| //            if( !m_runningTest->addSection( oss.str() ) ) // deprecated | ||||
| //                return false; | ||||
|  | ||||
|             m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; | ||||
|  | ||||
|             m_reporter->sectionStarting( sectionInfo ); | ||||
| @@ -205,13 +211,15 @@ namespace Catch { | ||||
|             bool missingAssertions = false; | ||||
|             if( assertions.total() == 0 && | ||||
|                     m_config->warnAboutMissingAssertions() && | ||||
|                     !m_runningTest->isBranchSection() ) { | ||||
|                     !m_testCaseTracker->currentSectionHasChildren() ) { | ||||
| //                    m_runningTest->isBranchSection() ) { // deprecated | ||||
|                 m_totals.assertions.failed++; | ||||
|                 assertions.failed++; | ||||
|                 missingAssertions = true; | ||||
|  | ||||
|             } | ||||
|             m_runningTest->endSection( info.name, false ); | ||||
| //            m_runningTest->endSection( info.name, false ); // deprecated | ||||
|             m_testCaseTracker->leaveSection(); | ||||
|  | ||||
|             m_reporter->sectionEnded( SectionStats( info, assertions, missingAssertions ) ); | ||||
|             m_messages.clear(); | ||||
| @@ -264,9 +272,13 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|         void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { | ||||
|             TestCaseInfo const& testCaseInfo = m_runningTest->getTestCase().getTestCaseInfo(); | ||||
|             SectionInfo testCaseSection( testCaseInfo.name, testCaseInfo.description, testCaseInfo.lineInfo ); | ||||
|             m_reporter->sectionStarting( testCaseSection ); | ||||
|             try { | ||||
|                 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", m_runningTest->getTestCase().getTestCaseInfo().lineInfo, "", ResultDisposition::Normal ); | ||||
|                 m_runningTest->reset(); | ||||
|                 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); | ||||
|                 //m_runningTest->reset(); // deprecated | ||||
|                 m_testCaseTracker->enter(); | ||||
|  | ||||
|                 if( m_reporter->getPreferences().shouldRedirectStdOut ) { | ||||
|                     StreamRedirect coutRedir( std::cout, redirectedCout ); | ||||
| @@ -276,12 +288,15 @@ namespace Catch { | ||||
|                 else { | ||||
|                     m_runningTest->getTestCase().invoke(); | ||||
|                 } | ||||
|                 m_runningTest->ranToCompletion(); | ||||
|                 //m_runningTest->ranToCompletion(); // deprecated | ||||
|                 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 )  ); | ||||
| @@ -295,6 +310,8 @@ namespace Catch { | ||||
|                 sectionEnded( it->info, it->prevAssertions ); | ||||
|             m_unfinishedSections.clear(); | ||||
|             m_messages.clear(); | ||||
|             SectionStats testCaseSectionStats( testCaseSection, Counts(), 0 ); // !TBD | ||||
|             m_reporter->sectionEnded( testCaseSectionStats ); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
| @@ -309,7 +326,8 @@ namespace Catch { | ||||
|  | ||||
|         TestRunInfo m_runInfo; | ||||
|         IMutableContext& m_context; | ||||
|         RunningTest* m_runningTest; | ||||
|         RunningTest* m_runningTest; // deprecated | ||||
|         Option<TestCaseTracker> m_testCaseTracker; | ||||
|         AssertionResult m_lastResult; | ||||
|  | ||||
|         Ptr<IConfig const> m_config; | ||||
|   | ||||
| @@ -57,6 +57,9 @@ namespace SectionTracking { | ||||
|         TrackedSection* getParent() { | ||||
|             return m_parent; | ||||
|         } | ||||
|         bool hasChildren() const { | ||||
|             return !m_children.empty(); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         std::string m_name; | ||||
| @@ -98,6 +101,9 @@ namespace SectionTracking { | ||||
|             m_completedASectionThisRun = true; | ||||
|         } | ||||
|  | ||||
|         bool currentSectinHasChildren() const { | ||||
|             return m_currentSection->hasChildren(); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         TrackedSection* m_currentSection; | ||||
| @@ -109,11 +115,11 @@ namespace SectionTracking { | ||||
|  | ||||
|         TestCaseTracker( std::string const& testCaseName ) | ||||
|         :   m_testCase( testCaseName, NULL ), | ||||
|             sections( m_testCase ) | ||||
|             m_sections( m_testCase ) | ||||
|         {} | ||||
|  | ||||
|         void enter() { | ||||
|             sections = SectionTracker( m_testCase ); | ||||
|             m_sections = SectionTracker( m_testCase ); | ||||
|             m_testCase.enter(); | ||||
|         } | ||||
|         void leave() { | ||||
| @@ -121,19 +127,23 @@ namespace SectionTracking { | ||||
|         } | ||||
|  | ||||
|         bool enterSection( std::string const& name ) { | ||||
|             return sections.enterSection( name ); | ||||
|             return m_sections.enterSection( name ); | ||||
|         } | ||||
|         void leaveSection() { | ||||
|             sections.leaveSection(); | ||||
|             m_sections.leaveSection(); | ||||
|         } | ||||
|          | ||||
|         bool isCompleted() const { | ||||
|             return m_testCase.runState() == TrackedSection::Completed; | ||||
|         } | ||||
|  | ||||
|         bool currentSectionHasChildren() const { | ||||
|             return m_sections.currentSectinHasChildren(); | ||||
|         } | ||||
|  | ||||
|     private: | ||||
|         TrackedSection m_testCase; | ||||
|         SectionTracker sections; | ||||
|         SectionTracker m_sections; | ||||
|     }; | ||||
|  | ||||
| } // namespace SectionTracking | ||||
|   | ||||
| @@ -271,12 +271,10 @@ namespace Catch { | ||||
|                     sections.push_back( section ); | ||||
|  | ||||
|                 // Sections | ||||
|                 if( !sections.empty() ) { | ||||
|                     typedef std::vector<ThreadedSectionInfo*>::const_reverse_iterator It; | ||||
|                     for( It it = sections.rbegin(), itEnd = sections.rend(); it != itEnd; ++it ) | ||||
|                         printHeaderString( (*it)->name, 2 ); | ||||
|  | ||||
|                 } | ||||
|                 std::vector<ThreadedSectionInfo*>::const_reverse_iterator | ||||
|                     it = sections.rbegin(), itEnd = sections.rend(); | ||||
|                 for( ++it; it != itEnd; ++it ) // Skip first section (test case) | ||||
|                     printHeaderString( (*it)->name, 2 ); | ||||
|             } | ||||
|             SourceLineInfo lineInfo = currentSectionInfo | ||||
|                                     ? currentSectionInfo->lineInfo | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
| namespace Catch { | ||||
|     class XmlReporter : public SharedImpl<IReporter> { | ||||
|     public: | ||||
|         XmlReporter( ReporterConfig const& config ) : m_config( config ) {} | ||||
|         XmlReporter( ReporterConfig const& config ) : m_config( config ), m_sectionDepth( 0 ) {} | ||||
|  | ||||
|         static std::string getDescription() { | ||||
|             return "Reports test results as an XML document"; | ||||
| @@ -56,18 +56,22 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|         virtual void StartSection( const std::string& sectionName, const std::string& description ) { | ||||
|             m_xml.startElement( "Section" ) | ||||
|                 .writeAttribute( "name", sectionName ) | ||||
|                 .writeAttribute( "description", description ); | ||||
|             if( m_sectionDepth++ > 0 ) { | ||||
|                 m_xml.startElement( "Section" ) | ||||
|                     .writeAttribute( "name", sectionName ) | ||||
|                     .writeAttribute( "description", description ); | ||||
|             } | ||||
|         } | ||||
|         virtual void NoAssertionsInSection( const std::string& ) {} | ||||
|         virtual void NoAssertionsInTestCase( const std::string& ) {} | ||||
|  | ||||
|         virtual void EndSection( const std::string& /*sectionName*/, const Counts& assertions ) { | ||||
|             m_xml.scopedElement( "OverallResults" ) | ||||
|                 .writeAttribute( "successes", assertions.passed ) | ||||
|                 .writeAttribute( "failures", assertions.failed ); | ||||
|             m_xml.endElement(); | ||||
|             if( --m_sectionDepth > 0 ) { | ||||
|                 m_xml.scopedElement( "OverallResults" ) | ||||
|                     .writeAttribute( "successes", assertions.passed ) | ||||
|                     .writeAttribute( "failures", assertions.failed ); | ||||
|                 m_xml.endElement(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         virtual void StartTestCase( const Catch::TestCaseInfo& testInfo ) { | ||||
| @@ -138,6 +142,7 @@ namespace Catch { | ||||
|         ReporterConfig m_config; | ||||
|         bool m_currentTestSuccess; | ||||
|         XmlWriter m_xml; | ||||
|         int m_sectionDepth; | ||||
|     }; | ||||
|  | ||||
| } // end namespace Catch | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -333,11 +333,11 @@ TEST_CASE( "vectors can be sized and resized", "[vector]" ) { | ||||
| } | ||||
|  | ||||
| // https://github.com/philsquared/Catch/issues/166 | ||||
| //TEST_CASE("CatchSectionInfiniteLoop", "") | ||||
| //{ | ||||
| //    SECTION("Outer", "") | ||||
| //        SECTION("Inner", "") | ||||
| //            SUCCEED("that's not flying - that's failing in style"); | ||||
| // | ||||
| //    FAIL("to infinity and beyond"); | ||||
| //} | ||||
| TEST_CASE("./failing/CatchSectionInfiniteLoop", "") | ||||
| { | ||||
|     SECTION("Outer", "") | ||||
|         SECTION("Inner", "") | ||||
|             SUCCEED("that's not flying - that's failing in style"); | ||||
|  | ||||
|     FAIL("to infinity and beyond"); | ||||
| } | ||||
|   | ||||
| @@ -38,15 +38,15 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" | ||||
|         SECTION(    "selftest/test counts/succeeding tests",  | ||||
|                     "Number of 'succeeding' tests is fixed" ) { | ||||
|             Totals totals = runner.runMatching( "./succeeding/*", 0, 2 ); | ||||
|             CHECK( totals.assertions.passed == 296 ); | ||||
|             CHECK( totals.assertions.passed == 298 ); | ||||
|             CHECK( totals.assertions.failed == 0 ); | ||||
|         } | ||||
|  | ||||
|         SECTION(    "selftest/test counts/failing tests",  | ||||
|                     "Number of 'failing' tests is fixed" ) { | ||||
|             Totals totals = runner.runMatching( "./failing/*", 1, 2 ); | ||||
|             CHECK( totals.assertions.passed == 1 ); | ||||
|             CHECK( totals.assertions.failed == 74 ); | ||||
|             CHECK( totals.assertions.passed == 2 ); | ||||
|             CHECK( totals.assertions.failed == 77 ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash