3142 template<
typename ArgT>
3145 for(
auto matcher : m_matchers ) {
3146 if (!matcher->match(
arg))
3153 description.
reserve( 4 + m_matchers.size()*32 );
3154 description +=
"( ";
3156 for(
auto matcher : m_matchers ) {
3160 description +=
" and ";
3161 description += matcher->toString();
3163 description +=
" )";
3168 m_matchers.push_back( &other );
3174 template<
typename ArgT>
3178 for(
auto matcher : m_matchers ) {
3179 if (matcher->match(
arg))
3186 description.
reserve( 4 + m_matchers.size()*32 );
3187 description +=
"( ";
3189 for(
auto matcher : m_matchers ) {
3193 description +=
" or ";
3194 description += matcher->toString();
3196 description +=
" )";
3201 m_matchers.push_back( &other );
3208 template<
typename ArgT>
3214 return !m_underlyingMatcher.match(
arg );
3218 return "not " + m_underlyingMatcher.toString();
3223 template<
typename T>
3227 template<
typename T>
3231 template<
typename T>
3240using namespace Matchers;
3254 namespace Floating {
3256 enum class FloatingPointKind : uint8_t;
3260 bool match(
double const& matchee)
const override;
3269 bool match(
double const& matchee)
const override;
3302template <
typename T>
3309 :m_predicate(
std::move(elem)),
3310 m_description(Detail::finalizeDescription(descr))
3314 return m_predicate(item);
3318 return m_description;
3328 template<
typename T>
3344 namespace StdString {
3414 template<
typename T>
3420 for (
auto const& el : v) {
3421 if (el == m_comparator) {
3435 template<
typename T>
3442 if (m_comparator.size() > v.
size())
3444 for (
auto const& comparator : m_comparator) {
3445 auto present =
false;
3446 for (
const auto& el : v) {
3447 if (el == comparator) {
3465 template<
typename T>
3475 if (m_comparator.size() != v.
size())
3478 if (m_comparator[i] != v[i])
3488 template<
typename T>
3494 if (m_comparator.size() != v.
size())
3497 if (m_comparator[i] != approx(v[i]))
3504 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
3509 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
3511 approx.
margin(newMargin);
3514 template <typename = typename std::enable_if<std::is_constructible<double, T>::value>
::type>
3516 approx.
scale(newScale);
3524 template<
typename T>
3530 if (m_target.size() != vec.
size()) {
3548 template<
typename T>
3553 template<
typename T>
3558 template<
typename T>
3563 template<
typename T>
3568 template<
typename T>
3579 template<
typename ArgT,
typename MatcherT>
3588 m_matcher( matcher ),
3589 m_matcherString( matcherString )
3593 auto matcherAsString = m_matcher.toString();
3595 if( matcherAsString == Detail::unprintableString )
3596 os << m_matcherString;
3598 os << matcherAsString;
3606 template<
typename ArgT,
typename MatcherT>
3614#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
3616 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3617 INTERNAL_CATCH_TRY { \
3618 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \
3619 } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \
3620 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3624#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \
3626 Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \
3627 if( catchAssertionHandler.allowThrows() ) \
3629 static_cast<void>(__VA_ARGS__ ); \
3630 catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \
3632 catch( exceptionType const& ex ) { \
3633 catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \
3636 catchAssertionHandler.handleUnexpectedInflightException(); \
3639 catchAssertionHandler.handleThrowingCallSkipped(); \
3640 INTERNAL_CATCH_REACT( catchAssertionHandler ) \
3672 virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;
3673 virtual
void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;
3684#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
3685 template <
typename Ex>
3696#define CATCH_PREPARE_EXCEPTION( type, msg ) \
3697 type( ( Catch::ReusableStringStream() << msg ).str() )
3698#define CATCH_INTERNAL_ERROR( msg ) \
3699 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::logic_error, CATCH_INTERNAL_LINEINFO << ": Internal Catch error: " << msg))
3700#define CATCH_ERROR( msg ) \
3701 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::domain_error, msg ))
3702#define CATCH_RUNTIME_ERROR( msg ) \
3703 Catch::throw_exception(CATCH_PREPARE_EXCEPTION( std::runtime_error, msg ))
3704#define CATCH_ENFORCE( condition, msg ) \
3705 do{ if( !(condition) ) CATCH_ERROR( msg ); } while(false)
3718 const char*
const m_msg =
"";
3725 const char*
what() const noexcept override final;
3728namespace Generators {
3732 template<
typename T,
typename... Args>
3738 template<
typename T>
3750 template<
typename T>
3765 template<
typename T>
3773 return m_values[m_idx];
3777 return m_idx < m_values.
size();
3781 template <
typename T>
3786 m_generator(
std::move(generator))
3789 return m_generator->
get();
3792 return m_generator->next();
3796 template <
typename T>
3800 template <
typename T>
3805 template<
typename T>
3808 size_t m_current = 0;
3816 template<
typename U>
3818 populate(
T(std::move(val)));
3820 template<
typename U,
typename... Gs>
3821 void populate(U&& valueOrGenerator, Gs... moreGenerators) {
3827 template <
typename... Gs>
3829 m_generators.
reserve(
sizeof...(Gs));
3834 return m_generators[m_current].get();
3838 if (m_current >= m_generators.
size()) {
3841 const bool current_status = m_generators[m_current].next();
3842 if (!current_status) {
3845 return m_current < m_generators.
size();
3849 template<
typename... Ts>
3855 template <
typename T>
3858 template<
typename T,
typename... Gs>
3862 template<
typename T>
3866 template<
typename T,
typename... Gs>
3870 template<
typename T,
typename U,
typename... Gs>
3877 template<
typename L>
3882 using UnderlyingType =
typename decltype(generatorExpression())
::type;
3890 return generator.
get();
3896#define GENERATE( ... ) \
3897 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3898#define GENERATE_COPY( ... ) \
3899 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3900#define GENERATE_REF( ... ) \
3901 Catch::Generators::generate( CATCH_INTERNAL_LINEINFO, [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } )
3907namespace Generators {
3909 template <
typename T>
3912 size_t m_returned = 0;
3916 m_generator(
std::move(generator)),
3919 assert(target != 0 &&
"Empty generators are not allowed");
3922 return m_generator.
get();
3926 if (m_returned >= m_target) {
3930 const auto success = m_generator.
next();
3934 m_returned = m_target;
3940 template <
typename T>
3945 template <
typename T,
typename Predicate>
3950 template <
typename P = Predicate>
3952 m_generator(
std::move(generator)),
3953 m_predicate(
std::forward<P>(pred))
3955 if (!m_predicate(m_generator.
get())) {
3958 auto has_initial_value = next();
3959 if (!has_initial_value) {
3966 return m_generator.
get();
3970 bool success = m_generator.
next();
3974 while (!m_predicate(m_generator.
get()) && (success = m_generator.
next()) ==
true);
3979 template <
typename T,
typename Predicate>
3984 template <
typename T>
3989 size_t m_current_repeat = 0;
3990 size_t m_repeat_index = 0;
3993 m_generator(
std::move(generator)),
3994 m_target_repeats(repeats)
3996 assert(m_target_repeats > 0 &&
"Repeat generator must repeat at least once");
4000 if (m_current_repeat == 0) {
4002 return m_returned.
back();
4004 return m_returned[m_repeat_index];
4014 if (m_current_repeat == 0) {
4015 const auto success = m_generator.
next();
4019 return m_current_repeat < m_target_repeats;
4024 if (m_repeat_index == m_returned.
size()) {
4028 return m_current_repeat < m_target_repeats;
4032 template <
typename T>
4037 template <
typename T,
typename U,
typename Func>
4045 template <
typename F2 = Func>
4047 m_generator(
std::move(generator)),
4048 m_function(
std::forward<F2>(function)),
4049 m_cache(m_function(m_generator.get()))
4056 const auto success = m_generator.
next();
4058 m_cache = m_function(m_generator.
get());
4064#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703
4068 template <
typename Func,
typename U>
4071 template <
typename Func,
typename U>
4075 template <
typename Func,
typename U,
typename T = MapFunctionReturnType<Func, U>>
4082 template <
typename T,
typename U,
typename Func>
4083 GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {
4084 return GeneratorWrapper<T>(
4085 pf::make_unique<MapGenerator<T, U, Func>>(
std::forward<Func>(function), std::move(generator))
4089 template <
typename T>
4094 bool m_used_up =
false;
4097 m_chunk_size(size), m_generator(
std::move(generator))
4099 m_chunk.
reserve(m_chunk_size);
4101 for (
size_t i = 1; i < m_chunk_size; ++i) {
4102 if (!m_generator.
next()) {
4113 for (
size_t idx = 0; idx < m_chunk_size; ++idx) {
4114 if (!m_generator.
next()) {
4123 template <
typename T>
4126 pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))
4142 struct IResultCapture;
4145 struct IMutableContext;
4174 if( !IMutableContext::currentContext )
4175 IMutableContext::createContext();
4176 return *IMutableContext::currentContext;
4205 NoAssertions = 0x01,
4228 BeforeStartAndExit = BeforeStart | BeforeExit
4265namespace Generators {
4267template <
typename Float>
4278 static_cast<void>(next());
4281 Float
const&
get()
const override {
4282 return m_current_number;
4285 m_current_number = m_dist(m_rand);
4290template <
typename Integer>
4300 static_cast<void>(next());
4303 Integer
const&
get()
const override {
4304 return m_current_number;
4307 m_current_number = m_dist(m_rand);
4314template <
typename T>
4316GeneratorWrapper<T>>
::type
4323template <
typename T>
4325GeneratorWrapper<T>>
::type
4332template <
typename T>
4344 m_positive(m_step >
T(0))
4346 assert(m_current != m_end &&
"Range start and end cannot be equal");
4347 assert(m_step !=
T(0) &&
"Step size cannot be zero");
4348 assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) &&
"Step moves away from end");
4360 m_current += m_step;
4361 return (m_positive) ? (m_current < m_end) : (m_current > m_end);
4365template <
typename T>
4371template <
typename T>
4391#pragma clang diagnostic push
4392#pragma clang diagnostic ignored "-Wpadded"
4397 struct ITestInvoker;
4403 ShouldFail = 1 << 2,
4406 NonPortable = 1 << 5,
4419 bool throws()
const;
4459#pragma clang diagnostic pop
4478#import <objc/runtime.h>
4500 class OcMethod :
public ITestInvoker {
4503 OcMethod( Class cls,
SEL sel ) : m_cls( cls ), m_sel( sel ) {}
4505 virtual void invoke()
const {
4506 id obj = [[m_cls alloc] init];
4508 performOptionalSelector( obj,
@selector(setUp) );
4509 performOptionalSelector( obj, m_sel );
4510 performOptionalSelector( obj,
@selector(tearDown) );
4512 arcSafeRelease( obj );
4515 virtual ~OcMethod() {}
4526 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
4527 SEL sel = NSSelectorFromString( selStr );
4528 arcSafeRelease( selStr );
4529 id value = performOptionalSelector( cls, sel );
4531 return [(NSString*)
value UTF8String];
4538 int noClasses = objc_getClassList(
nullptr, 0 );
4540 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)
malloc(
sizeof(Class) * noClasses);
4541 objc_getClassList( classes, noClasses );
4543 for(
int c = 0; c < noClasses; c++ ) {
4544 Class cls = classes[c];
4547 Method* methods = class_copyMethodList( cls, &
count );
4548 for( u_int m = 0;
m <
count ;
m++ ) {
4549 SEL selector = method_getName(methods[m]);
4551 if(
startsWith( methodName,
"Catch_TestCase_" ) ) {
4553 std::string name = Detail::getAnnotation( cls,
"Name", testCaseName );
4554 std::string desc = Detail::getAnnotation( cls,
"Description", testCaseName );
4555 const char* className = class_getName( cls );
4564 return noTestMethods;
4567#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
4569 namespace Matchers {
4571 namespace NSStringMatchers {
4573 struct StringHolder : MatcherBase<NSString*>{
4574 StringHolder( NSString* substr ) : m_substr( [substr
copy] ){}
4575 StringHolder( StringHolder
const& other ) : m_substr( [other.m_substr
copy] ){}
4577 arcSafeRelease( m_substr );
4580 bool match( NSString*
const& str )
const override {
4584 NSString* CATCH_ARC_STRONG m_substr;
4587 struct Equals : StringHolder {
4588 Equals( NSString* substr ) : StringHolder( substr ){}
4590 bool match( NSString*
const& str )
const override {
4591 return (str != nil || m_substr == nil ) &&
4592 [str isEqualToString:m_substr];
4596 return "equals string: " +
Catch::Detail::stringify( m_substr );
4601 Contains( NSString* substr ) : StringHolder( substr ){}
4603 bool match( NSString*
const& str )
const override {
4604 return (str != nil || m_substr == nil ) &&
4605 [str rangeOfString:m_substr].location != NSNotFound;
4609 return "contains string: " +
Catch::Detail::stringify( m_substr );
4614 StartsWith( NSString* substr ) : StringHolder( substr ){}
4616 bool match( NSString*
const& str )
const override {
4617 return (str != nil || m_substr == nil ) &&
4618 [str rangeOfString:m_substr].location == 0;
4622 return "starts with: " +
Catch::Detail::stringify( m_substr );
4626 EndsWith( NSString* substr ) : StringHolder( substr ){}
4628 bool match( NSString*
const& str )
const override {
4629 return (str != nil || m_substr == nil ) &&
4630 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
4634 return "ends with: " +
Catch::Detail::stringify( m_substr );
4641 inline Impl::NSStringMatchers::Equals
4642 Equals( NSString* substr ){
return Impl::NSStringMatchers::Equals( substr ); }
4644 inline Impl::NSStringMatchers::Contains
4645 Contains( NSString* substr ){
return Impl::NSStringMatchers::Contains( substr ); }
4647 inline Impl::NSStringMatchers::StartsWith
4648 StartsWith( NSString* substr ){
return Impl::NSStringMatchers::StartsWith( substr ); }
4650 inline Impl::NSStringMatchers::EndsWith
4651 EndsWith( NSString* substr ){
return Impl::NSStringMatchers::EndsWith( substr ); }
4655 using namespace Matchers;
4662#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix
4663#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \
4664+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \
4668+(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \
4672-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )
4674#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )
4679#ifdef CATCH_CONFIG_EXTERNAL_INTERFACES
4691#pragma clang diagnostic push
4692#pragma clang diagnostic ignored "-Wpadded"
4698#pragma clang diagnostic push
4699#pragma clang diagnostic ignored "-Wpadded"
4706 class WildcardPattern {
4707 enum WildcardPosition {
4709 WildcardAtStart = 1,
4711 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
4716 WildcardPattern(
std::string const& pattern, CaseSensitive::Choice caseSensitivity );
4717 virtual ~WildcardPattern() =
default;
4718 virtual bool matches(
std::string const& str )
const;
4722 CaseSensitive::Choice m_caseSensitivity;
4723 WildcardPosition m_wildcard = NoWildcard;
4738 virtual bool matches( TestCaseInfo
const& testCase )
const = 0;
4742 class NamePattern :
public Pattern {
4745 virtual ~NamePattern();
4746 bool matches( TestCaseInfo
const& testCase )
const override;
4748 WildcardPattern m_wildcardPattern;
4751 class TagPattern :
public Pattern {
4754 virtual ~TagPattern();
4755 bool matches( TestCaseInfo
const& testCase )
const override;
4760 class ExcludedPattern :
public Pattern {
4762 ExcludedPattern( PatternPtr
const& underlyingPattern );
4763 virtual ~ExcludedPattern();
4764 bool matches( TestCaseInfo
const& testCase )
const override;
4766 PatternPtr m_underlyingPattern;
4772 bool matches( TestCaseInfo
const& testCase )
const;
4776 bool hasFilters()
const;
4777 bool matches( TestCaseInfo
const& testCase )
const;
4782 friend class TestSpecParser;
4787#pragma clang diagnostic pop
4799 struct ITagAliasRegistry {
4800 virtual ~ITagAliasRegistry();
4805 static ITagAliasRegistry
const&
get();
4813 class TestSpecParser {
4814 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
4816 bool m_exclusion =
false;
4817 std::size_t m_start = std::string::npos, m_pos = 0;
4820 TestSpec::Filter m_currentFilter;
4821 TestSpec m_testSpec;
4822 ITagAliasRegistry
const* m_tagAliases =
nullptr;
4825 TestSpecParser( ITagAliasRegistry
const& tagAliases );
4828 TestSpec testSpec();
4831 void visitChar(
char c );
4832 void startNewMode( Mode mode,
std::size_t start );
4836 template<
typename T>
4840 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
4841 m_escapeChars.
clear();
4844 token = token.
substr( 8 );
4846 if( !token.
empty() ) {
4847 TestSpec::PatternPtr pattern = std::make_shared<T>( token );
4849 pattern = std::make_shared<TestSpec::ExcludedPattern>( pattern );
4850 m_currentFilter.m_patterns.push_back( pattern );
4852 m_exclusion =
false;
4863#pragma clang diagnostic pop
4873#ifndef CATCH_CONFIG_CONSOLE_WIDTH
4874#define CATCH_CONFIG_CONSOLE_WIDTH 80
4882 bool listTests =
false;
4883 bool listTags =
false;
4884 bool listReporters =
false;
4885 bool listTestNamesOnly =
false;
4887 bool showSuccessfulTests =
false;
4888 bool shouldDebugBreak =
false;
4889 bool noThrow =
false;
4890 bool showHelp =
false;
4891 bool showInvisibles =
false;
4892 bool filenamesAsTags =
false;
4893 bool libIdentify =
false;
4895 int abortAfter = -1;
4897 int benchmarkResolutionMultiple = 100;
4899 Verbosity verbosity = Verbosity::Normal;
4900 WarnAbout::What warnings = WarnAbout::Nothing;
4901 ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;
4902 RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;
4903 UseColour::YesOrNo useColour = UseColour::Auto;
4904 WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;
4909#ifndef CATCH_CONFIG_DEFAULT_REPORTER
4910#define CATCH_CONFIG_DEFAULT_REPORTER "console"
4912 std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;
4913#undef CATCH_CONFIG_DEFAULT_REPORTER
4919 class Config :
public IConfig {
4923 Config( ConfigData
const&
data );
4924 virtual ~Config() =
default;
4928 bool listTests()
const;
4929 bool listTestNamesOnly()
const;
4930 bool listTags()
const;
4931 bool listReporters()
const;
4939 TestSpec
const& testSpec()
const override;
4940 bool hasTestFilters()
const override;
4942 bool showHelp()
const;
4945 bool allowThrows()
const override;
4948 bool includeSuccessfulResults()
const override;
4949 bool warnAboutMissingAssertions()
const override;
4950 bool warnAboutNoTests()
const override;
4951 ShowDurations::OrNot showDurations()
const override;
4952 RunTests::InWhatOrder runOrder()
const override;
4953 unsigned int rngSeed()
const override;
4954 int benchmarkResolutionMultiple()
const override;
4955 UseColour::YesOrNo useColour()
const override;
4956 bool shouldDebugBreak()
const override;
4957 int abortAfter()
const override;
4958 bool showInvisibles()
const override;
4963 IStream
const* openStream();
4967 TestSpec m_testSpec;
4968 bool m_hasTestFilters =
false;
4980 struct AssertionResultData
4982 AssertionResultData() =
delete;
4984 AssertionResultData( ResultWas::OfType _resultType, LazyExpression
const& _lazyExpression );
4988 LazyExpression lazyExpression;
4989 ResultWas::OfType resultType;
4994 class AssertionResult {
4996 AssertionResult() =
delete;
4997 AssertionResult( AssertionInfo
const& info, AssertionResultData
const&
data );
5000 bool succeeded()
const;
5001 ResultWas::OfType getResultType()
const;
5002 bool hasExpression()
const;
5003 bool hasMessage()
const;
5006 bool hasExpandedExpression()
const;
5009 SourceLineInfo getSourceInfo()
const;
5010 StringRef getTestMacroName()
const;
5013 AssertionInfo m_info;
5014 AssertionResultData m_resultData;
5025 template<
typename T>
5028 Option() : nullableValue( nullptr ) {}
5029 Option(
T const& _value )
5030 : nullableValue( new( storage )
T( _value ) )
5032 Option( Option
const& _other )
5033 : nullableValue( _other ? new( storage )
T( *_other ) : nullptr )
5040 Option& operator= ( Option
const& _other ) {
5041 if( &_other !=
this ) {
5044 nullableValue =
new( storage )
T( *_other );
5048 Option& operator = (
T const& _value ) {
5050 nullableValue =
new( storage )
T( _value );
5056 nullableValue->~T();
5057 nullableValue =
nullptr;
5061 T const&
operator*()
const {
return *nullableValue; }
5062 T* operator->() {
return nullableValue; }
5063 const T* operator->()
const {
return nullableValue; }
5065 T valueOr(
T const& defaultValue )
const {
5066 return nullableValue ? *nullableValue : defaultValue;
5069 bool some()
const {
return nullableValue !=
nullptr; }
5070 bool none()
const {
return nullableValue ==
nullptr; }
5072 bool operator !()
const {
return nullableValue ==
nullptr; }
5073 explicit operator bool()
const {
5079 alignas(
alignof(
T))
char storage[sizeof(T)];
5093 struct ReporterConfig {
5094 explicit ReporterConfig( IConfigPtr
const& _fullConfig );
5096 ReporterConfig( IConfigPtr
const& _fullConfig,
std::ostream& _stream );
5106 struct ReporterPreferences {
5107 bool shouldRedirectStdOut =
false;
5108 bool shouldReportAllAssertions =
false;
5111 template<
typename T>
5112 struct LazyStat : Option<
T> {
5113 LazyStat& operator=(
T const& _value ) {
5114 Option<T>::operator=( _value );
5125 struct TestRunInfo {
5139 struct AssertionStats {
5140 AssertionStats( AssertionResult
const& _assertionResult,
5142 Totals
const& _totals );
5144 AssertionStats( AssertionStats
const& ) =
default;
5145 AssertionStats( AssertionStats && ) =
default;
5146 AssertionStats& operator = ( AssertionStats
const& ) =
delete;
5147 AssertionStats& operator = ( AssertionStats && ) =
delete;
5148 virtual ~AssertionStats();
5150 AssertionResult assertionResult;
5155 struct SectionStats {
5156 SectionStats( SectionInfo
const& _sectionInfo,
5157 Counts
const& _assertions,
5158 double _durationInSeconds,
5159 bool _missingAssertions );
5160 SectionStats( SectionStats
const& ) =
default;
5161 SectionStats( SectionStats && ) =
default;
5162 SectionStats& operator = ( SectionStats
const& ) =
default;
5163 SectionStats& operator = ( SectionStats && ) =
default;
5164 virtual ~SectionStats();
5166 SectionInfo sectionInfo;
5168 double durationInSeconds;
5169 bool missingAssertions;
5172 struct TestCaseStats {
5173 TestCaseStats( TestCaseInfo
const& _testInfo,
5174 Totals
const& _totals,
5179 TestCaseStats( TestCaseStats
const& ) =
default;
5180 TestCaseStats( TestCaseStats && ) =
default;
5181 TestCaseStats& operator = ( TestCaseStats
const& ) =
default;
5182 TestCaseStats& operator = ( TestCaseStats && ) =
default;
5183 virtual ~TestCaseStats();
5185 TestCaseInfo testInfo;
5192 struct TestGroupStats {
5193 TestGroupStats( GroupInfo
const& _groupInfo,
5194 Totals
const& _totals,
5196 TestGroupStats( GroupInfo
const& _groupInfo );
5198 TestGroupStats( TestGroupStats
const& ) =
default;
5199 TestGroupStats( TestGroupStats && ) =
default;
5200 TestGroupStats& operator = ( TestGroupStats
const& ) =
default;
5201 TestGroupStats& operator = ( TestGroupStats && ) =
default;
5202 virtual ~TestGroupStats();
5204 GroupInfo groupInfo;
5209 struct TestRunStats {
5210 TestRunStats( TestRunInfo
const& _runInfo,
5211 Totals
const& _totals,
5214 TestRunStats( TestRunStats
const& ) =
default;
5215 TestRunStats( TestRunStats && ) =
default;
5216 TestRunStats& operator = ( TestRunStats
const& ) =
default;
5217 TestRunStats& operator = ( TestRunStats && ) =
default;
5218 virtual ~TestRunStats();
5220 TestRunInfo runInfo;
5225 struct BenchmarkInfo {
5228 struct BenchmarkStats {
5231 uint64_t elapsedTimeInNanoseconds;
5234 struct IStreamingReporter {
5235 virtual ~IStreamingReporter() =
default;
5241 virtual ReporterPreferences getPreferences()
const = 0;
5243 virtual void noMatchingTestCases(
std::string const& spec ) = 0;
5245 virtual void testRunStarting( TestRunInfo
const& testRunInfo ) = 0;
5246 virtual void testGroupStarting( GroupInfo
const& groupInfo ) = 0;
5248 virtual void testCaseStarting( TestCaseInfo
const& testInfo ) = 0;
5249 virtual void sectionStarting( SectionInfo
const& sectionInfo ) = 0;
5252 virtual void benchmarkStarting( BenchmarkInfo
const& ) {}
5254 virtual void assertionStarting( AssertionInfo
const& assertionInfo ) = 0;
5257 virtual bool assertionEnded( AssertionStats
const& assertionStats ) = 0;
5260 virtual void benchmarkEnded( BenchmarkStats
const& ) {}
5262 virtual void sectionEnded( SectionStats
const& sectionStats ) = 0;
5263 virtual void testCaseEnded( TestCaseStats
const& testCaseStats ) = 0;
5264 virtual void testGroupEnded( TestGroupStats
const& testGroupStats ) = 0;
5265 virtual void testRunEnded( TestRunStats
const& testRunStats ) = 0;
5267 virtual void skipTest( TestCaseInfo
const& testInfo ) = 0;
5270 virtual void fatalErrorEncountered( StringRef
name );
5272 virtual bool isMulti()
const;
5276 struct IReporterFactory {
5277 virtual ~IReporterFactory();
5278 virtual IStreamingReporterPtr
create( ReporterConfig
const& config )
const = 0;
5283 struct IReporterRegistry {
5287 virtual ~IReporterRegistry();
5288 virtual IStreamingReporterPtr
create(
std::string const&
name, IConfigPtr
const& config )
const = 0;
5289 virtual FactoryMap
const& getFactories()
const = 0;
5290 virtual Listeners
const& getListeners()
const = 0;
5305 void prepareExpandedExpression(AssertionResult& result);
5308 std::string getFormattedDuration(
double duration );
5312 template<
typename DerivedT>
5313 struct StreamingReporterBase : IStreamingReporter {
5315 StreamingReporterBase( ReporterConfig
const& _config )
5316 : m_config( _config.fullConfig() ),
5317 stream( _config.stream() )
5319 m_reporterPrefs.shouldRedirectStdOut =
false;
5320 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5321 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5324 ReporterPreferences getPreferences()
const override {
5325 return m_reporterPrefs;
5329 return { Verbosity::Normal };
5332 ~StreamingReporterBase()
override =
default;
5334 void noMatchingTestCases(
std::string const&)
override {}
5336 void testRunStarting(TestRunInfo
const& _testRunInfo)
override {
5337 currentTestRunInfo = _testRunInfo;
5340 void testGroupStarting(GroupInfo
const& _groupInfo)
override {
5341 currentGroupInfo = _groupInfo;
5344 void testCaseStarting(TestCaseInfo
const& _testInfo)
override {
5345 currentTestCaseInfo = _testInfo;
5347 void sectionStarting(SectionInfo
const& _sectionInfo)
override {
5348 m_sectionStack.push_back(_sectionInfo);
5351 void sectionEnded(SectionStats
const& )
override {
5352 m_sectionStack.pop_back();
5354 void testCaseEnded(TestCaseStats
const& )
override {
5355 currentTestCaseInfo.reset();
5357 void testGroupEnded(TestGroupStats
const& )
override {
5358 currentGroupInfo.reset();
5360 void testRunEnded(TestRunStats
const& )
override {
5361 currentTestCaseInfo.reset();
5362 currentGroupInfo.reset();
5363 currentTestRunInfo.reset();
5366 void skipTest(TestCaseInfo
const&)
override {
5374 LazyStat<TestRunInfo> currentTestRunInfo;
5375 LazyStat<GroupInfo> currentGroupInfo;
5376 LazyStat<TestCaseInfo> currentTestCaseInfo;
5379 ReporterPreferences m_reporterPrefs;
5382 template<
typename DerivedT>
5383 struct CumulativeReporterBase : IStreamingReporter {
5384 template<
typename T,
typename ChildNodeT>
5386 explicit Node(
T const& _value ) :
value( _value ) {}
5391 ChildNodes children;
5393 struct SectionNode {
5394 explicit SectionNode(SectionStats
const& _stats) : stats(_stats) {}
5395 virtual ~SectionNode() =
default;
5397 bool operator == (SectionNode
const& other)
const {
5398 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
5407 ChildSections childSections;
5408 Assertions assertions;
5413 struct BySectionInfo {
5414 BySectionInfo( SectionInfo
const& other ) : m_other( other ) {}
5415 BySectionInfo( BySectionInfo
const& other ) : m_other( other.m_other ) {}
5417 return ((node->stats.sectionInfo.name == m_other.name) &&
5418 (node->stats.sectionInfo.lineInfo == m_other.lineInfo));
5420 void operator=(BySectionInfo
const&) =
delete;
5423 SectionInfo
const& m_other;
5426 using TestCaseNode = Node<TestCaseStats, SectionNode>;
5427 using TestGroupNode = Node<TestGroupStats, TestCaseNode>;
5428 using TestRunNode = Node<TestRunStats, TestGroupNode>;
5430 CumulativeReporterBase( ReporterConfig
const& _config )
5431 : m_config( _config.fullConfig() ),
5432 stream( _config.stream() )
5434 m_reporterPrefs.shouldRedirectStdOut =
false;
5435 if( !DerivedT::getSupportedVerbosities().
count( m_config->verbosity() ) )
5436 CATCH_ERROR(
"Verbosity level not supported by this reporter" );
5438 ~CumulativeReporterBase()
override =
default;
5440 ReporterPreferences getPreferences()
const override {
5441 return m_reporterPrefs;
5445 return { Verbosity::Normal };
5448 void testRunStarting( TestRunInfo
const& )
override {}
5449 void testGroupStarting( GroupInfo
const& )
override {}
5451 void testCaseStarting( TestCaseInfo
const& )
override {}
5453 void sectionStarting( SectionInfo
const& sectionInfo )
override {
5454 SectionStats incompleteStats( sectionInfo, Counts(), 0,
false );
5456 if( m_sectionStack.empty() ) {
5457 if( !m_rootSection )
5459 node = m_rootSection;
5462 SectionNode& parentNode = *m_sectionStack.back();
5465 parentNode.childSections.end(),
5466 BySectionInfo( sectionInfo ) );
5467 if( it == parentNode.childSections.end() ) {
5469 parentNode.childSections.push_back( node );
5474 m_sectionStack.push_back( node );
5475 m_deepestSection = std::move(node);
5478 void assertionStarting(AssertionInfo
const&)
override {}
5480 bool assertionEnded(AssertionStats
const& assertionStats)
override {
5481 assert(!m_sectionStack.empty());
5487 prepareExpandedExpression(
const_cast<AssertionResult&
>( assertionStats.assertionResult ) );
5488 SectionNode& sectionNode = *m_sectionStack.back();
5489 sectionNode.assertions.push_back(assertionStats);
5492 void sectionEnded(SectionStats
const& sectionStats)
override {
5493 assert(!m_sectionStack.empty());
5494 SectionNode& node = *m_sectionStack.back();
5495 node.stats = sectionStats;
5496 m_sectionStack.pop_back();
5498 void testCaseEnded(TestCaseStats
const& testCaseStats)
override {
5500 assert(m_sectionStack.size() == 0);
5501 node->children.push_back(m_rootSection);
5502 m_testCases.push_back(node);
5503 m_rootSection.reset();
5505 assert(m_deepestSection);
5506 m_deepestSection->stdOut = testCaseStats.stdOut;
5507 m_deepestSection->stdErr = testCaseStats.stdErr;
5509 void testGroupEnded(TestGroupStats
const& testGroupStats)
override {
5511 node->children.swap(m_testCases);
5512 m_testGroups.push_back(node);
5514 void testRunEnded(TestRunStats
const& testRunStats)
override {
5516 node->children.swap(m_testGroups);
5517 m_testRuns.push_back(node);
5518 testRunEndedCumulative();
5520 virtual void testRunEndedCumulative() = 0;
5522 void skipTest(TestCaseInfo
const&)
override {}
5536 ReporterPreferences m_reporterPrefs;
5540 char const* getLineOfChars() {
5541 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
5543 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
5544 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
5549 struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {
5550 TestEventListenerBase( ReporterConfig
const& _config );
5554 void assertionStarting(AssertionInfo
const&)
override;
5555 bool assertionEnded(AssertionStats
const&)
override;
5579 BrightRed = Bright | Red,
5580 BrightGreen = Bright | Green,
5581 LightGrey = Bright | Grey,
5582 BrightWhite = Bright | White,
5583 BrightYellow = Bright | Yellow,
5586 FileName = LightGrey,
5587 Warning = BrightYellow,
5588 ResultError = BrightRed,
5589 ResultSuccess = BrightGreen,
5590 ResultExpectedFailure = Warning,
5595 OriginalExpression = Cyan,
5596 ReconstructedExpression = BrightYellow,
5598 SecondaryText = LightGrey,
5603 Colour( Code _colourCode );
5604 Colour( Colour&& other )
noexcept;
5605 Colour& operator=( Colour&& other )
noexcept;
5609 static void use( Code _colourCode );
5612 bool m_moved =
false;
5625 template<
typename T>
5626 class ReporterRegistrar {
5628 class ReporterFactory :
public IReporterFactory {
5630 IStreamingReporterPtr
create( ReporterConfig
const& config )
const override {
5635 return T::getDescription();
5646 template<
typename T>
5647 class ListenerRegistrar {
5649 class ListenerFactory :
public IReporterFactory {
5651 IStreamingReporterPtr
create( ReporterConfig
const& config )
const override {
5661 ListenerRegistrar() {
5667#if !defined(CATCH_CONFIG_DISABLE)
5669#define CATCH_REGISTER_REPORTER( name, reporterType ) \
5670 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
5671 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \
5672 CATCH_INTERNAL_UNSUPPRESS_GLOBALS_WARNINGS
5674#define CATCH_REGISTER_LISTENER( listenerType ) \
5675 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \
5676 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \
5677 CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS
5680#define CATCH_REGISTER_REPORTER(name, reporterType)
5681#define CATCH_REGISTER_LISTENER(listenerType)
5691 struct CompactReporter : StreamingReporterBase<CompactReporter> {
5693 using StreamingReporterBase::StreamingReporterBase;
5695 ~CompactReporter()
override;
5699 ReporterPreferences getPreferences()
const override;
5701 void noMatchingTestCases(
std::string const& spec)
override;
5703 void assertionStarting(AssertionInfo
const&)
override;
5705 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5707 void sectionEnded(SectionStats
const& _sectionStats)
override;
5709 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5718#if defined(_MSC_VER)
5719#pragma warning(push)
5720#pragma warning(disable:4061)
5727 struct SummaryColumn;
5730 struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {
5733 ConsoleReporter(ReporterConfig
const& config);
5734 ~ConsoleReporter()
override;
5737 void noMatchingTestCases(
std::string const& spec)
override;
5739 void assertionStarting(AssertionInfo
const&)
override;
5741 bool assertionEnded(AssertionStats
const& _assertionStats)
override;
5743 void sectionStarting(SectionInfo
const& _sectionInfo)
override;
5744 void sectionEnded(SectionStats
const& _sectionStats)
override;
5746 void benchmarkStarting(BenchmarkInfo
const& info)
override;
5747 void benchmarkEnded(BenchmarkStats
const& stats)
override;
5749 void testCaseEnded(TestCaseStats
const& _testCaseStats)
override;
5750 void testGroupEnded(TestGroupStats
const& _testGroupStats)
override;
5751 void testRunEnded(TestRunStats
const& _testRunStats)
override;
5752 void testRunStarting(TestRunInfo
const& _testRunInfo)
override;
5757 void lazyPrintWithoutClosingBenchmarkTable();
5758 void lazyPrintRunInfo();
5759 void lazyPrintGroupInfo();
5760 void printTestCaseAndSectionHeader();
5769 void printTotals(Totals
const& totals);
5772 void printTotalsDivider(Totals
const& totals);
5773 void printSummaryDivider();
5774 void printTestFilters();
5777 bool m_headerPrinted =
false;
5782#if defined(_MSC_VER)
5797 enum ForWhat { ForTextNodes, ForAttributes };
5799 XmlEncode(
std::string const& str, ForWhat forWhat = ForTextNodes );
5813 class ScopedElement {
5815 ScopedElement( XmlWriter* writer );
5817 ScopedElement( ScopedElement&& other )
noexcept;
5818 ScopedElement& operator=( ScopedElement&& other )
noexcept;
5822 ScopedElement& writeText(
std::string const& text,
bool indent =
true );
5824 template<
typename T>
5825 ScopedElement& writeAttribute(
std::string const&
name,
T const& attribute ) {
5826 m_writer->writeAttribute(
name, attribute );
5831 mutable XmlWriter* m_writer =
nullptr;
5837 XmlWriter( XmlWriter
const& ) =
delete;
5838 XmlWriter& operator=( XmlWriter
const& ) =
delete;
5844 XmlWriter& endElement();
5850 template<
typename T>
5852 ReusableStringStream rss;
5854 return writeAttribute(
name, rss.str() );
5857 XmlWriter& writeText(
std::string const& text,
bool indent =
true );
5859 XmlWriter& writeComment(
std::string const& text );
5861 void writeStylesheetRef(
std::string const& url );
5863 XmlWriter& writeBlankLine();
5865 void ensureTagClosed();
5869 void writeDeclaration();
5871 void newlineIfNecessary();
5873 bool m_tagIsOpen =
false;
5874 bool m_needsNewline =
false;
5885 class JunitReporter :
public CumulativeReporterBase<JunitReporter> {
5887 JunitReporter(ReporterConfig
const& _config);
5889 ~JunitReporter()
override;
5893 void noMatchingTestCases(
std::string const& )
override;
5895 void testRunStarting(TestRunInfo
const& runInfo)
override;
5897 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5899 void testCaseStarting(TestCaseInfo
const& testCaseInfo)
override;
5900 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5902 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5904 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5906 void testRunEndedCumulative()
override;
5908 void writeGroup(TestGroupNode
const& groupNode,
double suiteTime);
5910 void writeTestCase(TestCaseNode
const& testCaseNode);
5914 SectionNode
const& sectionNode);
5916 void writeAssertions(SectionNode
const& sectionNode);
5917 void writeAssertion(AssertionStats
const& stats);
5923 unsigned int unexpectedExceptions = 0;
5924 bool m_okToFail =
false;
5933 class XmlReporter :
public StreamingReporterBase<XmlReporter> {
5935 XmlReporter(ReporterConfig
const& _config);
5937 ~XmlReporter()
override;
5943 void writeSourceInfo(SourceLineInfo
const& sourceInfo);
5947 void noMatchingTestCases(
std::string const& s)
override;
5949 void testRunStarting(TestRunInfo
const& testInfo)
override;
5951 void testGroupStarting(GroupInfo
const& groupInfo)
override;
5953 void testCaseStarting(TestCaseInfo
const& testInfo)
override;
5955 void sectionStarting(SectionInfo
const& sectionInfo)
override;
5957 void assertionStarting(AssertionInfo
const&)
override;
5959 bool assertionEnded(AssertionStats
const& assertionStats)
override;
5961 void sectionEnded(SectionStats
const& sectionStats)
override;
5963 void testCaseEnded(TestCaseStats
const& testCaseStats)
override;
5965 void testGroupEnded(TestGroupStats
const& testGroupStats)
override;
5967 void testRunEnded(TestRunStats
const& testRunStats)
override;
5970 Timer m_testCaseTimer;
5972 int m_sectionDepth = 0;
5988#pragma clang diagnostic push
5989#pragma clang diagnostic ignored "-Wweak-vtables"
6000namespace TestCaseTracking {
6002 struct NameAndLocation {
6004 SourceLineInfo location;
6006 NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location );
6014 virtual ~ITracker();
6017 virtual NameAndLocation
const& nameAndLocation()
const = 0;
6020 virtual bool isComplete()
const = 0;
6021 virtual bool isSuccessfullyCompleted()
const = 0;
6022 virtual bool isOpen()
const = 0;
6023 virtual bool hasChildren()
const = 0;
6025 virtual ITracker& parent() = 0;
6028 virtual void close() = 0;
6029 virtual void fail() = 0;
6030 virtual void markAsNeedingAnotherRun() = 0;
6032 virtual void addChild( ITrackerPtr
const& child ) = 0;
6033 virtual ITrackerPtr findChild( NameAndLocation
const& nameAndLocation ) = 0;
6034 virtual void openChild() = 0;
6037 virtual bool isSectionTracker()
const = 0;
6038 virtual bool isGeneratorTracker()
const = 0;
6041 class TrackerContext {
6049 ITrackerPtr m_rootTracker;
6050 ITracker* m_currentTracker =
nullptr;
6051 RunState m_runState = NotStarted;
6055 ITracker& startRun();
6059 void completeCycle();
6061 bool completedCycle()
const;
6062 ITracker& currentTracker();
6063 void setCurrentTracker( ITracker* tracker );
6066 class TrackerBase :
public ITracker {
6073 CompletedSuccessfully,
6078 NameAndLocation m_nameAndLocation;
6079 TrackerContext& m_ctx;
6081 Children m_children;
6082 CycleState m_runState = NotStarted;
6085 TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
6087 NameAndLocation
const& nameAndLocation()
const override;
6088 bool isComplete()
const override;
6089 bool isSuccessfullyCompleted()
const override;
6090 bool isOpen()
const override;
6091 bool hasChildren()
const override;
6093 void addChild( ITrackerPtr
const& child )
override;
6095 ITrackerPtr findChild( NameAndLocation
const& nameAndLocation )
override;
6096 ITracker& parent()
override;
6098 void openChild()
override;
6100 bool isSectionTracker()
const override;
6101 bool isGeneratorTracker()
const override;
6105 void close()
override;
6106 void fail()
override;
6107 void markAsNeedingAnotherRun()
override;
6110 void moveToParent();
6114 class SectionTracker :
public TrackerBase {
6117 SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent );
6119 bool isSectionTracker()
const override;
6121 bool isComplete()
const override;
6123 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation );
6133using TestCaseTracking::ITracker;
6134using TestCaseTracking::TrackerContext;
6135using TestCaseTracking::SectionTracker;
6145 struct LeakDetector {
6162bool marginComparison(
double lhs,
double rhs,
double margin) {
6163 return (lhs + margin >= rhs) && (rhs + margin >= lhs);
6171 Approx::Approx (
double value )
6172 : m_epsilon(
std::numeric_limits<float>::epsilon()*100 ),
6178 Approx Approx::custom() {
6182 Approx Approx::operator-()
const {
6184 temp.m_value = -temp.m_value;
6189 ReusableStringStream rss;
6194 bool Approx::equalityComparisonImpl(
const double other)
const {
6197 return marginComparison(m_value, other, m_margin) || marginComparison(m_value, other, m_epsilon * (m_scale +
std::fabs(m_value)));
6200 void Approx::setMargin(
double newMargin) {
6202 "Invalid Approx::margin: " << newMargin <<
'.'
6203 <<
" Approx::Margin has to be non-negative.");
6204 m_margin = newMargin;
6207 void Approx::setEpsilon(
double newEpsilon) {
6209 "Invalid Approx::epsilon: " << newEpsilon <<
'.'
6210 <<
" Approx::epsilon has to be in [0, 1]");
6211 m_epsilon = newEpsilon;
6217 Detail::Approx
operator "" _a(
long double val) {
6218 return Detail::Approx(val);
6220 Detail::Approx
operator "" _a(
unsigned long long val) {
6221 return Detail::Approx(val);
6226 return value.toString();
6236 bool isDebuggerActive();
6239#ifdef CATCH_PLATFORM_MAC
6241 #define CATCH_TRAP() __asm__("int $3\n" : : )
6243#elif defined(CATCH_PLATFORM_LINUX)
6247 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
6248 #define CATCH_TRAP() asm volatile ("int $3")
6252 #define CATCH_TRAP() raise(SIGTRAP)
6254#elif defined(_MSC_VER)
6255 #define CATCH_TRAP() __debugbreak()
6256#elif defined(__MINGW32__)
6257 extern "C" __declspec(dllimport)
void __stdcall DebugBreak();
6258 #define CATCH_TRAP() DebugBreak()
6262 #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()
6264 #define CATCH_BREAK_INTO_DEBUGGER() []{}()
6275#if defined(CATCH_PLATFORM_WINDOWS)
6277#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
6278# define CATCH_DEFINED_NOMINMAX
6281#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
6282# define CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6283# define WIN32_LEAN_AND_MEAN
6292#ifdef CATCH_DEFINED_NOMINMAX
6295#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN
6296# undef WIN32_LEAN_AND_MEAN
6302#if defined( CATCH_CONFIG_WINDOWS_SEH )
6306 struct FatalConditionHandler {
6308 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo);
6309 FatalConditionHandler();
6310 static void reset();
6311 ~FatalConditionHandler();
6315 static ULONG guaranteeSize;
6316 static PVOID exceptionHandlerHandle;
6321#elif defined ( CATCH_CONFIG_POSIX_SIGNALS )
6327 struct FatalConditionHandler {
6330 static struct sigaction oldSigActions[];
6331 static stack_t oldSigStack;
6332 static char altStackMem[];
6334 static void handleSignal(
int sig );
6336 FatalConditionHandler();
6337 ~FatalConditionHandler();
6338 static void reset();
6346 struct FatalConditionHandler {
6358 struct IMutableContext;
6362 class RunContext :
public IResultCapture,
public IRunner {
6365 RunContext( RunContext
const& ) =
delete;
6366 RunContext& operator =( RunContext
const& ) =
delete;
6368 explicit RunContext( IConfigPtr
const& _config, IStreamingReporterPtr&& reporter );
6370 ~RunContext()
override;
6375 Totals runTest(TestCase
const& testCase);
6378 IStreamingReporter& reporter()
const;
6384 ( AssertionInfo
const& info,
6385 ITransientExpression
const& expr,
6386 AssertionReaction& reaction )
override;
6388 ( AssertionInfo
const& info,
6389 ResultWas::OfType resultType,
6390 StringRef
const& message,
6391 AssertionReaction& reaction )
override;
6392 void handleUnexpectedExceptionNotThrown
6393 ( AssertionInfo
const& info,
6394 AssertionReaction& reaction )
override;
6395 void handleUnexpectedInflightException
6396 ( AssertionInfo
const& info,
6398 AssertionReaction& reaction )
override;
6399 void handleIncomplete
6400 ( AssertionInfo
const& info )
override;
6402 ( AssertionInfo
const &info,
6403 ResultWas::OfType resultType,
6404 AssertionReaction &reaction )
override;
6406 bool sectionStarted( SectionInfo
const& sectionInfo, Counts& assertions )
override;
6408 void sectionEnded( SectionEndInfo
const& endInfo )
override;
6409 void sectionEndedEarly( SectionEndInfo
const& endInfo )
override;
6413 void benchmarkStarting( BenchmarkInfo
const& info )
override;
6414 void benchmarkEnded( BenchmarkStats
const& stats )
override;
6416 void pushScopedMessage( MessageInfo
const& message )
override;
6417 void popScopedMessage( MessageInfo
const& message )
override;
6419 void emplaceUnscopedMessage( MessageBuilder
const& builder )
override;
6423 const AssertionResult* getLastResult()
const override;
6425 void exceptionEarlyReported()
override;
6427 void handleFatalErrorCondition( StringRef message )
override;
6429 bool lastAssertionPassed()
override;
6431 void assertionPassed()
override;
6435 bool aborting() const final;
6439 void runCurrentTest(
std::
string& redirectedCout,
std::
string& redirectedCerr );
6440 void invokeActiveTestCase();
6442 void resetAssertionInfo();
6443 bool testForMissingAssertions( Counts& assertions );
6445 void assertionEnded( AssertionResult const& result );
6447 ( AssertionInfo const &info,
6448 ResultWas::OfType resultType,
6449 ITransientExpression const *expr,
6452 void populateReaction( AssertionReaction& reaction );
6456 void handleUnfinishedSections();
6458 TestRunInfo m_runInfo;
6459 IMutableContext& m_context;
6460 TestCase const* m_activeTestCase =
nullptr;
6461 ITracker* m_testCaseTracker =
nullptr;
6462 Option<AssertionResult> m_lastResult;
6464 IConfigPtr m_config;
6466 IStreamingReporterPtr m_reporter;
6467 std::vector<MessageInfo> m_messages;
6468 std::vector<ScopedMessage> m_messageScopes;
6469 AssertionInfo m_lastAssertionInfo;
6470 std::vector<SectionEndInfo> m_unfinishedSections;
6471 std::vector<ITracker*> m_activeSections;
6472 TrackerContext m_trackerContext;
6473 bool m_lastAssertionPassed = false;
6474 bool m_shouldReportUnexpected = true;
6475 bool m_includeSuccessfulResults;
6485 expr.streamReconstructedExpression( os );
6490 LazyExpression::LazyExpression(
bool isNegated )
6491 : m_isNegated( isNegated )
6496 LazyExpression::operator
bool()
const {
6497 return m_transientExpression !=
nullptr;
6501 if( lazyExpr.m_isNegated )
6505 if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )
6506 os <<
"(" << *lazyExpr.m_transientExpression <<
")";
6508 os << *lazyExpr.m_transientExpression;
6511 os <<
"{** error - unchecked empty expression requested **}";
6517 ( StringRef
const& macroName,
6518 SourceLineInfo
const& lineInfo,
6519 StringRef capturedExpression,
6521 : m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },
6544 CATCH_BREAK_INTO_DEBUGGER();
6547#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
6550 CATCH_ERROR(
"Test failure requires aborting test!" );
6588 AssertionResultData::AssertionResultData(
ResultWas::OfType _resultType, LazyExpression
const & _lazyExpression):
6589 lazyExpression(_lazyExpression),
6590 resultType(_resultType) {}
6592 std::string AssertionResultData::reconstructExpression()
const {
6594 if( reconstructedExpression.empty() ) {
6595 if( lazyExpression ) {
6596 ReusableStringStream rss;
6597 rss << lazyExpression;
6598 reconstructedExpression = rss.str();
6601 return reconstructedExpression;
6604 AssertionResult::AssertionResult( AssertionInfo
const& info, AssertionResultData
const&
data )
6606 m_resultData(
data )
6610 bool AssertionResult::succeeded()
const {
6615 bool AssertionResult::isOk()
const {
6620 return m_resultData.resultType;
6623 bool AssertionResult::hasExpression()
const {
6624 return m_info.capturedExpression[0] != 0;
6627 bool AssertionResult::hasMessage()
const {
6628 return !m_resultData.message.empty();
6631 std::string AssertionResult::getExpression()
const {
6633 return "!(" + m_info.capturedExpression + ")";
6635 return m_info.capturedExpression;
6638 std::string AssertionResult::getExpressionInMacro()
const {
6640 if( m_info.macroName[0] == 0 )
6641 expr = m_info.capturedExpression;
6643 expr.
reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );
6644 expr += m_info.macroName;
6646 expr += m_info.capturedExpression;
6652 bool AssertionResult::hasExpandedExpression()
const {
6653 return hasExpression() && getExpandedExpression() != getExpression();
6656 std::string AssertionResult::getExpandedExpression()
const {
6657 std::string expr = m_resultData.reconstructExpression();
6664 return m_resultData.message;
6666 SourceLineInfo AssertionResult::getSourceInfo()
const {
6667 return m_info.lineInfo;
6670 StringRef AssertionResult::getTestMacroName()
const {
6671 return m_info.macroName;
6688 auto elapsed = m_timer.getElapsedNanoseconds();
6691 if( elapsed < m_resolution ) {
6692 m_iterationsToRun *= 10;
6706 using StringMatcher = Matchers::Impl::MatcherBase<std::string>;
6713 MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );
6714 handler.handleExpr( expr );
6726#ifdef CLARA_CONFIG_CONSOLE_WIDTH
6727#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6728#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6730#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1
6733#pragma clang diagnostic push
6734#pragma clang diagnostic ignored "-Wweak-vtables"
6735#pragma clang diagnostic ignored "-Wexit-time-destructors"
6736#pragma clang diagnostic ignored "-Wshadow"
6750#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6751#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80
6754#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6755#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH
6758#ifndef CLARA_CONFIG_OPTIONAL_TYPE
6760#if __has_include(<optional>) && __cplusplus >= 201703L
6762#define CLARA_CONFIG_OPTIONAL_TYPE std::optional
6784#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH
6785#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80
6792inline auto isWhitespace(
char c) ->
bool {
6794 return chars.
find(c) != std::string::npos;
6796inline auto isBreakableBefore(
char c) ->
bool {
6798 return chars.
find(c) != std::string::npos;
6800inline auto isBreakableAfter(
char c) ->
bool {
6802 return chars.
find(c) != std::string::npos;
6809 size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
6810 size_t m_indent = 0;
6811 size_t m_initialIndent = std::string::npos;
6817 Column
const& m_column;
6818 size_t m_stringIndex = 0;
6823 bool m_suffix =
false;
6825 iterator(Column
const& column,
size_t stringIndex)
6827 m_stringIndex(stringIndex) {}
6829 auto line() const ->
std::
string const& {
return m_column.m_strings[m_stringIndex]; }
6831 auto isBoundary(
size_t at)
const ->
bool {
6833 assert(at <= line().
size());
6835 return at == line().size() ||
6836 (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
6837 isBreakableBefore(line()[at]) ||
6838 isBreakableAfter(line()[at - 1]);
6842 assert(m_stringIndex < m_column.m_strings.size());
6845 auto width = m_column.m_width - indent();
6847 if (line()[m_pos] ==
'\n') {
6850 while (m_end < line().
size() && line()[m_end] !=
'\n')
6853 if (m_end < m_pos + width) {
6854 m_len = m_end - m_pos;
6857 while (len > 0 && !isBoundary(m_pos + len))
6859 while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
6871 auto indent() const ->
size_t {
6872 auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;
6873 return initial == std::string::npos ? m_column.m_indent : initial;
6877 return std::string(indent(),
' ') + (m_suffix ? plain + "-" : plain);
6887 explicit iterator(Column
const& column) : m_column(column) {
6888 assert(m_column.m_width > m_column.m_indent);
6889 assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
6895 auto operator *() const ->
std::
string {
6896 assert(m_stringIndex < m_column.m_strings.size());
6897 assert(m_pos <= m_end);
6898 return addIndentAndSuffix(line().substr(m_pos, m_len));
6901 auto operator ++() -> iterator& {
6903 if (m_pos < line().
size() && line()[m_pos] ==
'\n')
6906 while (m_pos < line().
size() && isWhitespace(line()[m_pos]))
6909 if (m_pos == line().
size()) {
6913 if (m_stringIndex < m_column.m_strings.size())
6917 auto operator ++(
int) -> iterator {
6918 iterator
prev(*
this);
6923 auto operator ==(iterator
const& other)
const ->
bool {
6925 m_pos == other.m_pos &&
6926 m_stringIndex == other.m_stringIndex &&
6927 &m_column == &other.m_column;
6929 auto operator !=(iterator
const& other)
const ->
bool {
6933 using const_iterator = iterator;
6937 auto width(
size_t newWidth) -> Column& {
6938 assert(newWidth > 0);
6942 auto indent(
size_t newIndent) -> Column& {
6943 m_indent = newIndent;
6946 auto initialIndent(
size_t newIndent) -> Column& {
6947 m_initialIndent = newIndent;
6951 auto width() const ->
size_t {
return m_width; }
6952 auto begin() const -> iterator {
return iterator(*
this); }
6953 auto end() const -> iterator {
return { *
this, m_strings.
size() }; }
6957 for (
auto line : col) {
6967 auto operator + (Column
const& other)->Columns;
6969 auto toString() const ->
std::
string {
6976class Spacer :
public Column {
6979 explicit Spacer(
size_t spaceWidth) : Column(
"") {
6995 size_t m_activeIterators;
6997 iterator(Columns
const& columns, EndTag)
6998 : m_columns(columns.m_columns),
6999 m_activeIterators(0) {
7002 for (
auto const& col : m_columns)
7003 m_iterators.push_back(col.
end());
7013 explicit iterator(Columns
const& columns)
7014 : m_columns(columns.m_columns),
7015 m_activeIterators(m_columns.
size()) {
7018 for (
auto const& col : m_columns)
7019 m_iterators.push_back(col.
begin());
7022 auto operator ==(iterator
const& other)
const ->
bool {
7023 return m_iterators == other.m_iterators;
7025 auto operator !=(iterator
const& other)
const ->
bool {
7026 return m_iterators != other.m_iterators;
7028 auto operator *() const ->
std::
string {
7031 for (
size_t i = 0; i < m_columns.
size(); ++i) {
7032 auto width = m_columns[i].width();
7033 if (m_iterators[i] != m_columns[i].
end()) {
7035 row += padding + col;
7036 if (col.
size() < width)
7041 padding +=
std::string(width, ' ');
7046 auto operator ++() -> iterator& {
7047 for (
size_t i = 0; i < m_columns.
size(); ++i) {
7048 if (m_iterators[i] != m_columns[i].
end())
7053 auto operator ++(
int) -> iterator {
7054 iterator
prev(*
this);
7059 using const_iterator = iterator;
7061 auto begin() const -> iterator {
return iterator(*
this); }
7062 auto end() const -> iterator {
return { *
this, iterator::EndTag() }; }
7064 auto operator += (Column
const& col) -> Columns& {
7068 auto operator + (Column
const& col) -> Columns {
7069 Columns combined = *
this;
7077 for (
auto line : cols) {
7087 auto toString() const ->
std::
string {
7094inline auto Column::operator + (Column
const& other) -> Columns {
7114#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )
7115#define CATCH_PLATFORM_WINDOWS
7118namespace Catch {
namespace clara {
7122 template<
typename L>
7123 struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};
7125 template<
typename ClassT,
typename ReturnT,
typename... Args>
7126 struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {
7127 static const bool isValid =
false;
7130 template<
typename ClassT,
typename ReturnT,
typename ArgT>
7131 struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {
7132 static const bool isValid =
true;
7134 using ReturnType = ReturnT;
7146 Args(
int argc,
char const*
const* argv )
7147 : m_exeName(argv[0]),
7148 m_args(argv + 1, argv + argc) {}
7151 : m_exeName( *args.
begin() ),
7152 m_args( args.
begin()+1, args.
end() )
7155 auto exeName() const ->
std::
string {
7162 enum class TokenType {
7170 inline auto isOptPrefix(
char c ) ->
bool {
7172#ifdef CATCH_PLATFORM_WINDOWS
7186 m_tokenBuffer.
resize( 0 );
7189 while( it != itEnd && it->empty() )
7193 auto const &
next = *it;
7194 if( isOptPrefix( next[0] ) ) {
7195 auto delimiterPos =
next.find_first_of(
" :=" );
7196 if( delimiterPos != std::string::npos ) {
7197 m_tokenBuffer.
push_back( { TokenType::Option,
next.substr( 0, delimiterPos ) } );
7198 m_tokenBuffer.
push_back( { TokenType::Argument,
next.substr( delimiterPos + 1 ) } );
7200 if( next[1] !=
'-' &&
next.size() > 2 ) {
7202 for(
size_t i = 1; i <
next.size(); ++i ) {
7204 m_tokenBuffer.
push_back( { TokenType::Option, opt } );
7217 explicit TokenStream( Args
const &args ) : TokenStream( args.m_args.
begin(), args.m_args.
end() ) {}
7219 TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {
7223 explicit operator bool()
const {
7224 return !m_tokenBuffer.
empty() || it != itEnd;
7227 auto count() const ->
size_t {
return m_tokenBuffer.
size() + (itEnd - it); }
7230 assert( !m_tokenBuffer.
empty() );
7231 return m_tokenBuffer.
front();
7234 auto operator->() const -> Token const * {
7235 assert( !m_tokenBuffer.
empty() );
7236 return &m_tokenBuffer.
front();
7239 auto operator++() -> TokenStream & {
7240 if( m_tokenBuffer.
size() >= 2 ) {
7241 m_tokenBuffer.
erase( m_tokenBuffer.
begin() );
7254 Ok, LogicError, RuntimeError
7258 ResultBase( Type
type ) : m_type(
type ) {}
7259 virtual ~ResultBase() =
default;
7261 virtual void enforceOk()
const = 0;
7266 template<
typename T>
7267 class ResultValueBase :
public ResultBase {
7269 auto value() const ->
T const & {
7275 ResultValueBase( Type
type ) : ResultBase(
type ) {}
7277 ResultValueBase( ResultValueBase
const &other ) : ResultBase( other ) {
7278 if( m_type == ResultBase::Ok )
7279 new( &m_value )
T( other.m_value );
7282 ResultValueBase( Type,
T const &
value ) : ResultBase( Ok ) {
7283 new( &m_value )
T(
value );
7286 auto operator=( ResultValueBase
const &other ) -> ResultValueBase & {
7287 if( m_type == ResultBase::Ok )
7289 ResultBase::operator=(other);
7290 if( m_type == ResultBase::Ok )
7291 new( &m_value )
T( other.m_value );
7295 ~ResultValueBase()
override {
7306 class ResultValueBase<void> :
public ResultBase {
7308 using ResultBase::ResultBase;
7311 template<
typename T =
void>
7312 class BasicResult :
public ResultValueBase<
T> {
7314 template<
typename U>
7315 explicit BasicResult( BasicResult<U>
const &other )
7316 : ResultValueBase<
T>( other.
type() ),
7317 m_errorMessage( other.errorMessage() )
7319 assert(
type() != ResultBase::Ok );
7322 template<
typename U>
7323 static auto ok( U
const &
value ) -> BasicResult {
return { ResultBase::Ok,
value }; }
7324 static auto ok() -> BasicResult {
return { ResultBase::Ok }; }
7325 static auto logicError(
std::string const &message ) -> BasicResult {
return { ResultBase::LogicError, message }; }
7326 static auto runtimeError(
std::string const &message ) -> BasicResult {
return { ResultBase::RuntimeError, message }; }
7328 explicit operator bool()
const {
return m_type == ResultBase::Ok; }
7329 auto type() const -> ResultBase::Type {
return m_type; }
7330 auto errorMessage() const ->
std::
string {
return m_errorMessage; }
7333 void enforceOk()
const override {
7337 assert( m_type != ResultBase::LogicError );
7338 assert( m_type != ResultBase::RuntimeError );
7339 if( m_type != ResultBase::Ok )
7346 : ResultValueBase<
T>(
type),
7347 m_errorMessage(message)
7349 assert( m_type != ResultBase::Ok );
7352 using ResultValueBase<
T>::ResultValueBase;
7353 using ResultBase::m_type;
7356 enum class ParseResultType {
7357 Matched, NoMatch, ShortCircuitAll, ShortCircuitSame
7363 ParseState( ParseResultType
type, TokenStream
const &remainingTokens )
7365 m_remainingTokens( remainingTokens )
7368 auto type() const -> ParseResultType {
return m_type; }
7369 auto remainingTokens() const -> TokenStream {
return m_remainingTokens; }
7372 ParseResultType m_type;
7373 TokenStream m_remainingTokens;
7376 using Result = BasicResult<void>;
7377 using ParserResult = BasicResult<ParseResultType>;
7378 using InternalParseResult = BasicResult<ParseState>;
7380 struct HelpColumns {
7385 template<
typename T>
7386 inline auto convertInto(
std::string const &source,
T& target ) -> ParserResult {
7391 return ParserResult::runtimeError(
"Unable to convert '" + source +
"' to destination type" );
7393 return ParserResult::ok( ParseResultType::Matched );
7397 return ParserResult::ok( ParseResultType::Matched );
7399 inline auto convertInto(
std::string const &source,
bool &target ) -> ParserResult {
7402 if (srcLC ==
"y" || srcLC ==
"1" || srcLC ==
"true" || srcLC ==
"yes" || srcLC ==
"on")
7404 else if (srcLC ==
"n" || srcLC ==
"0" || srcLC ==
"false" || srcLC ==
"no" || srcLC ==
"off")
7407 return ParserResult::runtimeError(
"Expected a boolean value but did not recognise: '" + source +
"'" );
7408 return ParserResult::ok( ParseResultType::Matched );
7410#ifdef CLARA_CONFIG_OPTIONAL_TYPE
7411 template<
typename T>
7412 inline auto convertInto(
std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {
7414 auto result = convertInto( source, temp );
7416 target = std::move(temp);
7421 struct NonCopyable {
7422 NonCopyable() =
default;
7423 NonCopyable( NonCopyable
const & ) =
delete;
7424 NonCopyable( NonCopyable && ) =
delete;
7425 NonCopyable &operator=( NonCopyable
const & ) =
delete;
7426 NonCopyable &operator=( NonCopyable && ) =
delete;
7429 struct BoundRef : NonCopyable {
7430 virtual ~BoundRef() =
default;
7431 virtual auto isContainer() const ->
bool {
return false; }
7432 virtual auto isFlag() const ->
bool {
return false; }
7434 struct BoundValueRefBase : BoundRef {
7435 virtual auto setValue(
std::string const &
arg ) -> ParserResult = 0;
7437 struct BoundFlagRefBase : BoundRef {
7438 virtual auto setFlag(
bool flag ) -> ParserResult = 0;
7439 virtual auto isFlag() const ->
bool {
return true; }
7442 template<
typename T>
7443 struct BoundValueRef : BoundValueRefBase {
7446 explicit BoundValueRef(
T &ref ) : m_ref(
ref ) {}
7448 auto setValue(
std::string const &
arg ) -> ParserResult
override {
7449 return convertInto(
arg, m_ref );
7453 template<
typename T>
7454 struct BoundValueRef<
std::vector<
T>> : BoundValueRefBase {
7459 auto isContainer() const ->
bool override {
return true; }
7461 auto setValue(
std::string const &
arg ) -> ParserResult
override {
7465 m_ref.push_back( temp );
7470 struct BoundFlagRef : BoundFlagRefBase {
7473 explicit BoundFlagRef(
bool &ref ) : m_ref(
ref ) {}
7475 auto setFlag(
bool flag ) -> ParserResult
override {
7477 return ParserResult::ok( ParseResultType::Matched );
7481 template<
typename ReturnType>
7482 struct LambdaInvoker {
7485 template<
typename L,
typename ArgType>
7486 static auto invoke( L
const &lambda, ArgType
const &
arg ) -> ParserResult {
7487 return lambda(
arg );
7492 struct LambdaInvoker<void> {
7493 template<
typename L,
typename ArgType>
7494 static auto invoke( L
const &lambda, ArgType
const &
arg ) -> ParserResult {
7496 return ParserResult::ok( ParseResultType::Matched );
7500 template<
typename ArgType,
typename L>
7501 inline auto invokeLambda( L
const &lambda,
std::string const &
arg ) -> ParserResult {
7506 : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );
7509 template<
typename L>
7510 struct BoundLambda : BoundValueRefBase {
7513 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7514 explicit BoundLambda( L
const &lambda ) : m_lambda( lambda ) {}
7516 auto setValue(
std::string const &
arg ) -> ParserResult
override {
7517 return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda,
arg );
7521 template<
typename L>
7522 struct BoundFlagLambda : BoundFlagRefBase {
7525 static_assert( UnaryLambdaTraits<L>::isValid,
"Supplied lambda must take exactly one argument" );
7528 explicit BoundFlagLambda( L
const &lambda ) : m_lambda( lambda ) {}
7530 auto setFlag(
bool flag ) -> ParserResult
override {
7531 return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );
7535 enum class Optionality { Optional, Required };
7541 virtual ~ParserBase() =
default;
7542 virtual auto validate() const -> Result {
return Result::ok(); }
7543 virtual auto parse(
std::string const& exeName, TokenStream
const &tokens)
const -> InternalParseResult = 0;
7544 virtual auto cardinality() const ->
size_t {
return 1; }
7546 auto parse( Args
const &args )
const -> InternalParseResult {
7547 return parse( args.exeName(), TokenStream( args ) );
7551 template<
typename DerivedT>
7552 class ComposableParserImpl :
public ParserBase {
7554 template<
typename T>
7555 auto operator|(
T const &other )
const -> Parser;
7557 template<
typename T>
7558 auto operator+(
T const &other )
const -> Parser;
7562 template<
typename DerivedT>
7563 class ParserRefImpl :
public ComposableParserImpl<DerivedT> {
7565 Optionality m_optionality = Optionality::Optional;
7573 template<
typename T>
7579 template<
typename LambdaT>
7580 ParserRefImpl( LambdaT
const &ref,
std::string const &hint )
7585 auto operator()(
std::string const &description ) -> DerivedT & {
7586 m_description = description;
7587 return static_cast<DerivedT &
>( *this );
7590 auto optional() -> DerivedT & {
7591 m_optionality = Optionality::Optional;
7592 return static_cast<DerivedT &
>( *this );
7595 auto required() -> DerivedT & {
7596 m_optionality = Optionality::Required;
7597 return static_cast<DerivedT &
>( *this );
7600 auto isOptional() const ->
bool {
7601 return m_optionality == Optionality::Optional;
7604 auto cardinality() const ->
size_t override {
7605 if( m_ref->isContainer() )
7611 auto hint() const ->
std::
string {
return m_hint; }
7614 class ExeName :
public ComposableParserImpl<ExeName> {
7618 template<
typename LambdaT>
7626 explicit ExeName(
std::string &ref ) : ExeName() {
7630 template<
typename LambdaT>
7631 explicit ExeName( LambdaT
const& lambda ) : ExeName() {
7636 auto parse(
std::string const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
7637 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7640 auto name() const ->
std::
string {
return *m_name; }
7641 auto set(
std::string const& newName ) -> ParserResult {
7643 auto lastSlash = newName.find_last_of(
"\\/" );
7644 auto filename = ( lastSlash == std::string::npos )
7646 : newName.substr( lastSlash+1 );
7650 return m_ref->setValue( filename );
7652 return ParserResult::ok( ParseResultType::Matched );
7656 class Arg :
public ParserRefImpl<Arg> {
7658 using ParserRefImpl::ParserRefImpl;
7660 auto parse(
std::string const &, TokenStream
const &tokens )
const -> InternalParseResult
override {
7661 auto validationResult = validate();
7662 if( !validationResult )
7663 return InternalParseResult( validationResult );
7665 auto remainingTokens = tokens;
7666 auto const &token = *remainingTokens;
7667 if( token.type != TokenType::Argument )
7668 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7670 assert( !m_ref->isFlag() );
7671 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.
get() );
7673 auto result = valueRef->setValue( remainingTokens->token );
7675 return InternalParseResult( result );
7677 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7682#ifdef CATCH_PLATFORM_WINDOWS
7683 if( optName[0] ==
'/' )
7684 return "-" + optName.substr( 1 );
7690 class Opt :
public ParserRefImpl<Opt> {
7695 template<
typename LambdaT>
7696 explicit Opt( LambdaT
const &ref ) : ParserRefImpl(
std::
make_shared<BoundFlagLambda<LambdaT>>(
ref ) ) {}
7698 explicit Opt(
bool &ref ) : ParserRefImpl(
std::
make_shared<BoundFlagRef>(
ref ) ) {}
7700 template<
typename LambdaT>
7701 Opt( LambdaT
const &ref,
std::string const &hint ) : ParserRefImpl(
ref, hint ) {}
7703 template<
typename T>
7704 Opt(
T &ref,
std::string const &hint ) : ParserRefImpl(
ref, hint ) {}
7706 auto operator[](
std::string const &optName ) -> Opt & {
7711 auto getHelpColumns() const ->
std::vector<HelpColumns> {
7714 for(
auto const &opt : m_optNames ) {
7721 if( !m_hint.
empty() )
7722 oss <<
" <" << m_hint <<
">";
7723 return { { oss.
str(), m_description } };
7726 auto isMatch(
std::string const &optToken )
const ->
bool {
7727 auto normalisedToken = normaliseOpt( optToken );
7728 for(
auto const &
name : m_optNames ) {
7729 if( normaliseOpt(
name ) == normalisedToken )
7735 using ParserBase::parse;
7737 auto parse(
std::string const&, TokenStream
const &tokens )
const -> InternalParseResult
override {
7738 auto validationResult = validate();
7739 if( !validationResult )
7740 return InternalParseResult( validationResult );
7742 auto remainingTokens = tokens;
7743 if( remainingTokens && remainingTokens->type == TokenType::Option ) {
7744 auto const &token = *remainingTokens;
7745 if( isMatch(token.token ) ) {
7746 if( m_ref->isFlag() ) {
7747 auto flagRef =
static_cast<detail::BoundFlagRefBase*
>( m_ref.
get() );
7748 auto result = flagRef->setFlag(
true );
7750 return InternalParseResult( result );
7751 if(
result.value() == ParseResultType::ShortCircuitAll )
7752 return InternalParseResult::ok( ParseState(
result.value(), remainingTokens ) );
7754 auto valueRef =
static_cast<detail::BoundValueRefBase*
>( m_ref.
get() );
7756 if( !remainingTokens )
7757 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
7758 auto const &argToken = *remainingTokens;
7759 if( argToken.type != TokenType::Argument )
7760 return InternalParseResult::runtimeError(
"Expected argument following " + token.token );
7761 auto result = valueRef->setValue( argToken.token );
7763 return InternalParseResult( result );
7764 if(
result.value() == ParseResultType::ShortCircuitAll )
7765 return InternalParseResult::ok( ParseState(
result.value(), remainingTokens ) );
7767 return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );
7770 return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );
7773 auto validate() const -> Result
override {
7774 if( m_optNames.
empty() )
7775 return Result::logicError(
"No options supplied to Opt" );
7776 for(
auto const &
name : m_optNames ) {
7778 return Result::logicError(
"Option name cannot be empty" );
7779#ifdef CATCH_PLATFORM_WINDOWS
7780 if(
name[0] !=
'-' &&
name[0] !=
'/' )
7781 return Result::logicError(
"Option name must begin with '-' or '/'" );
7783 if(
name[0] !=
'-' )
7784 return Result::logicError(
"Option name must begin with '-'" );
7787 return ParserRefImpl::validate();
7792 Help(
bool &showHelpFlag )
7793 : Opt([&](
bool flag ) {
7794 showHelpFlag = flag;
7795 return ParserResult::ok( ParseResultType::ShortCircuitAll );
7798 static_cast<Opt &
>( *this )
7799 (
"display usage information")
7800 [
"-?"][
"-h"][
"--help"]
7805 struct Parser : ParserBase {
7807 mutable ExeName m_exeName;
7811 auto operator|=( ExeName
const &exeName ) -> Parser & {
7812 m_exeName = exeName;
7816 auto operator|=( Arg
const &
arg ) -> Parser & {
7821 auto operator|=( Opt
const &opt ) -> Parser & {
7826 auto operator|=( Parser
const &other ) -> Parser & {
7827 m_options.
insert(m_options.
end(), other.m_options.begin(), other.m_options.end());
7828 m_args.
insert(m_args.
end(), other.m_args.begin(), other.m_args.end());
7832 template<
typename T>
7833 auto operator|(
T const &other )
const -> Parser {
7834 return Parser( *
this ) |= other;
7838 template<
typename T>
7839 auto operator+=(
T const &other ) -> Parser & {
return operator|=( other ); }
7840 template<
typename T>
7843 auto getHelpColumns() const ->
std::vector<HelpColumns> {
7845 for (
auto const &o : m_options) {
7846 auto childCols = o.getHelpColumns();
7847 cols.
insert( cols.
end(), childCols.begin(), childCols.end() );
7853 if (!m_exeName.name().empty()) {
7854 os <<
"usage:\n" <<
" " << m_exeName.name() <<
" ";
7855 bool required =
true,
first =
true;
7856 for(
auto const &
arg : m_args ) {
7861 if(
arg.isOptional() && required ) {
7865 os <<
"<" <<
arg.hint() <<
">";
7866 if(
arg.cardinality() == 0 )
7871 if( !m_options.
empty() )
7873 os <<
"\n\nwhere options are:" <<
std::endl;
7876 auto rows = getHelpColumns();
7877 size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;
7878 size_t optWidth = 0;
7879 for(
auto const &cols : rows )
7882 optWidth = (
std::min)(optWidth, consoleWidth/2);
7884 for(
auto const &cols : rows ) {
7886 TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) +
7887 TextFlow::Spacer(4) +
7888 TextFlow::Column( cols.
right ).width( consoleWidth - 7 - optWidth );
7894 parser.writeToStream( os );
7898 auto validate() const -> Result
override {
7899 for(
auto const &opt : m_options ) {
7900 auto result = opt.validate();
7904 for(
auto const &
arg : m_args ) {
7909 return Result::ok();
7912 using ParserBase::parse;
7914 auto parse(
std::string const& exeName, TokenStream
const &tokens )
const -> InternalParseResult
override {
7917 ParserBase
const* parser =
nullptr;
7920 const size_t totalParsers = m_options.
size() + m_args.
size();
7921 assert( totalParsers < 512 );
7923 ParserInfo parseInfos[512];
7927 for (
auto const &opt : m_options) parseInfos[i++].parser = &opt;
7928 for (
auto const &
arg : m_args) parseInfos[i++].parser = &
arg;
7931 m_exeName.set( exeName );
7933 auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );
7934 while(
result.value().remainingTokens() ) {
7935 bool tokenParsed =
false;
7937 for(
size_t i = 0; i < totalParsers; ++i ) {
7938 auto& parseInfo = parseInfos[i];
7939 if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {
7940 result = parseInfo.parser->parse(exeName, result.value().remainingTokens());
7943 if (result.value().type() != ParseResultType::NoMatch) {
7951 if(
result.value().type() == ParseResultType::ShortCircuitAll )
7954 return InternalParseResult::runtimeError(
"Unrecognised token: " +
result.value().remainingTokens()->token );
7961 template<
typename DerivedT>
7962 template<
typename T>
7963 auto ComposableParserImpl<DerivedT>::operator|(
T const &other )
const -> Parser {
7964 return Parser() |
static_cast<DerivedT
const &
>( *this ) | other;
7969using detail::Parser;
7981using detail::ExeName;
7987using detail::ParseResultType;
7990using detail::ParserResult;
7996#pragma clang diagnostic pop
8000#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
8001#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
8002#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
8008 clara::Parser makeCommandLineParser( ConfigData& config );
8018 clara::Parser makeCommandLineParser( ConfigData& config ) {
8020 using namespace clara;
8022 auto const setWarning = [&](
std::string const& warning ) {
8023 auto warningSet = [&]() {
8024 if( warning ==
"NoAssertions" )
8027 if ( warning ==
"NoTests" )
8034 return ParserResult::runtimeError(
"Unrecognised warning: '" + warning +
"'" );
8035 config.warnings =
static_cast<WarnAbout::What>( config.warnings | warningSet );
8036 return ParserResult::ok( ParseResultType::Matched );
8038 auto const loadTestNamesFromFile = [&](
std::string const& filename ) {
8041 return ParserResult::runtimeError(
"Unable to load input file: '" + filename +
"'" );
8048 line =
'"' + line + '"';
8049 config.testsOrTags.push_back( line +
',' );
8052 return ParserResult::ok( ParseResultType::Matched );
8054 auto const setTestOrder = [&](
std::string const& order ) {
8062 return clara::ParserResult::runtimeError(
"Unrecognised ordering: '" + order +
"'" );
8063 return ParserResult::ok( ParseResultType::Matched );
8065 auto const setRngSeed = [&](
std::string const& seed ) {
8066 if( seed !=
"time" )
8067 return clara::detail::convertInto( seed, config.rngSeed );
8068 config.rngSeed =
static_cast<unsigned int>(
std::time(
nullptr) );
8069 return ParserResult::ok( ParseResultType::Matched );
8071 auto const setColourUsage = [&](
std::string const& useColour ) {
8072 auto mode =
toLower( useColour );
8076 else if( mode ==
"no" )
8078 else if( mode ==
"auto" )
8081 return ParserResult::runtimeError(
"colour mode must be one of: auto, yes or no. '" + useColour +
"' not recognised" );
8082 return ParserResult::ok( ParseResultType::Matched );
8084 auto const setWaitForKeypress = [&](
std::string const& keypress ) {
8085 auto keypressLc =
toLower( keypress );
8086 if( keypressLc ==
"start" )
8088 else if( keypressLc ==
"exit" )
8090 else if( keypressLc ==
"both" )
8093 return ParserResult::runtimeError(
"keypress argument must be one of: start, exit or both. '" + keypress +
"' not recognised" );
8094 return ParserResult::ok( ParseResultType::Matched );
8096 auto const setVerbosity = [&](
std::string const& verbosity ) {
8097 auto lcVerbosity =
toLower( verbosity );
8098 if( lcVerbosity ==
"quiet" )
8100 else if( lcVerbosity ==
"normal" )
8102 else if( lcVerbosity ==
"high" )
8105 return ParserResult::runtimeError(
"Unrecognised verbosity, '" + verbosity +
"'" );
8106 return ParserResult::ok( ParseResultType::Matched );
8108 auto const setReporter = [&](
std::string const& reporter ) {
8111 auto lcReporter =
toLower( reporter );
8112 auto result = factories.find( lcReporter );
8114 if( factories.end() != result )
8115 config.reporterName = lcReporter;
8117 return ParserResult::runtimeError(
"Unrecognized reporter, '" + reporter +
"'. Check available with --list-reporters" );
8118 return ParserResult::ok( ParseResultType::Matched );
8122 = ExeName( config.processName )
8123 | Help( config.showHelp )
8124 | Opt( config.listTests )
8125 ["-l"]["--list-tests"]
8126 (
"list all/matching test cases" )
8127 | Opt( config.listTags )
8128 ["-t"]["--list-tags"]
8129 (
"list all/matching tags" )
8130 | Opt( config.showSuccessfulTests )
8132 (
"include successful tests in output" )
8133 | Opt( config.shouldDebugBreak )
8135 (
"break into debugger on failure" )
8136 | Opt( config.noThrow )
8138 (
"skip exception tests" )
8139 | Opt( config.showInvisibles )
8140 ["-i"]["--invisibles"]
8141 (
"show invisibles (tabs, newlines)" )
8142 | Opt( config.outputFilename,
"filename" )
8144 (
"output filename" )
8145 | Opt( setReporter,
"name" )
8146 ["-r"]["--reporter"]
8147 (
"reporter to use (defaults to console)" )
8148 | Opt( config.name,
"name" )
8151 | Opt( [&](
bool ){ config.abortAfter = 1; } )
8153 (
"abort at first failure" )
8154 | Opt( [&](
int x ){ config.abortAfter = x; },
"no. failures" )
8156 (
"abort after x failures" )
8157 | Opt( setWarning,
"warning name" )
8159 (
"enable warnings" )
8161 [
"-d"][
"--durations"]
8162 (
"show test durations" )
8163 | Opt( loadTestNamesFromFile,
"filename" )
8164 ["-f"]["--input-file"]
8165 (
"load test names to run from a file" )
8166 | Opt( config.filenamesAsTags )
8167 ["-#"]["--filenames-as-tags"]
8168 (
"adds a tag for the filename" )
8169 | Opt( config.sectionsToRun,
"section name" )
8171 (
"specify section to run" )
8172 | Opt( setVerbosity,
"quiet|normal|high" )
8173 ["-v"]["--verbosity"]
8174 (
"set output verbosity" )
8175 | Opt( config.listTestNamesOnly )
8176 ["--list-test-names-only"]
8177 (
"list all/matching test cases names only" )
8178 | Opt( config.listReporters )
8179 ["--list-reporters"]
8180 (
"list all reporters" )
8181 | Opt( setTestOrder,
"decl|lex|rand" )
8183 (
"test case order (defaults to decl)" )
8184 | Opt( setRngSeed,
"'time'|number" )
8186 (
"set a specific seed for random numbers" )
8187 | Opt( setColourUsage,
"yes|no" )
8189 (
"should output be colourised" )
8190 | Opt( config.libIdentify )
8192 (
"report name and version according to libidentify standard" )
8193 | Opt( setWaitForKeypress,
"start|exit|both" )
8194 ["--wait-for-keypress"]
8195 (
"waits for a keypress before exiting" )
8196 | Opt( config.benchmarkResolutionMultiple,
"multiplier" )
8197 ["--benchmark-resolution-multiple"]
8198 (
"multiple of clock resolution to run benchmarks" )
8200 | Arg( config.testsOrTags,
"test name|pattern|tags" )
8201 (
"which test or tests to use" );
8216 return file[0] ==
'\0';
8219 return line == other.line && (file == other.file ||
std::strcmp(file, other.file) == 0);
8224 return line < other.line || ( line == other.line && file != other.file && (
std::strcmp(file, other.file) < 0));
8229 os <<
info.file <<
'(' <<
info.line <<
')';
8231 os <<
info.file <<
':' <<
info.line;
8249 Config::Config( ConfigData
const&
data )
8251 m_stream( openStream() )
8253 TestSpecParser parser(ITagAliasRegistry::get());
8254 if (!
data.testsOrTags.empty()) {
8255 m_hasTestFilters =
true;
8256 for(
auto const& testOrTags :
data.testsOrTags )
8257 parser.parse( testOrTags );
8259 m_testSpec = parser.testSpec();
8263 return m_data.outputFilename ;
8266 bool Config::listTests()
const {
return m_data.listTests; }
8267 bool Config::listTestNamesOnly()
const {
return m_data.listTestNamesOnly; }
8268 bool Config::listTags()
const {
return m_data.listTags; }
8269 bool Config::listReporters()
const {
return m_data.listReporters; }
8271 std::string Config::getProcessName()
const {
return m_data.processName; }
8272 std::string const& Config::getReporterName()
const {
return m_data.reporterName; }
8277 TestSpec
const& Config::testSpec()
const {
return m_testSpec; }
8278 bool Config::hasTestFilters()
const {
return m_hasTestFilters; }
8280 bool Config::showHelp()
const {
return m_data.showHelp; }
8283 bool Config::allowThrows()
const {
return !m_data.noThrow; }
8284 std::ostream& Config::stream()
const {
return m_stream->stream(); }
8285 std::string Config::name()
const {
return m_data.name.
empty() ? m_data.processName : m_data.name; }
8286 bool Config::includeSuccessfulResults()
const {
return m_data.showSuccessfulTests; }
8288 bool Config::warnAboutNoTests()
const {
return !!(m_data.warnings &
WarnAbout::NoTests); }
8291 unsigned int Config::rngSeed()
const {
return m_data.rngSeed; }
8292 int Config::benchmarkResolutionMultiple()
const {
return m_data.benchmarkResolutionMultiple; }
8294 bool Config::shouldDebugBreak()
const {
return m_data.shouldDebugBreak; }
8295 int Config::abortAfter()
const {
return m_data.abortAfter; }
8296 bool Config::showInvisibles()
const {
return m_data.showInvisibles; }
8297 Verbosity Config::verbosity()
const {
return m_data.verbosity; }
8299 IStream
const* Config::openStream() {
8307#if defined(__clang__)
8308# pragma clang diagnostic push
8309# pragma clang diagnostic ignored "-Wexit-time-destructors"
8332 struct IColourImpl {
8333 virtual ~IColourImpl() =
default;
8334 virtual void use( Colour::Code _colourCode ) = 0;
8337 struct NoColourImpl : IColourImpl {
8338 void use( Colour::Code ) {}
8340 static IColourImpl* instance() {
8341 static NoColourImpl s_instance;
8349#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
8350# ifdef CATCH_PLATFORM_WINDOWS
8351# define CATCH_CONFIG_COLOUR_WINDOWS
8353# define CATCH_CONFIG_COLOUR_ANSI
8357#if defined ( CATCH_CONFIG_COLOUR_WINDOWS )
8362 class Win32ColourImpl :
public IColourImpl {
8364 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
8366 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
8367 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
8368 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
8369 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
8372 void use( Colour::Code _colourCode )
override {
8373 switch( _colourCode ) {
8374 case Colour::None:
return setTextAttribute( originalForegroundAttributes );
8375 case Colour::White:
return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8376 case Colour::Red:
return setTextAttribute( FOREGROUND_RED );
8377 case Colour::Green:
return setTextAttribute( FOREGROUND_GREEN );
8378 case Colour::Blue:
return setTextAttribute( FOREGROUND_BLUE );
8379 case Colour::Cyan:
return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
8380 case Colour::Yellow:
return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
8381 case Colour::Grey:
return setTextAttribute( 0 );
8383 case Colour::LightGrey:
return setTextAttribute( FOREGROUND_INTENSITY );
8384 case Colour::BrightRed:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
8385 case Colour::BrightGreen:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
8386 case Colour::BrightWhite:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
8387 case Colour::BrightYellow:
return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );
8397 void setTextAttribute( WORD _textAttribute ) {
8398 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
8400 HANDLE stdoutHandle;
8401 WORD originalForegroundAttributes;
8402 WORD originalBackgroundAttributes;
8405 IColourImpl* platformColourInstance() {
8406 static Win32ColourImpl s_instance;
8410 ? config->useColour()
8416 : NoColourImpl::instance();
8422#elif defined( CATCH_CONFIG_COLOUR_ANSI )
8433 class PosixColourImpl :
public IColourImpl {
8435 void use( Colour::Code _colourCode )
override {
8436 switch( _colourCode ) {
8438 case Colour::White:
return setColour(
"[0m" );
8439 case Colour::Red:
return setColour(
"[0;31m" );
8440 case Colour::Green:
return setColour(
"[0;32m" );
8441 case Colour::Blue:
return setColour(
"[0;34m" );
8442 case Colour::Cyan:
return setColour(
"[0;36m" );
8443 case Colour::Yellow:
return setColour(
"[0;33m" );
8444 case Colour::Grey:
return setColour(
"[1;30m" );
8446 case Colour::LightGrey:
return setColour(
"[0;37m" );
8447 case Colour::BrightRed:
return setColour(
"[1;31m" );
8448 case Colour::BrightGreen:
return setColour(
"[1;32m" );
8449 case Colour::BrightWhite:
return setColour(
"[1;37m" );
8450 case Colour::BrightYellow:
return setColour(
"[1;33m" );
8456 static IColourImpl* instance() {
8457 static PosixColourImpl s_instance;
8462 void setColour(
const char* _escapeCode ) {
8464 <<
'\033' << _escapeCode;
8468 bool useColourOnPlatform() {
8470#ifdef CATCH_PLATFORM_MAC
8471 !isDebuggerActive() &&
8473#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))
8474 isatty(STDOUT_FILENO)
8480 IColourImpl* platformColourInstance() {
8484 ? config->useColour()
8487 colourMode = useColourOnPlatform()
8491 ? PosixColourImpl::instance()
8492 : NoColourImpl::instance();
8502 static IColourImpl* platformColourInstance() {
return NoColourImpl::instance(); }
8510 Colour::Colour( Code _colourCode ) { use( _colourCode ); }
8511 Colour::Colour( Colour&& rhs )
noexcept {
8512 m_moved = rhs.m_moved;
8515 Colour& Colour::operator=( Colour&& rhs )
noexcept {
8516 m_moved = rhs.m_moved;
8521 Colour::~Colour(){
if( !m_moved ) use( None ); }
8523 void Colour::use( Code _colourCode ) {
8524 static IColourImpl* impl = platformColourInstance();
8525 impl->use( _colourCode );
8534#if defined(__clang__)
8535# pragma clang diagnostic pop
8543 class Context :
public IMutableContext, NonCopyable {
8547 return m_resultCapture;
8549 IRunner* getRunner()
override {
8553 IConfigPtr const& getConfig()
const override {
8557 ~Context()
override;
8560 void setResultCapture( IResultCapture* resultCapture )
override {
8561 m_resultCapture = resultCapture;
8563 void setRunner( IRunner* runner )
override {
8566 void setConfig( IConfigPtr
const& config )
override {
8574 IRunner* m_runner =
nullptr;
8575 IResultCapture* m_resultCapture =
nullptr;
8591 Context::~Context() =
default;
8601 void writeToDebugConsole(
std::string const& text );
8605#ifdef CATCH_PLATFORM_WINDOWS
8608 void writeToDebugConsole(
std::string const& text ) {
8609 ::OutputDebugStringA( text.
c_str() );
8616 void writeToDebugConsole(
std::string const& text ) {
8626#ifdef CATCH_PLATFORM_MAC
8629# include <stdbool.h>
8630# include <sys/types.h>
8635#ifdef __apple_build_version__
8638# include <sys/sysctl.h>
8642 #ifdef __apple_build_version__
8648 bool isDebuggerActive(){
8650 struct kinfo_proc
info;
8656 info.kp_proc.p_flag = 0;
8663 mib[2] = KERN_PROC_PID;
8669 if( sysctl(mib,
sizeof(mib) /
sizeof(*mib), &info, &size,
nullptr, 0) != 0 ) {
8670 Catch::cerr() <<
"\n** Call to sysctl failed - unable to determine if debugger is active **\n" <<
std::endl;
8676 return ( (
info.kp_proc.p_flag & P_TRACED) != 0 );
8679 bool isDebuggerActive() {
8686#elif defined(CATCH_PLATFORM_LINUX)
8698 bool isDebuggerActive(){
8704 static const int PREFIX_LEN = 11;
8705 if( line.
compare(0, PREFIX_LEN,
"TracerPid:\t") == 0 ) {
8709 return line.
length() > PREFIX_LEN && line[PREFIX_LEN] !=
'0';
8716#elif defined(_MSC_VER)
8717 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8719 bool isDebuggerActive() {
8720 return IsDebuggerPresent() != 0;
8723#elif defined(__MINGW32__)
8724 extern "C" __declspec(dllimport)
int __stdcall IsDebuggerPresent();
8726 bool isDebuggerActive() {
8727 return IsDebuggerPresent() != 0;
8732 bool isDebuggerActive() {
return false; }
8743 if( lhs.
size() + rhs.
size() < 40 &&
8744 lhs.
find(
'\n') == std::string::npos &&
8745 rhs.
find(
'\n') == std::string::npos )
8746 os << lhs <<
" " << op <<
" " << rhs;
8748 os << lhs <<
"\n" << op <<
"\n" << rhs;
8755#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)
8758 Catch::cerr() <<
"Catch will terminate because it needed to throw an exception.\n"
8759 <<
"The message was: " << e.
what() <<
'\n';
8777 class EnumValuesRegistry :
public IMutableEnumValuesRegistry {
8781 EnumInfo
const& registerEnum( StringRef enumName, StringRef allEnums,
std::vector<int> const& values)
override;
8804 parsed.
reserve( enumValues.size() );
8805 for(
auto const& enumValue : enumValues ) {
8815 for(
auto const& valueToName :
m_values ) {
8816 if( valueToName.first ==
value )
8817 return valueToName.second;
8819 return "{** unexpected enum value **}";
8824 enumInfo->m_name = enumName;
8825 enumInfo->m_values.reserve(
values.size() );
8827 const auto valueNames = Catch::Detail::parseEnums( allValueNames );
8828 assert( valueNames.size() ==
values.size() );
8831 enumInfo->m_values.push_back({
value, valueNames[i++] });
8836 EnumInfo
const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames,
std::vector<int> const& values ) {
8837 auto enumInfo = makeEnumInfo( enumName, allValueNames, values );
8838 EnumInfo* raw = enumInfo.get();
8839 m_enumInfos.push_back( std::move( enumInfo ) );
8852 ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}
8853 ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }
8866 class ExceptionTranslatorRegistry :
public IExceptionTranslatorRegistry {
8868 ~ExceptionTranslatorRegistry();
8869 virtual void registerTranslator(
const IExceptionTranslator* translator );
8880#import "Foundation/Foundation.h"
8885 ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {
8888 void ExceptionTranslatorRegistry::registerTranslator(
const IExceptionTranslator* translator ) {
8892#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
8893 std::string ExceptionTranslatorRegistry::translateActiveException()
const {
8898 return tryTranslators();
8900 @catch (NSException *exception) {
8913 return "Non C++ exception. Possibly a CLR exception.";
8915 return tryTranslators();
8918 catch( TestFailureException& ) {
8927 catch(
const char* msg ) {
8931 return "Unknown exception";
8935 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
8936 if (m_translators.empty()) {
8939 return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());
8944 std::string ExceptionTranslatorRegistry::translateActiveException()
const {
8945 CATCH_INTERNAL_ERROR(
"Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8948 std::string ExceptionTranslatorRegistry::tryTranslators()
const {
8949 CATCH_INTERNAL_ERROR(
"Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");
8957#if defined(__GNUC__)
8958# pragma GCC diagnostic push
8959# pragma GCC diagnostic ignored "-Wmissing-field-initializers"
8962#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )
8966 void reportFatal(
char const *
const message ) {
8973#if defined( CATCH_CONFIG_WINDOWS_SEH )
8976 struct SignalDefs { DWORD id;
const char*
name; };
8981 static SignalDefs signalDefs[] = {
8982 {
static_cast<DWORD
>(EXCEPTION_ILLEGAL_INSTRUCTION),
"SIGILL - Illegal instruction signal" },
8983 {
static_cast<DWORD
>(EXCEPTION_STACK_OVERFLOW),
"SIGSEGV - Stack overflow" },
8984 {
static_cast<DWORD
>(EXCEPTION_ACCESS_VIOLATION),
"SIGSEGV - Segmentation violation signal" },
8985 {
static_cast<DWORD
>(EXCEPTION_INT_DIVIDE_BY_ZERO),
"Divide by zero error" },
8988 LONG CALLBACK FatalConditionHandler::handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
8989 for (
auto const& def : signalDefs) {
8990 if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {
8991 reportFatal(def.name);
8996 return EXCEPTION_CONTINUE_SEARCH;
8999 FatalConditionHandler::FatalConditionHandler() {
9003 guaranteeSize = 32 * 1024;
9004 exceptionHandlerHandle =
nullptr;
9006 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
9008 SetThreadStackGuarantee(&guaranteeSize);
9011 void FatalConditionHandler::reset() {
9013 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
9014 SetThreadStackGuarantee(&guaranteeSize);
9015 exceptionHandlerHandle =
nullptr;
9020 FatalConditionHandler::~FatalConditionHandler() {
9024bool FatalConditionHandler::isSet =
false;
9025ULONG FatalConditionHandler::guaranteeSize = 0;
9026PVOID FatalConditionHandler::exceptionHandlerHandle =
nullptr;
9030#elif defined( CATCH_CONFIG_POSIX_SIGNALS )
9041 constexpr static std::size_t sigStackSize = 32768 >= MINSIGSTKSZ ? 32768 : MINSIGSTKSZ;
9043 static SignalDefs signalDefs[] = {
9044 { SIGINT,
"SIGINT - Terminal interrupt signal" },
9045 { SIGILL,
"SIGILL - Illegal instruction signal" },
9046 { SIGFPE,
"SIGFPE - Floating point error signal" },
9047 { SIGSEGV,
"SIGSEGV - Segmentation violation signal" },
9048 { SIGTERM,
"SIGTERM - Termination request signal" },
9049 { SIGABRT,
"SIGABRT - Abort (abnormal termination) signal" }
9052 void FatalConditionHandler::handleSignal(
int sig ) {
9053 char const *
name =
"<unknown signal>";
9054 for (
auto const& def : signalDefs) {
9055 if (sig == def.id) {
9065 FatalConditionHandler::FatalConditionHandler() {
9068 sigStack.ss_sp = altStackMem;
9069 sigStack.ss_size = sigStackSize;
9070 sigStack.ss_flags = 0;
9071 sigaltstack(&sigStack, &oldSigStack);
9072 struct sigaction sa = { };
9074 sa.sa_handler = handleSignal;
9075 sa.sa_flags = SA_ONSTACK;
9076 for (
std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i) {
9077 sigaction(signalDefs[i].
id, &sa, &oldSigActions[i]);
9081 FatalConditionHandler::~FatalConditionHandler() {
9085 void FatalConditionHandler::reset() {
9088 for(
std::size_t i = 0; i <
sizeof(signalDefs)/
sizeof(SignalDefs); ++i ) {
9089 sigaction(signalDefs[i].
id, &oldSigActions[i],
nullptr);
9092 sigaltstack(&oldSigStack,
nullptr);
9097 bool FatalConditionHandler::isSet =
false;
9098 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
9099 stack_t FatalConditionHandler::oldSigStack = {};
9100 char FatalConditionHandler::altStackMem[sigStackSize] = {};
9107 void FatalConditionHandler::reset() {}
9112#if defined(__GNUC__)
9113# pragma GCC diagnostic pop
9128 void seedRng( IConfig
const& config );
9145namespace Generators {
9188 class ListeningReporter :
public IStreamingReporter {
9190 Reporters m_listeners;
9191 IStreamingReporterPtr m_reporter =
nullptr;
9192 ReporterPreferences m_preferences;
9195 ListeningReporter();
9197 void addListener( IStreamingReporterPtr&& listener );
9198 void addReporter( IStreamingReporterPtr&& reporter );
9202 ReporterPreferences getPreferences()
const override;
9204 void noMatchingTestCases(
std::string const& spec )
override;
9208 void benchmarkStarting( BenchmarkInfo
const& benchmarkInfo )
override;
9209 void benchmarkEnded( BenchmarkStats
const& benchmarkStats )
override;
9211 void testRunStarting( TestRunInfo
const& testRunInfo )
override;
9212 void testGroupStarting( GroupInfo
const& groupInfo )
override;
9213 void testCaseStarting( TestCaseInfo
const& testInfo )
override;
9214 void sectionStarting( SectionInfo
const& sectionInfo )
override;
9215 void assertionStarting( AssertionInfo
const& assertionInfo )
override;
9218 bool assertionEnded( AssertionStats
const& assertionStats )
override;
9219 void sectionEnded( SectionStats
const& sectionStats )
override;
9220 void testCaseEnded( TestCaseStats
const& testCaseStats )
override;
9221 void testGroupEnded( TestGroupStats
const& testGroupStats )
override;
9222 void testRunEnded( TestRunStats
const& testRunStats )
override;
9224 void skipTest( TestCaseInfo
const& testInfo )
override;
9225 bool isMulti()
const override;
9234 ReporterConfig::ReporterConfig(
IConfigPtr const& _fullConfig )
9235 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
9238 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
9240 std::ostream& ReporterConfig::stream()
const {
return *m_stream; }
9241 IConfigPtr ReporterConfig::fullConfig()
const {
return m_fullConfig; }
9243 TestRunInfo::TestRunInfo(
std::string const& _name ) :
name( _name ) {}
9249 groupIndex( _groupIndex ),
9250 groupsCounts( _groupsCount )
9253 AssertionStats::AssertionStats( AssertionResult
const& _assertionResult,
9255 Totals
const& _totals )
9256 : assertionResult( _assertionResult ),
9257 infoMessages( _infoMessages ),
9260 assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;
9262 if( assertionResult.hasMessage() ) {
9265 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
9266 builder << assertionResult.getMessage();
9267 builder.m_info.message = builder.m_stream.str();
9269 infoMessages.push_back( builder.m_info );
9273 AssertionStats::~AssertionStats() =
default;
9275 SectionStats::SectionStats( SectionInfo
const& _sectionInfo,
9276 Counts
const& _assertions,
9277 double _durationInSeconds,
9278 bool _missingAssertions )
9279 : sectionInfo( _sectionInfo ),
9280 assertions( _assertions ),
9281 durationInSeconds( _durationInSeconds ),
9282 missingAssertions( _missingAssertions )
9285 SectionStats::~SectionStats() =
default;
9287 TestCaseStats::TestCaseStats( TestCaseInfo
const& _testInfo,
9288 Totals
const& _totals,
9292 : testInfo( _testInfo ),
9296 aborting( _aborting )
9299 TestCaseStats::~TestCaseStats() =
default;
9301 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo,
9302 Totals
const& _totals,
9304 : groupInfo( _groupInfo ),
9306 aborting( _aborting )
9309 TestGroupStats::TestGroupStats( GroupInfo
const& _groupInfo )
9310 : groupInfo( _groupInfo ),
9314 TestGroupStats::~TestGroupStats() =
default;
9316 TestRunStats::TestRunStats( TestRunInfo
const& _runInfo,
9317 Totals
const& _totals,
9319 : runInfo( _runInfo ),
9321 aborting( _aborting )
9324 TestRunStats::~TestRunStats() =
default;
9326 void IStreamingReporter::fatalErrorEncountered( StringRef ) {}
9327 bool IStreamingReporter::isMulti()
const {
return false; }
9329 IReporterFactory::~IReporterFactory() =
default;
9330 IReporterRegistry::~IReporterRegistry() =
default;
9349#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
9354 LeakDetector::LeakDetector() {
9355 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
9356 flag |= _CRTDBG_LEAK_CHECK_DF;
9357 flag |= _CRTDBG_ALLOC_MEM_DF;
9358 _CrtSetDbgFlag(flag);
9359 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
9360 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
9362 _CrtSetBreakAlloc(-1);
9368 Catch::LeakDetector::LeakDetector() {}
9372Catch::LeakDetector::~LeakDetector() {
9386 std::size_t listTestsNamesOnly( Config
const& config );
9408 using namespace clara::TextFlow;
9419 TestSpec testSpec = config.testSpec();
9420 if( config.hasTestFilters() )
9427 for(
auto const& testCaseInfo : matchedTestCases ) {
9428 Colour::Code colour = testCaseInfo.isHidden()
9429 ? Colour::SecondaryText
9431 Colour colourGuard( colour );
9433 Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) <<
"\n";
9436 std::string description = testCaseInfo.description;
9437 if( description.
empty() )
9438 description =
"(NO DESCRIPTION)";
9441 if( !testCaseInfo.tags.empty() )
9442 Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) <<
"\n";
9445 if( !config.hasTestFilters() )
9448 Catch::cout() << pluralise( matchedTestCases.size(),
"matching test case" ) <<
'\n' <<
std::endl;
9449 return matchedTestCases.size();
9452 std::size_t listTestsNamesOnly( Config
const& config ) {
9453 TestSpec testSpec = config.testSpec();
9456 for(
auto const& testCaseInfo : matchedTestCases ) {
9466 return matchedTests;
9469 void TagInfo::add(
std::string const& spelling ) {
9471 spellings.insert( spelling );
9476 for(
auto const& spelling : spellings )
9477 out +=
"[" + spelling +
"]";
9482 TestSpec testSpec = config.testSpec();
9483 if( config.hasTestFilters() )
9484 Catch::cout() <<
"Tags for matching test cases:\n";
9492 for(
auto const& testCase : matchedTestCases ) {
9493 for(
auto const& tagName : testCase.getTestCaseInfo().tags ) {
9495 auto countIt = tagCounts.
find( lcaseTagName );
9496 if( countIt == tagCounts.
end() )
9498 countIt->second.add( tagName );
9502 for(
auto const& tagCount : tagCounts ) {
9503 ReusableStringStream rss;
9504 rss <<
" " <<
std::setw(2) << tagCount.second.count <<
" ";
9505 auto str = rss.str();
9506 auto wrapper = Column( tagCount.second.all() )
9508 .indent( str.size() )
9509 .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );
9513 return tagCounts.
size();
9520 for(
auto const& factoryKvp : factories )
9523 for(
auto const& factoryKvp : factories ) {
9525 << Column( factoryKvp.first +
":" )
9527 .
width( 5+maxNameLen )
9528 + Column( factoryKvp.second->getDescription() )
9531 .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )
9535 return factories.size();
9539 Option<std::size_t> listedCount;
9541 if( config->listTests() )
9542 listedCount = listedCount.valueOr(0) + listTests( *config );
9543 if( config->listTestNamesOnly() )
9544 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );
9545 if( config->listTags() )
9546 listedCount = listedCount.valueOr(0) + listTags( *config );
9547 if( config->listReporters() )
9548 listedCount = listedCount.valueOr(0) + listReporters();
9571using namespace Matchers;
9572using Matchers::Impl::MatcherBase;
9581 bool isnan(
float f);
9582 bool isnan(
double d);
9591 template <
typename T>
9593#if defined(CATCH_CONFIG_CPP11_TO_STRING)
9596 ReusableStringStream rss;
9611enum class FloatingPointKind : uint8_t {
9621template <
typename T>
9625struct Converter<float> {
9626 static_assert(
sizeof(float) ==
sizeof(int32_t),
"Important ULP matcher assumption violated");
9627 Converter(
float f) {
9634struct Converter<double> {
9635 static_assert(
sizeof(double) ==
sizeof(int64_t),
"Important ULP matcher assumption violated");
9636 Converter(
double d) {
9642template <
typename T>
9643auto convert(
T t) -> Converter<T> {
9644 return Converter<T>(t);
9647template <
typename FP>
9648bool almostEqualUlps(FP lhs, FP rhs,
int maxUlpDiff) {
9651 if (Catch::isnan(lhs) || Catch::isnan(rhs)) {
9655 auto lc = convert(lhs);
9656 auto rc = convert(rhs);
9658 if ((lc.i < 0) != (rc.i < 0)) {
9663 auto ulpDiff =
std::abs(lc.i - rc.i);
9664 return ulpDiff <= maxUlpDiff;
9673 :m_target{ target }, m_margin{ margin } {
9674 CATCH_ENFORCE(margin >= 0,
"Invalid margin: " << margin <<
'.'
9675 <<
" Margin has to be non-negative.");
9680 bool WithinAbsMatcher::match(
double const& matchee)
const {
9681 return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);
9685 return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);
9688 WithinUlpsMatcher::WithinUlpsMatcher(
double target,
int ulps, FloatingPointKind baseType)
9689 :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {
9690 CATCH_ENFORCE(ulps >= 0,
"Invalid ULP setting: " << ulps <<
'.'
9691 <<
" ULPs have to be non-negative.");
9694#if defined(__clang__)
9695#pragma clang diagnostic push
9697#pragma clang diagnostic ignored "-Wunreachable-code"
9700 bool WithinUlpsMatcher::match(
double const& matchee)
const {
9702 case FloatingPointKind::Float:
9703 return almostEqualUlps<float>(
static_cast<float>(matchee),
static_cast<float>(m_target), m_ulps);
9704 case FloatingPointKind::Double:
9705 return almostEqualUlps<double>(matchee, m_target, m_ulps);
9711#if defined(__clang__)
9712#pragma clang diagnostic pop
9716 return "is within " +
Catch::to_string(m_ulps) + " ULPs of " + ::Catch::Detail::stringify(m_target) + ((m_type == FloatingPointKind::Float)? "f" : "");
9721Floating::WithinUlpsMatcher
WithinULP(
double target,
int maxUlpDiff) {
9722 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);
9725Floating::WithinUlpsMatcher
WithinULP(
float target,
int maxUlpDiff) {
9726 return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);
9729Floating::WithinAbsMatcher
WithinAbs(
double target,
double margin) {
9730 return Floating::WithinAbsMatcher(target, margin);
9741 return "matches undescribed predicate";
9743 return "matches predicate: \"" + desc + '"';
9754 namespace StdString {
9757 : m_caseSensitivity( caseSensitivity ),
9758 m_str( adjustString( str ) )
9765 std::string CasedString::caseSensitivitySuffix()
const {
9767 ?
" (case insensitive)"
9771 StringMatcherBase::StringMatcherBase(
std::string const& operation, CasedString
const& comparator )
9772 : m_comparator( comparator ),
9773 m_operation( operation ) {
9778 description.
reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9779 m_comparator.caseSensitivitySuffix().size());
9780 description += m_operation;
9781 description += ": \"";
9782 description += m_comparator.m_str;
9783 description += "\"";
9784 description += m_comparator.caseSensitivitySuffix();
9788 EqualsMatcher::EqualsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"equals", comparator ) {}
9790 bool EqualsMatcher::match(
std::string const& source )
const {
9791 return m_comparator.adjustString( source ) == m_comparator.m_str;
9794 ContainsMatcher::ContainsMatcher( CasedString
const& comparator ) : StringMatcherBase(
"contains", comparator ) {}
9796 bool ContainsMatcher::match(
std::string const& source )
const {
9797 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9800 StartsWithMatcher::StartsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"starts with", comparator ) {}
9802 bool StartsWithMatcher::match(
std::string const& source )
const {
9803 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9806 EndsWithMatcher::EndsWithMatcher( CasedString
const& comparator ) : StringMatcherBase(
"ends with", comparator ) {}
9808 bool EndsWithMatcher::match(
std::string const& source )
const {
9809 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9814 bool RegexMatcher::match(
std::string const& matchee)
const {
9815 auto flags = std::regex::ECMAScript;
9817 flags |= std::regex::icase;
9824 return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");
9829 StdString::EqualsMatcher
Equals(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9830 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9832 StdString::ContainsMatcher
Contains(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9833 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9835 StdString::EndsWithMatcher
EndsWith(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9836 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9838 StdString::StartsWithMatcher
StartsWith(
std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9839 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9842 StdString::RegexMatcher
Matches(
std::string const& regex, CaseSensitive::Choice caseSensitivity) {
9843 return StdString::RegexMatcher(regex, caseSensitivity);
9864 SourceLineInfo
const& _lineInfo,
9866 : macroName( _macroName ),
9867 lineInfo( _lineInfo ),
9869 sequence( ++globalCount )
9886 SourceLineInfo
const& lineInfo,
9888 :m_info(macroName, lineInfo,
type) {}
9893 : m_info( builder.m_info ), m_moved()
9895 m_info.message = builder.m_stream.str();
9900 : m_info( old.m_info ), m_moved()
9912 auto trimmed = [&] (
size_t start,
size_t end) {
9913 while (names[start] ==
',' || isspace(names[start])) {
9916 while (names[end] ==
',' || isspace(names[end])) {
9919 return names.substr(start, end - start + 1);
9921 auto skipq = [&] (
size_t start,
char quote) {
9922 for (
auto i = start + 1; i < names.size() ; ++i) {
9923 if (names[i] == quote)
9925 if (names[i] ==
'\\')
9933 for (
size_t pos = 0; pos < names.size(); ++pos) {
9934 char c = names[pos];
9952 pos = skipq(pos, c);
9955 if (start != pos && openings.
size() == 0) {
9956 m_messages.emplace_back(macroName, lineInfo, resultType);
9957 m_messages.back().message = trimmed(start, pos);
9958 m_messages.back().message += " := ";
9963 assert(openings.
size() == 0 &&
"Mismatched openings");
9964 m_messages.emplace_back(macroName, lineInfo, resultType);
9965 m_messages.back().message = trimmed(start, names.size() - 1);
9966 m_messages.back().message += " := ";
9968 Capturer::~Capturer() {
9970 assert( m_captured == m_messages.size() );
9971 for(
size_t i = 0; i < m_captured; ++i )
9972 m_resultCapture.popScopedMessage( m_messages[i] );
9977 assert(
index < m_messages.size() );
9978 m_messages[index].message +=
value;
9988#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9989#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H
9997 class RedirectedStream {
10004 ~RedirectedStream();
10007 class RedirectedStdOut {
10008 ReusableStringStream m_rss;
10009 RedirectedStream m_cout;
10011 RedirectedStdOut();
10012 auto str() const ->
std::
string;
10018 class RedirectedStdErr {
10019 ReusableStringStream m_rss;
10020 RedirectedStream m_cerr;
10021 RedirectedStream m_clog;
10023 RedirectedStdErr();
10024 auto str() const ->
std::
string;
10027 class RedirectedStreams {
10029 RedirectedStreams(RedirectedStreams
const&) =
delete;
10030 RedirectedStreams& operator=(RedirectedStreams
const&) =
delete;
10031 RedirectedStreams(RedirectedStreams&&) =
delete;
10032 RedirectedStreams& operator=(RedirectedStreams&&) =
delete;
10035 ~RedirectedStreams();
10039 RedirectedStdOut m_redirectedStdOut;
10040 RedirectedStdErr m_redirectedStdErr;
10043#if defined(CATCH_CONFIG_NEW_CAPTURE)
10051 TempFile(TempFile
const&) =
delete;
10052 TempFile& operator=(TempFile
const&) =
delete;
10053 TempFile(TempFile&&) =
delete;
10054 TempFile& operator=(TempFile&&) =
delete;
10064 #if defined(_MSC_VER)
10065 char m_buffer[L_tmpnam] = { 0 };
10069 class OutputRedirect {
10071 OutputRedirect(OutputRedirect
const&) =
delete;
10072 OutputRedirect& operator=(OutputRedirect
const&) =
delete;
10073 OutputRedirect(OutputRedirect&&) =
delete;
10074 OutputRedirect& operator=(OutputRedirect&&) =
delete;
10080 int m_originalStdout = -1;
10081 int m_originalStderr = -1;
10082 TempFile m_stdoutFile;
10083 TempFile m_stderrFile;
10100#if defined(CATCH_CONFIG_NEW_CAPTURE)
10101 #if defined(_MSC_VER)
10105 #define fileno _fileno
10107 #include <unistd.h>
10114 : m_originalStream( originalStream ),
10115 m_redirectionStream( redirectionStream ),
10116 m_prevBuf( m_originalStream.rdbuf() )
10118 m_originalStream.rdbuf( m_redirectionStream.rdbuf() );
10121 RedirectedStream::~RedirectedStream() {
10122 m_originalStream.rdbuf( m_prevBuf );
10125 RedirectedStdOut::RedirectedStdOut() : m_cout(
Catch::
cout(), m_rss.
get() ) {}
10126 auto RedirectedStdOut::str() const ->
std::
string {
return m_rss.str(); }
10128 RedirectedStdErr::RedirectedStdErr()
10132 auto RedirectedStdErr::str() const ->
std::
string {
return m_rss.str(); }
10135 : m_redirectedCout(redirectedCout),
10136 m_redirectedCerr(redirectedCerr)
10139 RedirectedStreams::~RedirectedStreams() {
10140 m_redirectedCout += m_redirectedStdOut.str();
10141 m_redirectedCerr += m_redirectedStdErr.str();
10144#if defined(CATCH_CONFIG_NEW_CAPTURE)
10146#if defined(_MSC_VER)
10147 TempFile::TempFile() {
10148 if (tmpnam_s(m_buffer)) {
10151 if (
fopen_s(&m_file, m_buffer,
"w")) {
10153 if (strerror_s(
buffer, errno)) {
10160 TempFile::TempFile() {
10169 TempFile::~TempFile() {
10174#if defined(_MSC_VER)
10175 std::remove(m_buffer);
10179 FILE* TempFile::getFile() {
10194 m_originalStdout(dup(1)),
10195 m_originalStderr(dup(2)),
10196 m_stdoutDest(stdout_dest),
10197 m_stderrDest(stderr_dest) {
10198 dup2(fileno(m_stdoutFile.getFile()), 1);
10199 dup2(fileno(m_stderrFile.getFile()), 2);
10202 OutputRedirect::~OutputRedirect() {
10211 dup2(m_originalStdout, 1);
10212 dup2(m_originalStderr, 2);
10214 m_stdoutDest += m_stdoutFile.getContents();
10215 m_stderrDest += m_stderrFile.getContents();
10222#if defined(CATCH_CONFIG_NEW_CAPTURE)
10223 #if defined(_MSC_VER)
10236#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)
10237 bool isnan(
float f) {
10240 bool isnan(
double d) {
10245 bool isnan(
float f) {
10248 bool isnan(
double d) {
10264 void seedRng( IConfig
const& config ) {
10265 if( config.rngSeed() != 0 ) {
10267 rng().seed( config.rngSeed() );
10291 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const& config );
10298 class TestRegistry :
public ITestCaseRegistry {
10300 virtual ~TestRegistry() =
default;
10302 virtual void registerTest( TestCase
const& testCase );
10309 mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;
10317 class TestInvokerAsFunction :
public ITestInvoker {
10318 void(*m_testAsFunction)();
10320 TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept;
10322 void invoke() const override;
10325 std::
string extractClassName( StringRef const& classOrQualifiedMethodName );
10338 class ReporterRegistry :
public IReporterRegistry {
10342 ~ReporterRegistry()
override;
10346 void registerReporter(
std::string const&
name, IReporterFactoryPtr
const& factory );
10347 void registerListener( IReporterFactoryPtr
const& factory );
10349 FactoryMap
const& getFactories()
const override;
10350 Listeners
const& getListeners()
const override;
10353 FactoryMap m_factories;
10354 Listeners m_listeners;
10368 TagAlias(
std::string const& _tag, SourceLineInfo _lineInfo);
10371 SourceLineInfo lineInfo;
10381 class TagAliasRegistry :
public ITagAliasRegistry {
10383 ~TagAliasRegistry()
override;
10402 class StartupExceptionRegistry {
10407 std::vector<
std::exception_ptr> m_exceptions;
10417 struct ISingleton {
10418 virtual ~ISingleton();
10421 void addSingleton( ISingleton* singleton );
10422 void cleanupSingletons();
10424 template<
typename SingletonImplT,
typename InterfaceT = SingletonImplT,
typename MutableInterfaceT = InterfaceT>
10425 class Singleton : SingletonImplT,
public ISingleton {
10427 static auto getInternal() -> Singleton* {
10428 static Singleton* s_instance =
nullptr;
10429 if( !s_instance ) {
10430 s_instance =
new Singleton;
10431 addSingleton( s_instance );
10437 static auto get() -> InterfaceT
const& {
10438 return *getInternal();
10440 static auto getMutable() -> MutableInterfaceT& {
10441 return *getInternal();
10452 class RegistryHub :
public IRegistryHub,
public IMutableRegistryHub,
10453 private NonCopyable {
10456 RegistryHub() =
default;
10457 IReporterRegistry
const& getReporterRegistry()
const override {
10458 return m_reporterRegistry;
10460 ITestCaseRegistry
const& getTestCaseRegistry()
const override {
10461 return m_testCaseRegistry;
10463 IExceptionTranslatorRegistry
const& getExceptionTranslatorRegistry()
const override {
10464 return m_exceptionTranslatorRegistry;
10466 ITagAliasRegistry
const& getTagAliasRegistry()
const override {
10467 return m_tagAliasRegistry;
10469 StartupExceptionRegistry
const& getStartupExceptionRegistry()
const override {
10470 return m_exceptionRegistry;
10474 void registerReporter(
std::string const&
name, IReporterFactoryPtr
const& factory )
override {
10475 m_reporterRegistry.registerReporter(
name, factory );
10477 void registerListener( IReporterFactoryPtr
const& factory )
override {
10478 m_reporterRegistry.registerListener( factory );
10480 void registerTest( TestCase
const& testInfo )
override {
10481 m_testCaseRegistry.registerTest( testInfo );
10483 void registerTranslator(
const IExceptionTranslator* translator )
override {
10484 m_exceptionTranslatorRegistry.registerTranslator( translator );
10486 void registerTagAlias(
std::string const& alias,
std::string const& tag, SourceLineInfo
const& lineInfo )
override {
10487 m_tagAliasRegistry.add( alias, tag, lineInfo );
10489 void registerStartupException() noexcept
override {
10492 IMutableEnumValuesRegistry& getMutableEnumValuesRegistry()
override {
10493 return m_enumValuesRegistry;
10497 TestRegistry m_testCaseRegistry;
10498 ReporterRegistry m_reporterRegistry;
10499 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
10500 TagAliasRegistry m_tagAliasRegistry;
10501 StartupExceptionRegistry m_exceptionRegistry;
10502 Detail::EnumValuesRegistry m_enumValuesRegistry;
10506 using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;
10509 return RegistryHubSingleton::get();
10512 return RegistryHubSingleton::getMutable();
10515 cleanupSingletons();
10528 ReporterRegistry::~ReporterRegistry() =
default;
10530 IStreamingReporterPtr ReporterRegistry::create(
std::string const&
name, IConfigPtr
const& config )
const {
10531 auto it = m_factories.find(
name );
10532 if( it == m_factories.end() )
10534 return it->second->create( ReporterConfig( config ) );
10537 void ReporterRegistry::registerReporter(
std::string const&
name, IReporterFactoryPtr
const& factory ) {
10538 m_factories.emplace(
name, factory);
10540 void ReporterRegistry::registerListener( IReporterFactoryPtr
const& factory ) {
10541 m_listeners.push_back( factory );
10544 IReporterRegistry::FactoryMap
const& ReporterRegistry::getFactories()
const {
10545 return m_factories;
10547 IReporterRegistry::Listeners
const& ReporterRegistry::getListeners()
const {
10548 return m_listeners;
10557 bool isOk( ResultWas::OfType resultType ) {
10558 return ( resultType & ResultWas::FailureBit ) == 0;
10561 return flags == ResultWas::Info;
10564 ResultDisposition::Flags
operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
10565 return static_cast<ResultDisposition::Flags
>(
static_cast<int>( lhs ) |
static_cast<int>( rhs ) );
10569 bool shouldSuppressFailure(
int flags ) {
return ( flags & ResultDisposition::SuppressFail ) != 0; }
10581 namespace Generators {
10582 struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {
10585 GeneratorTracker( TestCaseTracking::NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
10586 : TrackerBase( nameAndLocation, ctx, parent )
10588 ~GeneratorTracker();
10590 static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation
const& nameAndLocation ) {
10593 ITracker& currentTracker = ctx.currentTracker();
10594 if( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
10595 assert( childTracker );
10596 assert( childTracker->isGeneratorTracker() );
10601 currentTracker.addChild( tracker );
10604 if( !ctx.completedCycle() && !tracker->isComplete() ) {
10612 bool isGeneratorTracker()
const override {
return true; }
10613 auto hasGenerator() const ->
bool override {
10614 return !!m_generator;
10616 void close()
override {
10617 TrackerBase::close();
10619 if (m_runState == CompletedSuccessfully && m_generator->next()) {
10620 m_children.clear();
10621 m_runState = Executing;
10626 auto getGenerator() const -> GeneratorBasePtr const&
override {
10627 return m_generator;
10629 void setGenerator( GeneratorBasePtr&& generator )
override {
10630 m_generator = std::move( generator );
10633 GeneratorTracker::~GeneratorTracker() {}
10636 RunContext::RunContext(IConfigPtr
const& _config, IStreamingReporterPtr&& reporter)
10637 : m_runInfo(_config->
name()),
10640 m_reporter(
std::move(reporter)),
10641 m_lastAssertionInfo{ StringRef(), SourceLineInfo(
"",0), StringRef(), ResultDisposition::
Normal },
10642 m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )
10644 m_context.setRunner(
this);
10645 m_context.setConfig(m_config);
10646 m_context.setResultCapture(
this);
10647 m_reporter->testRunStarting(m_runInfo);
10650 RunContext::~RunContext() {
10651 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));
10655 m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));
10659 m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));
10662 Totals RunContext::runTest(TestCase
const& testCase) {
10663 Totals prevTotals = m_totals;
10668 auto const& testInfo = testCase.getTestCaseInfo();
10670 m_reporter->testCaseStarting(testInfo);
10672 m_activeTestCase = &testCase;
10674 ITracker& rootTracker = m_trackerContext.startRun();
10675 assert(rootTracker.isSectionTracker());
10676 static_cast<SectionTracker&
>(rootTracker).addInitialFilters(m_config->getSectionsToRun());
10678 m_trackerContext.startCycle();
10679 m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));
10680 runCurrentTest(redirectedCout, redirectedCerr);
10681 }
while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());
10683 Totals deltaTotals = m_totals.delta(prevTotals);
10684 if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {
10685 deltaTotals.assertions.failed++;
10686 deltaTotals.testCases.passed--;
10687 deltaTotals.testCases.failed++;
10689 m_totals.testCases += deltaTotals.testCases;
10690 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10696 m_activeTestCase =
nullptr;
10697 m_testCaseTracker =
nullptr;
10699 return deltaTotals;
10706 IStreamingReporter& RunContext::reporter()
const {
10707 return *m_reporter;
10710 void RunContext::assertionEnded(AssertionResult
const & result) {
10712 m_totals.assertions.passed++;
10713 m_lastAssertionPassed =
true;
10714 }
else if (!
result.isOk()) {
10715 m_lastAssertionPassed =
false;
10716 if( m_activeTestCase->getTestCaseInfo().okToFail() )
10717 m_totals.assertions.failedButOk++;
10719 m_totals.assertions.failed++;
10722 m_lastAssertionPassed =
true;
10727 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));
10730 m_messageScopes.clear();
10733 resetAssertionInfo();
10736 void RunContext::resetAssertionInfo() {
10737 m_lastAssertionInfo.macroName = StringRef();
10738 m_lastAssertionInfo.capturedExpression =
"{Unknown expression after the reported line}"_sr;
10741 bool RunContext::sectionStarted(SectionInfo
const & sectionInfo, Counts & assertions) {
10742 ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));
10743 if (!sectionTracker.isOpen())
10745 m_activeSections.push_back(§ionTracker);
10747 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
10749 m_reporter->sectionStarting(sectionInfo);
10751 assertions = m_totals.assertions;
10755 auto RunContext::acquireGeneratorTracker( SourceLineInfo
const& lineInfo ) -> IGeneratorTracker& {
10756 using namespace Generators;
10757 GeneratorTracker& tracker = GeneratorTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation(
"generator", lineInfo ) );
10758 assert( tracker.isOpen() );
10759 m_lastAssertionInfo.lineInfo = lineInfo;
10763 bool RunContext::testForMissingAssertions(Counts& assertions) {
10764 if (assertions.total() != 0)
10766 if (!m_config->warnAboutMissingAssertions())
10768 if (m_trackerContext.currentTracker().hasChildren())
10770 m_totals.assertions.failed++;
10771 assertions.failed++;
10775 void RunContext::sectionEnded(SectionEndInfo
const & endInfo) {
10776 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
10777 bool missingAssertions = testForMissingAssertions(assertions);
10779 if (!m_activeSections.empty()) {
10780 m_activeSections.back()->close();
10781 m_activeSections.pop_back();
10784 m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));
10785 m_messages.clear();
10786 m_messageScopes.clear();
10789 void RunContext::sectionEndedEarly(SectionEndInfo
const & endInfo) {
10790 if (m_unfinishedSections.empty())
10791 m_activeSections.back()->fail();
10793 m_activeSections.back()->close();
10794 m_activeSections.pop_back();
10796 m_unfinishedSections.push_back(endInfo);
10798 void RunContext::benchmarkStarting( BenchmarkInfo
const& info ) {
10799 m_reporter->benchmarkStarting( info );
10801 void RunContext::benchmarkEnded( BenchmarkStats
const& stats ) {
10802 m_reporter->benchmarkEnded( stats );
10805 void RunContext::pushScopedMessage(MessageInfo
const & message) {
10806 m_messages.push_back(message);
10809 void RunContext::popScopedMessage(MessageInfo
const & message) {
10810 m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());
10813 void RunContext::emplaceUnscopedMessage( MessageBuilder
const& builder ) {
10814 m_messageScopes.emplace_back( builder );
10817 std::string RunContext::getCurrentTestName()
const {
10818 return m_activeTestCase
10819 ? m_activeTestCase->getTestCaseInfo().name
10823 const AssertionResult * RunContext::getLastResult()
const {
10824 return &(*m_lastResult);
10827 void RunContext::exceptionEarlyReported() {
10828 m_shouldReportUnexpected =
false;
10831 void RunContext::handleFatalErrorCondition( StringRef message ) {
10833 m_reporter->fatalErrorEncountered(message);
10838 tempResult.message = message;
10839 AssertionResult
result(m_lastAssertionInfo, tempResult);
10841 assertionEnded(result);
10843 handleUnfinishedSections();
10846 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10847 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10850 assertions.failed = 1;
10851 SectionStats testCaseSectionStats(testCaseSection, assertions, 0,
false);
10852 m_reporter->sectionEnded(testCaseSectionStats);
10854 auto const& testInfo = m_activeTestCase->getTestCaseInfo();
10856 Totals deltaTotals;
10857 deltaTotals.testCases.failed = 1;
10858 deltaTotals.assertions.failed = 1;
10859 m_reporter->testCaseEnded(TestCaseStats(testInfo,
10864 m_totals.testCases.failed++;
10866 m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals,
false));
10869 bool RunContext::lastAssertionPassed() {
10870 return m_lastAssertionPassed;
10873 void RunContext::assertionPassed() {
10874 m_lastAssertionPassed =
true;
10875 ++m_totals.assertions.passed;
10876 resetAssertionInfo();
10877 m_messageScopes.clear();
10880 bool RunContext::aborting()
const {
10881 return m_totals.assertions.failed >=
static_cast<std::size_t>(m_config->abortAfter());
10885 auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
10886 SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);
10887 m_reporter->sectionStarting(testCaseSection);
10888 Counts prevAssertions = m_totals.assertions;
10889 double duration = 0;
10890 m_shouldReportUnexpected =
true;
10893 seedRng(*m_config);
10897 if (m_reporter->getPreferences().shouldRedirectStdOut) {
10898#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)
10899 RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);
10902 invokeActiveTestCase();
10904 OutputRedirect r(redirectedCout, redirectedCerr);
10906 invokeActiveTestCase();
10910 invokeActiveTestCase();
10912 duration = timer.getElapsedSeconds();
10918 if( m_shouldReportUnexpected ) {
10919 AssertionReaction dummyReaction;
10923 Counts assertions = m_totals.assertions - prevAssertions;
10924 bool missingAssertions = testForMissingAssertions(assertions);
10926 m_testCaseTracker->close();
10927 handleUnfinishedSections();
10928 m_messages.clear();
10929 m_messageScopes.clear();
10931 SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);
10932 m_reporter->sectionEnded(testCaseSectionStats);
10935 void RunContext::invokeActiveTestCase() {
10936 FatalConditionHandler fatalConditionHandler;
10937 m_activeTestCase->invoke();
10938 fatalConditionHandler.reset();
10941 void RunContext::handleUnfinishedSections() {
10944 for (
auto it = m_unfinishedSections.rbegin(),
10945 itEnd = m_unfinishedSections.rend();
10949 m_unfinishedSections.clear();
10952 void RunContext::handleExpr(
10953 AssertionInfo
const& info,
10954 ITransientExpression
const& expr,
10955 AssertionReaction& reaction
10957 m_reporter->assertionStarting( info );
10960 bool result = expr.getResult() != negated;
10963 if (!m_includeSuccessfulResults) {
10972 populateReaction( reaction );
10975 void RunContext::reportExpr(
10976 AssertionInfo
const &info,
10978 ITransientExpression
const *expr,
10981 m_lastAssertionInfo =
info;
10982 AssertionResultData
data( resultType, LazyExpression( negated ) );
10984 AssertionResult assertionResult{
info,
data };
10985 assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;
10987 assertionEnded( assertionResult );
10990 void RunContext::handleMessage(
10991 AssertionInfo
const& info,
10993 StringRef
const& message,
10994 AssertionReaction& reaction
10996 m_reporter->assertionStarting( info );
10998 m_lastAssertionInfo =
info;
11000 AssertionResultData
data( resultType, LazyExpression(
false ) );
11001 data.message = message;
11002 AssertionResult assertionResult{ m_lastAssertionInfo,
data };
11003 assertionEnded( assertionResult );
11004 if( !assertionResult.isOk() )
11005 populateReaction( reaction );
11007 void RunContext::handleUnexpectedExceptionNotThrown(
11008 AssertionInfo
const& info,
11009 AssertionReaction& reaction
11014 void RunContext::handleUnexpectedInflightException(
11015 AssertionInfo
const& info,
11017 AssertionReaction& reaction
11019 m_lastAssertionInfo =
info;
11022 data.message = message;
11023 AssertionResult assertionResult{
info,
data };
11024 assertionEnded( assertionResult );
11025 populateReaction( reaction );
11028 void RunContext::populateReaction( AssertionReaction& reaction ) {
11029 reaction.shouldDebugBreak = m_config->shouldDebugBreak();
11033 void RunContext::handleIncomplete(
11034 AssertionInfo
const& info
11036 m_lastAssertionInfo =
info;
11039 data.message =
"Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
11040 AssertionResult assertionResult{
info,
data };
11041 assertionEnded( assertionResult );
11043 void RunContext::handleNonExpr(
11044 AssertionInfo
const &info,
11046 AssertionReaction &reaction
11048 m_lastAssertionInfo =
info;
11050 AssertionResultData
data( resultType, LazyExpression(
false ) );
11051 AssertionResult assertionResult{
info,
data };
11052 assertionEnded( assertionResult );
11054 if( !assertionResult.isOk() )
11055 populateReaction( reaction );
11072 m_sectionIncluded(
getResultCapture().sectionStarted( m_info, m_assertions ) )
11088 Section::operator
bool()
const {
11089 return m_sectionIncluded;
11099 ( SourceLineInfo
const& _lineInfo,
11102 lineInfo( _lineInfo )
11115 class Session : NonCopyable {
11119 ~Session()
override;
11121 void showHelp()
const;
11122 void libIdentify();
11124 int applyCommandLine(
int argc,
char const *
const * argv );
11125 #if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
11126 int applyCommandLine(
int argc,
wchar_t const *
const * argv );
11129 void useConfigData( ConfigData
const& configData );
11131 template<
typename CharT>
11132 int run(
int argc, CharT
const *
const argv[]) {
11133 if (m_startupExceptions)
11135 int returnCode = applyCommandLine(argc, argv);
11136 if (returnCode == 0)
11137 returnCode = run();
11143 clara::Parser
const& cli()
const;
11144 void cli( clara::Parser
const& newParser );
11145 ConfigData& configData();
11150 clara::Parser m_cli;
11151 ConfigData m_configData;
11153 bool m_startupExceptions =
false;
11167 Version( Version
const& ) =
delete;
11168 Version& operator=( Version
const& ) =
delete;
11169 Version(
unsigned int _majorVersion,
11170 unsigned int _minorVersion,
11171 unsigned int _patchNumber,
11172 char const *
const _branchName,
11173 unsigned int _buildNumber );
11175 unsigned int const majorVersion;
11176 unsigned int const minorVersion;
11177 unsigned int const patchNumber;
11180 char const *
const branchName;
11181 unsigned int const buildNumber;
11186 Version
const& libraryVersion();
11196 const int MaxExitCode = 255;
11200 CATCH_ENFORCE(reporter,
"No reporter registered with name: '" << reporterName <<
"'");
11207 return createReporter(config->getReporterName(), config);
11216 auto& multi =
static_cast<ListeningReporter&
>(*ret);
11218 for (
auto const& listener : listeners) {
11219 multi.addListener(listener->create(Catch::ReporterConfig(config)));
11221 multi.addReporter(createReporter(config->getReporterName(), config));
11226 auto reporter = makeReporter(config);
11228 RunContext context(config, std::move(reporter));
11232 context.testGroupStarting(config->name(), 1, 1);
11234 TestSpec testSpec = config->testSpec();
11237 for (
auto const& testCase : allTestCases) {
11238 bool matching = (!testSpec.hasFilters() && !testCase.isHidden()) ||
11239 (testSpec.hasFilters() &&
matchTest(testCase, testSpec, *config));
11241 if (!context.aborting() && matching)
11242 totals += context.runTest(testCase);
11244 context.reporter().skipTest(testCase);
11247 if (config->warnAboutNoTests() && totals.testCases.total() == 0) {
11248 ReusableStringStream testConfig;
11251 for (
const auto& input : config->getTestsOrTags()) {
11252 if (!first) { testConfig <<
' '; }
11254 testConfig << input;
11257 context.reporter().noMatchingTestCases(testConfig.str());
11261 context.testGroupEnded(config->name(), totals, 1, 1);
11267 for (
auto& testCase : tests) {
11268 auto tags = testCase.tags;
11272 if (lastSlash != std::string::npos) {
11273 filename.
erase(0, lastSlash);
11278 if (lastDot != std::string::npos) {
11279 filename.
erase(lastDot);
11282 tags.push_back(std::move(filename));
11283 setTags(testCase, tags);
11289 Session::Session() {
11290 static bool alreadyInstantiated =
false;
11291 if( alreadyInstantiated ) {
11297#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
11299 if ( !exceptions.empty() ) {
11303 m_startupExceptions =
true;
11304 Colour colourGuard( Colour::Red );
11305 Catch::cerr() <<
"Errors occurred during startup!" <<
'\n';
11307 for (
const auto& ex_ptr : exceptions ) {
11317 alreadyInstantiated =
true;
11318 m_cli = makeCommandLineParser( m_configData );
11320 Session::~Session() {
11324 void Session::showHelp()
const {
11326 <<
"\nCatch v" << libraryVersion() <<
"\n"
11328 <<
"For more detailed usage please see the project docs\n" <<
std::endl;
11330 void Session::libIdentify() {
11338 int Session::applyCommandLine(
int argc,
char const *
const * argv ) {
11339 if( m_startupExceptions )
11342 auto result = m_cli.parse( clara::Args( argc, argv ) );
11347 << Colour( Colour::Red )
11348 <<
"\nError(s) in input:\n"
11349 << Column(
result.errorMessage() ).indent( 2 )
11352 return MaxExitCode;
11355 if( m_configData.showHelp )
11357 if( m_configData.libIdentify )
11363#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(UNICODE)
11364 int Session::applyCommandLine(
int argc,
wchar_t const *
const * argv ) {
11366 char **utf8Argv =
new char *[ argc ];
11368 for (
int i = 0; i < argc; ++i ) {
11369 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL );
11371 utf8Argv[ i ] =
new char[ bufSize ];
11373 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL );
11376 int returnCode = applyCommandLine( argc, utf8Argv );
11378 for (
int i = 0; i < argc; ++i )
11379 delete [] utf8Argv[ i ];
11381 delete [] utf8Argv;
11387 void Session::useConfigData( ConfigData
const& configData ) {
11388 m_configData = configData;
11392 int Session::run() {
11393 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {
11397 int exitCode = runInternal();
11398 if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {
11399 Catch::cout() <<
"...waiting for enter/ return before exiting, with code: " << exitCode <<
std::endl;
11405 clara::Parser
const& Session::cli()
const {
11408 void Session::cli( clara::Parser
const& newParser ) {
11411 ConfigData& Session::configData() {
11412 return m_configData;
11414 Config& Session::config() {
11420 int Session::runInternal() {
11421 if( m_startupExceptions )
11424 if (m_configData.showHelp || m_configData.libIdentify) {
11431 seedRng( *m_config );
11433 if( m_configData.filenamesAsTags )
11434 applyFilenamesAsTags( *m_config );
11437 if( Option<std::size_t> listed = list( m_config ) )
11438 return static_cast<int>( *listed );
11440 auto totals = runTests( m_config );
11444 return (
std::min) (MaxExitCode, (
std::max) (totals.error,
static_cast<int>(totals.assertions.failed)));
11446#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)
11449 return MaxExitCode;
11465 if( !g_singletons )
11467 return g_singletons;
11471 ISingleton::~ISingleton() {}
11473 void addSingleton(ISingleton* singleton ) {
11474 getSingletons()->
push_back( singleton );
11476 void cleanupSingletons() {
11477 auto& singletons = getSingletons();
11478 for(
auto singleton : *singletons )
11481 singletons =
nullptr;
11491 m_exceptions.push_back(exception);
11499 return m_exceptions;
11517 namespace detail {
namespace {
11518 template<
typename WriterF, std::
size_t bufferSize=256>
11520 char data[bufferSize];
11528 ~StreamBufImpl() noexcept {
11529 StreamBufImpl::sync();
11533 int overflow(
int c )
override {
11537 if( pbase() == epptr() )
11538 m_writer(
std::string( 1,
static_cast<char>( c ) ) );
11540 sputc(
static_cast<char>( c ) );
11545 int sync()
override {
11546 if( pbase() != pptr() ) {
11547 m_writer(
std::string( pbase(),
static_cast<std::string::size_type
>( pptr() - pbase() ) ) );
11548 setp( pbase(), epptr() );
11556 struct OutputDebugWriter {
11559 writeToDebugConsole( str );
11565 class FileStream :
public IStream {
11568 FileStream( StringRef filename ) {
11569 m_ofs.
open( filename.c_str() );
11572 ~FileStream()
override =
default;
11581 class CoutStream :
public IStream {
11586 CoutStream() : m_os(
Catch::
cout().rdbuf() ) {}
11587 ~CoutStream()
override =
default;
11590 std::ostream& stream()
const override {
return m_os; }
11595 class DebugOutStream :
public IStream {
11600 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
11601 m_os( m_streamBuf.
get() )
11604 ~DebugOutStream()
override =
default;
11607 std::ostream& stream()
const override {
return m_os; }
11614 auto makeStream( StringRef
const &filename ) -> IStream
const* {
11615 if( filename.
empty() )
11616 return new detail::CoutStream();
11617 else if( filename[0] ==
'%' ) {
11618 if( filename ==
"%debug" )
11619 return new detail::DebugOutStream();
11621 CATCH_ERROR(
"Unrecognised stream: '" << filename <<
"'" );
11624 return new detail::FileStream( filename );
11628 struct StringStreams {
11634 if( m_unused.
empty() ) {
11636 return m_streams.
size()-1;
11646 m_streams[index]->copyfmt( m_referenceStream );
11652 : m_index( Singleton<StringStreams>::getMutable().add() ),
11653 m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].
get() )
11659 Singleton<StringStreams>::getMutable().release(
m_index );
11668#ifndef CATCH_CONFIG_NOSTDOUT
11686 char toLowerCh(
char c) {
11687 return static_cast<char>( std::tolower( c ) );
11695 return !s.
empty() && s[0] == prefix;
11701 return !s.
empty() && s[s.size()-1] == suffix;
11704 return s.
find( infix ) != std::string::npos;
11715 static char const* whitespaceChars =
"\n\r\t ";
11719 return start != std::string::npos ? str.
substr( start, 1+end-start ) :
std::string();
11723 bool replaced =
false;
11725 while( i != std::string::npos ) {
11727 str = str.
substr( 0, i ) + withThis + str.substr( i+replaceThis.
size() );
11728 if( i < str.
size()-withThis.
size() )
11729 i = str.
find( replaceThis, i+withThis.
size() );
11731 i = std::string::npos;
11739 for(
std::size_t pos = 0; pos < str.size(); ++pos ) {
11740 if( str[pos] == delimiter ) {
11741 if( pos - start > 1 )
11742 subStrings.
push_back( str.substr( start, pos-start ) );
11746 if( start < str.size() )
11747 subStrings.
push_back( str.substr( start, str.size()-start ) );
11752 : m_count(
count ),
11757 os << pluraliser.m_count <<
' ' << pluraliser.m_label;
11758 if( pluraliser.m_count != 1 )
11767#if defined(__clang__)
11768# pragma clang diagnostic push
11769# pragma clang diagnostic ignored "-Wexit-time-destructors"
11777 const uint32_t byte_2_lead = 0xC0;
11778 const uint32_t byte_3_lead = 0xE0;
11779 const uint32_t byte_4_lead = 0xF0;
11809 return m_data !=
nullptr;
11812 return m_start[m_size] !=
'\0';
11817 m_data =
new char[m_size+1];
11822 auto StringRef::substr( size_type start, size_type size )
const noexcept -> StringRef {
11823 if( start < m_size )
11824 return StringRef( m_start+start, size );
11826 return StringRef();
11830 size() == other.size() &&
11838 return m_start[index];
11846 if( ( c & byte_2_lead ) == byte_2_lead ) {
11848 if (( c & byte_3_lead ) == byte_3_lead )
11850 if( ( c & byte_4_lead ) == byte_4_lead )
11857 auto operator + ( StringRef
const& lhs, StringRef
const& rhs ) ->
std::string {
11859 str.
reserve( lhs.size() + rhs.size() );
11864 auto operator + ( StringRef
const& lhs,
const char* rhs ) ->
std::string {
11867 auto operator + (
char const* lhs, StringRef
const& rhs ) ->
std::string {
11872 return os.
write(str.currentData(), str.
size());
11876 lhs.
append(rhs.currentData(), rhs.size());
11882#if defined(__clang__)
11883# pragma clang diagnostic pop
11889 TagAlias::TagAlias(
std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}
11913 TagAliasRegistry::~TagAliasRegistry() {}
11915 TagAlias
const* TagAliasRegistry::find(
std::string const& alias )
const {
11916 auto it = m_registry.find( alias );
11917 if( it != m_registry.end() )
11918 return &(it->second);
11924 std::string expandedTestSpec = unexpandedTestSpec;
11925 for(
auto const& registryKvp : m_registry ) {
11927 if( pos != std::string::npos ) {
11928 expandedTestSpec = expandedTestSpec.
substr( 0, pos ) +
11929 registryKvp.second.tag +
11930 expandedTestSpec.substr( pos + registryKvp.
first.
size() );
11933 return expandedTestSpec;
11936 void TagAliasRegistry::add(
std::string const& alias,
std::string const& tag, SourceLineInfo
const& lineInfo ) {
11938 "error: tag alias, '" << alias <<
"' is not of the form [@alias name].\n" << lineInfo );
11941 "error: tag alias, '" << alias <<
"' already registered.\n"
11942 <<
"\tFirst seen at: " <<
find(alias)->lineInfo <<
"\n"
11943 <<
"\tRedefined at: " << lineInfo );
11946 ITagAliasRegistry::~ITagAliasRegistry() {}
11948 ITagAliasRegistry
const& ITagAliasRegistry::get() {
11968 else if( tag ==
"!throws" )
11970 else if( tag ==
"!shouldfail" )
11972 else if( tag ==
"!mayfail" )
11974 else if( tag ==
"!nonportable" )
11976 else if( tag ==
"!benchmark" )
11984 void enforceNotReservedTag(
std::string const& tag, SourceLineInfo
const& _lineInfo ) {
11986 "Tag name: [" << tag <<
"] is not allowed.\n"
11987 <<
"Tag names starting with non alphanumeric characters are reserved\n"
11994 NameAndTags
const& nameAndTags,
11995 SourceLineInfo
const& _lineInfo )
11997 bool isHidden =
false;
12002 bool inTag =
false;
12004 for (
char c : _descOrTags) {
12017 enforceNotReservedTag( tag, _lineInfo );
12037 TestCaseInfo
info( nameAndTags.name, _className, desc, tags, _lineInfo );
12038 return TestCase( _testCase, std::move(info) );
12044 testCaseInfo.lcaseTags.clear();
12046 for(
auto const& tag : tags ) {
12049 testCaseInfo.lcaseTags.push_back( lcaseTag );
12051 testCaseInfo.tags = std::move(tags);
12058 SourceLineInfo
const& _lineInfo )
12060 className( _className ),
12061 description( _description ),
12062 lineInfo( _lineInfo ),
12065 setTags( *
this, _tags );
12085 for (
const auto& tag :
tags) {
12086 full_size += tag.
size();
12089 for (
const auto& tag :
tags) {
12098 TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo(
std::move(
info) ), test( testCase ) {}
12102 other.name = _newName;
12111 return test.get() == other.test.get() &&
12112 name == other.name &&
12117 return name < other.name;
12137 switch( config.runOrder() ) {
12151 bool matchTest( TestCase
const& testCase, TestSpec
const& testSpec, IConfig
const& config ) {
12152 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
12157 for(
auto const& function : functions ) {
12158 auto prev = seenFunctions.
insert( function );
12160 "error: TEST_CASE( \"" << function.name <<
"\" ) already defined.\n"
12161 <<
"\tFirst seen at " <<
prev.first->getTestCaseInfo().lineInfo <<
"\n"
12162 <<
"\tRedefined at " << function.getTestCaseInfo().lineInfo );
12169 for (
auto const& testCase : testCases) {
12170 if ((!testSpec.hasFilters() && !testCase.isHidden()) ||
12171 (testSpec.hasFilters() &&
matchTest(testCase, testSpec, config))) {
12181 void TestRegistry::registerTest( TestCase
const& testCase ) {
12183 if(
name.empty() ) {
12184 ReusableStringStream rss;
12185 rss <<
"Anonymous test case " << ++m_unnamedCount;
12186 return registerTest( testCase.withName( rss.str() ) );
12188 m_functions.push_back( testCase );
12192 return m_functions;
12195 if( m_sortedFunctions.empty() )
12196 enforceNoDuplicateTestCases( m_functions );
12198 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
12199 m_sortedFunctions = sortTests( config, m_functions );
12200 m_currentSortOrder = config.runOrder();
12202 return m_sortedFunctions;
12206 TestInvokerAsFunction::TestInvokerAsFunction(
void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}
12208 void TestInvokerAsFunction::invoke()
const {
12209 m_testAsFunction();
12212 std::string extractClassName( StringRef
const& classOrQualifiedMethodName ) {
12213 std::string className = classOrQualifiedMethodName;
12218 if( penultimateColons == std::string::npos )
12219 penultimateColons = 1;
12220 className = className.
substr( penultimateColons, lastColons-penultimateColons );
12235#if defined(__clang__)
12236# pragma clang diagnostic push
12237# pragma clang diagnostic ignored "-Wexit-time-destructors"
12241namespace TestCaseTracking {
12243 NameAndLocation::NameAndLocation(
std::string const& _name, SourceLineInfo
const& _location )
12245 location( _location )
12248 ITracker::~ITracker() =
default;
12250 ITracker& TrackerContext::startRun() {
12252 m_currentTracker =
nullptr;
12253 m_runState = Executing;
12254 return *m_rootTracker;
12257 void TrackerContext::endRun() {
12258 m_rootTracker.reset();
12259 m_currentTracker =
nullptr;
12260 m_runState = NotStarted;
12263 void TrackerContext::startCycle() {
12264 m_currentTracker = m_rootTracker.get();
12265 m_runState = Executing;
12267 void TrackerContext::completeCycle() {
12268 m_runState = CompletedCycle;
12271 bool TrackerContext::completedCycle()
const {
12272 return m_runState == CompletedCycle;
12274 ITracker& TrackerContext::currentTracker() {
12275 return *m_currentTracker;
12277 void TrackerContext::setCurrentTracker( ITracker* tracker ) {
12278 m_currentTracker = tracker;
12281 TrackerBase::TrackerBase( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
12282 : m_nameAndLocation( nameAndLocation ),
12287 NameAndLocation
const& TrackerBase::nameAndLocation()
const {
12288 return m_nameAndLocation;
12290 bool TrackerBase::isComplete()
const {
12291 return m_runState == CompletedSuccessfully || m_runState == Failed;
12293 bool TrackerBase::isSuccessfullyCompleted()
const {
12294 return m_runState == CompletedSuccessfully;
12296 bool TrackerBase::isOpen()
const {
12297 return m_runState != NotStarted && !isComplete();
12299 bool TrackerBase::hasChildren()
const {
12300 return !m_children.empty();
12303 void TrackerBase::addChild( ITrackerPtr
const& child ) {
12304 m_children.push_back( child );
12307 ITrackerPtr TrackerBase::findChild( NameAndLocation
const& nameAndLocation ) {
12308 auto it =
std::find_if( m_children.begin(), m_children.end(),
12309 [&nameAndLocation]( ITrackerPtr
const& tracker ){
12311 tracker->nameAndLocation().location == nameAndLocation.location &&
12312 tracker->nameAndLocation().name == nameAndLocation.name;
12314 return( it != m_children.end() )
12318 ITracker& TrackerBase::parent() {
12319 assert( m_parent );
12323 void TrackerBase::openChild() {
12324 if( m_runState != ExecutingChildren ) {
12325 m_runState = ExecutingChildren;
12327 m_parent->openChild();
12331 bool TrackerBase::isSectionTracker()
const {
return false; }
12332 bool TrackerBase::isGeneratorTracker()
const {
return false; }
12334 void TrackerBase::open() {
12335 m_runState = Executing;
12338 m_parent->openChild();
12341 void TrackerBase::close() {
12344 while( &m_ctx.currentTracker() !=
this )
12345 m_ctx.currentTracker().close();
12347 switch( m_runState ) {
12348 case NeedsAnotherRun:
12352 m_runState = CompletedSuccessfully;
12354 case ExecutingChildren:
12355 if( m_children.empty() || m_children.back()->isComplete() )
12356 m_runState = CompletedSuccessfully;
12360 case CompletedSuccessfully:
12368 m_ctx.completeCycle();
12370 void TrackerBase::fail() {
12371 m_runState = Failed;
12373 m_parent->markAsNeedingAnotherRun();
12375 m_ctx.completeCycle();
12377 void TrackerBase::markAsNeedingAnotherRun() {
12378 m_runState = NeedsAnotherRun;
12381 void TrackerBase::moveToParent() {
12382 assert( m_parent );
12383 m_ctx.setCurrentTracker( m_parent );
12385 void TrackerBase::moveToThis() {
12386 m_ctx.setCurrentTracker(
this );
12389 SectionTracker::SectionTracker( NameAndLocation
const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
12390 : TrackerBase( nameAndLocation, ctx, parent )
12393 while( !parent->isSectionTracker() )
12394 parent = &parent->parent();
12396 SectionTracker& parentSection =
static_cast<SectionTracker&
>( *parent );
12397 addNextFilters( parentSection.m_filters );
12401 bool SectionTracker::isComplete()
const {
12402 bool complete =
true;
12404 if ((m_filters.empty() || m_filters[0] ==
"") ||
12405 std::find(m_filters.begin(), m_filters.end(),
12406 m_nameAndLocation.name) != m_filters.end())
12407 complete = TrackerBase::isComplete();
12412 bool SectionTracker::isSectionTracker()
const {
return true; }
12414 SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation
const& nameAndLocation ) {
12417 ITracker& currentTracker = ctx.currentTracker();
12418 if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {
12419 assert( childTracker );
12420 assert( childTracker->isSectionTracker() );
12425 currentTracker.addChild( section );
12427 if( !ctx.completedCycle() )
12428 section->tryOpen();
12432 void SectionTracker::tryOpen() {
12433 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
12438 if( !filters.
empty() ) {
12439 m_filters.push_back(
"");
12440 m_filters.push_back(
"");
12441 m_filters.insert( m_filters.end(), filters.
begin(), filters.
end() );
12445 if( filters.
size() > 1 )
12446 m_filters.insert( m_filters.end(), ++filters.
begin(), filters.
end() );
12451using TestCaseTracking::ITracker;
12452using TestCaseTracking::TrackerContext;
12453using TestCaseTracking::SectionTracker;
12457#if defined(__clang__)
12458# pragma clang diagnostic pop
12465 auto makeTestInvoker(
void(*testAsFunction)() ) noexcept -> ITestInvoker* {
12466 return new(
std::nothrow) TestInvokerAsFunction( testAsFunction );
12471 AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo
const& lineInfo, StringRef
const& classOrMethod, NameAndTags
const& nameAndTags )
noexcept {
12477 extractClassName( classOrMethod ),
12498 TestSpec::Pattern::~Pattern() =
default;
12499 TestSpec::NamePattern::~NamePattern() =
default;
12500 TestSpec::TagPattern::~TagPattern() =
default;
12501 TestSpec::ExcludedPattern::~ExcludedPattern() =
default;
12504 : m_wildcardPattern(
toLower(
name ), CaseSensitive::No )
12506 bool TestSpec::NamePattern::matches( TestCaseInfo
const& testCase )
const {
12507 return m_wildcardPattern.matches(
toLower( testCase.name ) );
12510 TestSpec::TagPattern::TagPattern(
std::string const& tag ) : m_tag(
toLower( tag ) ) {}
12511 bool TestSpec::TagPattern::matches( TestCaseInfo
const& testCase )
const {
12513 end(testCase.lcaseTags),
12514 m_tag) !=
end(testCase.lcaseTags);
12517 TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr
const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
12518 bool TestSpec::ExcludedPattern::matches( TestCaseInfo
const& testCase )
const {
return !m_underlyingPattern->matches( testCase ); }
12520 bool TestSpec::Filter::matches( TestCaseInfo
const& testCase )
const {
12522 for(
auto const& pattern : m_patterns ) {
12523 if( !pattern->matches( testCase ) )
12529 bool TestSpec::hasFilters()
const {
12530 return !m_filters.empty();
12532 bool TestSpec::matches( TestCaseInfo
const& testCase )
const {
12534 for(
auto const& filter : m_filters )
12535 if(
filter.matches( testCase ) )
12545 TestSpecParser::TestSpecParser( ITagAliasRegistry
const& tagAliases ) : m_tagAliases( &tagAliases ) {}
12547 TestSpecParser& TestSpecParser::parse(
std::string const&
arg ) {
12549 m_exclusion =
false;
12550 m_start = std::string::npos;
12551 m_arg = m_tagAliases->expandAliases(
arg );
12552 m_escapeChars.
clear();
12553 for( m_pos = 0; m_pos < m_arg.
size(); ++m_pos )
12554 visitChar( m_arg[m_pos] );
12555 if( m_mode == Name )
12556 addPattern<TestSpec::NamePattern>();
12559 TestSpec TestSpecParser::testSpec() {
12564 void TestSpecParser::visitChar(
char c ) {
12565 if( m_mode == None ) {
12568 case '~': m_exclusion =
true;
return;
12569 case '[':
return startNewMode( Tag, ++m_pos );
12570 case '"':
return startNewMode( QuotedName, ++m_pos );
12571 case '\\':
return escape();
12572 default: startNewMode( Name, m_pos );
break;
12575 if( m_mode == Name ) {
12577 addPattern<TestSpec::NamePattern>();
12580 else if( c ==
'[' ) {
12581 if( subString() ==
"exclude:" )
12582 m_exclusion =
true;
12584 addPattern<TestSpec::NamePattern>();
12585 startNewMode( Tag, ++m_pos );
12587 else if( c ==
'\\' )
12590 else if( m_mode == EscapedName )
12592 else if( m_mode == QuotedName && c ==
'"' )
12593 addPattern<TestSpec::NamePattern>();
12594 else if( m_mode == Tag && c ==
']' )
12595 addPattern<TestSpec::TagPattern>();
12597 void TestSpecParser::startNewMode( Mode mode,
std::size_t start ) {
12601 void TestSpecParser::escape() {
12602 if( m_mode == None )
12604 m_mode = EscapedName;
12607 std::string TestSpecParser::subString()
const {
return m_arg.
substr( m_start, m_pos - m_start ); }
12609 void TestSpecParser::addFilter() {
12610 if( !m_currentFilter.m_patterns.empty() ) {
12611 m_testSpec.m_filters.push_back( m_currentFilter );
12612 m_currentFilter = TestSpec::Filter();
12617 return TestSpecParser( ITagAliasRegistry::get() ).parse(
arg ).testSpec();
12626static const uint64_t nanosecondsInSecond = 1000000000;
12635 auto estimateClockResolution() -> uint64_t {
12637 static const uint64_t iterations = 1000000;
12647 }
while( ticks == baseTicks );
12649 auto delta = ticks - baseTicks;
12655 if (ticks > startTime + 3 * nanosecondsInSecond) {
12656 return sum / ( i + 1u );
12662 return sum/iterations;
12666 static auto s_resolution = estimateClockResolution();
12667 return s_resolution;
12670 void Timer::start() {
12673 auto Timer::getElapsedNanoseconds() const -> uint64_t {
12676 auto Timer::getElapsedMicroseconds() const -> uint64_t {
12677 return getElapsedNanoseconds()/1000;
12679 auto Timer::getElapsedMilliseconds() const ->
unsigned int {
12680 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
12682 auto Timer::getElapsedSeconds() const ->
double {
12683 return getElapsedMicroseconds()/1000000.0;
12690#if defined(__clang__)
12691# pragma clang diagnostic push
12692# pragma clang diagnostic ignored "-Wexit-time-destructors"
12693# pragma clang diagnostic ignored "-Wglobal-constructors"
12697#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)
12698#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER
12711 const int hexThreshold = 255;
12713 struct Endianness {
12714 enum Arch { Big, Little };
12716 static Arch which() {
12719 char asChar[sizeof (int)];
12723 return ( u.asChar[
sizeof(
int)-1] == 1 ) ? Big : Little;
12730 int i = 0,
end =
static_cast<int>(
size ), inc = 1;
12731 if( Endianness::which() == Endianness::Little ) {
12736 unsigned char const *
bytes =
static_cast<unsigned char const *
>(object);
12737 ReusableStringStream rss;
12739 for( ; i !=
end; i += inc )
12740 rss <<
std::setw(2) << static_cast<unsigned>(
bytes[i]);
12745template<
typename T>
12747 if (Catch::isnan(
value)) {
12751 ReusableStringStream rss;
12757 if( i != std::string::npos && i != d.
size()-1 ) {
12773 return '"' + str + '"';
12777 for (
char c : str) {
12794#ifdef CATCH_CONFIG_CPP17_STRING_VIEW
12796 return ::Catch::Detail::stringify(
std::string{ str });
12802 return ::Catch::Detail::stringify(
std::string{ str });
12804 return{
"{null string}" };
12809 return ::Catch::Detail::stringify(
std::string{ str });
12811 return{
"{null string}" };
12815#ifdef CATCH_CONFIG_WCHAR
12819 for (
auto c : wstr) {
12820 s += (c <= 0xff) ? static_cast<
char>(c) : '?';
12822 return ::Catch::Detail::stringify(s);
12825# ifdef CATCH_CONFIG_CPP17_STRING_VIEW
12833 return ::Catch::Detail::stringify(
std::wstring{ str });
12835 return{
"{null string}" };
12840 return ::Catch::Detail::stringify(
std::wstring{ str });
12842 return{
"{null string}" };
12848 return ::Catch::Detail::stringify(
static_cast<long long>(
value));
12851 return ::Catch::Detail::stringify(
static_cast<long long>(
value));
12854 ReusableStringStream rss;
12856 if (
value > Detail::hexThreshold) {
12863 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(
value));
12866 return ::Catch::Detail::stringify(
static_cast<unsigned long long>(
value));
12869 ReusableStringStream rss;
12871 if (
value > Detail::hexThreshold) {
12878 return b ?
"true" :
"false";
12882 if (
value ==
'\r') {
12884 }
else if (
value ==
'\f') {
12886 }
else if (
value ==
'\n') {
12888 }
else if (
value ==
'\t') {
12891 return ::Catch::Detail::stringify(
static_cast<unsigned int>(
value));
12893 char chstr[] =
"' '";
12899 return ::Catch::Detail::stringify(
static_cast<signed char>(c));
12902 return ::Catch::Detail::stringify(
static_cast<char>(c));
12909int StringMaker<float>::precision = 5;
12912 return fpToString(
value, precision) + 'f';
12915int StringMaker<double>::precision = 10;
12918 return fpToString(
value, precision);
12921std::string ratio_string<std::atto>::symbol() {
return "a"; }
12922std::string ratio_string<std::femto>::symbol() {
return "f"; }
12923std::string ratio_string<std::pico>::symbol() {
return "p"; }
12924std::string ratio_string<std::nano>::symbol() {
return "n"; }
12925std::string ratio_string<std::micro>::symbol() {
return "u"; }
12926std::string ratio_string<std::milli>::symbol() {
return "m"; }
12930#if defined(__clang__)
12931# pragma clang diagnostic pop
12978 Totals diff = *
this - prevTotals;
12979 if( diff.assertions.failed > 0 )
12981 else if( diff.assertions.failedButOk > 0 )
12996#if defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)
13011 (
unsigned int _majorVersion,
13012 unsigned int _minorVersion,
13013 unsigned int _patchNumber,
13014 char const *
const _branchName,
13015 unsigned int _buildNumber )
13016 : majorVersion( _majorVersion ),
13017 minorVersion( _minorVersion ),
13018 patchNumber( _patchNumber ),
13019 branchName( _branchName ),
13020 buildNumber( _buildNumber )
13024 os << version.majorVersion <<
'.'
13025 << version.minorVersion <<
'.'
13026 << version.patchNumber;
13028 if (version.branchName[0]) {
13029 os <<
'-' << version.branchName
13030 <<
'.' << version.buildNumber;
13035 Version
const& libraryVersion() {
13036 static Version version( 2, 8, 0,
"", 0 );
13048 WildcardPattern::WildcardPattern(
std::string const& pattern,
13050 : m_caseSensitivity( caseSensitivity ),
13051 m_pattern( adjustCase( pattern ) )
13054 m_pattern = m_pattern.substr( 1 );
13055 m_wildcard = WildcardAtStart;
13057 if(
endsWith( m_pattern,
'*' ) ) {
13058 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
13059 m_wildcard =
static_cast<WildcardPosition
>( m_wildcard | WildcardAtEnd );
13063 bool WildcardPattern::matches(
std::string const& str )
const {
13064 switch( m_wildcard ) {
13066 return m_pattern == adjustCase( str );
13067 case WildcardAtStart:
13068 return endsWith( adjustCase( str ), m_pattern );
13069 case WildcardAtEnd:
13070 return startsWith( adjustCase( str ), m_pattern );
13071 case WildcardAtBothEnds:
13072 return contains( adjustCase( str ), m_pattern );
13087using uchar =
unsigned char;
13093 size_t trailingBytes(
unsigned char c) {
13094 if ((c & 0xE0) == 0xC0) {
13097 if ((c & 0xF0) == 0xE0) {
13100 if ((c & 0xF8) == 0xF0) {
13106 uint32_t headerValue(
unsigned char c) {
13107 if ((c & 0xE0) == 0xC0) {
13110 if ((c & 0xF0) == 0xE0) {
13113 if ((c & 0xF8) == 0xF0) {
13119 void hexEscapeChar(
std::ostream& os,
unsigned char c) {
13120 std::ios_base::fmtflags f(os.
flags());
13123 <<
static_cast<int>(c);
13129 XmlEncode::XmlEncode(
std::string const& str, ForWhat forWhat )
13131 m_forWhat( forWhat )
13138 for(
std::size_t idx = 0; idx < m_str.size(); ++ idx ) {
13139 uchar c = m_str[idx];
13141 case '<': os <<
"<";
break;
13142 case '&': os <<
"&";
break;
13146 if (idx > 2 && m_str[idx - 1] ==
']' && m_str[idx - 2] ==
']')
13153 if (m_forWhat == ForAttributes)
13164 if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {
13165 hexEscapeChar(os, c);
13183 hexEscapeChar(os, c);
13187 auto encBytes = trailingBytes(c);
13189 if (idx + encBytes - 1 >= m_str.size()) {
13190 hexEscapeChar(os, c);
13197 uint32_t
value = headerValue(c);
13199 uchar nc = m_str[idx + n];
13200 valid &= ((nc & 0xC0) == 0x80);
13209 (0x80 <=
value && value < 0x800 && encBytes > 2) ||
13210 (0x800 <
value && value < 0x10000 && encBytes > 3) ||
13212 (
value >= 0x110000)
13214 hexEscapeChar(os, c);
13220 os << m_str[idx + n];
13222 idx += encBytes - 1;
13229 xmlEncode.encodeTo( os );
13233 XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer )
13234 : m_writer( writer )
13237 XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept
13238 : m_writer( other.m_writer ){
13239 other.m_writer =
nullptr;
13241 XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other )
noexcept {
13243 m_writer->endElement();
13245 m_writer = other.m_writer;
13246 other.m_writer =
nullptr;
13250 XmlWriter::ScopedElement::~ScopedElement() {
13252 m_writer->endElement();
13255 XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText(
std::string const& text,
bool indent ) {
13256 m_writer->writeText( text, indent );
13262 writeDeclaration();
13265 XmlWriter::~XmlWriter() {
13266 while( !m_tags.empty() )
13272 newlineIfNecessary();
13273 m_os << m_indent <<
'<' <<
name;
13274 m_tags.push_back(
name );
13276 m_tagIsOpen =
true;
13280 XmlWriter::ScopedElement XmlWriter::scopedElement(
std::string const&
name ) {
13281 ScopedElement scoped(
this );
13282 startElement(
name );
13286 XmlWriter& XmlWriter::endElement() {
13287 newlineIfNecessary();
13288 m_indent = m_indent.substr( 0, m_indent.size()-2 );
13289 if( m_tagIsOpen ) {
13291 m_tagIsOpen =
false;
13294 m_os << m_indent <<
"</" << m_tags.back() <<
">";
13302 if( !
name.empty() && !attribute.
empty() )
13303 m_os <<
' ' <<
name <<
"=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) <<
'"';
13307 XmlWriter& XmlWriter::writeAttribute(
std::string const&
name,
bool attribute ) {
13308 m_os <<
' ' <<
name <<
"=\"" << ( attribute ?
"true" :
"false" ) <<
'"';
13312 XmlWriter& XmlWriter::writeText(
std::string const& text,
bool indent ) {
13313 if( !text.
empty() ){
13314 bool tagWasOpen = m_tagIsOpen;
13316 if( tagWasOpen && indent )
13318 m_os << XmlEncode( text );
13319 m_needsNewline =
true;
13324 XmlWriter& XmlWriter::writeComment(
std::string const& text ) {
13326 m_os << m_indent <<
"<!--" << text <<
"-->";
13327 m_needsNewline =
true;
13331 void XmlWriter::writeStylesheetRef(
std::string const& url ) {
13332 m_os <<
"<?xml-stylesheet type=\"text/xsl\" href=\"" << url <<
"\"?>\n";
13335 XmlWriter& XmlWriter::writeBlankLine() {
13341 void XmlWriter::ensureTagClosed() {
13342 if( m_tagIsOpen ) {
13344 m_tagIsOpen =
false;
13348 void XmlWriter::writeDeclaration() {
13349 m_os <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
13352 void XmlWriter::newlineIfNecessary() {
13353 if( m_needsNewline ) {
13355 m_needsNewline =
false;
13369 void prepareExpandedExpression(AssertionResult& result) {
13370 result.getExpandedExpression();
13375 std::string getFormattedDuration(
double duration ) {
13380 const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
13381 char buffer[maxDoubleSize];
13386 sprintf_s(
buffer,
"%.3f", duration);
13394 ReusableStringStream oss;
13396 for (
auto&& filter : container)
13408 TestEventListenerBase::TestEventListenerBase(ReporterConfig
const & _config)
13409 :StreamingReporterBase(_config) {}
13415 void TestEventListenerBase::assertionStarting(AssertionInfo
const &) {}
13417 bool TestEventListenerBase::assertionEnded(AssertionStats
const &) {
13427#ifdef CATCH_PLATFORM_MAC
13428 const char* failedString() {
return "FAILED"; }
13429 const char* passedString() {
return "PASSED"; }
13431 const char* failedString() {
return "failed"; }
13432 const char* passedString() {
return "passed"; }
13436 Catch::Colour::Code dimColour() {
return Catch::Colour::FileName; }
13440 count == 2 ?
"both " :
"all " ;
13453void printTotals(
std::ostream& out,
const Totals& totals) {
13454 if (totals.testCases.total() == 0) {
13455 out <<
"No tests ran.";
13456 }
else if (totals.testCases.failed == totals.testCases.total()) {
13457 Colour colour(Colour::ResultError);
13459 totals.assertions.failed == totals.assertions.total() ?
13460 bothOrAll(totals.assertions.failed) :
std::string();
13462 "Failed " << bothOrAll(totals.testCases.failed)
13463 << pluralise(totals.testCases.failed,
"test case") <<
", "
13464 "failed " << qualify_assertions_failed <<
13465 pluralise(totals.assertions.failed,
"assertion") <<
'.';
13466 }
else if (totals.assertions.total() == 0) {
13468 "Passed " << bothOrAll(totals.testCases.total())
13469 << pluralise(totals.testCases.total(),
"test case")
13470 <<
" (no assertions).";
13471 }
else if (totals.assertions.failed) {
13472 Colour colour(Colour::ResultError);
13474 "Failed " << pluralise(totals.testCases.failed,
"test case") <<
", "
13475 "failed " << pluralise(totals.assertions.failed,
"assertion") <<
'.';
13477 Colour colour(Colour::ResultSuccess);
13479 "Passed " << bothOrAll(totals.testCases.passed)
13480 << pluralise(totals.testCases.passed,
"test case") <<
13481 " with " << pluralise(totals.assertions.passed,
"assertion") <<
'.';
13486class AssertionPrinter {
13488 AssertionPrinter& operator= (AssertionPrinter
const&) =
delete;
13489 AssertionPrinter(AssertionPrinter
const&) =
delete;
13490 AssertionPrinter(
std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13492 ,
result(_stats.assertionResult)
13493 , messages(_stats.infoMessages)
13494 , itMessage(_stats.infoMessages.
begin())
13495 , printInfoMessages(_printInfoMessages) {}
13500 itMessage = messages.begin();
13502 switch (
result.getResultType()) {
13503 case ResultWas::Ok:
13504 printResultType(Colour::ResultSuccess, passedString());
13505 printOriginalExpression();
13506 printReconstructedExpression();
13507 if (!
result.hasExpression())
13508 printRemainingMessages(Colour::None);
13510 printRemainingMessages();
13512 case ResultWas::ExpressionFailed:
13514 printResultType(Colour::ResultSuccess, failedString() +
std::string(
" - but was ok"));
13516 printResultType(Colour::Error, failedString());
13517 printOriginalExpression();
13518 printReconstructedExpression();
13519 printRemainingMessages();
13521 case ResultWas::ThrewException:
13522 printResultType(Colour::Error, failedString());
13523 printIssue(
"unexpected exception with message:");
13525 printExpressionWas();
13526 printRemainingMessages();
13528 case ResultWas::FatalErrorCondition:
13529 printResultType(Colour::Error, failedString());
13530 printIssue(
"fatal error condition with message:");
13532 printExpressionWas();
13533 printRemainingMessages();
13535 case ResultWas::DidntThrowException:
13536 printResultType(Colour::Error, failedString());
13537 printIssue(
"expected exception, got none");
13538 printExpressionWas();
13539 printRemainingMessages();
13541 case ResultWas::Info:
13542 printResultType(Colour::None,
"info");
13544 printRemainingMessages();
13546 case ResultWas::Warning:
13547 printResultType(Colour::None,
"warning");
13549 printRemainingMessages();
13551 case ResultWas::ExplicitFailure:
13552 printResultType(Colour::Error, failedString());
13553 printIssue(
"explicitly");
13554 printRemainingMessages(Colour::None);
13557 case ResultWas::Unknown:
13558 case ResultWas::FailureBit:
13559 case ResultWas::Exception:
13560 printResultType(Colour::Error,
"** internal error **");
13566 void printSourceInfo()
const {
13567 Colour colourGuard(Colour::FileName);
13568 stream <<
result.getSourceInfo() <<
':';
13571 void printResultType(Colour::Code colour,
std::string const& passOrFail)
const {
13572 if (!passOrFail.
empty()) {
13574 Colour colourGuard(colour);
13575 stream <<
' ' << passOrFail;
13581 void printIssue(
std::string const& issue)
const {
13582 stream <<
' ' << issue;
13585 void printExpressionWas() {
13586 if (
result.hasExpression()) {
13589 Colour colour(dimColour());
13590 stream <<
" expression was:";
13592 printOriginalExpression();
13596 void printOriginalExpression()
const {
13597 if (
result.hasExpression()) {
13598 stream <<
' ' <<
result.getExpression();
13602 void printReconstructedExpression()
const {
13603 if (
result.hasExpandedExpression()) {
13605 Colour colour(dimColour());
13606 stream <<
" for: ";
13608 stream <<
result.getExpandedExpression();
13612 void printMessage() {
13613 if (itMessage != messages.end()) {
13614 stream <<
" '" << itMessage->message <<
'\'';
13619 void printRemainingMessages(Colour::Code colour = dimColour()) {
13620 if (itMessage == messages.end())
13628 Colour colourGuard(colour);
13629 stream <<
" with " << pluralise(N,
"message") <<
':';
13632 for (; itMessage != itEnd; ) {
13634 if (printInfoMessages || itMessage->type != ResultWas::Info) {
13635 stream <<
" '" << itMessage->message <<
'\'';
13636 if (++itMessage != itEnd) {
13637 Colour colourGuard(dimColour());
13646 AssertionResult
const&
result;
13649 bool printInfoMessages;
13655 return "Reports test results on a single line, suitable for IDEs";
13658 ReporterPreferences CompactReporter::getPreferences()
const {
13659 return m_reporterPrefs;
13662 void CompactReporter::noMatchingTestCases(
std::string const& spec ) {
13663 stream <<
"No test cases matched '" << spec <<
'\'' <<
std::endl;
13666 void CompactReporter::assertionStarting( AssertionInfo
const& ) {}
13668 bool CompactReporter::assertionEnded( AssertionStats
const& _assertionStats ) {
13669 AssertionResult
const&
result = _assertionStats.assertionResult;
13671 bool printInfoMessages =
true;
13674 if( !m_config->includeSuccessfulResults() &&
result.isOk() ) {
13677 printInfoMessages =
false;
13680 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
13687 void CompactReporter::sectionEnded(SectionStats
const& _sectionStats) {
13689 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name <<
std::endl;
13693 void CompactReporter::testRunEnded( TestRunStats
const& _testRunStats ) {
13694 printTotals( stream, _testRunStats.totals );
13696 StreamingReporterBase::testRunEnded( _testRunStats );
13699 CompactReporter::~CompactReporter() {}
13701 CATCH_REGISTER_REPORTER(
"compact", CompactReporter )
13710#if defined(_MSC_VER)
13711#pragma warning(push)
13712#pragma warning(disable:4061)
13722class ConsoleAssertionPrinter {
13724 ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter
const&) =
delete;
13725 ConsoleAssertionPrinter(ConsoleAssertionPrinter
const&) =
delete;
13726 ConsoleAssertionPrinter(
std::ostream& _stream, AssertionStats
const& _stats,
bool _printInfoMessages)
13729 result(_stats.assertionResult),
13730 colour(Colour::None),
13731 message(
result.getMessage()),
13732 messages(_stats.infoMessages),
13733 printInfoMessages(_printInfoMessages) {
13734 switch (
result.getResultType()) {
13735 case ResultWas::Ok:
13736 colour = Colour::Success;
13737 passOrFail =
"PASSED";
13739 if (_stats.infoMessages.size() == 1)
13740 messageLabel =
"with message";
13741 if (_stats.infoMessages.size() > 1)
13742 messageLabel =
"with messages";
13744 case ResultWas::ExpressionFailed:
13746 colour = Colour::Success;
13747 passOrFail =
"FAILED - but was ok";
13749 colour = Colour::Error;
13750 passOrFail =
"FAILED";
13752 if (_stats.infoMessages.size() == 1)
13753 messageLabel =
"with message";
13754 if (_stats.infoMessages.size() > 1)
13755 messageLabel =
"with messages";
13757 case ResultWas::ThrewException:
13758 colour = Colour::Error;
13759 passOrFail =
"FAILED";
13760 messageLabel =
"due to unexpected exception with ";
13761 if (_stats.infoMessages.size() == 1)
13762 messageLabel += "message";
13763 if (_stats.infoMessages.size() > 1)
13764 messageLabel += "messages";
13766 case ResultWas::FatalErrorCondition:
13767 colour = Colour::Error;
13768 passOrFail =
"FAILED";
13769 messageLabel =
"due to a fatal error condition";
13771 case ResultWas::DidntThrowException:
13772 colour = Colour::Error;
13773 passOrFail =
"FAILED";
13774 messageLabel =
"because no exception was thrown where one was expected";
13776 case ResultWas::Info:
13777 messageLabel =
"info";
13779 case ResultWas::Warning:
13780 messageLabel =
"warning";
13782 case ResultWas::ExplicitFailure:
13783 passOrFail =
"FAILED";
13784 colour = Colour::Error;
13785 if (_stats.infoMessages.size() == 1)
13786 messageLabel =
"explicitly with message";
13787 if (_stats.infoMessages.size() > 1)
13788 messageLabel =
"explicitly with messages";
13791 case ResultWas::Unknown:
13792 case ResultWas::FailureBit:
13793 case ResultWas::Exception:
13794 passOrFail =
"** internal error **";
13795 colour = Colour::Error;
13800 void print()
const {
13802 if (stats.totals.assertions.total() > 0) {
13804 printOriginalExpression();
13805 printReconstructedExpression();
13813 void printResultType()
const {
13814 if (!passOrFail.
empty()) {
13815 Colour colourGuard(colour);
13816 stream << passOrFail <<
":\n";
13819 void printOriginalExpression()
const {
13820 if (
result.hasExpression()) {
13821 Colour colourGuard(Colour::OriginalExpression);
13823 stream <<
result.getExpressionInMacro();
13827 void printReconstructedExpression()
const {
13828 if (
result.hasExpandedExpression()) {
13829 stream <<
"with expansion:\n";
13830 Colour colourGuard(Colour::ReconstructedExpression);
13831 stream << Column(
result.getExpandedExpression()).indent(2) <<
'\n';
13834 void printMessage()
const {
13835 if (!messageLabel.empty())
13836 stream << messageLabel <<
':' <<
'\n';
13837 for (
auto const& msg : messages) {
13839 if (printInfoMessages || msg.type != ResultWas::Info)
13840 stream << Column(msg.message).indent(2) <<
'\n';
13843 void printSourceInfo()
const {
13844 Colour colourGuard(Colour::FileName);
13845 stream <<
result.getSourceInfo() <<
": ";
13849 AssertionStats
const& stats;
13850 AssertionResult
const&
result;
13851 Colour::Code colour;
13856 bool printInfoMessages;
13860 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;
13861 return (ratio == 0 && number > 0) ? 1 : ratio;
13865 if (i > j && i > k)
13874 enum Justification { Left, Right };
13877 Justification justification;
13879struct ColumnBreak {};
13891 static const uint64_t s_nanosecondsInAMicrosecond = 1000;
13892 static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;
13893 static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;
13894 static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;
13896 uint64_t m_inNanoseconds;
13900 explicit Duration(uint64_t inNanoseconds, Unit units = Unit::Auto)
13901 : m_inNanoseconds(inNanoseconds),
13903 if (m_units == Unit::Auto) {
13904 if (m_inNanoseconds < s_nanosecondsInAMicrosecond)
13905 m_units = Unit::Nanoseconds;
13906 else if (m_inNanoseconds < s_nanosecondsInAMillisecond)
13907 m_units = Unit::Microseconds;
13908 else if (m_inNanoseconds < s_nanosecondsInASecond)
13909 m_units = Unit::Milliseconds;
13910 else if (m_inNanoseconds < s_nanosecondsInAMinute)
13911 m_units = Unit::Seconds;
13913 m_units = Unit::Minutes;
13918 auto value() const ->
double {
13920 case Unit::Microseconds:
13921 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMicrosecond);
13922 case Unit::Milliseconds:
13923 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMillisecond);
13924 case Unit::Seconds:
13925 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInASecond);
13926 case Unit::Minutes:
13927 return m_inNanoseconds /
static_cast<double>(s_nanosecondsInAMinute);
13929 return static_cast<double>(m_inNanoseconds);
13932 auto unitsAsString() const ->
std::
string {
13934 case Unit::Nanoseconds:
13936 case Unit::Microseconds:
13938 case Unit::Milliseconds:
13940 case Unit::Seconds:
13942 case Unit::Minutes:
13945 return "** internal error **";
13950 return os << duration.value() <<
" " << duration.unitsAsString();
13955class TablePrinter {
13959 int m_currentColumn = -1;
13960 bool m_isOpen =
false;
13965 m_columnInfos(
std::move( columnInfos ) ) {}
13967 auto columnInfos() const ->
std::vector<ColumnInfo> const& {
13968 return m_columnInfos;
13974 *
this << RowBreak();
13975 for (
auto const& info : m_columnInfos)
13976 *this <<
info.
name << ColumnBreak();
13977 *
this << RowBreak();
13978 m_os << Catch::getLineOfChars<
'-'>() <<
"\n";
13983 *
this << RowBreak();
13989 template<
typename T>
13995 friend TablePrinter&
operator << (TablePrinter& tp, ColumnBreak) {
13996 auto colStr = tp.m_oss.str();
14001 if (tp.m_currentColumn ==
static_cast<int>(tp.m_columnInfos.size() - 1)) {
14002 tp.m_currentColumn = -1;
14005 tp.m_currentColumn++;
14007 auto colInfo = tp.m_columnInfos[tp.m_currentColumn];
14008 auto padding = (strSize + 2 < static_cast<
std::size_t>(colInfo.width))
14009 ? std::string(colInfo.width - (strSize + 2), ' ')
14011 if (colInfo.justification == ColumnInfo::Left)
14012 tp.m_os << colStr << padding <<
" ";
14014 tp.m_os << padding << colStr <<
" ";
14018 friend TablePrinter&
operator << (TablePrinter& tp, RowBreak) {
14019 if (tp.m_currentColumn > 0) {
14021 tp.m_currentColumn = -1;
14027ConsoleReporter::ConsoleReporter(ReporterConfig
const& config)
14028 : StreamingReporterBase(config),
14029 m_tablePrinter(new TablePrinter(config.stream(),
14031 {
"benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 32, ColumnInfo::Left },
14032 {
"iters", 8, ColumnInfo::Right },
14033 {
"elapsed ns", 14, ColumnInfo::Right },
14034 {
"average", 14, ColumnInfo::Right }
14036ConsoleReporter::~ConsoleReporter() =
default;
14039 return "Reports test results as plain lines of text";
14042void ConsoleReporter::noMatchingTestCases(
std::string const& spec) {
14043 stream <<
"No test cases matched '" << spec <<
'\'' <<
std::endl;
14046void ConsoleReporter::assertionStarting(AssertionInfo
const&) {}
14048bool ConsoleReporter::assertionEnded(AssertionStats
const& _assertionStats) {
14049 AssertionResult
const&
result = _assertionStats.assertionResult;
14051 bool includeResults = m_config->includeSuccessfulResults() || !
result.isOk();
14059 ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);
14065void ConsoleReporter::sectionStarting(SectionInfo
const& _sectionInfo) {
14066 m_headerPrinted =
false;
14067 StreamingReporterBase::sectionStarting(_sectionInfo);
14069void ConsoleReporter::sectionEnded(SectionStats
const& _sectionStats) {
14070 m_tablePrinter->close();
14071 if (_sectionStats.missingAssertions) {
14073 Colour colour(Colour::ResultError);
14074 if (m_sectionStack.size() > 1)
14075 stream <<
"\nNo assertions in section";
14077 stream <<
"\nNo assertions in test case";
14078 stream <<
" '" << _sectionStats.sectionInfo.name <<
"'\n" <<
std::endl;
14081 stream << getFormattedDuration(_sectionStats.durationInSeconds) <<
" s: " << _sectionStats.sectionInfo.name <<
std::endl;
14083 if (m_headerPrinted) {
14084 m_headerPrinted =
false;
14086 StreamingReporterBase::sectionEnded(_sectionStats);
14089void ConsoleReporter::benchmarkStarting(BenchmarkInfo
const& info) {
14090 lazyPrintWithoutClosingBenchmarkTable();
14092 auto nameCol = Column(
info.name ).width(
static_cast<std::size_t>( m_tablePrinter->columnInfos()[0].width - 2 ) );
14094 bool firstLine =
true;
14095 for (
auto line : nameCol) {
14097 (*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();
14101 (*m_tablePrinter) << line << ColumnBreak();
14104void ConsoleReporter::benchmarkEnded(BenchmarkStats
const& stats) {
14105 Duration average(stats.elapsedTimeInNanoseconds / stats.iterations);
14107 << stats.iterations << ColumnBreak()
14108 << stats.elapsedTimeInNanoseconds << ColumnBreak()
14109 << average << ColumnBreak();
14112void ConsoleReporter::testCaseEnded(TestCaseStats
const& _testCaseStats) {
14113 m_tablePrinter->close();
14114 StreamingReporterBase::testCaseEnded(_testCaseStats);
14115 m_headerPrinted =
false;
14117void ConsoleReporter::testGroupEnded(TestGroupStats
const& _testGroupStats) {
14118 if (currentGroupInfo.used) {
14119 printSummaryDivider();
14120 stream <<
"Summary for group '" << _testGroupStats.groupInfo.name <<
"':\n";
14121 printTotals(_testGroupStats.totals);
14124 StreamingReporterBase::testGroupEnded(_testGroupStats);
14126void ConsoleReporter::testRunEnded(TestRunStats
const& _testRunStats) {
14127 printTotalsDivider(_testRunStats.totals);
14128 printTotals(_testRunStats.totals);
14130 StreamingReporterBase::testRunEnded(_testRunStats);
14132void ConsoleReporter::testRunStarting(TestRunInfo
const& _testInfo) {
14133 StreamingReporterBase::testRunStarting(_testInfo);
14134 printTestFilters();
14137void ConsoleReporter::lazyPrint() {
14139 m_tablePrinter->close();
14140 lazyPrintWithoutClosingBenchmarkTable();
14143void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {
14145 if (!currentTestRunInfo.used)
14146 lazyPrintRunInfo();
14147 if (!currentGroupInfo.used)
14148 lazyPrintGroupInfo();
14150 if (!m_headerPrinted) {
14151 printTestCaseAndSectionHeader();
14152 m_headerPrinted =
true;
14155void ConsoleReporter::lazyPrintRunInfo() {
14156 stream << '\n' << getLineOfChars<'~'>() <<
'\n';
14157 Colour colour(Colour::SecondaryText);
14158 stream << currentTestRunInfo->name
14159 <<
" is a Catch v" << libraryVersion() <<
" host application.\n"
14160 <<
"Run with -? for options\n\n";
14162 if (m_config->rngSeed() != 0)
14163 stream <<
"Randomness seeded to: " << m_config->rngSeed() <<
"\n\n";
14165 currentTestRunInfo.used =
true;
14167void ConsoleReporter::lazyPrintGroupInfo() {
14168 if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {
14169 printClosedHeader(
"Group: " + currentGroupInfo->name);
14170 currentGroupInfo.used =
true;
14173void ConsoleReporter::printTestCaseAndSectionHeader() {
14174 assert(!m_sectionStack.empty());
14175 printOpenHeader(currentTestCaseInfo->name);
14177 if (m_sectionStack.size() > 1) {
14178 Colour colourGuard(Colour::Headers);
14181 it = m_sectionStack.begin() + 1,
14182 itEnd = m_sectionStack.
end();
14183 for (; it != itEnd; ++it)
14184 printHeaderString(it->
name, 2);
14187 SourceLineInfo lineInfo = m_sectionStack.
back().lineInfo;
14189 if (!lineInfo.empty()) {
14190 stream << getLineOfChars<
'-'>() <<
'\n';
14191 Colour colourGuard(Colour::FileName);
14192 stream << lineInfo <<
'\n';
14194 stream << getLineOfChars<
'.'>() <<
'\n' <<
std::endl;
14197void ConsoleReporter::printClosedHeader(
std::string const& _name) {
14198 printOpenHeader(_name);
14199 stream << getLineOfChars<
'.'>() <<
'\n';
14201void ConsoleReporter::printOpenHeader(
std::string const& _name) {
14202 stream << getLineOfChars<
'-'>() <<
'\n';
14204 Colour colourGuard(Colour::Headers);
14205 printHeaderString(_name);
14213 if (i != std::string::npos)
14217 stream << Column(_string).indent(indent + i).initialIndent(indent) <<
'\n';
14220struct SummaryColumn {
14222 SummaryColumn(
std::string _label, Colour::Code _colour )
14223 : label(
std::move( _label ) ),
14224 colour( _colour ) {}
14226 ReusableStringStream rss;
14229 for (
auto& oldRow : rows) {
14230 while (oldRow.size() < row.
size())
14231 oldRow =
' ' + oldRow;
14232 while (oldRow.size() > row.
size())
14240 Colour::Code colour;
14245void ConsoleReporter::printTotals( Totals
const& totals ) {
14246 if (totals.testCases.total() == 0) {
14247 stream << Colour(Colour::Warning) <<
"No tests ran\n";
14248 }
else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {
14249 stream << Colour(Colour::ResultSuccess) <<
"All tests passed";
14251 << pluralise(totals.assertions.passed,
"assertion") <<
" in "
14252 << pluralise(totals.testCases.passed,
"test case") <<
')'
14257 columns.
push_back(SummaryColumn(
"", Colour::None)
14258 .addRow(totals.testCases.total())
14259 .addRow(totals.assertions.total()));
14260 columns.
push_back(SummaryColumn(
"passed", Colour::Success)
14261 .addRow(totals.testCases.passed)
14262 .addRow(totals.assertions.passed));
14263 columns.
push_back(SummaryColumn(
"failed", Colour::ResultError)
14264 .addRow(totals.testCases.failed)
14265 .addRow(totals.assertions.failed));
14266 columns.
push_back(SummaryColumn(
"failed as expected", Colour::ResultExpectedFailure)
14267 .addRow(totals.testCases.failedButOk)
14268 .addRow(totals.assertions.failedButOk));
14270 printSummaryRow(
"test cases", columns, 0);
14271 printSummaryRow(
"assertions", columns, 1);
14275 for (
auto col : cols) {
14277 if (col.label.empty()) {
14278 stream << label <<
": ";
14282 stream << Colour(Colour::Warning) <<
"- none -";
14283 }
else if (
value !=
"0") {
14284 stream << Colour(Colour::LightGrey) <<
" | ";
14285 stream << Colour(col.colour)
14286 <<
value <<
' ' << col.label;
14292void ConsoleReporter::printTotalsDivider(Totals
const& totals) {
14293 if (totals.testCases.total() > 0) {
14294 std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());
14295 std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());
14296 std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());
14297 while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)
14298 findMax(failedRatio, failedButOkRatio, passedRatio)++;
14299 while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)
14300 findMax(failedRatio, failedButOkRatio, passedRatio)--;
14302 stream << Colour(Colour::Error) <<
std::string(failedRatio,
'=');
14303 stream << Colour(Colour::ResultExpectedFailure) <<
std::string(failedButOkRatio,
'=');
14304 if (totals.testCases.allPassed())
14305 stream << Colour(Colour::ResultSuccess) <<
std::string(passedRatio,
'=');
14307 stream << Colour(Colour::Success) <<
std::string(passedRatio,
'=');
14309 stream << Colour(Colour::Warning) <<
std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1,
'=');
14313void ConsoleReporter::printSummaryDivider() {
14314 stream << getLineOfChars<
'-'>() <<
'\n';
14317void ConsoleReporter::printTestFilters() {
14318 if (m_config->testSpec().hasFilters())
14319 stream << Colour(Colour::BrightYellow) <<
"Filters: " << serializeFilters( m_config->getTestsOrTags() ) <<
'\n';
14322CATCH_REGISTER_REPORTER(
"console", ConsoleReporter)
14326#if defined(_MSC_VER)
14327#pragma warning(pop)
14345 auto const timeStampSize =
sizeof(
"2017-01-16T17:06:45Z");
14355 char timeStamp[timeStampSize];
14356 const char *
const fmt =
"%Y-%m-%dT%H:%M:%SZ";
14370 if (it != tags.
end())
14376 JunitReporter::JunitReporter( ReporterConfig
const& _config )
14377 : CumulativeReporterBase( _config ),
14378 xml( _config.stream() )
14380 m_reporterPrefs.shouldRedirectStdOut =
true;
14381 m_reporterPrefs.shouldReportAllAssertions =
true;
14384 JunitReporter::~JunitReporter() {}
14387 return "Reports test results in an XML format that looks like Ant's junitreport target";
14390 void JunitReporter::noMatchingTestCases(
std::string const& ) {}
14392 void JunitReporter::testRunStarting( TestRunInfo
const& runInfo ) {
14393 CumulativeReporterBase::testRunStarting( runInfo );
14394 xml.startElement(
"testsuites" );
14397 void JunitReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14398 suiteTimer.start();
14399 stdOutForSuite.clear();
14400 stdErrForSuite.clear();
14401 unexpectedExceptions = 0;
14402 CumulativeReporterBase::testGroupStarting( groupInfo );
14405 void JunitReporter::testCaseStarting( TestCaseInfo
const& testCaseInfo ) {
14406 m_okToFail = testCaseInfo.okToFail();
14409 bool JunitReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14411 unexpectedExceptions++;
14412 return CumulativeReporterBase::assertionEnded( assertionStats );
14415 void JunitReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14416 stdOutForSuite += testCaseStats.stdOut;
14417 stdErrForSuite += testCaseStats.stdErr;
14418 CumulativeReporterBase::testCaseEnded( testCaseStats );
14421 void JunitReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14422 double suiteTime = suiteTimer.getElapsedSeconds();
14423 CumulativeReporterBase::testGroupEnded( testGroupStats );
14424 writeGroup( *m_testGroups.back(), suiteTime );
14427 void JunitReporter::testRunEndedCumulative() {
14431 void JunitReporter::writeGroup( TestGroupNode
const& groupNode,
double suiteTime ) {
14432 XmlWriter::ScopedElement e = xml.scopedElement(
"testsuite" );
14434 TestGroupStats
const& stats = groupNode.value;
14435 xml.writeAttribute(
"name", stats.groupInfo.name );
14436 xml.writeAttribute(
"errors", unexpectedExceptions );
14437 xml.writeAttribute(
"failures", stats.totals.assertions.failed-unexpectedExceptions );
14438 xml.writeAttribute(
"tests", stats.totals.assertions.total() );
14439 xml.writeAttribute(
"hostname",
"tbd" );
14441 xml.writeAttribute(
"time",
"" );
14443 xml.writeAttribute(
"time", suiteTime );
14444 xml.writeAttribute(
"timestamp", getCurrentTimestamp() );
14447 if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {
14448 auto properties = xml.scopedElement(
"properties");
14449 if (m_config->hasTestFilters()) {
14450 xml.scopedElement(
"property")
14451 .writeAttribute(
"name",
"filters")
14452 .writeAttribute(
"value", serializeFilters(m_config->getTestsOrTags()));
14454 if (m_config->rngSeed() != 0) {
14455 xml.scopedElement(
"property")
14456 .writeAttribute(
"name",
"random-seed")
14457 .writeAttribute(
"value", m_config->rngSeed());
14462 for(
auto const& child : groupNode.children )
14463 writeTestCase( *child );
14465 xml.scopedElement(
"system-out" ).writeText(
trim( stdOutForSuite ),
false );
14466 xml.scopedElement(
"system-err" ).writeText(
trim( stdErrForSuite ),
false );
14469 void JunitReporter::writeTestCase( TestCaseNode
const& testCaseNode ) {
14470 TestCaseStats
const& stats = testCaseNode.value;
14474 assert( testCaseNode.children.size() == 1 );
14475 SectionNode
const& rootSection = *testCaseNode.children.front();
14477 std::string className = stats.testInfo.className;
14479 if( className.
empty() ) {
14480 className = fileNameTag(stats.testInfo.tags);
14481 if ( className.
empty() )
14482 className =
"global";
14485 if ( !m_config->name().empty() )
14486 className = m_config->name() + "." + className;
14488 writeSection( className,
"", rootSection );
14491 void JunitReporter::writeSection(
std::string const& className,
14493 SectionNode
const& sectionNode ) {
14495 if( !rootName.
empty() )
14498 if( !sectionNode.assertions.empty() ||
14499 !sectionNode.stdOut.empty() ||
14500 !sectionNode.stdErr.empty() ) {
14501 XmlWriter::ScopedElement e = xml.scopedElement(
"testcase" );
14502 if( className.
empty() ) {
14503 xml.writeAttribute(
"classname",
name );
14504 xml.writeAttribute(
"name",
"root" );
14507 xml.writeAttribute(
"classname", className );
14508 xml.writeAttribute(
"name",
name );
14512 writeAssertions( sectionNode );
14514 if( !sectionNode.stdOut.empty() )
14515 xml.scopedElement(
"system-out" ).writeText(
trim( sectionNode.stdOut ),
false );
14516 if( !sectionNode.stdErr.empty() )
14517 xml.scopedElement(
"system-err" ).writeText(
trim( sectionNode.stdErr ),
false );
14519 for(
auto const& childNode : sectionNode.childSections )
14520 if( className.
empty() )
14521 writeSection(
name,
"", *childNode );
14523 writeSection( className,
name, *childNode );
14526 void JunitReporter::writeAssertions( SectionNode
const& sectionNode ) {
14527 for(
auto const& assertion : sectionNode.assertions )
14528 writeAssertion( assertion );
14531 void JunitReporter::writeAssertion( AssertionStats
const& stats ) {
14532 AssertionResult
const&
result = stats.assertionResult;
14535 switch(
result.getResultType() ) {
14538 elementName =
"error";
14541 elementName =
"failure";
14544 elementName =
"failure";
14547 elementName =
"failure";
14557 elementName =
"internalError";
14561 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
14563 xml.writeAttribute(
"message",
result.getExpandedExpression() );
14564 xml.writeAttribute(
"type",
result.getTestMacroName() );
14566 ReusableStringStream rss;
14567 if( !
result.getMessage().empty() )
14568 rss <<
result.getMessage() <<
'\n';
14569 for(
auto const& msg : stats.infoMessages )
14570 if( msg.
type == ResultWas::Info )
14571 rss << msg.message <<
'\n';
14573 rss <<
"at " <<
result.getSourceInfo();
14574 xml.writeText( rss.str(),
false );
14578 CATCH_REGISTER_REPORTER(
"junit", JunitReporter )
14588 ListeningReporter::ListeningReporter() {
14590 m_preferences.shouldReportAllAssertions =
true;
14593 void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {
14594 m_listeners.push_back( std::move( listener ) );
14597 void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {
14598 assert(!m_reporter &&
"Listening reporter can wrap only 1 real reporter");
14599 m_reporter = std::move( reporter );
14600 m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;
14603 ReporterPreferences ListeningReporter::getPreferences()
const {
14604 return m_preferences;
14611 void ListeningReporter::noMatchingTestCases(
std::string const& spec ) {
14612 for (
auto const& listener : m_listeners ) {
14613 listener->noMatchingTestCases( spec );
14615 m_reporter->noMatchingTestCases( spec );
14618 void ListeningReporter::benchmarkStarting( BenchmarkInfo
const& benchmarkInfo ) {
14619 for (
auto const& listener : m_listeners ) {
14620 listener->benchmarkStarting( benchmarkInfo );
14622 m_reporter->benchmarkStarting( benchmarkInfo );
14624 void ListeningReporter::benchmarkEnded( BenchmarkStats
const& benchmarkStats ) {
14625 for (
auto const& listener : m_listeners ) {
14626 listener->benchmarkEnded( benchmarkStats );
14628 m_reporter->benchmarkEnded( benchmarkStats );
14631 void ListeningReporter::testRunStarting( TestRunInfo
const& testRunInfo ) {
14632 for (
auto const& listener : m_listeners ) {
14633 listener->testRunStarting( testRunInfo );
14635 m_reporter->testRunStarting( testRunInfo );
14638 void ListeningReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14639 for (
auto const& listener : m_listeners ) {
14640 listener->testGroupStarting( groupInfo );
14642 m_reporter->testGroupStarting( groupInfo );
14645 void ListeningReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
14646 for (
auto const& listener : m_listeners ) {
14647 listener->testCaseStarting( testInfo );
14649 m_reporter->testCaseStarting( testInfo );
14652 void ListeningReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
14653 for (
auto const& listener : m_listeners ) {
14654 listener->sectionStarting( sectionInfo );
14656 m_reporter->sectionStarting( sectionInfo );
14659 void ListeningReporter::assertionStarting( AssertionInfo
const& assertionInfo ) {
14660 for (
auto const& listener : m_listeners ) {
14661 listener->assertionStarting( assertionInfo );
14663 m_reporter->assertionStarting( assertionInfo );
14667 bool ListeningReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14668 for(
auto const& listener : m_listeners ) {
14669 static_cast<void>( listener->assertionEnded( assertionStats ) );
14671 return m_reporter->assertionEnded( assertionStats );
14674 void ListeningReporter::sectionEnded( SectionStats
const& sectionStats ) {
14675 for (
auto const& listener : m_listeners ) {
14676 listener->sectionEnded( sectionStats );
14678 m_reporter->sectionEnded( sectionStats );
14681 void ListeningReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14682 for (
auto const& listener : m_listeners ) {
14683 listener->testCaseEnded( testCaseStats );
14685 m_reporter->testCaseEnded( testCaseStats );
14688 void ListeningReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14689 for (
auto const& listener : m_listeners ) {
14690 listener->testGroupEnded( testGroupStats );
14692 m_reporter->testGroupEnded( testGroupStats );
14695 void ListeningReporter::testRunEnded( TestRunStats
const& testRunStats ) {
14696 for (
auto const& listener : m_listeners ) {
14697 listener->testRunEnded( testRunStats );
14699 m_reporter->testRunEnded( testRunStats );
14702 void ListeningReporter::skipTest( TestCaseInfo
const& testInfo ) {
14703 for (
auto const& listener : m_listeners ) {
14704 listener->skipTest( testInfo );
14706 m_reporter->skipTest( testInfo );
14709 bool ListeningReporter::isMulti()
const {
14717#if defined(_MSC_VER)
14718#pragma warning(push)
14719#pragma warning(disable:4061)
14725 XmlReporter::XmlReporter( ReporterConfig
const& _config )
14726 : StreamingReporterBase( _config ),
14727 m_xml(_config.stream())
14729 m_reporterPrefs.shouldRedirectStdOut =
true;
14730 m_reporterPrefs.shouldReportAllAssertions =
true;
14733 XmlReporter::~XmlReporter() =
default;
14736 return "Reports test results as an XML document";
14739 std::string XmlReporter::getStylesheetRef()
const {
14743 void XmlReporter::writeSourceInfo( SourceLineInfo
const& sourceInfo ) {
14745 .writeAttribute(
"filename", sourceInfo.file )
14746 .writeAttribute(
"line", sourceInfo.line );
14749 void XmlReporter::noMatchingTestCases(
std::string const& s ) {
14750 StreamingReporterBase::noMatchingTestCases( s );
14753 void XmlReporter::testRunStarting( TestRunInfo
const& testInfo ) {
14754 StreamingReporterBase::testRunStarting( testInfo );
14756 if( !stylesheetRef.
empty() )
14757 m_xml.writeStylesheetRef( stylesheetRef );
14758 m_xml.startElement(
"Catch" );
14759 if( !m_config->name().empty() )
14760 m_xml.writeAttribute(
"name", m_config->name() );
14761 if (m_config->testSpec().hasFilters())
14762 m_xml.writeAttribute(
"filters", serializeFilters( m_config->getTestsOrTags() ) );
14763 if( m_config->rngSeed() != 0 )
14764 m_xml.scopedElement(
"Randomness" )
14765 .writeAttribute(
"seed", m_config->rngSeed() );
14768 void XmlReporter::testGroupStarting( GroupInfo
const& groupInfo ) {
14769 StreamingReporterBase::testGroupStarting( groupInfo );
14770 m_xml.startElement(
"Group" )
14771 .writeAttribute(
"name", groupInfo.name );
14774 void XmlReporter::testCaseStarting( TestCaseInfo
const& testInfo ) {
14775 StreamingReporterBase::testCaseStarting(testInfo);
14776 m_xml.startElement(
"TestCase" )
14777 .writeAttribute(
"name",
trim( testInfo.name ) )
14778 .writeAttribute(
"description", testInfo.description )
14779 .writeAttribute(
"tags", testInfo.tagsAsString() );
14781 writeSourceInfo( testInfo.lineInfo );
14784 m_testCaseTimer.start();
14785 m_xml.ensureTagClosed();
14788 void XmlReporter::sectionStarting( SectionInfo
const& sectionInfo ) {
14789 StreamingReporterBase::sectionStarting( sectionInfo );
14790 if( m_sectionDepth++ > 0 ) {
14791 m_xml.startElement(
"Section" )
14792 .writeAttribute(
"name",
trim( sectionInfo.name ) );
14793 writeSourceInfo( sectionInfo.lineInfo );
14794 m_xml.ensureTagClosed();
14798 void XmlReporter::assertionStarting( AssertionInfo
const& ) { }
14800 bool XmlReporter::assertionEnded( AssertionStats
const& assertionStats ) {
14802 AssertionResult
const&
result = assertionStats.assertionResult;
14804 bool includeResults = m_config->includeSuccessfulResults() || !
result.isOk();
14808 for(
auto const& msg : assertionStats.infoMessages ) {
14810 m_xml.scopedElement(
"Info" )
14811 .writeText( msg.message );
14813 m_xml.scopedElement(
"Warning" )
14814 .writeText( msg.message );
14824 if(
result.hasExpression() ) {
14825 m_xml.startElement(
"Expression" )
14826 .writeAttribute(
"success",
result.succeeded() )
14827 .writeAttribute(
"type",
result.getTestMacroName() );
14829 writeSourceInfo(
result.getSourceInfo() );
14831 m_xml.scopedElement(
"Original" )
14832 .writeText(
result.getExpression() );
14833 m_xml.scopedElement(
"Expanded" )
14834 .writeText(
result.getExpandedExpression() );
14838 switch(
result.getResultType() ) {
14840 m_xml.startElement(
"Exception" );
14841 writeSourceInfo(
result.getSourceInfo() );
14842 m_xml.writeText(
result.getMessage() );
14843 m_xml.endElement();
14846 m_xml.startElement(
"FatalErrorCondition" );
14847 writeSourceInfo(
result.getSourceInfo() );
14848 m_xml.writeText(
result.getMessage() );
14849 m_xml.endElement();
14852 m_xml.scopedElement(
"Info" )
14853 .writeText(
result.getMessage() );
14859 m_xml.startElement(
"Failure" );
14860 writeSourceInfo(
result.getSourceInfo() );
14861 m_xml.writeText(
result.getMessage() );
14862 m_xml.endElement();
14868 if(
result.hasExpression() )
14869 m_xml.endElement();
14874 void XmlReporter::sectionEnded( SectionStats
const& sectionStats ) {
14875 StreamingReporterBase::sectionEnded( sectionStats );
14876 if( --m_sectionDepth > 0 ) {
14877 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResults" );
14878 e.writeAttribute(
"successes", sectionStats.assertions.passed );
14879 e.writeAttribute(
"failures", sectionStats.assertions.failed );
14880 e.writeAttribute(
"expectedFailures", sectionStats.assertions.failedButOk );
14883 e.writeAttribute(
"durationInSeconds", sectionStats.durationInSeconds );
14885 m_xml.endElement();
14889 void XmlReporter::testCaseEnded( TestCaseStats
const& testCaseStats ) {
14890 StreamingReporterBase::testCaseEnded( testCaseStats );
14891 XmlWriter::ScopedElement e = m_xml.scopedElement(
"OverallResult" );
14892 e.writeAttribute(
"success", testCaseStats.totals.assertions.allOk() );
14895 e.writeAttribute(
"durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
14897 if( !testCaseStats.stdOut.empty() )
14898 m_xml.scopedElement(
"StdOut" ).writeText(
trim( testCaseStats.stdOut ),
false );
14899 if( !testCaseStats.stdErr.empty() )
14900 m_xml.scopedElement(
"StdErr" ).writeText(
trim( testCaseStats.stdErr ),
false );
14902 m_xml.endElement();
14905 void XmlReporter::testGroupEnded( TestGroupStats
const& testGroupStats ) {
14906 StreamingReporterBase::testGroupEnded( testGroupStats );
14908 m_xml.scopedElement(
"OverallResults" )
14909 .writeAttribute(
"successes", testGroupStats.totals.assertions.passed )
14910 .writeAttribute(
"failures", testGroupStats.totals.assertions.failed )
14911 .writeAttribute(
"expectedFailures", testGroupStats.totals.assertions.failedButOk );
14912 m_xml.endElement();
14915 void XmlReporter::testRunEnded( TestRunStats
const& testRunStats ) {
14916 StreamingReporterBase::testRunEnded( testRunStats );
14917 m_xml.scopedElement(
"OverallResults" )
14918 .writeAttribute(
"successes", testRunStats.totals.assertions.passed )
14919 .writeAttribute(
"failures", testRunStats.totals.assertions.failed )
14920 .writeAttribute(
"expectedFailures", testRunStats.totals.assertions.failedButOk );
14921 m_xml.endElement();
14924 CATCH_REGISTER_REPORTER(
"xml", XmlReporter )
14928#if defined(_MSC_VER)
14929#pragma warning(pop)
14934 LeakDetector leakDetector;
14938#pragma clang diagnostic pop
14944#ifdef CATCH_CONFIG_MAIN
14949#if defined(CATCH_CONFIG_WCHAR) && defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)
14951extern "C" int wmain (
int argc,
wchar_t * argv[],
wchar_t * []) {
14954int main (
int argc,
char * argv[]) {
14957 return Catch::Session().run( argc, argv );
14963int main (
int argc,
char *
const argv[]) {
14964#if !CATCH_ARC_ENABLED
14965 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
14968 Catch::registerTestMethods();
14969 int result = Catch::Session().run( argc, (
char**)argv );
14971#if !CATCH_ARC_ENABLED
14983#if !defined(CATCH_CONFIG_IMPL_ONLY)
14985#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
14986# undef CLARA_CONFIG_MAIN
14989#if !defined(CATCH_CONFIG_DISABLE)
14992#ifdef CATCH_CONFIG_PREFIX_ALL
14994#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14995#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
14997#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
14998#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
14999#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
15000#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15001#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
15003#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
15005#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15006#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
15007#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15008#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15009#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
15011#define CATCH_CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15012#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
15013#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
15014#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15015#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
15017#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15019#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15020#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
15022#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
15025#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
15026#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )
15027#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
15028#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )
15030#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
15031#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
15032#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
15033#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
15034#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
15035#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
15036#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
15037#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15038#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15040#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
15042#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
15043#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15044#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
15045#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15046#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
15047#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
15048#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
15049#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
15050#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
15052#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
15053#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
15054#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
15055#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
15056#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
15057#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
15058#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
15059#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
15062#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
15063#define CATCH_STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__ , #__VA_ARGS__ ); CATCH_SUCCEED( #__VA_ARGS__ )
15064#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )
15066#define CATCH_STATIC_REQUIRE( ... ) CATCH_REQUIRE( __VA_ARGS__ )
15067#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )
15071#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
15072#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
15073#define CATCH_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
15074#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
15075#define CATCH_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
15076#define CATCH_AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
15077#define CATCH_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
15078#define CATCH_AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
15083#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )
15084#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
15086#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )
15087#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
15088#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
15089#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15090#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )
15092#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )
15094#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15095#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )
15096#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15097#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15098#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )
15100#define CHECK_THROWS( ... ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15101#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
15102#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
15103#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15104#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
15106#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15108#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15109#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
15111#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
15114#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
15115#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )
15116#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
15117#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )
15119#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
15120#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
15121#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
15122#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
15123#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
15124#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )
15125#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
15126#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15127#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
15128#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()
15130#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
15131#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15132#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )
15133#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15134#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
15135#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )
15136#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )
15137#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )
15138#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )
15140#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )
15141#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )
15142#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
15143#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
15144#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )
15145#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )
15146#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )
15147#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )
15150#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)
15151#define STATIC_REQUIRE( ... ) static_assert( __VA_ARGS__, #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )
15152#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )
15154#define STATIC_REQUIRE( ... ) REQUIRE( __VA_ARGS__ )
15155#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )
15160#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
15163#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
15164#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
15166#define GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Given: " << desc )
15167#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )
15168#define WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " When: " << desc )
15169#define AND_WHEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )
15170#define THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " Then: " << desc )
15171#define AND_THEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( " And: " << desc )
15179#ifdef CATCH_CONFIG_PREFIX_ALL
15181#define CATCH_REQUIRE( ... ) (void)(0)
15182#define CATCH_REQUIRE_FALSE( ... ) (void)(0)
15184#define CATCH_REQUIRE_THROWS( ... ) (void)(0)
15185#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
15186#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
15187#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15188#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
15190#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)
15192#define CATCH_CHECK( ... ) (void)(0)
15193#define CATCH_CHECK_FALSE( ... ) (void)(0)
15194#define CATCH_CHECKED_IF( ... ) if (__VA_ARGS__)
15195#define CATCH_CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
15196#define CATCH_CHECK_NOFAIL( ... ) (void)(0)
15198#define CATCH_CHECK_THROWS( ... ) (void)(0)
15199#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
15200#define CATCH_CHECK_THROWS_WITH( expr, matcher ) (void)(0)
15201#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15202#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
15204#define CATCH_CHECK_NOTHROW( ... ) (void)(0)
15206#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15207#define CATCH_CHECK_THAT( arg, matcher ) (void)(0)
15209#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)
15212#define CATCH_INFO( msg ) (void)(0)
15213#define CATCH_UNSCOPED_INFO( msg ) (void)(0)
15214#define CATCH_WARN( msg ) (void)(0)
15215#define CATCH_CAPTURE( msg ) (void)(0)
15217#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15218#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15219#define CATCH_METHOD_AS_TEST_CASE( method, ... )
15220#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)
15221#define CATCH_SECTION( ... )
15222#define CATCH_DYNAMIC_SECTION( ... )
15223#define CATCH_FAIL( ... ) (void)(0)
15224#define CATCH_FAIL_CHECK( ... ) (void)(0)
15225#define CATCH_SUCCEED( ... ) (void)(0)
15227#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15229#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
15230#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
15231#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
15232#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
15233#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
15234#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15235#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15236#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15237#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15239#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
15240#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
15241#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
15242#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
15243#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15244#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )
15245#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15246#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15250#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15251#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
15252#define CATCH_GIVEN( desc )
15253#define CATCH_AND_GIVEN( desc )
15254#define CATCH_WHEN( desc )
15255#define CATCH_AND_WHEN( desc )
15256#define CATCH_THEN( desc )
15257#define CATCH_AND_THEN( desc )
15259#define CATCH_STATIC_REQUIRE( ... ) (void)(0)
15260#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)
15265#define REQUIRE( ... ) (void)(0)
15266#define REQUIRE_FALSE( ... ) (void)(0)
15268#define REQUIRE_THROWS( ... ) (void)(0)
15269#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)
15270#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)
15271#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15272#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
15274#define REQUIRE_NOTHROW( ... ) (void)(0)
15276#define CHECK( ... ) (void)(0)
15277#define CHECK_FALSE( ... ) (void)(0)
15278#define CHECKED_IF( ... ) if (__VA_ARGS__)
15279#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))
15280#define CHECK_NOFAIL( ... ) (void)(0)
15282#define CHECK_THROWS( ... ) (void)(0)
15283#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)
15284#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)
15285#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15286#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)
15288#define CHECK_NOTHROW( ... ) (void)(0)
15290#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)
15291#define CHECK_THAT( arg, matcher ) (void)(0)
15293#define REQUIRE_THAT( arg, matcher ) (void)(0)
15296#define INFO( msg ) (void)(0)
15297#define UNSCOPED_INFO( msg ) (void)(0)
15298#define WARN( msg ) (void)(0)
15299#define CAPTURE( msg ) (void)(0)
15301#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15302#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15303#define METHOD_AS_TEST_CASE( method, ... )
15304#define REGISTER_TEST_CASE( Function, ... ) (void)(0)
15305#define SECTION( ... )
15306#define DYNAMIC_SECTION( ... )
15307#define FAIL( ... ) (void)(0)
15308#define FAIL_CHECK( ... ) (void)(0)
15309#define SUCCEED( ... ) (void)(0)
15310#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))
15312#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR
15313#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)
15314#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)
15315#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)
15316#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )
15317#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
15318#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
15319#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15320#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15322#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )
15323#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )
15324#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )
15325#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )
15326#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
15327#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )
15328#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15329#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )
15332#define STATIC_REQUIRE( ... ) (void)(0)
15333#define STATIC_REQUIRE_FALSE( ... ) (void)(0)
15337#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
15340#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )
15341#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )
15343#define GIVEN( desc )
15344#define AND_GIVEN( desc )
15345#define WHEN( desc )
15346#define AND_WHEN( desc )
15347#define THEN( desc )
15348#define AND_THEN( desc )
15361# pragma warning(pop)
15363# pragma clang diagnostic pop
15365#elif defined __GNUC__
15366# pragma GCC diagnostic pop