mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Merge branch 'dev-better-verbosity' of https://github.com/BMBurstein/Catch
This commit is contained in:
		
							
								
								
									
										87
									
								
								include/external/tbc_text_format.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										87
									
								
								include/external/tbc_text_format.h
									
									
									
									
										vendored
									
									
								
							| @@ -53,13 +53,55 @@ namespace Tbc { | ||||
|     public: | ||||
|         Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) | ||||
|         : attr( _attr ) | ||||
|         { | ||||
|             init( _str ); | ||||
|         } | ||||
|  | ||||
|         template<typename T> | ||||
|         Text( T const& _val, TextAttributes const& _attr = TextAttributes() ) | ||||
|         : attr( _attr ) | ||||
|         { | ||||
|             std::ostringstream oss; | ||||
|             oss << _val; | ||||
|             init( oss.str() ); | ||||
|         } | ||||
|  | ||||
|         typedef std::vector<std::string>::const_iterator const_iterator; | ||||
|  | ||||
|         const_iterator begin() const { return lines.begin(); } | ||||
|         const_iterator end() const { return lines.end(); } | ||||
|         std::string const& last() const { return lines.back(); } | ||||
|         std::size_t size() const { return lines.size(); } | ||||
|         std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } | ||||
|         std::string toString() const { | ||||
|             std::ostringstream oss; | ||||
|             oss << *this; | ||||
|             return oss.str(); | ||||
|         } | ||||
|  | ||||
|         inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { | ||||
|             for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); | ||||
|                 it != itEnd; ++it ) { | ||||
|                 if( it != _text.begin() ) | ||||
|                     _stream << "\n"; | ||||
|                 _stream << *it; | ||||
|             } | ||||
|             return _stream; | ||||
|         } | ||||
|  | ||||
|  | ||||
|     private: | ||||
|         TextAttributes attr; | ||||
|         std::vector<std::string> lines; | ||||
|  | ||||
|         void init( std::string const& _str ) | ||||
|         { | ||||
|             const std::string wrappableBeforeChars = "[({<\t"; | ||||
|             const std::string wrappableAfterChars = "])}>-,./|\\"; | ||||
|             const std::string wrappableInsteadOfChars = " \n\r"; | ||||
|             std::string indent = _attr.initialIndent != std::string::npos | ||||
|                 ? std::string( _attr.initialIndent, ' ' ) | ||||
|                 : std::string( _attr.indent, ' ' ); | ||||
|             std::string indent = attr.initialIndent != std::string::npos | ||||
|                 ? std::string( attr.initialIndent, ' ' ) | ||||
|                 : std::string( attr.indent, ' ' ); | ||||
|  | ||||
|             typedef std::string::const_iterator iterator; | ||||
|             iterator it = _str.begin(); | ||||
| @@ -74,7 +116,7 @@ namespace Tbc { | ||||
|  | ||||
|  | ||||
|                 std::string suffix; | ||||
|                 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) ); | ||||
|                 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), attr.width-static_cast<size_t>( indent.size() ) ); | ||||
|                 iterator itEnd = it+width; | ||||
|                 iterator itNext = _str.end(); | ||||
|  | ||||
| @@ -121,42 +163,11 @@ namespace Tbc { | ||||
|                 } | ||||
|                 lines.push_back( indent + std::string( it, itEnd ) + suffix ); | ||||
|  | ||||
|                 if( indent.size() != _attr.indent ) | ||||
|                     indent = std::string( _attr.indent, ' ' ); | ||||
|                 if( indent.size() != attr.indent ) | ||||
|                     indent = std::string( attr.indent, ' ' ); | ||||
|                 it = itNext; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|  | ||||
|  | ||||
|         typedef std::vector<std::string>::const_iterator const_iterator; | ||||
|  | ||||
|         const_iterator begin() const { return lines.begin(); } | ||||
|         const_iterator end() const { return lines.end(); } | ||||
|         std::string const& last() const { return lines.back(); } | ||||
|         std::size_t size() const { return lines.size(); } | ||||
|         std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } | ||||
|         std::string toString() const { | ||||
|             std::ostringstream oss; | ||||
|             oss << *this; | ||||
|             return oss.str(); | ||||
|         } | ||||
|  | ||||
|         inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { | ||||
|             for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); | ||||
|                 it != itEnd; ++it ) { | ||||
|                 if( it != _text.begin() ) | ||||
|                     _stream << "\n"; | ||||
|                 _stream << *it; | ||||
|             } | ||||
|             return _stream; | ||||
|         } | ||||
|  | ||||
|  | ||||
|     private: | ||||
|         std::string str; | ||||
|         TextAttributes attr; | ||||
|         std::vector<std::string> lines; | ||||
|     }; | ||||
|  | ||||
| } // end namespace Tbc | ||||
| @@ -165,4 +176,4 @@ namespace Tbc { | ||||
| } // end outer namespace | ||||
| #endif | ||||
|  | ||||
| #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED | ||||
| #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED | ||||
| @@ -30,8 +30,6 @@ namespace Catch { | ||||
|     bool Config::listTags() const           { return m_data.listTags; } | ||||
|     bool Config::listReporters() const      { return m_data.listReporters; } | ||||
|  | ||||
|     Verbosity Config::verbosity() const     { return m_data.verbosity; } | ||||
|  | ||||
|     std::string Config::getProcessName() const { return m_data.processName; } | ||||
|  | ||||
|     std::vector<std::string> const& Config::getReporterNames() const { return m_data.reporterNames; } | ||||
| @@ -54,6 +52,7 @@ namespace Catch { | ||||
|     bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; } | ||||
|     int Config::abortAfter() const                     { return m_data.abortAfter; } | ||||
|     bool Config::showInvisibles() const                { return m_data.showInvisibles; } | ||||
|     Verbosity Config::verbosity() const                { return m_data.verbosity; } | ||||
|  | ||||
|     IStream const* Config::openStream() { | ||||
|         if( m_data.outputFilename.empty() ) | ||||
|   | ||||
| @@ -70,8 +70,6 @@ namespace Catch { | ||||
|         bool listTags() const; | ||||
|         bool listReporters() const; | ||||
|  | ||||
|         Verbosity verbosity() const; | ||||
|  | ||||
|         std::string getProcessName() const; | ||||
|  | ||||
|         std::vector<std::string> const& getReporterNames() const; | ||||
| @@ -94,6 +92,7 @@ namespace Catch { | ||||
|         virtual bool shouldDebugBreak() const override; | ||||
|         virtual int abortAfter() const override; | ||||
|         virtual bool showInvisibles() const override; | ||||
|         virtual Verbosity verbosity() const override; | ||||
|  | ||||
|     private: | ||||
|  | ||||
|   | ||||
| @@ -55,7 +55,6 @@ namespace Catch { | ||||
|     IMutableRegistryHub::~IMutableRegistryHub() {} | ||||
|     IExceptionTranslator::~IExceptionTranslator() {} | ||||
|     IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} | ||||
|  | ||||
|     IRunner::~IRunner() {} | ||||
|     IMutableContext::~IMutableContext() {} | ||||
|     IConfig::~IConfig() {} | ||||
|   | ||||
| @@ -64,6 +64,7 @@ namespace Catch { | ||||
|         virtual unsigned int rngSeed() const = 0; | ||||
|         virtual UseColour::YesOrNo useColour() const = 0; | ||||
|         virtual std::vector<std::string> const& getSectionsToRun() const = 0; | ||||
|         virtual Verbosity verbosity() const = 0; | ||||
|     }; | ||||
|  | ||||
|     using IConfigPtr = std::shared_ptr<IConfig const>; | ||||
|   | ||||
| @@ -22,6 +22,7 @@ | ||||
| #include <string> | ||||
| #include <iosfwd> | ||||
| #include <map> | ||||
| #include <set> | ||||
| #include <memory> | ||||
|  | ||||
| namespace Catch { | ||||
| @@ -162,8 +163,9 @@ namespace Catch { | ||||
|     struct IStreamingReporter { | ||||
|         virtual ~IStreamingReporter() = default; | ||||
|  | ||||
|         // Implementing class must also provide the following static method: | ||||
|         // Implementing class must also provide the following static methods: | ||||
|         // static std::string getDescription(); | ||||
|         // static std::set<Verbosity> getSupportedVerbosities() | ||||
|  | ||||
|         virtual ReporterPreferences getPreferences() const = 0; | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,8 @@ | ||||
| #include "catch_interfaces_reporter.h" | ||||
| #include "catch_interfaces_testcase.h" | ||||
|  | ||||
| #include "catch_text.h" | ||||
|  | ||||
| #include "catch_clara.h" // For TextFlow | ||||
|  | ||||
| #include "catch_console_colour.hpp" | ||||
| @@ -43,12 +45,13 @@ namespace Catch { | ||||
|  | ||||
|             Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n"; | ||||
|             if( config.verbosity() >= Verbosity::High ) { | ||||
|                 std::string description = testCaseInfo.description.empty() | ||||
|                     ? std::string( "(NO DESCRIPTION)" ) | ||||
|                     : testCaseInfo.description; | ||||
|                 Catch::cout() | ||||
|                     << "    " << testCaseInfo.lineInfo << "\n" | ||||
|                     << Column( description ).indent( 4 ) << "\n"; | ||||
|                 TextAttributes descAttr; | ||||
|                 descAttr.setIndent( 4 ); | ||||
|                 Catch::cout() << Text( testCaseInfo.lineInfo, descAttr ) << std::endl; | ||||
|                 std::string description = testCaseInfo.description; | ||||
|                 if( description == "" ) | ||||
|                     description = "(NO DESCRIPTION)"; | ||||
|                 Catch::cout() << Text( description, descAttr ) << std::endl; | ||||
|             } | ||||
|             if( !testCaseInfo.tags.empty() ) | ||||
|                 Catch::cout() << Column( testCaseInfo.tagsAsString ).indent( 6 ) << "\n"; | ||||
|   | ||||
| @@ -16,7 +16,7 @@ | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct AutomakeReporter : StreamingReporterBase { | ||||
|     struct AutomakeReporter : StreamingReporterBase<AutomakeReporter> { | ||||
|         AutomakeReporter( ReporterConfig const& _config ) | ||||
|           :   StreamingReporterBase( _config ) | ||||
|         {} | ||||
|   | ||||
| @@ -39,181 +39,6 @@ namespace Catch { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     StreamingReporterBase::StreamingReporterBase(ReporterConfig const& _config) | ||||
|     :   m_config(_config.fullConfig()), | ||||
|         stream(_config.stream()) | ||||
|     { | ||||
|         m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|     } | ||||
|  | ||||
|     ReporterPreferences StreamingReporterBase::getPreferences() const { | ||||
|         return m_reporterPrefs; | ||||
|     } | ||||
|  | ||||
|     StreamingReporterBase::~StreamingReporterBase() {} | ||||
|  | ||||
|     void StreamingReporterBase::noMatchingTestCases(std::string const &) {} | ||||
|  | ||||
|     void StreamingReporterBase::testRunStarting(TestRunInfo const & _testRunInfo) { | ||||
|         currentTestRunInfo = _testRunInfo; | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::testGroupStarting(GroupInfo const & _groupInfo) { | ||||
|         currentGroupInfo = _groupInfo; | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::testCaseStarting(TestCaseInfo const & _testInfo) { | ||||
|         currentTestCaseInfo = _testInfo; | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::sectionStarting(SectionInfo const & _sectionInfo) { | ||||
|         m_sectionStack.push_back(_sectionInfo); | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::sectionEnded(SectionStats const &) { | ||||
|         m_sectionStack.pop_back(); | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::testCaseEnded(TestCaseStats const &) { | ||||
|         currentTestCaseInfo.reset(); | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::testGroupEnded(TestGroupStats const &) { | ||||
|         currentGroupInfo.reset(); | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::testRunEnded(TestRunStats const &) { | ||||
|         currentTestCaseInfo.reset(); | ||||
|         currentGroupInfo.reset(); | ||||
|         currentTestRunInfo.reset(); | ||||
|     } | ||||
|  | ||||
|     void StreamingReporterBase::skipTest(TestCaseInfo const &) { | ||||
|         // Don't do anything with this by default. | ||||
|         // It can optionally be overridden in the derived class. | ||||
|     } | ||||
|  | ||||
|     CumulativeReporterBase::CumulativeReporterBase(ReporterConfig const & _config) | ||||
|         : m_config(_config.fullConfig()), | ||||
|         stream(_config.stream()) { | ||||
|         m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|     } | ||||
|  | ||||
|     CumulativeReporterBase::~CumulativeReporterBase() {} | ||||
|  | ||||
|     ReporterPreferences CumulativeReporterBase::getPreferences() const { | ||||
|         return m_reporterPrefs; | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::testRunStarting(TestRunInfo const &) {} | ||||
|  | ||||
|     void CumulativeReporterBase::testGroupStarting(GroupInfo const &) {} | ||||
|  | ||||
|     void CumulativeReporterBase::testCaseStarting(TestCaseInfo const &) {} | ||||
|  | ||||
|     void CumulativeReporterBase::sectionStarting(SectionInfo const & sectionInfo) { | ||||
|         SectionStats incompleteStats(sectionInfo, Counts(), 0, false); | ||||
|         std::shared_ptr<SectionNode> node; | ||||
|         if (m_sectionStack.empty()) { | ||||
|             if (!m_rootSection) | ||||
|                 m_rootSection = std::make_shared<SectionNode>(incompleteStats); | ||||
|             node = m_rootSection; | ||||
|         } else { | ||||
|             SectionNode& parentNode = *m_sectionStack.back(); | ||||
|             auto it = | ||||
|                 std::find_if(parentNode.childSections.begin(), | ||||
|                              parentNode.childSections.end(), | ||||
|                              BySectionInfo(sectionInfo)); | ||||
|             if (it == parentNode.childSections.end()) { | ||||
|                 node = std::make_shared<SectionNode>(incompleteStats); | ||||
|                 parentNode.childSections.push_back(node); | ||||
|             } else | ||||
|                 node = *it; | ||||
|         } | ||||
|         m_sectionStack.push_back(node); | ||||
|         m_deepestSection = node; | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::assertionStarting(AssertionInfo const &) {} | ||||
|  | ||||
|     bool CumulativeReporterBase::assertionEnded(AssertionStats const & assertionStats) { | ||||
|         assert(!m_sectionStack.empty()); | ||||
|         SectionNode& sectionNode = *m_sectionStack.back(); | ||||
|         sectionNode.assertions.push_back(assertionStats); | ||||
|         // AssertionResult holds a pointer to a temporary DecomposedExpression, | ||||
|         // which getExpandedExpression() calls to build the expression string. | ||||
|         // Our section stack copy of the assertionResult will likely outlive the | ||||
|         // temporary, so it must be expanded or discarded now to avoid calling | ||||
|         // a destroyed object later. | ||||
|         prepareExpandedExpression(sectionNode.assertions.back().assertionResult); | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::sectionEnded(SectionStats const & sectionStats) { | ||||
|         assert(!m_sectionStack.empty()); | ||||
|         SectionNode& node = *m_sectionStack.back(); | ||||
|         node.stats = sectionStats; | ||||
|         m_sectionStack.pop_back(); | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::testCaseEnded(TestCaseStats const & testCaseStats) { | ||||
|         auto node = std::make_shared<TestCaseNode>(testCaseStats); | ||||
|         assert(m_sectionStack.size() == 0); | ||||
|         node->children.push_back(m_rootSection); | ||||
|         m_testCases.push_back(node); | ||||
|         m_rootSection.reset(); | ||||
|  | ||||
|         assert(m_deepestSection); | ||||
|         m_deepestSection->stdOut = testCaseStats.stdOut; | ||||
|         m_deepestSection->stdErr = testCaseStats.stdErr; | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::testGroupEnded(TestGroupStats const & testGroupStats) { | ||||
|         auto node = std::make_shared<TestGroupNode>(testGroupStats); | ||||
|         node->children.swap(m_testCases); | ||||
|         m_testGroups.push_back(node); | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::testRunEnded(TestRunStats const & testRunStats) { | ||||
|         auto node = std::make_shared<TestRunNode>(testRunStats); | ||||
|         node->children.swap(m_testGroups); | ||||
|         m_testRuns.push_back(node); | ||||
|         testRunEndedCumulative(); | ||||
|     } | ||||
|  | ||||
|     void CumulativeReporterBase::skipTest(TestCaseInfo const &) {} | ||||
|  | ||||
|     void CumulativeReporterBase::prepareExpandedExpression(AssertionResult & result) const { | ||||
|         if (result.isOk()) | ||||
|             result.discardDecomposedExpression(); | ||||
|         else | ||||
|             result.expandDecomposedExpression(); | ||||
|     } | ||||
|  | ||||
|     CumulativeReporterBase::SectionNode::SectionNode(SectionStats const& _stats) | ||||
|         :stats(_stats) {} | ||||
|     CumulativeReporterBase::SectionNode::~SectionNode() {} | ||||
|  | ||||
|     bool CumulativeReporterBase::SectionNode::operator==(SectionNode const & other) const { | ||||
|         return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; | ||||
|     } | ||||
|  | ||||
|     bool CumulativeReporterBase::SectionNode::operator==(std::shared_ptr<SectionNode> const& other) const { | ||||
|         return operator==(*other); | ||||
|     } | ||||
|  | ||||
|  | ||||
|     CumulativeReporterBase::BySectionInfo::BySectionInfo(SectionInfo const& other) | ||||
|         :m_other(other) {} | ||||
|  | ||||
|     CumulativeReporterBase::BySectionInfo::BySectionInfo(BySectionInfo const & other) | ||||
|         :m_other(other.m_other) {} | ||||
|  | ||||
|     bool CumulativeReporterBase::BySectionInfo::operator()(std::shared_ptr<SectionNode> const & node) const { | ||||
|         return node->stats.sectionInfo.lineInfo == m_other.lineInfo; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config) | ||||
|         :StreamingReporterBase(_config) {} | ||||
|  | ||||
|   | ||||
| @@ -21,28 +21,62 @@ namespace Catch { | ||||
|     // Returns double formatted as %.3f (format expected on output) | ||||
|     std::string getFormattedDuration( double duration ); | ||||
|  | ||||
|     template<typename DerivedT> | ||||
|     struct StreamingReporterBase : IStreamingReporter { | ||||
|  | ||||
|         StreamingReporterBase(ReporterConfig const& _config); | ||||
|         StreamingReporterBase( ReporterConfig const& _config ) | ||||
|         :   m_config( _config.fullConfig() ), | ||||
|             stream( _config.stream() ) | ||||
|         { | ||||
|             m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|             CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); | ||||
|         } | ||||
|  | ||||
|         virtual ReporterPreferences getPreferences() const override; | ||||
|         virtual ReporterPreferences getPreferences() const override { | ||||
|             return m_reporterPrefs; | ||||
|         } | ||||
|  | ||||
|         virtual ~StreamingReporterBase() override; | ||||
|         static std::set<Verbosity> getSupportedVerbosities() { | ||||
|             return { Verbosity::Normal }; | ||||
|         } | ||||
|  | ||||
|         virtual void noMatchingTestCases(std::string const&) override; | ||||
|         virtual ~StreamingReporterBase() override = default; | ||||
|  | ||||
|         virtual void testRunStarting(TestRunInfo const& _testRunInfo) override; | ||||
|         virtual void testGroupStarting(GroupInfo const& _groupInfo) override; | ||||
|         virtual void noMatchingTestCases(std::string const&) override {} | ||||
|  | ||||
|         virtual void testCaseStarting(TestCaseInfo const& _testInfo) override; | ||||
|         virtual void sectionStarting(SectionInfo const& _sectionInfo) override; | ||||
|         virtual void testRunStarting(TestRunInfo const& _testRunInfo) override { | ||||
|             currentTestRunInfo = _testRunInfo; | ||||
|         } | ||||
|         virtual void testGroupStarting(GroupInfo const& _groupInfo) override { | ||||
|             currentGroupInfo = _groupInfo; | ||||
|         } | ||||
|  | ||||
|         virtual void sectionEnded(SectionStats const& /* _sectionStats */) override; | ||||
|         virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override; | ||||
|         virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override; | ||||
|         virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override; | ||||
|         virtual void testCaseStarting(TestCaseInfo const& _testInfo) override  { | ||||
|             currentTestCaseInfo = _testInfo; | ||||
|         } | ||||
|         virtual void sectionStarting(SectionInfo const& _sectionInfo) override { | ||||
|             m_sectionStack.push_back(_sectionInfo); | ||||
|         } | ||||
|  | ||||
|         virtual void skipTest(TestCaseInfo const&) override; | ||||
|         virtual void sectionEnded(SectionStats const& /* _sectionStats */) override { | ||||
|             m_sectionStack.pop_back(); | ||||
|         } | ||||
|         virtual void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override { | ||||
|             currentTestCaseInfo.reset(); | ||||
|         } | ||||
|         virtual void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override { | ||||
|             currentGroupInfo.reset(); | ||||
|         } | ||||
|         virtual void testRunEnded(TestRunStats const& /* _testRunStats */) override { | ||||
|             currentTestCaseInfo.reset(); | ||||
|             currentGroupInfo.reset(); | ||||
|             currentTestRunInfo.reset(); | ||||
|         } | ||||
|  | ||||
|         virtual void skipTest(TestCaseInfo const&) override { | ||||
|             // Don't do anything with this by default. | ||||
|             // It can optionally be overridden in the derived class. | ||||
|         } | ||||
|  | ||||
|         IConfigPtr m_config; | ||||
|         std::ostream& stream; | ||||
| @@ -55,6 +89,7 @@ namespace Catch { | ||||
|         ReporterPreferences m_reporterPrefs; | ||||
|     }; | ||||
|  | ||||
|     template<typename DerivedT> | ||||
|     struct CumulativeReporterBase : IStreamingReporter { | ||||
|         template<typename T, typename ChildNodeT> | ||||
|         struct Node { | ||||
| @@ -66,11 +101,15 @@ namespace Catch { | ||||
|             ChildNodes children; | ||||
|         }; | ||||
|         struct SectionNode { | ||||
|             explicit SectionNode(SectionStats const& _stats); | ||||
|             virtual ~SectionNode(); | ||||
|             explicit SectionNode(SectionStats const& _stats) : stats(_stats) {} | ||||
|             virtual ~SectionNode() = default; | ||||
|  | ||||
|             bool operator == (SectionNode const& other) const; | ||||
|             bool operator == (std::shared_ptr<SectionNode> const& other) const; | ||||
|             bool operator == (SectionNode const& other) const { | ||||
|                 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; | ||||
|             } | ||||
|             bool operator == (std::shared_ptr<SectionNode> const& other) const { | ||||
|                 return operator==(*other); | ||||
|             } | ||||
|  | ||||
|             SectionStats stats; | ||||
|             using ChildSections = std::vector<std::shared_ptr<SectionNode>>; | ||||
| @@ -82,9 +121,11 @@ namespace Catch { | ||||
|         }; | ||||
|  | ||||
|         struct BySectionInfo { | ||||
|             BySectionInfo(SectionInfo const& other); | ||||
|             BySectionInfo(BySectionInfo const& other); | ||||
|             bool operator() (std::shared_ptr<SectionNode> const& node) const; | ||||
|             BySectionInfo(SectionInfo const& other) : m_other(other) {} | ||||
|             BySectionInfo(BySectionInfo const& other) : m_other(other.m_other) {} | ||||
|             bool operator() (std::shared_ptr<SectionNode> const& node) const { | ||||
|                 return node->stats.sectionInfo.lineInfo == m_other.lineInfo; | ||||
|             } | ||||
|             void operator=(BySectionInfo const&) = delete; | ||||
|  | ||||
|         private: | ||||
| @@ -96,30 +137,105 @@ namespace Catch { | ||||
|         using TestGroupNode = Node<TestGroupStats, TestCaseNode>; | ||||
|         using TestRunNode = Node<TestRunStats, TestGroupNode>; | ||||
|  | ||||
|         CumulativeReporterBase(ReporterConfig const& _config); | ||||
|         ~CumulativeReporterBase(); | ||||
|         CumulativeReporterBase( ReporterConfig const& _config ) | ||||
|         :   m_config( _config.fullConfig() ), | ||||
|             stream( _config.stream() ) | ||||
|         { | ||||
|             m_reporterPrefs.shouldRedirectStdOut = false; | ||||
|             CATCH_ENFORCE( DerivedT::getSupportedVerbosities().count( m_config->verbosity() ), "Verbosity level not supported by this reporter" ); | ||||
|         } | ||||
|         virtual ~CumulativeReporterBase() = default; | ||||
|  | ||||
|         virtual ReporterPreferences getPreferences() const override; | ||||
|         virtual ReporterPreferences getPreferences() const override { | ||||
|             return m_reporterPrefs; | ||||
|         } | ||||
|  | ||||
|         virtual void testRunStarting(TestRunInfo const&) override; | ||||
|         virtual void testGroupStarting(GroupInfo const&) override; | ||||
|         static std::set<Verbosity> getSupportedVerbosities() { | ||||
|             return { Verbosity::Normal }; | ||||
|         } | ||||
|  | ||||
|         virtual void testCaseStarting(TestCaseInfo const&) override; | ||||
|         virtual void testRunStarting( TestRunInfo const& ) override {} | ||||
|         virtual void testGroupStarting( GroupInfo const& ) override {} | ||||
|  | ||||
|         virtual void sectionStarting(SectionInfo const& sectionInfo) override; | ||||
|         virtual void testCaseStarting( TestCaseInfo const& ) override {} | ||||
|  | ||||
|         virtual void assertionStarting(AssertionInfo const&) override; | ||||
|         virtual void sectionStarting( SectionInfo const& sectionInfo ) override { | ||||
|             SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); | ||||
|             std::shared_ptr<SectionNode> node; | ||||
|             if( m_sectionStack.empty() ) { | ||||
|                 if( !m_rootSection ) | ||||
|                     m_rootSection = std::make_shared<SectionNode>( incompleteStats ); | ||||
|                 node = m_rootSection; | ||||
|             } | ||||
|             else { | ||||
|                 SectionNode& parentNode = *m_sectionStack.back(); | ||||
|                 typename SectionNode::ChildSections::const_iterator it = | ||||
|                     std::find_if(   parentNode.childSections.begin(), | ||||
|                                     parentNode.childSections.end(), | ||||
|                                     BySectionInfo( sectionInfo ) ); | ||||
|                 if( it == parentNode.childSections.end() ) { | ||||
|                     node = std::make_shared<SectionNode>( incompleteStats ); | ||||
|                     parentNode.childSections.push_back( node ); | ||||
|                 } | ||||
|                 else | ||||
|                     node = *it; | ||||
|             } | ||||
|             m_sectionStack.push_back( node ); | ||||
|             m_deepestSection = node; | ||||
|         } | ||||
|  | ||||
|         virtual bool assertionEnded(AssertionStats const& assertionStats) override; | ||||
|         virtual void sectionEnded(SectionStats const& sectionStats) override; | ||||
|         virtual void testCaseEnded(TestCaseStats const& testCaseStats) override; | ||||
|         virtual void testGroupEnded(TestGroupStats const& testGroupStats) override; | ||||
|         virtual void testRunEnded(TestRunStats const& testRunStats) override; | ||||
|         virtual void assertionStarting(AssertionInfo const&) override {} | ||||
|  | ||||
|         virtual bool assertionEnded(AssertionStats const& assertionStats) override { | ||||
|             assert(!m_sectionStack.empty()); | ||||
|             SectionNode& sectionNode = *m_sectionStack.back(); | ||||
|             sectionNode.assertions.push_back(assertionStats); | ||||
|             // AssertionResult holds a pointer to a temporary DecomposedExpression, | ||||
|             // which getExpandedExpression() calls to build the expression string. | ||||
|             // Our section stack copy of the assertionResult will likely outlive the | ||||
|             // temporary, so it must be expanded or discarded now to avoid calling | ||||
|             // a destroyed object later. | ||||
|             prepareExpandedExpression(sectionNode.assertions.back().assertionResult); | ||||
|             return true; | ||||
|         } | ||||
|         virtual void sectionEnded(SectionStats const& sectionStats) override { | ||||
|             assert(!m_sectionStack.empty()); | ||||
|             SectionNode& node = *m_sectionStack.back(); | ||||
|             node.stats = sectionStats; | ||||
|             m_sectionStack.pop_back(); | ||||
|         } | ||||
|         virtual void testCaseEnded(TestCaseStats const& testCaseStats) override { | ||||
|             auto node = std::make_shared<TestCaseNode>(testCaseStats); | ||||
|             assert(m_sectionStack.size() == 0); | ||||
|             node->children.push_back(m_rootSection); | ||||
|             m_testCases.push_back(node); | ||||
|             m_rootSection.reset(); | ||||
|          | ||||
|             assert(m_deepestSection); | ||||
|             m_deepestSection->stdOut = testCaseStats.stdOut; | ||||
|             m_deepestSection->stdErr = testCaseStats.stdErr; | ||||
|         } | ||||
|         virtual void testGroupEnded(TestGroupStats const& testGroupStats) override { | ||||
|             auto node = std::make_shared<TestGroupNode>(testGroupStats); | ||||
|             node->children.swap(m_testCases); | ||||
|             m_testGroups.push_back(node); | ||||
|         } | ||||
|         virtual void testRunEnded(TestRunStats const& testRunStats) override { | ||||
|             auto node = std::make_shared<TestRunNode>(testRunStats); | ||||
|             node->children.swap(m_testGroups); | ||||
|             m_testRuns.push_back(node); | ||||
|             testRunEndedCumulative(); | ||||
|         } | ||||
|         virtual void testRunEndedCumulative() = 0; | ||||
|  | ||||
|         virtual void skipTest(TestCaseInfo const&) override; | ||||
|         virtual void skipTest(TestCaseInfo const&) override {} | ||||
|  | ||||
|         virtual void prepareExpandedExpression(AssertionResult& result) const; | ||||
|         virtual void prepareExpandedExpression(AssertionResult& result) const { | ||||
|             if (result.isOk()) | ||||
|                 result.discardDecomposedExpression(); | ||||
|             else | ||||
|                 result.expandDecomposedExpression(); | ||||
|         } | ||||
|  | ||||
|         IConfigPtr m_config; | ||||
|         std::ostream& stream; | ||||
| @@ -147,8 +263,8 @@ namespace Catch { | ||||
|     } | ||||
|  | ||||
|  | ||||
|     struct TestEventListenerBase : StreamingReporterBase { | ||||
|         TestEventListenerBase(ReporterConfig const& _config); | ||||
|     struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> { | ||||
|         TestEventListenerBase( ReporterConfig const& _config ); | ||||
|  | ||||
|         virtual void assertionStarting(AssertionInfo const&) override; | ||||
|         virtual bool assertionEnded(AssertionStats const&) override; | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct CompactReporter : StreamingReporterBase { | ||||
|     struct CompactReporter : StreamingReporterBase<CompactReporter> { | ||||
|  | ||||
|         using StreamingReporterBase::StreamingReporterBase; | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct ConsoleReporter : StreamingReporterBase { | ||||
|     struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> { | ||||
|         using StreamingReporterBase::StreamingReporterBase; | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -48,7 +48,7 @@ namespace Catch { | ||||
|  | ||||
|     } | ||||
|  | ||||
|     class JunitReporter : public CumulativeReporterBase { | ||||
|     class JunitReporter : public CumulativeReporterBase<JunitReporter> { | ||||
|     public: | ||||
|         JunitReporter( ReporterConfig const& _config ) | ||||
|         :   CumulativeReporterBase( _config ), | ||||
|   | ||||
| @@ -18,6 +18,11 @@ namespace Catch { | ||||
|         return m_reporters[0]->getPreferences(); | ||||
|     } | ||||
|  | ||||
|     std::set<Verbosity> getSupportedVerbosities() { | ||||
|         return { }; | ||||
|     } | ||||
|  | ||||
|      | ||||
|     void MultipleReporters::noMatchingTestCases( std::string const& spec ) { | ||||
|         for( auto const& reporter : m_reporters ) | ||||
|             reporter->noMatchingTestCases( spec ); | ||||
|   | ||||
							
								
								
									
										64
									
								
								include/reporters/catch_reporter_multi.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								include/reporters/catch_reporter_multi.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| /* | ||||
|  *  Created by Phil on 5/08/2015. | ||||
|  *  Copyright 2015 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_REPORTER_MULTI_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED | ||||
|  | ||||
| #include "../internal/catch_interfaces_reporter.h" | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
| class MultipleReporters : public IStreamingReporter { | ||||
|     typedef std::vector<IStreamingReporterPtr> Reporters; | ||||
|     Reporters m_reporters; | ||||
|  | ||||
| public: | ||||
|     void add( IStreamingReporterPtr&& reporter ); | ||||
|  | ||||
| public: // IStreamingReporter | ||||
|  | ||||
|     virtual ReporterPreferences getPreferences() const override; | ||||
|  | ||||
|     static std::set<Verbosity> getSupportedVerbosities(); | ||||
|  | ||||
|     virtual void noMatchingTestCases( std::string const& spec ) override; | ||||
|  | ||||
|  | ||||
|     virtual void testRunStarting( TestRunInfo const& testRunInfo ) override; | ||||
|  | ||||
|     virtual void testGroupStarting( GroupInfo const& groupInfo ) override; | ||||
|  | ||||
|  | ||||
|     virtual void testCaseStarting( TestCaseInfo const& testInfo ) override; | ||||
|  | ||||
|     virtual void sectionStarting( SectionInfo const& sectionInfo ) override; | ||||
|  | ||||
|  | ||||
|     virtual void assertionStarting( AssertionInfo const& assertionInfo ) override; | ||||
|  | ||||
|  | ||||
|     // The return value indicates if the messages buffer should be cleared: | ||||
|     virtual bool assertionEnded( AssertionStats const& assertionStats ) override; | ||||
|  | ||||
|     virtual void sectionEnded( SectionStats const& sectionStats ) override; | ||||
|  | ||||
|     virtual void testCaseEnded( TestCaseStats const& testCaseStats ) override; | ||||
|  | ||||
|     virtual void testGroupEnded( TestGroupStats const& testGroupStats ) override; | ||||
|  | ||||
|     virtual void testRunEnded( TestRunStats const& testRunStats ) override; | ||||
|  | ||||
|  | ||||
|     virtual void skipTest( TestCaseInfo const& testInfo ) override; | ||||
|  | ||||
|     virtual bool isMulti() const override; | ||||
|  | ||||
| }; | ||||
|  | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED | ||||
| @@ -19,7 +19,7 @@ | ||||
|  | ||||
| namespace Catch { | ||||
|  | ||||
|     struct TAPReporter : StreamingReporterBase { | ||||
|     struct TAPReporter : StreamingReporterBase<TAPReporter> { | ||||
|  | ||||
|         using StreamingReporterBase::StreamingReporterBase; | ||||
|  | ||||
|   | ||||
| @@ -25,7 +25,7 @@ namespace Catch { | ||||
|  | ||||
|     using namespace clara::TextFlow; | ||||
|  | ||||
|     struct TeamCityReporter : StreamingReporterBase { | ||||
|     struct TeamCityReporter : StreamingReporterBase<TeamCityReporter> { | ||||
|         TeamCityReporter( ReporterConfig const& _config ) | ||||
|         :   StreamingReporterBase( _config ) | ||||
|         { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
| #include "../internal/catch_timer.h" | ||||
|  | ||||
| namespace Catch { | ||||
|     class XmlReporter : public StreamingReporterBase { | ||||
|     class XmlReporter : public StreamingReporterBase<XmlReporter> { | ||||
|     public: | ||||
|         XmlReporter( ReporterConfig const& _config ) | ||||
|         :   StreamingReporterBase( _config ), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin Hořeňovský
					Martin Hořeňovský