mirror of
				https://github.com/catchorg/Catch2.git
				synced 2025-10-31 20:27:11 +01:00 
			
		
		
		
	Fairly major reworking of console reporter (still in progress).
Changed reporter interface a bit.
This commit is contained in:
		| @@ -13,6 +13,7 @@ | ||||
| #include "internal/catch_runner_impl.hpp" | ||||
| #include "internal/catch_test_spec.h" | ||||
| #include "internal/catch_version.h" | ||||
| #include "internal/catch_line_wrap.h" | ||||
|  | ||||
| #include <fstream> | ||||
| #include <stdlib.h> | ||||
| @@ -42,13 +43,10 @@ namespace Catch { | ||||
|             Runner context( m_configWrapper, m_reporter ); // This Runner will be renamed Context | ||||
|             Totals totals; | ||||
|  | ||||
|             std::vector<TestCaseFilters>::const_iterator it = filterGroups.begin(); | ||||
|             std::vector<TestCaseFilters>::const_iterator itEnd = filterGroups.end(); | ||||
|  | ||||
|             for(; it != itEnd && !context.aborting(); ++it ) { | ||||
|                 context.testGroupStarting( it->getName() ); | ||||
|                 totals += runTestsForGroup( context, *it ); | ||||
|                 context.testGroupEnded( it->getName(), totals ); | ||||
|             for( std::size_t i=0; i < filterGroups.size() && !context.aborting(); ++i ) { | ||||
|                 context.testGroupStarting( filterGroups[i].getName(), i, filterGroups.size() ); | ||||
|                 totals += runTestsForGroup( context, filterGroups[i] ); | ||||
|                 context.testGroupEnded( filterGroups[i].getName(), totals, i, filterGroups.size() ); | ||||
|             } | ||||
|             return totals; | ||||
|         } | ||||
| @@ -153,50 +151,6 @@ namespace Catch { | ||||
|         os << "\nFor more detail usage please see: https://github.com/philsquared/Catch/wiki/Command-line\n" << std::endl; | ||||
|     } | ||||
|  | ||||
|     inline void addIndent( std::ostream& os, std::size_t indent ) { | ||||
|         while( indent-- > 0 ) | ||||
|             os << ' '; | ||||
|     } | ||||
|  | ||||
|     inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) { | ||||
|         std::size_t width = columns-indent; | ||||
|         std::size_t tab = 0; | ||||
|         std::size_t wrapPoint = width; | ||||
|         for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) { | ||||
|             if( pos == width ) { | ||||
|                 addIndent( os, indent ); | ||||
|                 os << paragraph.substr( 0, wrapPoint ) << "\n"; | ||||
|                 return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab ); | ||||
|             } | ||||
|             if( paragraph[pos] == '\t' ) { | ||||
|                     tab = pos; | ||||
|                     paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 ); | ||||
|                     pos--; | ||||
|             } | ||||
|             else if( paragraph[pos] == ' ' ) { | ||||
|                 wrapPoint = pos; | ||||
|             } | ||||
|         } | ||||
|         addIndent( os, indent ); | ||||
|         os << paragraph << "\n"; | ||||
|     } | ||||
|  | ||||
|     inline std::string addLineBreaks( const std::string& str, std::size_t columns, std::size_t indent = 0 ) { | ||||
|         std::ostringstream oss; | ||||
|         std::string::size_type pos = 0; | ||||
|         std::string::size_type newline = str.find_first_of( '\n' ); | ||||
|         while( newline != std::string::npos ) { | ||||
|             std::string paragraph = str.substr( pos, newline-pos ); | ||||
|             recursivelyWrapLine( oss, paragraph, columns, indent ); | ||||
|             pos = newline+1; | ||||
|             newline = str.find_first_of( '\n', pos ); | ||||
|         } | ||||
|         if( pos != str.size() ) | ||||
|             recursivelyWrapLine( oss, str.substr( pos, str.size()-pos ), columns, indent ); | ||||
|  | ||||
|         return oss.str(); | ||||
|     } | ||||
|  | ||||
|     inline void showHelp( const CommandParser& parser ) { | ||||
|         AllOptions options; | ||||
|         Options::HelpOptionParser helpOpt; | ||||
| @@ -207,8 +161,7 @@ namespace Catch { | ||||
|                 displayedSpecificOption = true; | ||||
|                 std::cout   << "\n" << opt.optionNames() << " " << opt.argsSynopsis() << "\n\n" | ||||
|                             << opt.optionSummary() << "\n\n" | ||||
|  | ||||
|                 << addLineBreaks( opt.optionDescription(), 80, 2 ) << "\n" << std::endl; | ||||
|                             << wrapLongStrings( opt.optionDescription(), 80, 2 ) << "\n" << std::endl; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -119,9 +119,9 @@ namespace Catch { | ||||
|      | ||||
|     inline std::ostream& operator << ( std::ostream& os, const SourceLineInfo& info ) { | ||||
| #ifndef __GNUG__ | ||||
|         os << info.file << "(" << info.line << "): "; | ||||
|         os << info.file << "(" << info.line << ")"; | ||||
| #else                 | ||||
|         os << info.file << ":" << info.line << ": ";             | ||||
|         os << info.file << ":" << info.line; | ||||
| #endif             | ||||
|         return os; | ||||
|     } | ||||
| @@ -129,7 +129,7 @@ namespace Catch { | ||||
|     CATCH_ATTRIBUTE_NORETURN | ||||
|     inline void throwLogicError( const std::string& message, const SourceLineInfo& locationInfo ) { | ||||
|         std::ostringstream oss; | ||||
|         oss << "Internal Catch error: '" << message << "' at: " << locationInfo; | ||||
|         oss << locationInfo << ": Internal Catch error: '" << message << "'"; | ||||
|         throw std::logic_error( oss.str() ); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -27,6 +27,7 @@ | ||||
| #include "catch_test_case_info.hpp" | ||||
| #include "catch_tags.hpp" | ||||
| #include "catch_version.hpp" | ||||
| #include "catch_line_wrap.hpp" | ||||
|  | ||||
| #include "../reporters/catch_reporter_basic.hpp" | ||||
| #include "../reporters/catch_reporter_xml.hpp" | ||||
|   | ||||
| @@ -49,8 +49,17 @@ namespace Catch | ||||
|         std::string name; | ||||
|     }; | ||||
|     struct GroupInfo { | ||||
|         GroupInfo( std::string const& _name ) : name( _name ) {} | ||||
|         GroupInfo(  std::string const& _name, | ||||
|                     std::size_t _groupIndex, | ||||
|                     std::size_t _groupsCount ) | ||||
|         :   name( _name ), | ||||
|             groupIndex( _groupIndex ), | ||||
|             groupsCounts( _groupsCount ) | ||||
|         {} | ||||
|  | ||||
|         std::string name; | ||||
|         std::size_t groupIndex; | ||||
|         std::size_t groupsCounts; | ||||
|     }; | ||||
|  | ||||
|     struct SectionInfo { | ||||
| @@ -174,7 +183,7 @@ namespace Catch | ||||
|     struct IStreamingReporter : IShared { | ||||
|         virtual ~IStreamingReporter(); | ||||
|  | ||||
|         // Implementing class must also provide the following static methid: | ||||
|         // Implementing class must also provide the following static method: | ||||
|         // static std::string getDescription(); | ||||
|  | ||||
|         virtual ReporterPreferences getPreferences() const = 0; | ||||
|   | ||||
							
								
								
									
										20
									
								
								include/internal/catch_line_wrap.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								include/internal/catch_line_wrap.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| /* | ||||
|  *  Created by Phil on 11/1/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_LINE_WRAP_H_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_LINE_WRAP_H_INCLUDED | ||||
|  | ||||
| #include <string> | ||||
|  | ||||
| namespace Catch { | ||||
|      | ||||
|     void wrapLongStrings( std::ostream& stream, const std::string& str, std::size_t columns, std::size_t indent = 0 ); | ||||
|     std::string wrapLongStrings( const std::string& str, std::size_t columns, std::size_t indent = 0 ); | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_LINE_WRAP_H_INCLUDED | ||||
							
								
								
									
										67
									
								
								include/internal/catch_line_wrap.hpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								include/internal/catch_line_wrap.hpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /* | ||||
|  *  Created by Phil on 11/1/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_LINE_WRAP_HPP_INCLUDED | ||||
| #define TWOBLUECUBES_CATCH_LINE_WRAP_HPP_INCLUDED | ||||
|  | ||||
| #include "catch_line_wrap.h" | ||||
|  | ||||
| namespace Catch { | ||||
|      | ||||
|     namespace { | ||||
|         inline void addIndent( std::ostream& os, std::size_t indent ) { | ||||
|             while( indent-- > 0 ) | ||||
|                 os << ' '; | ||||
|         } | ||||
|          | ||||
|         inline void recursivelyWrapLine( std::ostream& os, std::string paragraph, std::size_t columns, std::size_t indent ) { | ||||
|             std::size_t width = columns-indent; | ||||
|             std::size_t tab = 0; | ||||
|             std::size_t wrapPoint = width; | ||||
|             for( std::size_t pos = 0; pos < paragraph.size(); ++pos ) { | ||||
|                 if( pos == width ) { | ||||
|                     addIndent( os, indent ); | ||||
|                     os << paragraph.substr( 0, wrapPoint ) << "\n"; | ||||
|                     return recursivelyWrapLine( os, paragraph.substr( wrapPoint+1 ), columns, indent+tab ); | ||||
|                 } | ||||
|                 if( paragraph[pos] == '\t' ) { | ||||
|                     tab = pos; | ||||
|                     paragraph = paragraph.substr( 0, tab ) + paragraph.substr( tab+1 ); | ||||
|                     pos--; | ||||
|                 } | ||||
|                 else if( paragraph[pos] == ' ' ) { | ||||
|                     wrapPoint = pos; | ||||
|                 } | ||||
|             } | ||||
|             addIndent( os, indent ); | ||||
|             os << paragraph; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     void wrapLongStrings( std::ostream& stream, const std::string& str, std::size_t columns, std::size_t indent ) { | ||||
|         std::string::size_type pos = 0; | ||||
|         std::string::size_type newline = str.find_first_of( '\n' ); | ||||
|         while( newline != std::string::npos ) { | ||||
|             std::string paragraph = str.substr( pos, newline-pos ); | ||||
|             recursivelyWrapLine( stream, paragraph, columns, indent ); | ||||
|             stream << "\n"; | ||||
|             pos = newline+1; | ||||
|             newline = str.find_first_of( '\n', pos ); | ||||
|         } | ||||
|         if( pos != str.size() ) | ||||
|             recursivelyWrapLine( stream, str.substr( pos, str.size()-pos ), columns, indent ); | ||||
|     } | ||||
|  | ||||
|     std::string wrapLongStrings( const std::string& str, std::size_t columns, std::size_t indent ) { | ||||
|         std::ostringstream oss; | ||||
|         wrapLongStrings( oss, str, columns, indent ); | ||||
|         return oss.str();         | ||||
|     } | ||||
|      | ||||
| } // end namespace Catch | ||||
|  | ||||
| #endif // TWOBLUECUBES_CATCH_LINE_WRAP_HPP_INCLUDED | ||||
| @@ -16,7 +16,7 @@ namespace Catch { | ||||
|     NotImplementedException::NotImplementedException( const SourceLineInfo& lineInfo ) | ||||
|     :   m_lineInfo( lineInfo ) { | ||||
|         std::ostringstream oss; | ||||
|         oss << lineInfo << "function "; | ||||
|         oss << lineInfo << ": function "; | ||||
|         oss << "not implemented"; | ||||
|         m_what = oss.str(); | ||||
|     } | ||||
|   | ||||
| @@ -80,27 +80,27 @@ namespace Catch { | ||||
|             m_context.setConfig( m_prevConfig ); | ||||
|         } | ||||
|  | ||||
|         void testGroupStarting( std::string const& testSpec ) { | ||||
|             m_reporter->testGroupStarting( GroupInfo( testSpec ) ); | ||||
|         void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { | ||||
|             m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); | ||||
|         } | ||||
|         void testGroupEnded( std::string const& testSpec, Totals const& totals ) { | ||||
|             m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec ), totals, aborting() ) ); | ||||
|         void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { | ||||
|             m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); | ||||
|         } | ||||
|  | ||||
|         Totals runMatching( const std::string& testSpec ) { | ||||
|         Totals runMatching( const std::string& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { | ||||
|  | ||||
|             std::vector<TestCase> matchingTests = getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec ); | ||||
|  | ||||
|             Totals totals; | ||||
|              | ||||
|             testGroupStarting( testSpec ); | ||||
|             testGroupStarting( testSpec, groupIndex, groupsCount ); | ||||
|  | ||||
|             std::vector<TestCase>::const_iterator it = matchingTests.begin(); | ||||
|             std::vector<TestCase>::const_iterator itEnd = matchingTests.end(); | ||||
|             for(; it != itEnd; ++it ) | ||||
|                 totals += runTest( *it ); | ||||
|  | ||||
|             testGroupEnded( testSpec, totals ); | ||||
|             testGroupEnded( testSpec, totals, groupIndex, groupsCount ); | ||||
|             return totals; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -167,7 +167,7 @@ namespace Catch { | ||||
|              | ||||
|             if( !assertionResult.getSourceInfo().empty() ) { | ||||
|                 TextColour colour( TextColour::FileName ); | ||||
|                 m_config.stream() << assertionResult.getSourceInfo(); | ||||
|                 m_config.stream() << assertionResult.getSourceInfo() << ": "; | ||||
|             } | ||||
|              | ||||
|             if( assertionResult.hasExpression() ) { | ||||
|   | ||||
| @@ -30,15 +30,67 @@ namespace Catch { | ||||
|             return prefs; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         static std::string const& getDashes() { | ||||
|             static const std::string dashes = "----------------------------------------------------------------"; | ||||
|             return dashes; | ||||
|         } | ||||
|         static std::string const& getDoubleDashes() { | ||||
|             static const std::string doubleDashes = "================================================================"; | ||||
|             return doubleDashes; | ||||
|         } | ||||
|         static std::string const& getSpaces() { | ||||
|             static const std::string spaces = "                                                               "; | ||||
|             return spaces; | ||||
|         } | ||||
|         static std::string getSpaces( int spaces ) { | ||||
|             return getSpaces().substr( 0, spaces > 0 ? static_cast<std::size_t>( spaces ) : 0 ); | ||||
|         } | ||||
|          | ||||
|         void printHeader( std::string const& _type, std::string const& _name ) { | ||||
|             stream  << getDashes() << "\n" | ||||
|                     << _type << ": '" << _name << "'\n" | ||||
|                     << getDashes() << std::endl; | ||||
|         } | ||||
|          | ||||
|         void lazyPrint() { | ||||
|             bool needsNewline = unusedTestCaseInfo || ( currentSectionInfo && !currentSectionInfo->printed ); | ||||
|             if( m_lazyTestCaseStats ) | ||||
|                 lazyPrintTestCaseStats(); | ||||
|             if( testRunInfo ) | ||||
|                 lazyPrintRunInfo(); | ||||
|             if( unusedGroupInfo ) | ||||
|                 lazyPrintGroupInfo(); | ||||
|             if( unusedTestCaseInfo ) | ||||
|                 lazyPrintTestCaseInfo(); | ||||
|             if( currentSectionInfo && !currentSectionInfo->printed ) | ||||
|                 lazyPrintSectionInfo(); | ||||
|             if( needsNewline ) | ||||
|                 stream << "\n"; | ||||
|              | ||||
|         } | ||||
|         void lazyPrintTestCaseStats() { | ||||
|             printTestCaseStats( *m_lazyTestCaseStats ); | ||||
|             m_lazyTestCaseStats.reset(); | ||||
|         } | ||||
|         void lazyPrintRunInfo() { | ||||
|             printHeader( "Started testing", testRunInfo->name ); | ||||
|             stream  << "\n"  << testRunInfo->name | ||||
|                     << " is a CATCH v"  << libraryVersion.majorVersion << "." | ||||
|                     << libraryVersion.minorVersion << " b" | ||||
|                     << libraryVersion.buildNumber; | ||||
|             if( libraryVersion.branchName != "master" ) | ||||
|                 stream << " (" << libraryVersion.branchName << ")"; | ||||
|             stream  << " host application.\n" | ||||
|                     << "Run with -? for options\n\n"; | ||||
|              | ||||
|             testRunInfo.reset(); | ||||
|         } | ||||
|         void lazyPrintGroupInfo() { | ||||
|             if( !unusedGroupInfo->name.empty() ) | ||||
|             if( !unusedGroupInfo->name.empty() && unusedGroupInfo->groupsCounts > 1 ) { | ||||
|                 printHeader( "Group", unusedGroupInfo->name ); | ||||
|                 unusedGroupInfo.reset(); | ||||
|             } | ||||
|         } | ||||
|         void lazyPrintTestCaseInfo() { | ||||
|             printHeader( "Test case", unusedTestCaseInfo->name ); | ||||
|             unusedTestCaseInfo.reset(); | ||||
| @@ -58,45 +110,10 @@ namespace Catch { | ||||
|             unusedSectionInfo.reset(); | ||||
|         } | ||||
|          | ||||
|         static std::string const& getDashes() { | ||||
|             static const std::string dashes = "----------------------------------------------------------------"; | ||||
|             return dashes; | ||||
|         } | ||||
|         static std::string const& getDoubleDashes() { | ||||
|             static const std::string doubleDashes = "================================================================"; | ||||
|             return doubleDashes; | ||||
|         } | ||||
|         static std::string const& getSpaces() { | ||||
|             static const std::string spaces = "                                                               "; | ||||
|             return spaces; | ||||
|         } | ||||
|         static std::string getSpaces( int spaces ) { | ||||
|             return getSpaces().substr( 0, spaces > 0 ? static_cast<std::size_t>( spaces ) : 0 ); | ||||
|         } | ||||
|          | ||||
|         void printHeader( std::string const& _type, std::string const& _name ) { | ||||
|             std::size_t labelLen =  _type.size() + _name.size() + 8; | ||||
|             std::size_t dashLen = getDashes().size(); | ||||
|             stream  << "-- " << _type << ": '" << _name << "' " | ||||
|                     << getDashes().substr( 0, labelLen < dashLen ? dashLen - labelLen : 0 ) | ||||
|                     << std::endl; | ||||
|         } | ||||
|  | ||||
|         void lazyPrint() { | ||||
|             if( testRunInfo ) | ||||
|                 lazyPrintRunInfo(); | ||||
|             if( unusedGroupInfo ) | ||||
|                 lazyPrintGroupInfo(); | ||||
|             if( unusedTestCaseInfo ) | ||||
|                 lazyPrintTestCaseInfo(); | ||||
|             if( currentSectionInfo && !currentSectionInfo->printed ) | ||||
|                 lazyPrintSectionInfo(); | ||||
|         } | ||||
|  | ||||
|         virtual void assertionStarting( AssertionInfo const& ) { | ||||
|         } | ||||
|         virtual void assertionEnded( AssertionStats const& _assertionStats ) { | ||||
|  | ||||
|         virtual void assertionEnded( AssertionStats const& _assertionStats ) { | ||||
|             AssertionResult const& result = _assertionStats.assertionResult; | ||||
|              | ||||
|             // Drop out if result was successful and we're not printing those | ||||
| @@ -105,111 +122,91 @@ namespace Catch { | ||||
|              | ||||
|             lazyPrint(); | ||||
|  | ||||
|             int inset = printLineInfo( result.getSourceInfo() ); | ||||
|             { | ||||
|                 TextColour colour( TextColour::FileName ); | ||||
|                 stream << result.getSourceInfo() << ":\n"; | ||||
|             } | ||||
|              | ||||
|             if( result.hasExpression() ) { | ||||
|                 TextColour colour( TextColour::OriginalExpression ); | ||||
|                 stream << result.getExpression() << "\n"; | ||||
|                 if( result.succeeded() ) { | ||||
|             if( _assertionStats.totals.assertions.total() > 0 ) { | ||||
|                 printOriginalExpression( result ); | ||||
|                 printResultType( result ); | ||||
|                 printReconstructedExpression( result ); | ||||
|             } | ||||
|             printMessage( result ); | ||||
|             stream << std::endl; | ||||
|         } | ||||
|          | ||||
|         void printResultType( AssertionResult const& _result ) { | ||||
|             if( _result.succeeded() ) { | ||||
|                 TextColour successColour( TextColour::Success ); | ||||
|                     stream << "succeeded"; | ||||
|                 stream << "passed"; | ||||
|             } | ||||
|             else if( _result.isOk() ) { | ||||
|                 TextColour okAnywayColour( TextColour::Success ); | ||||
|                 stream << "failed - but was ok"; | ||||
|             } | ||||
|             else { | ||||
|                 TextColour errorColour( TextColour::Error ); | ||||
|                 stream << "failed"; | ||||
|                     if( result.isOk() ) { | ||||
|                         TextColour okAnywayColour( TextColour::Success ); | ||||
|                         stream << " - but was ok"; | ||||
|                     } | ||||
|             } | ||||
|         } | ||||
|          | ||||
|             switch( result.getResultType() ) { | ||||
|         void printMessage( AssertionResult const& _result ) { | ||||
|             std::pair<std::string, std::string> message = getMessage( _result ); | ||||
|             if( !message.first.empty() ) | ||||
|                 stream << " " << message.first << ":\n"; | ||||
|             if( !message.second.empty() ) | ||||
|                 printWrappableString( message.second ); | ||||
|         } | ||||
|         std::pair<std::string, std::string> getMessage( AssertionResult const& _result ) { | ||||
|             switch( _result.getResultType() ) { | ||||
|                 case ResultWas::ThrewException: | ||||
|                 { | ||||
|                     TextColour colour( TextColour::Error ); | ||||
|                     if( result.hasExpression() ) | ||||
|                         stream << " with unexpected"; | ||||
|                     else | ||||
|                         stream << "Unexpected"; | ||||
|                     stream << " exception with message: '" << result.getMessage() << "'"; | ||||
|                 } | ||||
|                     break; | ||||
|                     return std::make_pair( "due to unexpected exception with message", _result.getMessage() ); | ||||
|                 case ResultWas::DidntThrowException: | ||||
|                 { | ||||
|                     TextColour colour( TextColour::Error ); | ||||
|                     if( result.hasExpression() ) | ||||
|                         stream << " because no exception was thrown where one was expected"; | ||||
|                     else | ||||
|                         stream << "No exception thrown where one was expected"; | ||||
|                 } | ||||
|                     break; | ||||
|                     return std::make_pair( "because no exception was thrown where one was expected", "" ); | ||||
|                 case ResultWas::Info: | ||||
|                 { | ||||
|                     TextColour colour( TextColour::ReconstructedExpression ); | ||||
|                     streamVariableLengthText( "info", result.getMessage() ); | ||||
|                 } | ||||
|                     break; | ||||
|                     return std::make_pair( "with info", _result.getMessage() ); | ||||
|                 case ResultWas::Warning: | ||||
|                 { | ||||
|                     TextColour colour( TextColour::ReconstructedExpression ); | ||||
|                     streamVariableLengthText( "warning", result.getMessage() ); | ||||
|                 } | ||||
|                     break; | ||||
|                     return std::make_pair( "with warning", _result.getMessage() ); | ||||
|                 case ResultWas::ExplicitFailure: | ||||
|                 { | ||||
|                     TextColour colour( TextColour::Error ); | ||||
|                     stream << "failed with message: '" << result.getMessage() << "'"; | ||||
|                 } | ||||
|                     break; | ||||
|                     return std::make_pair( "explicitly with message", _result.getMessage() ); | ||||
|  | ||||
|                 case ResultWas::Unknown: // These cases are here to prevent compiler warnings | ||||
|                 case ResultWas::Ok: | ||||
|                 case ResultWas::FailureBit: | ||||
|                 case ResultWas::ExpressionFailed: | ||||
|                 case ResultWas::Exception: | ||||
|                     if( !result.hasExpression() ) { | ||||
|                         if( result.succeeded() ) { | ||||
|                             TextColour colour( TextColour::Success ); | ||||
|                             stream << " succeeded"; | ||||
|                         } | ||||
|                         else { | ||||
|                             TextColour colour( TextColour::Error ); | ||||
|                             stream << " failed"; | ||||
|                             if( result.isOk() ) { | ||||
|                                 TextColour okAnywayColour( TextColour::Success ); | ||||
|                                 stream << " - but was ok"; | ||||
|                     if( _result.hasMessage() ) | ||||
|                         return std::make_pair( "with message", _result.getMessage() ); | ||||
|                     else | ||||
|                         return std::make_pair( "", "" ); | ||||
|             } | ||||
|         } | ||||
|         void printOriginalExpression( AssertionResult const& _result ) { | ||||
|             if( _result.hasExpression() ) { | ||||
|                 TextColour colour( TextColour::OriginalExpression ); | ||||
|                 stream  << "  " << _result.getTestMacroName() << "( " | ||||
|                         << _result.getExpression() | ||||
|                         << " )\n"; | ||||
|             } | ||||
|                     if( result.hasMessage() ) { | ||||
|                         stream << "\n"; | ||||
|         } | ||||
|         void printReconstructedExpression( AssertionResult const& _result ) { | ||||
|             if( _result.hasExpandedExpression() ) { | ||||
|                 stream << " with expansion:\n"; | ||||
|                 TextColour colour( TextColour::ReconstructedExpression ); | ||||
|                         streamVariableLengthText( "with message", result.getMessage() ); | ||||
|                     } | ||||
|                     break; | ||||
|             } | ||||
|  | ||||
|             if( result.hasExpandedExpression() ) { | ||||
|                 stream << "\nfor: "; | ||||
|                 TextColour colour( TextColour::ReconstructedExpression ); | ||||
|                 stream << getSpaces( inset-5 ) << result.getExpandedExpression(); | ||||
|             } | ||||
|              | ||||
|             stream << "\n" << std::endl; | ||||
|         } | ||||
|          | ||||
|         void streamVariableLengthText( std::string const& prefix, std::string const& text ) { | ||||
|             std::string trimmed = trim( text ); | ||||
|             if( trimmed.find_first_of( "\r\n" ) == std::string::npos ) { | ||||
|                 stream << "[" << prefix << ": " << trimmed << "]"; | ||||
|             } | ||||
|             else { | ||||
|                 stream  << "\n[" << prefix << "] >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>\n" << trimmed | ||||
|                         << "\n[end of " << prefix << "] <<<<<<<<<<<<<<<<<<<<<<<<\n"; | ||||
|                 printWrappableString( _result.getExpandedExpression() ); | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         void printAssertionCounts( std::string const& label, Counts const& counts ) { | ||||
|         void printWrappableString( std::string const& _string ) { | ||||
|             stream << wrapLongStrings( _string ) << "\n"; | ||||
|         } | ||||
|  | ||||
|         std::string wrapLongStrings( std::string const& _string ) { | ||||
|             return Catch::wrapLongStrings( _string, 70, 2 ); | ||||
|         } | ||||
|          | ||||
|         void printCounts( std::string const& label, Counts const& counts ) { | ||||
|             if( counts.total() == 1 ) { | ||||
|                 stream << "1 " << label << " - "; | ||||
|                 if( counts.failed ) | ||||
| @@ -242,10 +239,10 @@ namespace Catch { | ||||
|             } | ||||
|             else if( totals.assertions.failed ) { | ||||
|                 TextColour colour( TextColour::ResultError ); | ||||
|                 printAssertionCounts( "test case", totals.testCases ); | ||||
|                 printCounts( "test case", totals.testCases ); | ||||
|                 if( totals.testCases.failed > 0 ) { | ||||
|                     stream << " ("; | ||||
|                     printAssertionCounts( "assertion", totals.assertions ); | ||||
|                     printCounts( "assertion", totals.assertions ); | ||||
|                     stream << ")"; | ||||
|                 } | ||||
|             } | ||||
| @@ -258,48 +255,36 @@ namespace Catch { | ||||
|         } | ||||
|  | ||||
|         virtual void sectionEnded( SectionStats const& _sectionStats ) { | ||||
|             resetLastPrintedLine(); | ||||
|             if( _sectionStats.missingAssertions ) { | ||||
|                 lazyPrint(); | ||||
|                 TextColour colour( TextColour::ResultError ); | ||||
|                 stream << "\nNo assertions in section, '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; | ||||
|             } | ||||
|             if( currentSectionInfo && currentSectionInfo->printed ) { | ||||
|                 printSummarDivider(); | ||||
|                 stream << "Summary for section '" << _sectionStats.sectionInfo.name << "':\n"; | ||||
|                 Counts const& assertions = _sectionStats.assertions; | ||||
|                 if( assertions.failed ) { | ||||
|                     TextColour colour( TextColour::ResultError ); | ||||
|                     printAssertionCounts( "assertion", assertions ); | ||||
|                 } | ||||
|                 else { | ||||
|                     TextColour colour( TextColour::ResultSuccess ); | ||||
|                     stream  << ( assertions.passed > 1 ? "All " : "" ) | ||||
|                             << pluralise( assertions.passed, "assertion" ) << " passed" ; | ||||
|                 } | ||||
|                 stream << "\n" << std::endl; | ||||
|             } | ||||
|             StreamingReporterBase::sectionEnded( _sectionStats ); | ||||
|         } | ||||
|         void printTestCaseStats( TestCaseStats const& _testCaseStats ) { | ||||
|             m_atLeastOneTestCasePrinted = true; | ||||
|         } | ||||
|  | ||||
|         virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) { | ||||
|             resetLastPrintedLine(); | ||||
|  | ||||
|             if( _testCaseStats.missingAssertions ) { | ||||
|                 lazyPrint(); | ||||
|                 TextColour colour( TextColour::ResultError ); | ||||
|                 stream << "\nNo assertions in test case, '" << _testCaseStats.testInfo.name << "'\n" << std::endl; | ||||
|             } | ||||
|             if( !unusedTestCaseInfo ) { | ||||
|                 m_atLeastOneTestCasePrinted = true; | ||||
|                 printSummarDivider(); | ||||
|                 stream << "Summary for test case '" << _testCaseStats.testInfo.name << "':\n"; | ||||
|                 printTotals( _testCaseStats.totals ); | ||||
|                 stream << "\n" << std::endl; | ||||
|                 if( m_atLeastOneTestCasePrinted ) | ||||
|                     printTestCaseStats( _testCaseStats ); | ||||
|                 else | ||||
|                     m_lazyTestCaseStats = _testCaseStats; | ||||
|             } | ||||
|  | ||||
|             StreamingReporterBase::testCaseEnded( _testCaseStats ); | ||||
|         } | ||||
|         virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) { | ||||
|             if( !unusedGroupInfo ) { | ||||
|                 printSummarDivider(); | ||||
|                 printSummaryDivider(); | ||||
|                 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; | ||||
|                 printTotals( _testGroupStats.totals ); | ||||
|                 stream << "\n" << std::endl; | ||||
| @@ -309,7 +294,7 @@ namespace Catch { | ||||
|         virtual void testRunEnded( TestRunStats const& _testRunStats ) { | ||||
|             if( m_atLeastOneTestCasePrinted ) | ||||
|                 printTotalsDivider(); | ||||
|             stream << "Summary for all tests in '" << _testRunStats.runInfo.name << "':\n"; | ||||
| //            stream << "Summary for all tests in '" << _testRunStats.runInfo.name << "':\n"; | ||||
|             printTotals( _testRunStats.totals ); | ||||
|             stream << "\n" << std::endl; | ||||
|             StreamingReporterBase::testRunEnded( _testRunStats ); | ||||
| @@ -317,37 +302,15 @@ namespace Catch { | ||||
|  | ||||
|     private: | ||||
|         void printTotalsDivider() { | ||||
|             stream << "================================================================\n"; | ||||
|             stream << getDoubleDashes() << "\n"; | ||||
|         } | ||||
|         void printSummarDivider() { | ||||
|             stream << "----------------------------------------------------------------\n"; | ||||
|         } | ||||
|         static int countDigits( std::size_t number ) { | ||||
|             int digits = 1; | ||||
|             for( ; number != 0; digits++, number /= 10 ); | ||||
|             return digits; | ||||
|         void printSummaryDivider() { | ||||
|             stream << getDashes() << "\n"; | ||||
|         } | ||||
|          | ||||
|         // Returns number of characters printed | ||||
|         int printLineInfo( SourceLineInfo const& lineInfo ) { | ||||
|             if( lineInfo.empty() ) | ||||
|                 return 0; | ||||
|             if( m_lastPrintedLine.empty() || | ||||
|                     m_lastPrintedLine.file != lineInfo.file || | ||||
|                     abs( static_cast<int>( m_lastPrintedLine.line ) - static_cast<int>( lineInfo.line ) ) > 20 ) { | ||||
|                 TextColour colour( TextColour::FileName ); | ||||
|                 stream << lineInfo << "\n"; | ||||
|             } | ||||
|             TextColour colour( TextColour::FileName ); | ||||
|             stream << "[" << lineInfo.line << "]  "; | ||||
|             m_lastPrintedLine = lineInfo; | ||||
|             return 3 + countDigits( lineInfo.line ); | ||||
|         } | ||||
|         void resetLastPrintedLine() { | ||||
|             m_lastPrintedLine = SourceLineInfo(); | ||||
|         } | ||||
|     private: | ||||
|         bool m_atLeastOneTestCasePrinted; | ||||
|         SourceLineInfo m_lastPrintedLine; | ||||
|         Option<TestCaseStats> m_lazyTestCaseStats; | ||||
|  | ||||
|     }; | ||||
|  | ||||
|   | ||||
| @@ -26,3 +26,17 @@ CATCH_TEST_CASE( "./succeeding/generators/1", "Generators over two ranges" ) | ||||
|     CATCH_REQUIRE( multiply( i, 2 ) == i*2 ); | ||||
|     CATCH_REQUIRE( multiply( j, 2 ) == j*2 ); | ||||
| } | ||||
|  | ||||
| struct IntPair { int first, second; }; | ||||
|  | ||||
| CATCH_TEST_CASE( "./succeeding/generators/2", "Generator over a range of pairs" ) | ||||
| { | ||||
|     using namespace Catch::Generators; | ||||
|   | ||||
|     IntPair p[] = { { 0, 1 }, { 2, 3 } }; | ||||
|      | ||||
|     IntPair* i = CATCH_GENERATE( between( p, &p[1] ) ); | ||||
|      | ||||
|     CATCH_REQUIRE( i->first == i->second-1 ); | ||||
|      | ||||
| } | ||||
|   | ||||
| @@ -20,12 +20,12 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" | ||||
|                  | ||||
|         SECTION(    "selftest/expected result/failing tests",  | ||||
|                     "Tests in the 'failing' branch fail" ) { | ||||
|             MetaTestRunner::runMatching( "./failing/*",  MetaTestRunner::Expected::ToFail ); | ||||
|             MetaTestRunner::runMatching( "./failing/*",  MetaTestRunner::Expected::ToFail, 0, 2 ); | ||||
|         } | ||||
|          | ||||
|         SECTION(    "selftest/expected result/succeeding tests",  | ||||
|                     "Tests in the 'succeeding' branch succeed" ) { | ||||
|             MetaTestRunner::runMatching( "./succeeding/*",  MetaTestRunner::Expected::ToSucceed ); | ||||
|             MetaTestRunner::runMatching( "./succeeding/*",  MetaTestRunner::Expected::ToSucceed, 1, 2 ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| @@ -36,14 +36,14 @@ 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/*" ); | ||||
|             Totals totals = runner.runMatching( "./succeeding/*", 0, 2 ); | ||||
|             CHECK( totals.assertions.passed == 291 ); | ||||
|             CHECK( totals.assertions.failed == 0 ); | ||||
|         } | ||||
|  | ||||
|         SECTION(    "selftest/test counts/failing tests",  | ||||
|                     "Number of 'failing' tests is fixed" ) { | ||||
|             Totals totals = runner.runMatching( "./failing/*" );         | ||||
|             Totals totals = runner.runMatching( "./failing/*", 1, 2 ); | ||||
|             CHECK( totals.assertions.passed == 1 ); | ||||
|             CHECK( totals.assertions.failed == 72 ); | ||||
|         } | ||||
| @@ -53,7 +53,7 @@ TEST_CASE( "selftest/main", "Runs all Catch self tests and checks their results" | ||||
| TEST_CASE( "meta/Misc/Sections", "looped tests" ) { | ||||
|     Catch::EmbeddedRunner runner; | ||||
|      | ||||
|     Catch::Totals totals = runner.runMatching( "./mixed/Misc/Sections/nested2" ); | ||||
|     Catch::Totals totals = runner.runMatching( "./mixed/Misc/Sections/nested2", 0, 1 ); | ||||
|     CHECK( totals.assertions.passed == 2 ); | ||||
|     CHECK( totals.assertions.failed == 1 ); | ||||
| } | ||||
|   | ||||
| @@ -17,7 +17,7 @@ namespace Catch{ | ||||
|      | ||||
|     NullStreamingReporter::~NullStreamingReporter() {} | ||||
|  | ||||
|     Totals EmbeddedRunner::runMatching( const std::string& rawTestSpec, const std::string& ) { | ||||
|     Totals EmbeddedRunner::runMatching( const std::string& rawTestSpec, std::size_t groupIndex, std::size_t groupsCount, const std::string& ) { | ||||
|         std::ostringstream oss; | ||||
|         Config config; | ||||
|         config.setStreamBuf( oss.rdbuf() ); | ||||
| @@ -27,7 +27,7 @@ namespace Catch{ | ||||
|         // Scoped because Runner doesn't report EndTesting until its destructor | ||||
|         { | ||||
|             Runner runner( config, m_reporter.get() ); | ||||
|             totals = runner.runMatching( rawTestSpec ); | ||||
|             totals = runner.runMatching( rawTestSpec, groupIndex, groupsCount ); | ||||
|         } | ||||
|         return totals; | ||||
|     } | ||||
|   | ||||
| @@ -53,6 +53,8 @@ namespace Catch { | ||||
|         EmbeddedRunner() : m_reporter( new NullStreamingReporter() ) {} | ||||
|          | ||||
|         Totals runMatching( const std::string& rawTestSpec, | ||||
|                             std::size_t groupIndex, | ||||
|                             std::size_t groupsCount, | ||||
|                             const std::string& reporter = "console" ); | ||||
|          | ||||
|     private: | ||||
| @@ -67,12 +69,18 @@ namespace Catch { | ||||
|             ToFail | ||||
|         }; }; | ||||
|          | ||||
|         MetaTestRunner( Expected::Result expectedResult ) : m_expectedResult( expectedResult ) {} | ||||
|         MetaTestRunner( Expected::Result expectedResult, std::size_t groupIndex, std::size_t groupsCount ) | ||||
|         :   m_expectedResult( expectedResult ), | ||||
|             m_groupIndex( groupIndex ), | ||||
|             m_groupsCount( groupsCount ) | ||||
|         {} | ||||
|          | ||||
|         static void runMatching(    const std::string& testSpec,  | ||||
|                                     Expected::Result expectedResult ) { | ||||
|                                     Expected::Result expectedResult, | ||||
|                                     std::size_t groupIndex, | ||||
|                                     std::size_t groupsCount ) { | ||||
|             forEach(    getRegistryHub().getTestCaseRegistry().getMatchingTestCases( testSpec ),  | ||||
|                         MetaTestRunner( expectedResult ) ); | ||||
|                         MetaTestRunner( expectedResult, groupIndex, groupsCount ) ); | ||||
|         } | ||||
|          | ||||
|         void operator()( const TestCase& testCase ) { | ||||
| @@ -81,7 +89,7 @@ namespace Catch { | ||||
|             { | ||||
|                 EmbeddedRunner runner; | ||||
|                 name = testCase.getTestCaseInfo().name; | ||||
|                 totals = runner.runMatching( name ); | ||||
|                 totals = runner.runMatching( name, m_groupIndex, m_groupsCount ); | ||||
|             } | ||||
|             switch( m_expectedResult ) { | ||||
|                 case Expected::ToSucceed: | ||||
| @@ -111,6 +119,8 @@ namespace Catch { | ||||
|  | ||||
|     private: | ||||
|         Expected::Result m_expectedResult; | ||||
|         std::size_t m_groupIndex; | ||||
|         std::size_t m_groupsCount; | ||||
|     }; | ||||
|      | ||||
|  | ||||
|   | ||||
| @@ -7,6 +7,7 @@ | ||||
| 	objects = { | ||||
|  | ||||
| /* Begin PBXBuildFile section */ | ||||
| 		2694A1FD16A0000E004816E3 /* catch_line_wrap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2694A1FB16A0000E004816E3 /* catch_line_wrap.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 */; }; | ||||
| 		4A45DA2916161F3D004F8D6B /* catch_streambuf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4A45DA2816161F3D004F8D6B /* catch_streambuf.cpp */; }; | ||||
| @@ -52,6 +53,9 @@ | ||||
| /* End PBXCopyFilesBuildPhase section */ | ||||
|  | ||||
| /* Begin PBXFileReference section */ | ||||
| 		2694A1F8169FFF9B004816E3 /* catch_line_wrap.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_line_wrap.h; sourceTree = "<group>"; }; | ||||
| 		2694A1FA169FFFEC004816E3 /* catch_line_wrap.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_line_wrap.hpp; sourceTree = "<group>"; }; | ||||
| 		2694A1FB16A0000E004816E3 /* catch_line_wrap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = catch_line_wrap.cpp; sourceTree = "<group>"; }; | ||||
| 		4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.h; path = catch_test_case_info.hpp; sourceTree = "<group>"; }; | ||||
| 		4A084F1D15DAD15F0027E631 /* catch_test_spec.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = catch_test_spec.h; sourceTree = "<group>"; }; | ||||
| 		4A3D7DD01503869D005F9203 /* catch_matchers.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = catch_matchers.hpp; sourceTree = "<group>"; }; | ||||
| @@ -270,6 +274,7 @@ | ||||
| 				4AB3D99F1616219100C9A0F8 /* catch_interfaces_config.cpp */, | ||||
| 				4AB3D9A1161621B500C9A0F8 /* catch_interfaces_generators.cpp */, | ||||
| 				4ACE21CA166CA1B300FB5509 /* catch_option.cpp */, | ||||
| 				2694A1FB16A0000E004816E3 /* catch_line_wrap.cpp */, | ||||
| 			); | ||||
| 			name = SurrogateCpps; | ||||
| 			sourceTree = "<group>"; | ||||
| @@ -288,6 +293,7 @@ | ||||
| 				4A90B59D15D24FE900EF71BC /* catch_assertionresult.hpp */, | ||||
| 				4A90B59E15D2521E00EF71BC /* catch_expressionresult_builder.hpp */, | ||||
| 				4A084F1C15DACEEA0027E631 /* catch_test_case_info.hpp */, | ||||
| 				2694A1FA169FFFEC004816E3 /* catch_line_wrap.hpp */, | ||||
| 			); | ||||
| 			name = impl; | ||||
| 			sourceTree = "<group>"; | ||||
| @@ -374,6 +380,7 @@ | ||||
| 				4AB77CB51551AEA200857BF0 /* catch_ptr.hpp */, | ||||
| 				4AEE0326161431070071E950 /* catch_streambuf.h */, | ||||
| 				4ACE21C8166CA19700FB5509 /* catch_option.hpp */, | ||||
| 				2694A1F8169FFF9B004816E3 /* catch_line_wrap.h */, | ||||
| 			); | ||||
| 			name = Infrastructure; | ||||
| 			sourceTree = "<group>"; | ||||
| @@ -465,6 +472,7 @@ | ||||
| 				4AB3D9A01616219100C9A0F8 /* catch_interfaces_config.cpp in Sources */, | ||||
| 				4AB3D9A2161621B500C9A0F8 /* catch_interfaces_generators.cpp in Sources */, | ||||
| 				4ACE21CC166CA1B300FB5509 /* catch_option.cpp in Sources */, | ||||
| 				2694A1FD16A0000E004816E3 /* catch_line_wrap.cpp in Sources */, | ||||
| 			); | ||||
| 			runOnlyForDeploymentPostprocessing = 0; | ||||
| 		}; | ||||
|   | ||||
| @@ -0,0 +1,2 @@ | ||||
| // This file is only here to verify (to the extent possible) the self sufficiency of the header | ||||
| #include "catch_line_wrap.h" | ||||
		Reference in New Issue
	
	Block a user
	 Phil Nash
					Phil Nash