1 /* 2 * Catch v1.9.6 3 * Generated: 2017-06-27 12:19:54.557875 4 * ---------------------------------------------------------- 5 * This file has been merged from multiple headers. Please don't edit it directly 6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved. 7 * 8 * Distributed under the Boost Software License, Version 1.0. (See accompanying 9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 10 */ 11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 13 14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED 15 16 #ifdef __clang__ 17 # pragma clang system_header 18 #elif defined __GNUC__ 19 # pragma GCC system_header 20 #endif 21 22 // #included from: internal/catch_suppress_warnings.h 23 24 #ifdef __clang__ 25 # ifdef __ICC // icpc defines the __clang__ macro 26 # pragma warning(push) 27 # pragma warning(disable: 161 1682) 28 # else // __ICC 29 # pragma clang diagnostic ignored "-Wglobal-constructors" 30 # pragma clang diagnostic ignored "-Wvariadic-macros" 31 # pragma clang diagnostic ignored "-Wc99-extensions" 32 # pragma clang diagnostic ignored "-Wunused-variable" 33 # pragma clang diagnostic push 34 # pragma clang diagnostic ignored "-Wpadded" 35 # pragma clang diagnostic ignored "-Wc++98-compat" 36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 37 # pragma clang diagnostic ignored "-Wswitch-enum" 38 # pragma clang diagnostic ignored "-Wcovered-switch-default" 39 # endif 40 #elif defined __GNUC__ 41 # pragma GCC diagnostic ignored "-Wvariadic-macros" 42 # pragma GCC diagnostic ignored "-Wunused-variable" 43 # pragma GCC diagnostic ignored "-Wparentheses" 44 45 # pragma GCC diagnostic push 46 # pragma GCC diagnostic ignored "-Wpadded" 47 #endif 48 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER) 49 # define CATCH_IMPL 50 #endif 51 52 #ifdef CATCH_IMPL 53 # ifndef CLARA_CONFIG_MAIN 54 # define CLARA_CONFIG_MAIN_NOT_DEFINED 55 # define CLARA_CONFIG_MAIN 56 # endif 57 #endif 58 59 // #included from: internal/catch_notimplemented_exception.h 60 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED 61 62 // #included from: catch_common.h 63 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED 64 65 // #included from: catch_compiler_capabilities.h 66 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED 67 68 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler 69 // The following features are defined: 70 // 71 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported? 72 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported? 73 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods 74 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported? 75 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported 76 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported? 77 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported? 78 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) 79 // CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported? 80 // CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported? 81 82 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported? 83 84 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported? 85 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported? 86 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported? 87 // CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported? 88 // **************** 89 // Note to maintainers: if new toggles are added please document them 90 // in configuration.md, too 91 // **************** 92 93 // In general each macro has a _NO_<feature name> form 94 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature. 95 // Many features, at point of detection, define an _INTERNAL_ macro, so they 96 // can be combined, en-mass, with the _NO_ forms later. 97 98 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11 99 100 #ifdef __cplusplus 101 102 # if __cplusplus >= 201103L 103 # define CATCH_CPP11_OR_GREATER 104 # endif 105 106 # if __cplusplus >= 201402L 107 # define CATCH_CPP14_OR_GREATER 108 # endif 109 110 #endif 111 112 #ifdef __clang__ 113 114 # if __has_feature(cxx_nullptr) 115 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR 116 # endif 117 118 # if __has_feature(cxx_noexcept) 119 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT 120 # endif 121 122 # if defined(CATCH_CPP11_OR_GREATER) 123 # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 124 _Pragma( "clang diagnostic push" ) \ 125 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) 126 # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ 127 _Pragma( "clang diagnostic pop" ) 128 129 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 130 _Pragma( "clang diagnostic push" ) \ 131 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" ) 132 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 133 _Pragma( "clang diagnostic pop" ) 134 # endif 135 136 #endif // __clang__ 137 138 //////////////////////////////////////////////////////////////////////////////// 139 // We know some environments not to support full POSIX signals 140 #if defined(__CYGWIN__) || defined(__QNX__) 141 142 # if !defined(CATCH_CONFIG_POSIX_SIGNALS) 143 # define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS 144 # endif 145 146 #endif 147 148 //////////////////////////////////////////////////////////////////////////////// 149 // Cygwin 150 #ifdef __CYGWIN__ 151 152 // Required for some versions of Cygwin to declare gettimeofday 153 // see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin 154 # define _BSD_SOURCE 155 156 #endif // __CYGWIN__ 157 158 //////////////////////////////////////////////////////////////////////////////// 159 // Borland 160 #ifdef __BORLANDC__ 161 162 #endif // __BORLANDC__ 163 164 //////////////////////////////////////////////////////////////////////////////// 165 // EDG 166 #ifdef __EDG_VERSION__ 167 168 #endif // __EDG_VERSION__ 169 170 //////////////////////////////////////////////////////////////////////////////// 171 // Digital Mars 172 #ifdef __DMC__ 173 174 #endif // __DMC__ 175 176 //////////////////////////////////////////////////////////////////////////////// 177 // GCC 178 #ifdef __GNUC__ 179 180 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) 181 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR 182 # endif 183 184 // - otherwise more recent versions define __cplusplus >= 201103L 185 // and will get picked up below 186 187 #endif // __GNUC__ 188 189 //////////////////////////////////////////////////////////////////////////////// 190 // Visual C++ 191 #ifdef _MSC_VER 192 193 #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH 194 195 #if (_MSC_VER >= 1600) 196 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR 197 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR 198 #endif 199 200 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) 201 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT 202 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 203 #define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE 204 #define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS 205 #endif 206 207 #endif // _MSC_VER 208 209 //////////////////////////////////////////////////////////////////////////////// 210 211 // Use variadic macros if the compiler supports them 212 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \ 213 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \ 214 ( defined __GNUC__ && __GNUC__ >= 3 ) || \ 215 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L ) 216 217 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS 218 219 #endif 220 221 // Use __COUNTER__ if the compiler supports it 222 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \ 223 ( defined __GNUC__ && ( __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 )) ) || \ 224 ( defined __clang__ && __clang_major__ >= 3 ) 225 226 #define CATCH_INTERNAL_CONFIG_COUNTER 227 228 #endif 229 230 //////////////////////////////////////////////////////////////////////////////// 231 // C++ language feature support 232 233 // catch all support for C++11 234 #if defined(CATCH_CPP11_OR_GREATER) 235 236 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) 237 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR 238 # endif 239 240 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT 241 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT 242 # endif 243 244 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 245 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 246 # endif 247 248 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM 249 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM 250 # endif 251 252 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE 253 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE 254 # endif 255 256 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS 257 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS 258 # endif 259 260 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) 261 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG 262 # endif 263 264 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) 265 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE 266 # endif 267 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) 268 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR 269 # endif 270 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) 271 # define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE 272 # endif 273 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) 274 # define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS 275 # endif 276 277 #endif // __cplusplus >= 201103L 278 279 // Now set the actual defines based on the above + anything the user has configured 280 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11) 281 # define CATCH_CONFIG_CPP11_NULLPTR 282 #endif 283 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11) 284 # define CATCH_CONFIG_CPP11_NOEXCEPT 285 #endif 286 #if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11) 287 # define CATCH_CONFIG_CPP11_GENERATED_METHODS 288 #endif 289 #if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11) 290 # define CATCH_CONFIG_CPP11_IS_ENUM 291 #endif 292 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11) 293 # define CATCH_CONFIG_CPP11_TUPLE 294 #endif 295 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS) 296 # define CATCH_CONFIG_VARIADIC_MACROS 297 #endif 298 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11) 299 # define CATCH_CONFIG_CPP11_LONG_LONG 300 #endif 301 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11) 302 # define CATCH_CONFIG_CPP11_OVERRIDE 303 #endif 304 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11) 305 # define CATCH_CONFIG_CPP11_UNIQUE_PTR 306 #endif 307 // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for 308 // analytics) because, at time of writing, __COUNTER__ is not properly handled by it. 309 // This does not affect compilation 310 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__) 311 # define CATCH_CONFIG_COUNTER 312 #endif 313 #if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11) 314 # define CATCH_CONFIG_CPP11_SHUFFLE 315 #endif 316 # if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11) 317 # define CATCH_CONFIG_CPP11_TYPE_TRAITS 318 # endif 319 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) 320 # define CATCH_CONFIG_WINDOWS_SEH 321 #endif 322 // This is set by default, because we assume that unix compilers are posix-signal-compatible by default. 323 #if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS) 324 # define CATCH_CONFIG_POSIX_SIGNALS 325 #endif 326 327 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) 328 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS 329 # define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS 330 #endif 331 #if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS) 332 # define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS 333 # define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 334 #endif 335 336 // noexcept support: 337 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT) 338 # define CATCH_NOEXCEPT noexcept 339 # define CATCH_NOEXCEPT_IS(x) noexcept(x) 340 #else 341 # define CATCH_NOEXCEPT throw() 342 # define CATCH_NOEXCEPT_IS(x) 343 #endif 344 345 // nullptr support 346 #ifdef CATCH_CONFIG_CPP11_NULLPTR 347 # define CATCH_NULL nullptr 348 #else 349 # define CATCH_NULL NULL 350 #endif 351 352 // override support 353 #ifdef CATCH_CONFIG_CPP11_OVERRIDE 354 # define CATCH_OVERRIDE override 355 #else 356 # define CATCH_OVERRIDE 357 #endif 358 359 // unique_ptr support 360 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR 361 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T> 362 #else 363 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T> 364 #endif 365 366 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line 367 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) 368 #ifdef CATCH_CONFIG_COUNTER 369 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ ) 370 #else 371 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ ) 372 #endif 373 374 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr 375 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr ) 376 377 #include <sstream> 378 #include <algorithm> 379 380 namespace Catch { 381 382 struct IConfig; 383 384 struct CaseSensitive { enum Choice { 385 Yes, 386 No 387 }; }; 388 389 class NonCopyable { 390 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 391 NonCopyable( NonCopyable const& ) = delete; 392 NonCopyable( NonCopyable && ) = delete; 393 NonCopyable& operator = ( NonCopyable const& ) = delete; 394 NonCopyable& operator = ( NonCopyable && ) = delete; 395 #else 396 NonCopyable( NonCopyable const& info ); 397 NonCopyable& operator = ( NonCopyable const& ); 398 #endif 399 400 protected: NonCopyable()401 NonCopyable() {} 402 virtual ~NonCopyable(); 403 }; 404 405 class SafeBool { 406 public: 407 typedef void (SafeBool::*type)() const; 408 makeSafe(bool value)409 static type makeSafe( bool value ) { 410 return value ? &SafeBool::trueValue : 0; 411 } 412 private: trueValue()413 void trueValue() const {} 414 }; 415 416 template<typename ContainerT> deleteAll(ContainerT & container)417 inline void deleteAll( ContainerT& container ) { 418 typename ContainerT::const_iterator it = container.begin(); 419 typename ContainerT::const_iterator itEnd = container.end(); 420 for(; it != itEnd; ++it ) 421 delete *it; 422 } 423 template<typename AssociativeContainerT> deleteAllValues(AssociativeContainerT & container)424 inline void deleteAllValues( AssociativeContainerT& container ) { 425 typename AssociativeContainerT::const_iterator it = container.begin(); 426 typename AssociativeContainerT::const_iterator itEnd = container.end(); 427 for(; it != itEnd; ++it ) 428 delete it->second; 429 } 430 431 bool startsWith( std::string const& s, std::string const& prefix ); 432 bool startsWith( std::string const& s, char prefix ); 433 bool endsWith( std::string const& s, std::string const& suffix ); 434 bool endsWith( std::string const& s, char suffix ); 435 bool contains( std::string const& s, std::string const& infix ); 436 void toLowerInPlace( std::string& s ); 437 std::string toLower( std::string const& s ); 438 std::string trim( std::string const& str ); 439 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ); 440 441 struct pluralise { 442 pluralise( std::size_t count, std::string const& label ); 443 444 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ); 445 446 std::size_t m_count; 447 std::string m_label; 448 }; 449 450 struct SourceLineInfo { 451 452 SourceLineInfo(); 453 SourceLineInfo( char const* _file, std::size_t _line ); 454 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 455 SourceLineInfo(SourceLineInfo const& other) = default; 456 SourceLineInfo( SourceLineInfo && ) = default; 457 SourceLineInfo& operator = ( SourceLineInfo const& ) = default; 458 SourceLineInfo& operator = ( SourceLineInfo && ) = default; 459 # endif 460 bool empty() const; 461 bool operator == ( SourceLineInfo const& other ) const; 462 bool operator < ( SourceLineInfo const& other ) const; 463 464 char const* file; 465 std::size_t line; 466 }; 467 468 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ); 469 470 // This is just here to avoid compiler warnings with macro constants and boolean literals isTrue(bool value)471 inline bool isTrue( bool value ){ return value; } alwaysTrue()472 inline bool alwaysTrue() { return true; } alwaysFalse()473 inline bool alwaysFalse() { return false; } 474 475 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ); 476 477 void seedRng( IConfig const& config ); 478 unsigned int rngSeed(); 479 480 // Use this in variadic streaming macros to allow 481 // >> +StreamEndStop 482 // as well as 483 // >> stuff +StreamEndStop 484 struct StreamEndStop { 485 std::string operator+() { 486 return std::string(); 487 } 488 }; 489 template<typename T> 490 T const& operator + ( T const& value, StreamEndStop ) { 491 return value; 492 } 493 } 494 495 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) ) 496 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO ); 497 498 namespace Catch { 499 500 class NotImplementedException : public std::exception 501 { 502 public: 503 NotImplementedException( SourceLineInfo const& lineInfo ); NotImplementedException(NotImplementedException const &)504 NotImplementedException( NotImplementedException const& ) {} 505 ~NotImplementedException()506 virtual ~NotImplementedException() CATCH_NOEXCEPT {} 507 508 virtual const char* what() const CATCH_NOEXCEPT; 509 510 private: 511 std::string m_what; 512 SourceLineInfo m_lineInfo; 513 }; 514 515 } // end namespace Catch 516 517 /////////////////////////////////////////////////////////////////////////////// 518 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO ) 519 520 // #included from: internal/catch_context.h 521 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED 522 523 // #included from: catch_interfaces_generators.h 524 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED 525 526 #include <string> 527 528 namespace Catch { 529 530 struct IGeneratorInfo { 531 virtual ~IGeneratorInfo(); 532 virtual bool moveNext() = 0; 533 virtual std::size_t getCurrentIndex() const = 0; 534 }; 535 536 struct IGeneratorsForTest { 537 virtual ~IGeneratorsForTest(); 538 539 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0; 540 virtual bool moveNext() = 0; 541 }; 542 543 IGeneratorsForTest* createGeneratorsForTest(); 544 545 } // end namespace Catch 546 547 // #included from: catch_ptr.hpp 548 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED 549 550 #ifdef __clang__ 551 # pragma clang diagnostic push 552 # pragma clang diagnostic ignored "-Wpadded" 553 #endif 554 555 namespace Catch { 556 557 // An intrusive reference counting smart pointer. 558 // T must implement addRef() and release() methods 559 // typically implementing the IShared interface 560 template<typename T> 561 class Ptr { 562 public: Ptr()563 Ptr() : m_p( CATCH_NULL ){} Ptr(T * p)564 Ptr( T* p ) : m_p( p ){ 565 if( m_p ) 566 m_p->addRef(); 567 } Ptr(Ptr const & other)568 Ptr( Ptr const& other ) : m_p( other.m_p ){ 569 if( m_p ) 570 m_p->addRef(); 571 } ~Ptr()572 ~Ptr(){ 573 if( m_p ) 574 m_p->release(); 575 } reset()576 void reset() { 577 if( m_p ) 578 m_p->release(); 579 m_p = CATCH_NULL; 580 } 581 Ptr& operator = ( T* p ){ 582 Ptr temp( p ); 583 swap( temp ); 584 return *this; 585 } 586 Ptr& operator = ( Ptr const& other ){ 587 Ptr temp( other ); 588 swap( temp ); 589 return *this; 590 } swap(Ptr & other)591 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); } get()592 T* get() const{ return m_p; } 593 T& operator*() const { return *m_p; } 594 T* operator->() const { return m_p; } 595 bool operator !() const { return m_p == CATCH_NULL; } type()596 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); } 597 598 private: 599 T* m_p; 600 }; 601 602 struct IShared : NonCopyable { 603 virtual ~IShared(); 604 virtual void addRef() const = 0; 605 virtual void release() const = 0; 606 }; 607 608 template<typename T = IShared> 609 struct SharedImpl : T { 610 SharedImplSharedImpl611 SharedImpl() : m_rc( 0 ){} 612 addRefSharedImpl613 virtual void addRef() const { 614 ++m_rc; 615 } releaseSharedImpl616 virtual void release() const { 617 if( --m_rc == 0 ) 618 delete this; 619 } 620 621 mutable unsigned int m_rc; 622 }; 623 624 } // end namespace Catch 625 626 #ifdef __clang__ 627 # pragma clang diagnostic pop 628 #endif 629 630 namespace Catch { 631 632 class TestCase; 633 class Stream; 634 struct IResultCapture; 635 struct IRunner; 636 struct IGeneratorsForTest; 637 struct IConfig; 638 639 struct IContext 640 { 641 virtual ~IContext(); 642 643 virtual IResultCapture* getResultCapture() = 0; 644 virtual IRunner* getRunner() = 0; 645 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0; 646 virtual bool advanceGeneratorsForCurrentTest() = 0; 647 virtual Ptr<IConfig const> getConfig() const = 0; 648 }; 649 650 struct IMutableContext : IContext 651 { 652 virtual ~IMutableContext(); 653 virtual void setResultCapture( IResultCapture* resultCapture ) = 0; 654 virtual void setRunner( IRunner* runner ) = 0; 655 virtual void setConfig( Ptr<IConfig const> const& config ) = 0; 656 }; 657 658 IContext& getCurrentContext(); 659 IMutableContext& getCurrentMutableContext(); 660 void cleanUpContext(); 661 Stream createStream( std::string const& streamName ); 662 663 } 664 665 // #included from: internal/catch_test_registry.hpp 666 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED 667 668 // #included from: catch_interfaces_testcase.h 669 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED 670 671 #include <vector> 672 673 namespace Catch { 674 675 class TestSpec; 676 677 struct ITestCase : IShared { 678 virtual void invoke () const = 0; 679 protected: 680 virtual ~ITestCase(); 681 }; 682 683 class TestCase; 684 struct IConfig; 685 686 struct ITestCaseRegistry { 687 virtual ~ITestCaseRegistry(); 688 virtual std::vector<TestCase> const& getAllTests() const = 0; 689 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0; 690 }; 691 692 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ); 693 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ); 694 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ); 695 696 } 697 698 namespace Catch { 699 700 template<typename C> 701 class MethodTestCase : public SharedImpl<ITestCase> { 702 703 public: MethodTestCase(void (C::* method)())704 MethodTestCase( void (C::*method)() ) : m_method( method ) {} 705 invoke()706 virtual void invoke() const { 707 C obj; 708 (obj.*m_method)(); 709 } 710 711 private: ~MethodTestCase()712 virtual ~MethodTestCase() {} 713 714 void (C::*m_method)(); 715 }; 716 717 typedef void(*TestFunction)(); 718 719 struct NameAndDesc { 720 NameAndDesc( const char* _name = "", const char* _description= "" ) nameNameAndDesc721 : name( _name ), description( _description ) 722 {} 723 724 const char* name; 725 const char* description; 726 }; 727 728 void registerTestCase 729 ( ITestCase* testCase, 730 char const* className, 731 NameAndDesc const& nameAndDesc, 732 SourceLineInfo const& lineInfo ); 733 734 struct AutoReg { 735 736 AutoReg 737 ( TestFunction function, 738 SourceLineInfo const& lineInfo, 739 NameAndDesc const& nameAndDesc ); 740 741 template<typename C> AutoRegAutoReg742 AutoReg 743 ( void (C::*method)(), 744 char const* className, 745 NameAndDesc const& nameAndDesc, 746 SourceLineInfo const& lineInfo ) { 747 748 registerTestCase 749 ( new MethodTestCase<C>( method ), 750 className, 751 nameAndDesc, 752 lineInfo ); 753 } 754 755 ~AutoReg(); 756 757 private: 758 AutoReg( AutoReg const& ); 759 void operator= ( AutoReg const& ); 760 }; 761 762 void registerTestCaseFunction 763 ( TestFunction function, 764 SourceLineInfo const& lineInfo, 765 NameAndDesc const& nameAndDesc ); 766 767 } // end namespace Catch 768 769 #ifdef CATCH_CONFIG_VARIADIC_MACROS 770 /////////////////////////////////////////////////////////////////////////////// 771 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \ 772 static void TestName(); \ 773 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 774 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \ 775 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ 776 static void TestName() 777 #define INTERNAL_CATCH_TESTCASE( ... ) \ 778 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ ) 779 780 /////////////////////////////////////////////////////////////////////////////// 781 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \ 782 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 783 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \ 784 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 785 786 /////////////////////////////////////////////////////////////////////////////// 787 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\ 788 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 789 namespace{ \ 790 struct TestName : ClassName{ \ 791 void test(); \ 792 }; \ 793 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \ 794 } \ 795 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ 796 void TestName::test() 797 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \ 798 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ ) 799 800 /////////////////////////////////////////////////////////////////////////////// 801 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \ 802 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 803 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \ 804 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 805 806 #else 807 /////////////////////////////////////////////////////////////////////////////// 808 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \ 809 static void TestName(); \ 810 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 811 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\ 812 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ 813 static void TestName() 814 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \ 815 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc ) 816 817 /////////////////////////////////////////////////////////////////////////////// 818 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \ 819 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 820 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \ 821 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 822 823 /////////////////////////////////////////////////////////////////////////////// 824 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\ 825 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 826 namespace{ \ 827 struct TestCaseName : ClassName{ \ 828 void test(); \ 829 }; \ 830 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \ 831 } \ 832 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \ 833 void TestCaseName::test() 834 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\ 835 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc ) 836 837 /////////////////////////////////////////////////////////////////////////////// 838 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \ 839 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \ 840 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \ 841 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 842 843 #endif 844 845 // #included from: internal/catch_capture.hpp 846 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED 847 848 // #included from: catch_result_builder.h 849 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED 850 851 // #included from: catch_result_type.h 852 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED 853 854 namespace Catch { 855 856 // ResultWas::OfType enum 857 struct ResultWas { enum OfType { 858 Unknown = -1, 859 Ok = 0, 860 Info = 1, 861 Warning = 2, 862 863 FailureBit = 0x10, 864 865 ExpressionFailed = FailureBit | 1, 866 ExplicitFailure = FailureBit | 2, 867 868 Exception = 0x100 | FailureBit, 869 870 ThrewException = Exception | 1, 871 DidntThrowException = Exception | 2, 872 873 FatalErrorCondition = 0x200 | FailureBit 874 875 }; }; 876 isOk(ResultWas::OfType resultType)877 inline bool isOk( ResultWas::OfType resultType ) { 878 return ( resultType & ResultWas::FailureBit ) == 0; 879 } isJustInfo(int flags)880 inline bool isJustInfo( int flags ) { 881 return flags == ResultWas::Info; 882 } 883 884 // ResultDisposition::Flags enum 885 struct ResultDisposition { enum Flags { 886 Normal = 0x01, 887 888 ContinueOnFailure = 0x02, // Failures fail test, but execution continues 889 FalseTest = 0x04, // Prefix expression with ! 890 SuppressFail = 0x08 // Failures are reported but do not fail the test 891 }; }; 892 893 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) { 894 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) ); 895 } 896 shouldContinueOnFailure(int flags)897 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; } isFalseTest(int flags)898 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; } shouldSuppressFailure(int flags)899 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; } 900 901 } // end namespace Catch 902 903 // #included from: catch_assertionresult.h 904 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED 905 906 #include <string> 907 908 namespace Catch { 909 910 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison; 911 912 struct DecomposedExpression 913 { ~DecomposedExpressionDecomposedExpression914 virtual ~DecomposedExpression() {} isBinaryExpressionDecomposedExpression915 virtual bool isBinaryExpression() const { 916 return false; 917 } 918 virtual void reconstructExpression( std::string& dest ) const = 0; 919 920 // Only simple binary comparisons can be decomposed. 921 // If more complex check is required then wrap sub-expressions in parentheses. 922 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& ); 923 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& ); 924 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& ); 925 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& ); 926 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& ); 927 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& ); 928 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& ); 929 930 private: 931 DecomposedExpression& operator = (DecomposedExpression const&); 932 }; 933 934 struct AssertionInfo 935 { AssertionInfoAssertionInfo936 AssertionInfo() {} 937 AssertionInfo( char const * _macroName, 938 SourceLineInfo const& _lineInfo, 939 char const * _capturedExpression, 940 ResultDisposition::Flags _resultDisposition, 941 char const * _secondArg = ""); 942 943 char const * macroName; 944 SourceLineInfo lineInfo; 945 char const * capturedExpression; 946 ResultDisposition::Flags resultDisposition; 947 char const * secondArg; 948 }; 949 950 struct AssertionResultData 951 { AssertionResultDataAssertionResultData952 AssertionResultData() : decomposedExpression( CATCH_NULL ) 953 , resultType( ResultWas::Unknown ) 954 , negated( false ) 955 , parenthesized( false ) {} 956 negateAssertionResultData957 void negate( bool parenthesize ) { 958 negated = !negated; 959 parenthesized = parenthesize; 960 if( resultType == ResultWas::Ok ) 961 resultType = ResultWas::ExpressionFailed; 962 else if( resultType == ResultWas::ExpressionFailed ) 963 resultType = ResultWas::Ok; 964 } 965 reconstructExpressionAssertionResultData966 std::string const& reconstructExpression() const { 967 if( decomposedExpression != CATCH_NULL ) { 968 decomposedExpression->reconstructExpression( reconstructedExpression ); 969 if( parenthesized ) { 970 reconstructedExpression.insert( 0, 1, '(' ); 971 reconstructedExpression.append( 1, ')' ); 972 } 973 if( negated ) { 974 reconstructedExpression.insert( 0, 1, '!' ); 975 } 976 decomposedExpression = CATCH_NULL; 977 } 978 return reconstructedExpression; 979 } 980 981 mutable DecomposedExpression const* decomposedExpression; 982 mutable std::string reconstructedExpression; 983 std::string message; 984 ResultWas::OfType resultType; 985 bool negated; 986 bool parenthesized; 987 }; 988 989 class AssertionResult { 990 public: 991 AssertionResult(); 992 AssertionResult( AssertionInfo const& info, AssertionResultData const& data ); 993 ~AssertionResult(); 994 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 995 AssertionResult( AssertionResult const& ) = default; 996 AssertionResult( AssertionResult && ) = default; 997 AssertionResult& operator = ( AssertionResult const& ) = default; 998 AssertionResult& operator = ( AssertionResult && ) = default; 999 # endif 1000 1001 bool isOk() const; 1002 bool succeeded() const; 1003 ResultWas::OfType getResultType() const; 1004 bool hasExpression() const; 1005 bool hasMessage() const; 1006 std::string getExpression() const; 1007 std::string getExpressionInMacro() const; 1008 bool hasExpandedExpression() const; 1009 std::string getExpandedExpression() const; 1010 std::string getMessage() const; 1011 SourceLineInfo getSourceInfo() const; 1012 std::string getTestMacroName() const; 1013 void discardDecomposedExpression() const; 1014 void expandDecomposedExpression() const; 1015 1016 protected: 1017 AssertionInfo m_info; 1018 AssertionResultData m_resultData; 1019 }; 1020 1021 } // end namespace Catch 1022 1023 // #included from: catch_matchers.hpp 1024 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED 1025 1026 namespace Catch { 1027 namespace Matchers { 1028 namespace Impl { 1029 1030 template<typename ArgT> struct MatchAllOf; 1031 template<typename ArgT> struct MatchAnyOf; 1032 template<typename ArgT> struct MatchNotOf; 1033 1034 class MatcherUntypedBase { 1035 public: toString()1036 std::string toString() const { 1037 if( m_cachedToString.empty() ) 1038 m_cachedToString = describe(); 1039 return m_cachedToString; 1040 } 1041 1042 protected: 1043 virtual ~MatcherUntypedBase(); 1044 virtual std::string describe() const = 0; 1045 mutable std::string m_cachedToString; 1046 private: 1047 MatcherUntypedBase& operator = ( MatcherUntypedBase const& ); 1048 }; 1049 1050 template<typename ObjectT> 1051 struct MatcherMethod { 1052 virtual bool match( ObjectT const& arg ) const = 0; 1053 }; 1054 template<typename PtrT> 1055 struct MatcherMethod<PtrT*> { 1056 virtual bool match( PtrT* arg ) const = 0; 1057 }; 1058 1059 template<typename ObjectT, typename ComparatorT = ObjectT> 1060 struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> { 1061 1062 MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const; 1063 MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const; 1064 MatchNotOf<ComparatorT> operator ! () const; 1065 }; 1066 1067 template<typename ArgT> 1068 struct MatchAllOf : MatcherBase<ArgT> { 1069 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { 1070 for( std::size_t i = 0; i < m_matchers.size(); ++i ) { 1071 if (!m_matchers[i]->match(arg)) 1072 return false; 1073 } 1074 return true; 1075 } 1076 virtual std::string describe() const CATCH_OVERRIDE { 1077 std::string description; 1078 description.reserve( 4 + m_matchers.size()*32 ); 1079 description += "( "; 1080 for( std::size_t i = 0; i < m_matchers.size(); ++i ) { 1081 if( i != 0 ) 1082 description += " and "; 1083 description += m_matchers[i]->toString(); 1084 } 1085 description += " )"; 1086 return description; 1087 } 1088 1089 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) { 1090 m_matchers.push_back( &other ); 1091 return *this; 1092 } 1093 1094 std::vector<MatcherBase<ArgT> const*> m_matchers; 1095 }; 1096 template<typename ArgT> 1097 struct MatchAnyOf : MatcherBase<ArgT> { 1098 1099 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { 1100 for( std::size_t i = 0; i < m_matchers.size(); ++i ) { 1101 if (m_matchers[i]->match(arg)) 1102 return true; 1103 } 1104 return false; 1105 } 1106 virtual std::string describe() const CATCH_OVERRIDE { 1107 std::string description; 1108 description.reserve( 4 + m_matchers.size()*32 ); 1109 description += "( "; 1110 for( std::size_t i = 0; i < m_matchers.size(); ++i ) { 1111 if( i != 0 ) 1112 description += " or "; 1113 description += m_matchers[i]->toString(); 1114 } 1115 description += " )"; 1116 return description; 1117 } 1118 1119 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) { 1120 m_matchers.push_back( &other ); 1121 return *this; 1122 } 1123 1124 std::vector<MatcherBase<ArgT> const*> m_matchers; 1125 }; 1126 1127 template<typename ArgT> 1128 struct MatchNotOf : MatcherBase<ArgT> { 1129 1130 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {} 1131 1132 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE { 1133 return !m_underlyingMatcher.match( arg ); 1134 } 1135 1136 virtual std::string describe() const CATCH_OVERRIDE { 1137 return "not " + m_underlyingMatcher.toString(); 1138 } 1139 MatcherBase<ArgT> const& m_underlyingMatcher; 1140 }; 1141 1142 template<typename ObjectT, typename ComparatorT> 1143 MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const { 1144 return MatchAllOf<ComparatorT>() && *this && other; 1145 } 1146 template<typename ObjectT, typename ComparatorT> 1147 MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const { 1148 return MatchAnyOf<ComparatorT>() || *this || other; 1149 } 1150 template<typename ObjectT, typename ComparatorT> 1151 MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const { 1152 return MatchNotOf<ComparatorT>( *this ); 1153 } 1154 1155 } // namespace Impl 1156 1157 // The following functions create the actual matcher objects. 1158 // This allows the types to be inferred 1159 // - deprecated: prefer ||, && and ! 1160 template<typename T> 1161 inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) { 1162 return Impl::MatchNotOf<T>( underlyingMatcher ); 1163 } 1164 template<typename T> 1165 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) { 1166 return Impl::MatchAllOf<T>() && m1 && m2; 1167 } 1168 template<typename T> 1169 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) { 1170 return Impl::MatchAllOf<T>() && m1 && m2 && m3; 1171 } 1172 template<typename T> 1173 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) { 1174 return Impl::MatchAnyOf<T>() || m1 || m2; 1175 } 1176 template<typename T> 1177 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) { 1178 return Impl::MatchAnyOf<T>() || m1 || m2 || m3; 1179 } 1180 1181 } // namespace Matchers 1182 1183 using namespace Matchers; 1184 using Matchers::Impl::MatcherBase; 1185 1186 } // namespace Catch 1187 1188 namespace Catch { 1189 1190 struct TestFailureException{}; 1191 1192 template<typename T> class ExpressionLhs; 1193 1194 struct CopyableStream { 1195 CopyableStream() {} 1196 CopyableStream( CopyableStream const& other ) { 1197 oss << other.oss.str(); 1198 } 1199 CopyableStream& operator=( CopyableStream const& other ) { 1200 oss.str(std::string()); 1201 oss << other.oss.str(); 1202 return *this; 1203 } 1204 std::ostringstream oss; 1205 }; 1206 1207 class ResultBuilder : public DecomposedExpression { 1208 public: 1209 ResultBuilder( char const* macroName, 1210 SourceLineInfo const& lineInfo, 1211 char const* capturedExpression, 1212 ResultDisposition::Flags resultDisposition, 1213 char const* secondArg = "" ); 1214 ~ResultBuilder(); 1215 1216 template<typename T> 1217 ExpressionLhs<T const&> operator <= ( T const& operand ); 1218 ExpressionLhs<bool> operator <= ( bool value ); 1219 1220 template<typename T> 1221 ResultBuilder& operator << ( T const& value ) { 1222 m_stream().oss << value; 1223 return *this; 1224 } 1225 1226 ResultBuilder& setResultType( ResultWas::OfType result ); 1227 ResultBuilder& setResultType( bool result ); 1228 1229 void endExpression( DecomposedExpression const& expr ); 1230 1231 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE; 1232 1233 AssertionResult build() const; 1234 AssertionResult build( DecomposedExpression const& expr ) const; 1235 1236 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal ); 1237 void captureResult( ResultWas::OfType resultType ); 1238 void captureExpression(); 1239 void captureExpectedException( std::string const& expectedMessage ); 1240 void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ); 1241 void handleResult( AssertionResult const& result ); 1242 void react(); 1243 bool shouldDebugBreak() const; 1244 bool allowThrows() const; 1245 1246 template<typename ArgT, typename MatcherT> 1247 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString ); 1248 1249 void setExceptionGuard(); 1250 void unsetExceptionGuard(); 1251 1252 private: 1253 AssertionInfo m_assertionInfo; 1254 AssertionResultData m_data; 1255 1256 static CopyableStream &m_stream() 1257 { 1258 static CopyableStream s; 1259 return s; 1260 } 1261 1262 bool m_shouldDebugBreak; 1263 bool m_shouldThrow; 1264 bool m_guardException; 1265 }; 1266 1267 } // namespace Catch 1268 1269 // Include after due to circular dependency: 1270 // #included from: catch_expression_lhs.hpp 1271 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED 1272 1273 // #included from: catch_evaluate.hpp 1274 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED 1275 1276 #ifdef _MSC_VER 1277 # pragma warning(push) 1278 # pragma warning(disable:4389) // '==' : signed/unsigned mismatch 1279 # pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform) 1280 #endif 1281 1282 #include <cstddef> 1283 1284 namespace Catch { 1285 namespace Internal { 1286 1287 enum Operator { 1288 IsEqualTo, 1289 IsNotEqualTo, 1290 IsLessThan, 1291 IsGreaterThan, 1292 IsLessThanOrEqualTo, 1293 IsGreaterThanOrEqualTo 1294 }; 1295 1296 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } }; 1297 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } }; 1298 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } }; 1299 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } }; 1300 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } }; 1301 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } }; 1302 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } }; 1303 1304 template<typename T> 1305 inline T& opCast(T const& t) { return const_cast<T&>(t); } 1306 1307 // nullptr_t support based on pull request #154 from Konstantin Baumann 1308 #ifdef CATCH_CONFIG_CPP11_NULLPTR 1309 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; } 1310 #endif // CATCH_CONFIG_CPP11_NULLPTR 1311 1312 // So the compare overloads can be operator agnostic we convey the operator as a template 1313 // enum, which is used to specialise an Evaluator for doing the comparison. 1314 template<typename T1, typename T2, Operator Op> 1315 class Evaluator{}; 1316 1317 template<typename T1, typename T2> 1318 struct Evaluator<T1, T2, IsEqualTo> { 1319 static bool evaluate( T1 const& lhs, T2 const& rhs) { 1320 return bool( opCast( lhs ) == opCast( rhs ) ); 1321 } 1322 }; 1323 template<typename T1, typename T2> 1324 struct Evaluator<T1, T2, IsNotEqualTo> { 1325 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 1326 return bool( opCast( lhs ) != opCast( rhs ) ); 1327 } 1328 }; 1329 template<typename T1, typename T2> 1330 struct Evaluator<T1, T2, IsLessThan> { 1331 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 1332 return bool( opCast( lhs ) < opCast( rhs ) ); 1333 } 1334 }; 1335 template<typename T1, typename T2> 1336 struct Evaluator<T1, T2, IsGreaterThan> { 1337 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 1338 return bool( opCast( lhs ) > opCast( rhs ) ); 1339 } 1340 }; 1341 template<typename T1, typename T2> 1342 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> { 1343 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 1344 return bool( opCast( lhs ) >= opCast( rhs ) ); 1345 } 1346 }; 1347 template<typename T1, typename T2> 1348 struct Evaluator<T1, T2, IsLessThanOrEqualTo> { 1349 static bool evaluate( T1 const& lhs, T2 const& rhs ) { 1350 return bool( opCast( lhs ) <= opCast( rhs ) ); 1351 } 1352 }; 1353 1354 template<Operator Op, typename T1, typename T2> 1355 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) { 1356 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); 1357 } 1358 1359 // This level of indirection allows us to specialise for integer types 1360 // to avoid signed/ unsigned warnings 1361 1362 // "base" overload 1363 template<Operator Op, typename T1, typename T2> 1364 bool compare( T1 const& lhs, T2 const& rhs ) { 1365 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs ); 1366 } 1367 1368 // unsigned X to int 1369 template<Operator Op> bool compare( unsigned int lhs, int rhs ) { 1370 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 1371 } 1372 template<Operator Op> bool compare( unsigned long lhs, int rhs ) { 1373 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 1374 } 1375 template<Operator Op> bool compare( unsigned char lhs, int rhs ) { 1376 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) ); 1377 } 1378 1379 // unsigned X to long 1380 template<Operator Op> bool compare( unsigned int lhs, long rhs ) { 1381 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 1382 } 1383 template<Operator Op> bool compare( unsigned long lhs, long rhs ) { 1384 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 1385 } 1386 template<Operator Op> bool compare( unsigned char lhs, long rhs ) { 1387 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) ); 1388 } 1389 1390 // int to unsigned X 1391 template<Operator Op> bool compare( int lhs, unsigned int rhs ) { 1392 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 1393 } 1394 template<Operator Op> bool compare( int lhs, unsigned long rhs ) { 1395 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 1396 } 1397 template<Operator Op> bool compare( int lhs, unsigned char rhs ) { 1398 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs ); 1399 } 1400 1401 // long to unsigned X 1402 template<Operator Op> bool compare( long lhs, unsigned int rhs ) { 1403 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1404 } 1405 template<Operator Op> bool compare( long lhs, unsigned long rhs ) { 1406 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1407 } 1408 template<Operator Op> bool compare( long lhs, unsigned char rhs ) { 1409 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1410 } 1411 1412 // pointer to long (when comparing against NULL) 1413 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) { 1414 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 1415 } 1416 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) { 1417 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 1418 } 1419 1420 // pointer to int (when comparing against NULL) 1421 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) { 1422 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 1423 } 1424 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) { 1425 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 1426 } 1427 1428 #ifdef CATCH_CONFIG_CPP11_LONG_LONG 1429 // long long to unsigned X 1430 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) { 1431 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1432 } 1433 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) { 1434 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1435 } 1436 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) { 1437 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1438 } 1439 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) { 1440 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs ); 1441 } 1442 1443 // unsigned long long to X 1444 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) { 1445 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 1446 } 1447 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) { 1448 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 1449 } 1450 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) { 1451 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 1452 } 1453 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) { 1454 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs ); 1455 } 1456 1457 // pointer to long long (when comparing against NULL) 1458 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) { 1459 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs ); 1460 } 1461 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) { 1462 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) ); 1463 } 1464 #endif // CATCH_CONFIG_CPP11_LONG_LONG 1465 1466 #ifdef CATCH_CONFIG_CPP11_NULLPTR 1467 // pointer to nullptr_t (when comparing against nullptr) 1468 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) { 1469 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs ); 1470 } 1471 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) { 1472 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr ); 1473 } 1474 #endif // CATCH_CONFIG_CPP11_NULLPTR 1475 1476 } // end of namespace Internal 1477 } // end of namespace Catch 1478 1479 #ifdef _MSC_VER 1480 # pragma warning(pop) 1481 #endif 1482 1483 // #included from: catch_tostring.h 1484 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED 1485 1486 #include <sstream> 1487 #include <iomanip> 1488 #include <limits> 1489 #include <vector> 1490 #include <cstddef> 1491 1492 #ifdef __OBJC__ 1493 // #included from: catch_objc_arc.hpp 1494 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED 1495 1496 #import <Foundation/Foundation.h> 1497 1498 #ifdef __has_feature 1499 #define CATCH_ARC_ENABLED __has_feature(objc_arc) 1500 #else 1501 #define CATCH_ARC_ENABLED 0 1502 #endif 1503 1504 void arcSafeRelease( NSObject* obj ); 1505 id performOptionalSelector( id obj, SEL sel ); 1506 1507 #if !CATCH_ARC_ENABLED 1508 inline void arcSafeRelease( NSObject* obj ) { 1509 [obj release]; 1510 } 1511 inline id performOptionalSelector( id obj, SEL sel ) { 1512 if( [obj respondsToSelector: sel] ) 1513 return [obj performSelector: sel]; 1514 return nil; 1515 } 1516 #define CATCH_UNSAFE_UNRETAINED 1517 #define CATCH_ARC_STRONG 1518 #else 1519 inline void arcSafeRelease( NSObject* ){} 1520 inline id performOptionalSelector( id obj, SEL sel ) { 1521 #ifdef __clang__ 1522 # pragma clang diagnostic push 1523 # pragma clang diagnostic ignored "-Warc-performSelector-leaks" 1524 #endif 1525 if( [obj respondsToSelector: sel] ) 1526 return [obj performSelector: sel]; 1527 #ifdef __clang__ 1528 # pragma clang diagnostic pop 1529 #endif 1530 return nil; 1531 } 1532 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained 1533 #define CATCH_ARC_STRONG __strong 1534 #endif 1535 1536 #endif 1537 1538 #ifdef CATCH_CONFIG_CPP11_TUPLE 1539 #include <tuple> 1540 #endif 1541 1542 #ifdef CATCH_CONFIG_CPP11_IS_ENUM 1543 #include <type_traits> 1544 #endif 1545 1546 namespace Catch { 1547 1548 // Why we're here. 1549 template<typename T> 1550 std::string toString( T const& value ); 1551 1552 // Built in overloads 1553 1554 std::string toString( std::string const& value ); 1555 std::string toString( std::wstring const& value ); 1556 std::string toString( const char* const value ); 1557 std::string toString( char* const value ); 1558 std::string toString( const wchar_t* const value ); 1559 std::string toString( wchar_t* const value ); 1560 std::string toString( int value ); 1561 std::string toString( unsigned long value ); 1562 std::string toString( unsigned int value ); 1563 std::string toString( const double value ); 1564 std::string toString( const float value ); 1565 std::string toString( bool value ); 1566 std::string toString( char value ); 1567 std::string toString( signed char value ); 1568 std::string toString( unsigned char value ); 1569 1570 #ifdef CATCH_CONFIG_CPP11_LONG_LONG 1571 std::string toString( long long value ); 1572 std::string toString( unsigned long long value ); 1573 #endif 1574 1575 #ifdef CATCH_CONFIG_CPP11_NULLPTR 1576 std::string toString( std::nullptr_t ); 1577 #endif 1578 1579 #ifdef __OBJC__ 1580 std::string toString( NSString const * const& nsstring ); 1581 std::string toString( NSString * CATCH_ARC_STRONG & nsstring ); 1582 std::string toString( NSObject* const& nsObject ); 1583 #endif 1584 1585 namespace Detail { 1586 1587 extern const std::string unprintableString; 1588 1589 #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK) 1590 struct BorgType { 1591 template<typename T> BorgType( T const& ); 1592 }; 1593 1594 struct TrueType { char sizer[1]; }; 1595 struct FalseType { char sizer[2]; }; 1596 1597 TrueType& testStreamable( std::ostream& ); 1598 FalseType testStreamable( FalseType ); 1599 1600 FalseType operator<<( std::ostream const&, BorgType const& ); 1601 1602 template<typename T> 1603 struct IsStreamInsertable { 1604 static std::ostream &s; 1605 static T const&t; 1606 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) }; 1607 }; 1608 #else 1609 template<typename T> 1610 class IsStreamInsertable { 1611 template<typename SS, typename TT> 1612 static auto test(int) 1613 -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() ); 1614 1615 template<typename, typename> 1616 static auto test(...) -> std::false_type; 1617 1618 public: 1619 static const bool value = decltype(test<std::ostream,const T&>(0))::value; 1620 }; 1621 #endif 1622 1623 #if defined(CATCH_CONFIG_CPP11_IS_ENUM) 1624 template<typename T, 1625 bool IsEnum = std::is_enum<T>::value 1626 > 1627 struct EnumStringMaker 1628 { 1629 static std::string convert( T const& ) { return unprintableString; } 1630 }; 1631 1632 template<typename T> 1633 struct EnumStringMaker<T,true> 1634 { 1635 static std::string convert( T const& v ) 1636 { 1637 return ::Catch::toString( 1638 static_cast<typename std::underlying_type<T>::type>(v) 1639 ); 1640 } 1641 }; 1642 #endif 1643 template<bool C> 1644 struct StringMakerBase { 1645 #if defined(CATCH_CONFIG_CPP11_IS_ENUM) 1646 template<typename T> 1647 static std::string convert( T const& v ) 1648 { 1649 return EnumStringMaker<T>::convert( v ); 1650 } 1651 #else 1652 template<typename T> 1653 static std::string convert( T const& ) { return unprintableString; } 1654 #endif 1655 }; 1656 1657 template<> 1658 struct StringMakerBase<true> { 1659 template<typename T> 1660 static std::string convert( T const& _value ) { 1661 std::ostringstream oss; 1662 oss << _value; 1663 return oss.str(); 1664 } 1665 }; 1666 1667 std::string rawMemoryToString( const void *object, std::size_t size ); 1668 1669 template<typename T> 1670 inline std::string rawMemoryToString( const T& object ) { 1671 return rawMemoryToString( &object, sizeof(object) ); 1672 } 1673 1674 } // end namespace Detail 1675 1676 template<typename T> 1677 struct StringMaker : 1678 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {}; 1679 1680 template<typename T> 1681 struct StringMaker<T*> { 1682 template<typename U> 1683 static std::string convert( U* p ) { 1684 if( !p ) 1685 return "NULL"; 1686 else 1687 return Detail::rawMemoryToString( p ); 1688 } 1689 }; 1690 1691 template<typename R, typename C> 1692 struct StringMaker<R C::*> { 1693 static std::string convert( R C::* p ) { 1694 if( !p ) 1695 return "NULL"; 1696 else 1697 return Detail::rawMemoryToString( p ); 1698 } 1699 }; 1700 1701 namespace Detail { 1702 template<typename InputIterator> 1703 std::string rangeToString( InputIterator first, InputIterator last ); 1704 } 1705 1706 //template<typename T, typename Allocator> 1707 //struct StringMaker<std::vector<T, Allocator> > { 1708 // static std::string convert( std::vector<T,Allocator> const& v ) { 1709 // return Detail::rangeToString( v.begin(), v.end() ); 1710 // } 1711 //}; 1712 1713 template<typename T, typename Allocator> 1714 std::string toString( std::vector<T,Allocator> const& v ) { 1715 return Detail::rangeToString( v.begin(), v.end() ); 1716 } 1717 1718 #ifdef CATCH_CONFIG_CPP11_TUPLE 1719 1720 // toString for tuples 1721 namespace TupleDetail { 1722 template< 1723 typename Tuple, 1724 std::size_t N = 0, 1725 bool = (N < std::tuple_size<Tuple>::value) 1726 > 1727 struct ElementPrinter { 1728 static void print( const Tuple& tuple, std::ostream& os ) 1729 { 1730 os << ( N ? ", " : " " ) 1731 << Catch::toString(std::get<N>(tuple)); 1732 ElementPrinter<Tuple,N+1>::print(tuple,os); 1733 } 1734 }; 1735 1736 template< 1737 typename Tuple, 1738 std::size_t N 1739 > 1740 struct ElementPrinter<Tuple,N,false> { 1741 static void print( const Tuple&, std::ostream& ) {} 1742 }; 1743 1744 } 1745 1746 template<typename ...Types> 1747 struct StringMaker<std::tuple<Types...>> { 1748 1749 static std::string convert( const std::tuple<Types...>& tuple ) 1750 { 1751 std::ostringstream os; 1752 os << '{'; 1753 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os ); 1754 os << " }"; 1755 return os.str(); 1756 } 1757 }; 1758 #endif // CATCH_CONFIG_CPP11_TUPLE 1759 1760 namespace Detail { 1761 template<typename T> 1762 std::string makeString( T const& value ) { 1763 return StringMaker<T>::convert( value ); 1764 } 1765 } // end namespace Detail 1766 1767 /// \brief converts any type to a string 1768 /// 1769 /// The default template forwards on to ostringstream - except when an 1770 /// ostringstream overload does not exist - in which case it attempts to detect 1771 /// that and writes {?}. 1772 /// Overload (not specialise) this template for custom typs that you don't want 1773 /// to provide an ostream overload for. 1774 template<typename T> 1775 std::string toString( T const& value ) { 1776 return StringMaker<T>::convert( value ); 1777 } 1778 1779 namespace Detail { 1780 template<typename InputIterator> 1781 std::string rangeToString( InputIterator first, InputIterator last ) { 1782 std::ostringstream oss; 1783 oss << "{ "; 1784 if( first != last ) { 1785 oss << Catch::toString( *first ); 1786 for( ++first ; first != last ; ++first ) 1787 oss << ", " << Catch::toString( *first ); 1788 } 1789 oss << " }"; 1790 return oss.str(); 1791 } 1792 } 1793 1794 } // end namespace Catch 1795 1796 namespace Catch { 1797 1798 template<typename LhsT, Internal::Operator Op, typename RhsT> 1799 class BinaryExpression; 1800 1801 template<typename ArgT, typename MatcherT> 1802 class MatchExpression; 1803 1804 // Wraps the LHS of an expression and overloads comparison operators 1805 // for also capturing those and RHS (if any) 1806 template<typename T> 1807 class ExpressionLhs : public DecomposedExpression { 1808 public: 1809 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {} 1810 1811 ExpressionLhs& operator = ( const ExpressionLhs& ); 1812 1813 template<typename RhsT> 1814 BinaryExpression<T, Internal::IsEqualTo, RhsT const&> 1815 operator == ( RhsT const& rhs ) { 1816 return captureExpression<Internal::IsEqualTo>( rhs ); 1817 } 1818 1819 template<typename RhsT> 1820 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&> 1821 operator != ( RhsT const& rhs ) { 1822 return captureExpression<Internal::IsNotEqualTo>( rhs ); 1823 } 1824 1825 template<typename RhsT> 1826 BinaryExpression<T, Internal::IsLessThan, RhsT const&> 1827 operator < ( RhsT const& rhs ) { 1828 return captureExpression<Internal::IsLessThan>( rhs ); 1829 } 1830 1831 template<typename RhsT> 1832 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&> 1833 operator > ( RhsT const& rhs ) { 1834 return captureExpression<Internal::IsGreaterThan>( rhs ); 1835 } 1836 1837 template<typename RhsT> 1838 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&> 1839 operator <= ( RhsT const& rhs ) { 1840 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs ); 1841 } 1842 1843 template<typename RhsT> 1844 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&> 1845 operator >= ( RhsT const& rhs ) { 1846 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs ); 1847 } 1848 1849 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) { 1850 return captureExpression<Internal::IsEqualTo>( rhs ); 1851 } 1852 1853 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) { 1854 return captureExpression<Internal::IsNotEqualTo>( rhs ); 1855 } 1856 1857 void endExpression() { 1858 m_truthy = m_lhs ? true : false; 1859 m_rb 1860 .setResultType( m_truthy ) 1861 .endExpression( *this ); 1862 } 1863 1864 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 1865 dest = Catch::toString( m_lhs ); 1866 } 1867 1868 private: 1869 template<Internal::Operator Op, typename RhsT> 1870 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const { 1871 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs ); 1872 } 1873 1874 template<Internal::Operator Op> 1875 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const { 1876 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs ); 1877 } 1878 1879 private: 1880 ResultBuilder& m_rb; 1881 T m_lhs; 1882 bool m_truthy; 1883 }; 1884 1885 template<typename LhsT, Internal::Operator Op, typename RhsT> 1886 class BinaryExpression : public DecomposedExpression { 1887 public: 1888 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs ) 1889 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {} 1890 1891 BinaryExpression& operator = ( BinaryExpression& ); 1892 1893 void endExpression() const { 1894 m_rb 1895 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) ) 1896 .endExpression( *this ); 1897 } 1898 1899 virtual bool isBinaryExpression() const CATCH_OVERRIDE { 1900 return true; 1901 } 1902 1903 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 1904 std::string lhs = Catch::toString( m_lhs ); 1905 std::string rhs = Catch::toString( m_rhs ); 1906 char delim = lhs.size() + rhs.size() < 40 && 1907 lhs.find('\n') == std::string::npos && 1908 rhs.find('\n') == std::string::npos ? ' ' : '\n'; 1909 dest.reserve( 7 + lhs.size() + rhs.size() ); 1910 // 2 for spaces around operator 1911 // 2 for operator 1912 // 2 for parentheses (conditionally added later) 1913 // 1 for negation (conditionally added later) 1914 dest = lhs; 1915 dest += delim; 1916 dest += Internal::OperatorTraits<Op>::getName(); 1917 dest += delim; 1918 dest += rhs; 1919 } 1920 1921 private: 1922 ResultBuilder& m_rb; 1923 LhsT m_lhs; 1924 RhsT m_rhs; 1925 }; 1926 1927 template<typename ArgT, typename MatcherT> 1928 class MatchExpression : public DecomposedExpression { 1929 public: 1930 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString ) 1931 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {} 1932 1933 virtual bool isBinaryExpression() const CATCH_OVERRIDE { 1934 return true; 1935 } 1936 1937 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE { 1938 std::string matcherAsString = m_matcher.toString(); 1939 dest = Catch::toString( m_arg ); 1940 dest += ' '; 1941 if( matcherAsString == Detail::unprintableString ) 1942 dest += m_matcherString; 1943 else 1944 dest += matcherAsString; 1945 } 1946 1947 private: 1948 ArgT m_arg; 1949 MatcherT m_matcher; 1950 char const* m_matcherString; 1951 }; 1952 1953 } // end namespace Catch 1954 1955 1956 namespace Catch { 1957 1958 template<typename T> 1959 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) { 1960 return ExpressionLhs<T const&>( *this, operand ); 1961 } 1962 1963 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) { 1964 return ExpressionLhs<bool>( *this, value ); 1965 } 1966 1967 template<typename ArgT, typename MatcherT> 1968 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher, 1969 char const* matcherString ) { 1970 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString ); 1971 setResultType( matcher.match( arg ) ); 1972 endExpression( expr ); 1973 } 1974 1975 } // namespace Catch 1976 1977 // #included from: catch_message.h 1978 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED 1979 1980 #include <string> 1981 1982 namespace Catch { 1983 1984 struct MessageInfo { 1985 MessageInfo( std::string const& _macroName, 1986 SourceLineInfo const& _lineInfo, 1987 ResultWas::OfType _type ); 1988 1989 std::string macroName; 1990 SourceLineInfo lineInfo; 1991 ResultWas::OfType type; 1992 std::string message; 1993 unsigned int sequence; 1994 1995 bool operator == ( MessageInfo const& other ) const { 1996 return sequence == other.sequence; 1997 } 1998 bool operator < ( MessageInfo const& other ) const { 1999 return sequence < other.sequence; 2000 } 2001 private: 2002 static unsigned int globalCount; 2003 }; 2004 2005 struct MessageBuilder { 2006 MessageBuilder( std::string const& macroName, 2007 SourceLineInfo const& lineInfo, 2008 ResultWas::OfType type ) 2009 : m_info( macroName, lineInfo, type ) 2010 {} 2011 2012 template<typename T> 2013 MessageBuilder& operator << ( T const& value ) { 2014 m_stream << value; 2015 return *this; 2016 } 2017 2018 MessageInfo m_info; 2019 std::ostringstream m_stream; 2020 }; 2021 2022 class ScopedMessage { 2023 public: 2024 ScopedMessage( MessageBuilder const& builder ); 2025 ScopedMessage( ScopedMessage const& other ); 2026 ~ScopedMessage(); 2027 2028 MessageInfo m_info; 2029 }; 2030 2031 } // end namespace Catch 2032 2033 // #included from: catch_interfaces_capture.h 2034 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED 2035 2036 #include <string> 2037 2038 namespace Catch { 2039 2040 class TestCase; 2041 class AssertionResult; 2042 struct AssertionInfo; 2043 struct SectionInfo; 2044 struct SectionEndInfo; 2045 struct MessageInfo; 2046 class ScopedMessageBuilder; 2047 struct Counts; 2048 2049 struct IResultCapture { 2050 2051 virtual ~IResultCapture(); 2052 2053 virtual void assertionEnded( AssertionResult const& result ) = 0; 2054 virtual bool sectionStarted( SectionInfo const& sectionInfo, 2055 Counts& assertions ) = 0; 2056 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0; 2057 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0; 2058 virtual void pushScopedMessage( MessageInfo const& message ) = 0; 2059 virtual void popScopedMessage( MessageInfo const& message ) = 0; 2060 2061 virtual std::string getCurrentTestName() const = 0; 2062 virtual const AssertionResult* getLastResult() const = 0; 2063 2064 virtual void exceptionEarlyReported() = 0; 2065 2066 virtual void handleFatalErrorCondition( std::string const& message ) = 0; 2067 }; 2068 2069 IResultCapture& getResultCapture(); 2070 } 2071 2072 // #included from: catch_debugger.h 2073 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED 2074 2075 // #included from: catch_platform.h 2076 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED 2077 2078 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) 2079 # define CATCH_PLATFORM_MAC 2080 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED) 2081 # define CATCH_PLATFORM_IPHONE 2082 #elif defined(linux) || defined(__linux) || defined(__linux__) 2083 # define CATCH_PLATFORM_LINUX 2084 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) 2085 # define CATCH_PLATFORM_WINDOWS 2086 # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX) 2087 # define CATCH_DEFINES_NOMINMAX 2088 # endif 2089 # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN) 2090 # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN 2091 # endif 2092 #endif 2093 2094 #include <string> 2095 2096 namespace Catch{ 2097 2098 bool isDebuggerActive(); 2099 void writeToDebugConsole( std::string const& text ); 2100 } 2101 2102 #ifdef CATCH_PLATFORM_MAC 2103 2104 // The following code snippet based on: 2105 // http://cocoawithlove.com/2008/03/break-into-debugger.html 2106 #if defined(__ppc64__) || defined(__ppc__) 2107 #define CATCH_TRAP() \ 2108 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \ 2109 : : : "memory","r0","r3","r4" ) 2110 // backported from Catch2 2111 // revision b9853b4b356b83bb580c746c3a1f11101f9af54f 2112 // src/catch2/internal/catch_debugger.hpp 2113 #elif defined(__i386__) || defined(__x86_64__) 2114 #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */ 2115 #elif defined(__aarch64__) 2116 #define CATCH_TRAP() __asm__(".inst 0xd4200000") 2117 #endif 2118 2119 #elif defined(CATCH_PLATFORM_LINUX) 2120 // If we can use inline assembler, do it because this allows us to break 2121 // directly at the location of the failing check instead of breaking inside 2122 // raise() called from it, i.e. one stack frame below. 2123 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64)) 2124 #define CATCH_TRAP() asm volatile ("int $3") 2125 #else // Fall back to the generic way. 2126 #include <signal.h> 2127 2128 #define CATCH_TRAP() raise(SIGTRAP) 2129 #endif 2130 #elif defined(_MSC_VER) 2131 #define CATCH_TRAP() __debugbreak() 2132 #elif defined(__MINGW32__) 2133 extern "C" __declspec(dllimport) void __stdcall DebugBreak(); 2134 #define CATCH_TRAP() DebugBreak() 2135 #endif 2136 2137 #ifdef CATCH_TRAP 2138 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } 2139 #else 2140 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue(); 2141 #endif 2142 2143 // #included from: catch_interfaces_runner.h 2144 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED 2145 2146 namespace Catch { 2147 class TestCase; 2148 2149 struct IRunner { 2150 virtual ~IRunner(); 2151 virtual bool aborting() const = 0; 2152 }; 2153 } 2154 2155 #if defined(CATCH_CONFIG_FAST_COMPILE) 2156 /////////////////////////////////////////////////////////////////////////////// 2157 // We can speedup compilation significantly by breaking into debugger lower in 2158 // the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER 2159 // macro in each assertion 2160 #define INTERNAL_CATCH_REACT( resultBuilder ) \ 2161 resultBuilder.react(); 2162 2163 /////////////////////////////////////////////////////////////////////////////// 2164 // Another way to speed-up compilation is to omit local try-catch for REQUIRE* 2165 // macros. 2166 // This can potentially cause false negative, if the test code catches 2167 // the exception before it propagates back up to the runner. 2168 #define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \ 2169 do { \ 2170 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ 2171 __catchResult.setExceptionGuard(); \ 2172 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2173 ( __catchResult <= expr ).endExpression(); \ 2174 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 2175 __catchResult.unsetExceptionGuard(); \ 2176 INTERNAL_CATCH_REACT( __catchResult ) \ 2177 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look 2178 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 2179 2180 #define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \ 2181 do { \ 2182 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ 2183 __catchResult.setExceptionGuard(); \ 2184 __catchResult.captureMatch( arg, matcher, #matcher ); \ 2185 __catchResult.unsetExceptionGuard(); \ 2186 INTERNAL_CATCH_REACT( __catchResult ) \ 2187 } while( Catch::alwaysFalse() ) 2188 2189 #else 2190 /////////////////////////////////////////////////////////////////////////////// 2191 // In the event of a failure works out if the debugger needs to be invoked 2192 // and/or an exception thrown and takes appropriate action. 2193 // This needs to be done as a macro so the debugger will stop in the user 2194 // source code rather than in Catch library code 2195 #define INTERNAL_CATCH_REACT( resultBuilder ) \ 2196 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \ 2197 resultBuilder.react(); 2198 #endif 2199 2200 /////////////////////////////////////////////////////////////////////////////// 2201 #define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \ 2202 do { \ 2203 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ 2204 try { \ 2205 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \ 2206 ( __catchResult <= expr ).endExpression(); \ 2207 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \ 2208 } \ 2209 catch( ... ) { \ 2210 __catchResult.useActiveException( resultDisposition ); \ 2211 } \ 2212 INTERNAL_CATCH_REACT( __catchResult ) \ 2213 } while( Catch::isTrue( false && static_cast<bool>( !!(expr) ) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look 2214 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. 2215 2216 /////////////////////////////////////////////////////////////////////////////// 2217 #define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \ 2218 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ 2219 if( Catch::getResultCapture().getLastResult()->succeeded() ) 2220 2221 /////////////////////////////////////////////////////////////////////////////// 2222 #define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \ 2223 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \ 2224 if( !Catch::getResultCapture().getLastResult()->succeeded() ) 2225 2226 /////////////////////////////////////////////////////////////////////////////// 2227 #define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \ 2228 do { \ 2229 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \ 2230 try { \ 2231 static_cast<void>(expr); \ 2232 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 2233 } \ 2234 catch( ... ) { \ 2235 __catchResult.useActiveException( resultDisposition ); \ 2236 } \ 2237 INTERNAL_CATCH_REACT( __catchResult ) \ 2238 } while( Catch::alwaysFalse() ) 2239 2240 /////////////////////////////////////////////////////////////////////////////// 2241 #define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \ 2242 do { \ 2243 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \ 2244 if( __catchResult.allowThrows() ) \ 2245 try { \ 2246 static_cast<void>(expr); \ 2247 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ 2248 } \ 2249 catch( ... ) { \ 2250 __catchResult.captureExpectedException( matcher ); \ 2251 } \ 2252 else \ 2253 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 2254 INTERNAL_CATCH_REACT( __catchResult ) \ 2255 } while( Catch::alwaysFalse() ) 2256 2257 /////////////////////////////////////////////////////////////////////////////// 2258 #define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \ 2259 do { \ 2260 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \ 2261 if( __catchResult.allowThrows() ) \ 2262 try { \ 2263 static_cast<void>(expr); \ 2264 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \ 2265 } \ 2266 catch( const exceptionType& ) { \ 2267 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 2268 } \ 2269 catch( ... ) { \ 2270 __catchResult.useActiveException( resultDisposition ); \ 2271 } \ 2272 else \ 2273 __catchResult.captureResult( Catch::ResultWas::Ok ); \ 2274 INTERNAL_CATCH_REACT( __catchResult ) \ 2275 } while( Catch::alwaysFalse() ) 2276 2277 /////////////////////////////////////////////////////////////////////////////// 2278 #ifdef CATCH_CONFIG_VARIADIC_MACROS 2279 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \ 2280 do { \ 2281 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ 2282 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \ 2283 __catchResult.captureResult( messageType ); \ 2284 INTERNAL_CATCH_REACT( __catchResult ) \ 2285 } while( Catch::alwaysFalse() ) 2286 #else 2287 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, log ) \ 2288 do { \ 2289 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \ 2290 __catchResult << log + ::Catch::StreamEndStop(); \ 2291 __catchResult.captureResult( messageType ); \ 2292 INTERNAL_CATCH_REACT( __catchResult ) \ 2293 } while( Catch::alwaysFalse() ) 2294 #endif 2295 2296 /////////////////////////////////////////////////////////////////////////////// 2297 #define INTERNAL_CATCH_INFO( macroName, log ) \ 2298 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log; 2299 2300 /////////////////////////////////////////////////////////////////////////////// 2301 #define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \ 2302 do { \ 2303 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \ 2304 try { \ 2305 __catchResult.captureMatch( arg, matcher, #matcher ); \ 2306 } catch( ... ) { \ 2307 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \ 2308 } \ 2309 INTERNAL_CATCH_REACT( __catchResult ) \ 2310 } while( Catch::alwaysFalse() ) 2311 2312 // #included from: internal/catch_section.h 2313 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED 2314 2315 // #included from: catch_section_info.h 2316 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED 2317 2318 // #included from: catch_totals.hpp 2319 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED 2320 2321 #include <cstddef> 2322 2323 namespace Catch { 2324 2325 struct Counts { 2326 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {} 2327 2328 Counts operator - ( Counts const& other ) const { 2329 Counts diff; 2330 diff.passed = passed - other.passed; 2331 diff.failed = failed - other.failed; 2332 diff.failedButOk = failedButOk - other.failedButOk; 2333 return diff; 2334 } 2335 Counts& operator += ( Counts const& other ) { 2336 passed += other.passed; 2337 failed += other.failed; 2338 failedButOk += other.failedButOk; 2339 return *this; 2340 } 2341 2342 std::size_t total() const { 2343 return passed + failed + failedButOk; 2344 } 2345 bool allPassed() const { 2346 return failed == 0 && failedButOk == 0; 2347 } 2348 bool allOk() const { 2349 return failed == 0; 2350 } 2351 2352 std::size_t passed; 2353 std::size_t failed; 2354 std::size_t failedButOk; 2355 }; 2356 2357 struct Totals { 2358 2359 Totals operator - ( Totals const& other ) const { 2360 Totals diff; 2361 diff.assertions = assertions - other.assertions; 2362 diff.testCases = testCases - other.testCases; 2363 return diff; 2364 } 2365 2366 Totals delta( Totals const& prevTotals ) const { 2367 Totals diff = *this - prevTotals; 2368 if( diff.assertions.failed > 0 ) 2369 ++diff.testCases.failed; 2370 else if( diff.assertions.failedButOk > 0 ) 2371 ++diff.testCases.failedButOk; 2372 else 2373 ++diff.testCases.passed; 2374 return diff; 2375 } 2376 2377 Totals& operator += ( Totals const& other ) { 2378 assertions += other.assertions; 2379 testCases += other.testCases; 2380 return *this; 2381 } 2382 2383 Counts assertions; 2384 Counts testCases; 2385 }; 2386 } 2387 2388 #include <string> 2389 2390 namespace Catch { 2391 2392 struct SectionInfo { 2393 SectionInfo 2394 ( SourceLineInfo const& _lineInfo, 2395 std::string const& _name, 2396 std::string const& _description = std::string() ); 2397 2398 std::string name; 2399 std::string description; 2400 SourceLineInfo lineInfo; 2401 }; 2402 2403 struct SectionEndInfo { 2404 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds ) 2405 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds ) 2406 {} 2407 2408 SectionInfo sectionInfo; 2409 Counts prevAssertions; 2410 double durationInSeconds; 2411 }; 2412 2413 } // end namespace Catch 2414 2415 // #included from: catch_timer.h 2416 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED 2417 2418 #ifdef _MSC_VER 2419 2420 namespace Catch { 2421 typedef unsigned long long UInt64; 2422 } 2423 #else 2424 #include <stdint.h> 2425 namespace Catch { 2426 typedef uint64_t UInt64; 2427 } 2428 #endif 2429 2430 namespace Catch { 2431 class Timer { 2432 public: 2433 Timer() : m_ticks( 0 ) {} 2434 void start(); 2435 unsigned int getElapsedMicroseconds() const; 2436 unsigned int getElapsedMilliseconds() const; 2437 double getElapsedSeconds() const; 2438 2439 private: 2440 UInt64 m_ticks; 2441 }; 2442 2443 } // namespace Catch 2444 2445 #include <string> 2446 2447 namespace Catch { 2448 2449 class Section : NonCopyable { 2450 public: 2451 Section( SectionInfo const& info ); 2452 ~Section(); 2453 2454 // This indicates whether the section should be executed or not 2455 operator bool() const; 2456 2457 private: 2458 SectionInfo m_info; 2459 2460 std::string m_name; 2461 Counts m_assertions; 2462 bool m_sectionIncluded; 2463 Timer m_timer; 2464 }; 2465 2466 } // end namespace Catch 2467 2468 #ifdef CATCH_CONFIG_VARIADIC_MACROS 2469 #define INTERNAL_CATCH_SECTION( ... ) \ 2470 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) 2471 #else 2472 #define INTERNAL_CATCH_SECTION( name, desc ) \ 2473 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) ) 2474 #endif 2475 2476 // #included from: internal/catch_generators.hpp 2477 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED 2478 2479 #include <vector> 2480 #include <string> 2481 #include <stdlib.h> 2482 2483 namespace Catch { 2484 2485 template<typename T> 2486 struct IGenerator { 2487 virtual ~IGenerator() {} 2488 virtual T getValue( std::size_t index ) const = 0; 2489 virtual std::size_t size () const = 0; 2490 }; 2491 2492 template<typename T> 2493 class BetweenGenerator : public IGenerator<T> { 2494 public: 2495 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){} 2496 2497 virtual T getValue( std::size_t index ) const { 2498 return m_from+static_cast<int>( index ); 2499 } 2500 2501 virtual std::size_t size() const { 2502 return static_cast<std::size_t>( 1+m_to-m_from ); 2503 } 2504 2505 private: 2506 2507 T m_from; 2508 T m_to; 2509 }; 2510 2511 template<typename T> 2512 class ValuesGenerator : public IGenerator<T> { 2513 public: 2514 ValuesGenerator(){} 2515 2516 void add( T value ) { 2517 m_values.push_back( value ); 2518 } 2519 2520 virtual T getValue( std::size_t index ) const { 2521 return m_values[index]; 2522 } 2523 2524 virtual std::size_t size() const { 2525 return m_values.size(); 2526 } 2527 2528 private: 2529 std::vector<T> m_values; 2530 }; 2531 2532 template<typename T> 2533 class CompositeGenerator { 2534 public: 2535 CompositeGenerator() : m_totalSize( 0 ) {} 2536 2537 // *** Move semantics, similar to auto_ptr *** 2538 CompositeGenerator( CompositeGenerator& other ) 2539 : m_fileInfo( other.m_fileInfo ), 2540 m_totalSize( 0 ) 2541 { 2542 move( other ); 2543 } 2544 2545 CompositeGenerator& setFileInfo( const char* fileInfo ) { 2546 m_fileInfo = fileInfo; 2547 return *this; 2548 } 2549 2550 ~CompositeGenerator() { 2551 deleteAll( m_composed ); 2552 } 2553 2554 operator T () const { 2555 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize ); 2556 2557 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin(); 2558 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end(); 2559 for( size_t index = 0; it != itEnd; ++it ) 2560 { 2561 const IGenerator<T>* generator = *it; 2562 if( overallIndex >= index && overallIndex < index + generator->size() ) 2563 { 2564 return generator->getValue( overallIndex-index ); 2565 } 2566 index += generator->size(); 2567 } 2568 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" ); 2569 return T(); // Suppress spurious "not all control paths return a value" warning in Visual Studio - if you know how to fix this please do so 2570 } 2571 2572 void add( const IGenerator<T>* generator ) { 2573 m_totalSize += generator->size(); 2574 m_composed.push_back( generator ); 2575 } 2576 2577 CompositeGenerator& then( CompositeGenerator& other ) { 2578 move( other ); 2579 return *this; 2580 } 2581 2582 CompositeGenerator& then( T value ) { 2583 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); 2584 valuesGen->add( value ); 2585 add( valuesGen ); 2586 return *this; 2587 } 2588 2589 private: 2590 2591 void move( CompositeGenerator& other ) { 2592 m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() ); 2593 m_totalSize += other.m_totalSize; 2594 other.m_composed.clear(); 2595 } 2596 2597 std::vector<const IGenerator<T>*> m_composed; 2598 std::string m_fileInfo; 2599 size_t m_totalSize; 2600 }; 2601 2602 namespace Generators 2603 { 2604 template<typename T> 2605 CompositeGenerator<T> between( T from, T to ) { 2606 CompositeGenerator<T> generators; 2607 generators.add( new BetweenGenerator<T>( from, to ) ); 2608 return generators; 2609 } 2610 2611 template<typename T> 2612 CompositeGenerator<T> values( T val1, T val2 ) { 2613 CompositeGenerator<T> generators; 2614 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); 2615 valuesGen->add( val1 ); 2616 valuesGen->add( val2 ); 2617 generators.add( valuesGen ); 2618 return generators; 2619 } 2620 2621 template<typename T> 2622 CompositeGenerator<T> values( T val1, T val2, T val3 ){ 2623 CompositeGenerator<T> generators; 2624 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); 2625 valuesGen->add( val1 ); 2626 valuesGen->add( val2 ); 2627 valuesGen->add( val3 ); 2628 generators.add( valuesGen ); 2629 return generators; 2630 } 2631 2632 template<typename T> 2633 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) { 2634 CompositeGenerator<T> generators; 2635 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>(); 2636 valuesGen->add( val1 ); 2637 valuesGen->add( val2 ); 2638 valuesGen->add( val3 ); 2639 valuesGen->add( val4 ); 2640 generators.add( valuesGen ); 2641 return generators; 2642 } 2643 2644 } // end namespace Generators 2645 2646 using namespace Generators; 2647 2648 } // end namespace Catch 2649 2650 #define INTERNAL_CATCH_LINESTR2( line ) #line 2651 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line ) 2652 2653 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" ) 2654 2655 // #included from: internal/catch_interfaces_exception.h 2656 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED 2657 2658 #include <string> 2659 #include <vector> 2660 2661 // #included from: catch_interfaces_registry_hub.h 2662 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED 2663 2664 #include <string> 2665 2666 namespace Catch { 2667 2668 class TestCase; 2669 struct ITestCaseRegistry; 2670 struct IExceptionTranslatorRegistry; 2671 struct IExceptionTranslator; 2672 struct IReporterRegistry; 2673 struct IReporterFactory; 2674 struct ITagAliasRegistry; 2675 2676 struct IRegistryHub { 2677 virtual ~IRegistryHub(); 2678 2679 virtual IReporterRegistry const& getReporterRegistry() const = 0; 2680 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0; 2681 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0; 2682 2683 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0; 2684 }; 2685 2686 struct IMutableRegistryHub { 2687 virtual ~IMutableRegistryHub(); 2688 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0; 2689 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0; 2690 virtual void registerTest( TestCase const& testInfo ) = 0; 2691 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0; 2692 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0; 2693 }; 2694 2695 IRegistryHub& getRegistryHub(); 2696 IMutableRegistryHub& getMutableRegistryHub(); 2697 void cleanUp(); 2698 std::string translateActiveException(); 2699 2700 } 2701 2702 namespace Catch { 2703 2704 typedef std::string(*exceptionTranslateFunction)(); 2705 2706 struct IExceptionTranslator; 2707 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators; 2708 2709 struct IExceptionTranslator { 2710 virtual ~IExceptionTranslator(); 2711 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0; 2712 }; 2713 2714 struct IExceptionTranslatorRegistry { 2715 virtual ~IExceptionTranslatorRegistry(); 2716 2717 virtual std::string translateActiveException() const = 0; 2718 }; 2719 2720 class ExceptionTranslatorRegistrar { 2721 template<typename T> 2722 class ExceptionTranslator : public IExceptionTranslator { 2723 public: 2724 2725 ExceptionTranslator( std::string(*translateFunction)( T& ) ) 2726 : m_translateFunction( translateFunction ) 2727 {} 2728 2729 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE { 2730 try { 2731 if( it == itEnd ) 2732 throw; 2733 else 2734 return (*it)->translate( it+1, itEnd ); 2735 } 2736 catch( T& ex ) { 2737 return m_translateFunction( ex ); 2738 } 2739 } 2740 2741 protected: 2742 std::string(*m_translateFunction)( T& ); 2743 }; 2744 2745 public: 2746 template<typename T> 2747 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) { 2748 getMutableRegistryHub().registerTranslator 2749 ( new ExceptionTranslator<T>( translateFunction ) ); 2750 } 2751 }; 2752 } 2753 2754 /////////////////////////////////////////////////////////////////////////////// 2755 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \ 2756 static std::string translatorName( signature ); \ 2757 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\ 2758 static std::string translatorName( signature ) 2759 2760 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature ) 2761 2762 // #included from: internal/catch_approx.hpp 2763 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED 2764 2765 #include <cmath> 2766 #include <limits> 2767 2768 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) 2769 #include <type_traits> 2770 #endif 2771 2772 namespace Catch { 2773 namespace Detail { 2774 2775 class Approx { 2776 public: 2777 explicit Approx ( double value ) 2778 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ), 2779 m_margin( 0.0 ), 2780 m_scale( 1.0 ), 2781 m_value( value ) 2782 {} 2783 2784 Approx( Approx const& other ) 2785 : m_epsilon( other.m_epsilon ), 2786 m_margin( other.m_margin ), 2787 m_scale( other.m_scale ), 2788 m_value( other.m_value ) 2789 {} 2790 2791 static Approx custom() { 2792 return Approx( 0 ); 2793 } 2794 2795 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) 2796 2797 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2798 Approx operator()( T value ) { 2799 Approx approx( static_cast<double>(value) ); 2800 approx.epsilon( m_epsilon ); 2801 approx.margin( m_margin ); 2802 approx.scale( m_scale ); 2803 return approx; 2804 } 2805 2806 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2807 explicit Approx( T value ): Approx(static_cast<double>(value)) 2808 {} 2809 2810 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2811 friend bool operator == ( const T& lhs, Approx const& rhs ) { 2812 // Thanks to Richard Harris for his help refining this formula 2813 auto lhs_v = double(lhs); 2814 bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value))); 2815 if (relativeOK) { 2816 return true; 2817 } 2818 return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin; 2819 } 2820 2821 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2822 friend bool operator == ( Approx const& lhs, const T& rhs ) { 2823 return operator==( rhs, lhs ); 2824 } 2825 2826 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2827 friend bool operator != ( T lhs, Approx const& rhs ) { 2828 return !operator==( lhs, rhs ); 2829 } 2830 2831 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2832 friend bool operator != ( Approx const& lhs, T rhs ) { 2833 return !operator==( rhs, lhs ); 2834 } 2835 2836 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2837 friend bool operator <= ( T lhs, Approx const& rhs ) { 2838 return double(lhs) < rhs.m_value || lhs == rhs; 2839 } 2840 2841 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2842 friend bool operator <= ( Approx const& lhs, T rhs ) { 2843 return lhs.m_value < double(rhs) || lhs == rhs; 2844 } 2845 2846 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2847 friend bool operator >= ( T lhs, Approx const& rhs ) { 2848 return double(lhs) > rhs.m_value || lhs == rhs; 2849 } 2850 2851 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2852 friend bool operator >= ( Approx const& lhs, T rhs ) { 2853 return lhs.m_value > double(rhs) || lhs == rhs; 2854 } 2855 2856 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2857 Approx& epsilon( T newEpsilon ) { 2858 m_epsilon = double(newEpsilon); 2859 return *this; 2860 } 2861 2862 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2863 Approx& margin( T newMargin ) { 2864 m_margin = double(newMargin); 2865 return *this; 2866 } 2867 2868 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type> 2869 Approx& scale( T newScale ) { 2870 m_scale = double(newScale); 2871 return *this; 2872 } 2873 2874 #else 2875 2876 Approx operator()( double value ) { 2877 Approx approx( value ); 2878 approx.epsilon( m_epsilon ); 2879 approx.margin( m_margin ); 2880 approx.scale( m_scale ); 2881 return approx; 2882 } 2883 2884 friend bool operator == ( double lhs, Approx const& rhs ) { 2885 // Thanks to Richard Harris for his help refining this formula 2886 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) ); 2887 if (relativeOK) { 2888 return true; 2889 } 2890 return std::fabs(lhs - rhs.m_value) < rhs.m_margin; 2891 } 2892 2893 friend bool operator == ( Approx const& lhs, double rhs ) { 2894 return operator==( rhs, lhs ); 2895 } 2896 2897 friend bool operator != ( double lhs, Approx const& rhs ) { 2898 return !operator==( lhs, rhs ); 2899 } 2900 2901 friend bool operator != ( Approx const& lhs, double rhs ) { 2902 return !operator==( rhs, lhs ); 2903 } 2904 2905 friend bool operator <= ( double lhs, Approx const& rhs ) { 2906 return lhs < rhs.m_value || lhs == rhs; 2907 } 2908 2909 friend bool operator <= ( Approx const& lhs, double rhs ) { 2910 return lhs.m_value < rhs || lhs == rhs; 2911 } 2912 2913 friend bool operator >= ( double lhs, Approx const& rhs ) { 2914 return lhs > rhs.m_value || lhs == rhs; 2915 } 2916 2917 friend bool operator >= ( Approx const& lhs, double rhs ) { 2918 return lhs.m_value > rhs || lhs == rhs; 2919 } 2920 2921 Approx& epsilon( double newEpsilon ) { 2922 m_epsilon = newEpsilon; 2923 return *this; 2924 } 2925 2926 Approx& margin( double newMargin ) { 2927 m_margin = newMargin; 2928 return *this; 2929 } 2930 2931 Approx& scale( double newScale ) { 2932 m_scale = newScale; 2933 return *this; 2934 } 2935 #endif 2936 2937 std::string toString() const { 2938 std::ostringstream oss; 2939 oss << "Approx( " << Catch::toString( m_value ) << " )"; 2940 return oss.str(); 2941 } 2942 2943 private: 2944 double m_epsilon; 2945 double m_margin; 2946 double m_scale; 2947 double m_value; 2948 }; 2949 } 2950 2951 template<> 2952 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) { 2953 return value.toString(); 2954 } 2955 2956 } // end namespace Catch 2957 2958 // #included from: internal/catch_matchers_string.h 2959 #define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED 2960 2961 namespace Catch { 2962 namespace Matchers { 2963 2964 namespace StdString { 2965 2966 struct CasedString 2967 { 2968 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ); 2969 std::string adjustString( std::string const& str ) const; 2970 std::string caseSensitivitySuffix() const; 2971 2972 CaseSensitive::Choice m_caseSensitivity; 2973 std::string m_str; 2974 }; 2975 2976 struct StringMatcherBase : MatcherBase<std::string> { 2977 StringMatcherBase( std::string const& operation, CasedString const& comparator ); 2978 virtual std::string describe() const CATCH_OVERRIDE; 2979 2980 CasedString m_comparator; 2981 std::string m_operation; 2982 }; 2983 2984 struct EqualsMatcher : StringMatcherBase { 2985 EqualsMatcher( CasedString const& comparator ); 2986 virtual bool match( std::string const& source ) const CATCH_OVERRIDE; 2987 }; 2988 struct ContainsMatcher : StringMatcherBase { 2989 ContainsMatcher( CasedString const& comparator ); 2990 virtual bool match( std::string const& source ) const CATCH_OVERRIDE; 2991 }; 2992 struct StartsWithMatcher : StringMatcherBase { 2993 StartsWithMatcher( CasedString const& comparator ); 2994 virtual bool match( std::string const& source ) const CATCH_OVERRIDE; 2995 }; 2996 struct EndsWithMatcher : StringMatcherBase { 2997 EndsWithMatcher( CasedString const& comparator ); 2998 virtual bool match( std::string const& source ) const CATCH_OVERRIDE; 2999 }; 3000 3001 } // namespace StdString 3002 3003 // The following functions create the actual matcher objects. 3004 // This allows the types to be inferred 3005 3006 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3007 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3008 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3009 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ); 3010 3011 } // namespace Matchers 3012 } // namespace Catch 3013 3014 // #included from: internal/catch_matchers_vector.h 3015 #define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED 3016 3017 namespace Catch { 3018 namespace Matchers { 3019 3020 namespace Vector { 3021 3022 template<typename T> 3023 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> { 3024 3025 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {} 3026 3027 bool match(std::vector<T> const &v) const CATCH_OVERRIDE { 3028 return std::find(v.begin(), v.end(), m_comparator) != v.end(); 3029 } 3030 3031 virtual std::string describe() const CATCH_OVERRIDE { 3032 return "Contains: " + Catch::toString( m_comparator ); 3033 } 3034 3035 T const& m_comparator; 3036 }; 3037 3038 template<typename T> 3039 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > { 3040 3041 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3042 3043 bool match(std::vector<T> const &v) const CATCH_OVERRIDE { 3044 // !TBD: see note in EqualsMatcher 3045 if (m_comparator.size() > v.size()) 3046 return false; 3047 for (size_t i = 0; i < m_comparator.size(); ++i) 3048 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end()) 3049 return false; 3050 return true; 3051 } 3052 virtual std::string describe() const CATCH_OVERRIDE { 3053 return "Contains: " + Catch::toString( m_comparator ); 3054 } 3055 3056 std::vector<T> const& m_comparator; 3057 }; 3058 3059 template<typename T> 3060 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > { 3061 3062 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {} 3063 3064 bool match(std::vector<T> const &v) const CATCH_OVERRIDE { 3065 // !TBD: This currently works if all elements can be compared using != 3066 // - a more general approach would be via a compare template that defaults 3067 // to using !=. but could be specialised for, e.g. std::vector<T> etc 3068 // - then just call that directly 3069 if (m_comparator.size() != v.size()) 3070 return false; 3071 for (size_t i = 0; i < v.size(); ++i) 3072 if (m_comparator[i] != v[i]) 3073 return false; 3074 return true; 3075 } 3076 virtual std::string describe() const CATCH_OVERRIDE { 3077 return "Equals: " + Catch::toString( m_comparator ); 3078 } 3079 std::vector<T> const& m_comparator; 3080 }; 3081 3082 } // namespace Vector 3083 3084 // The following functions create the actual matcher objects. 3085 // This allows the types to be inferred 3086 3087 template<typename T> 3088 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) { 3089 return Vector::ContainsMatcher<T>( comparator ); 3090 } 3091 3092 template<typename T> 3093 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) { 3094 return Vector::ContainsElementMatcher<T>( comparator ); 3095 } 3096 3097 template<typename T> 3098 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) { 3099 return Vector::EqualsMatcher<T>( comparator ); 3100 } 3101 3102 } // namespace Matchers 3103 } // namespace Catch 3104 3105 // #included from: internal/catch_interfaces_tag_alias_registry.h 3106 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED 3107 3108 // #included from: catch_tag_alias.h 3109 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED 3110 3111 #include <string> 3112 3113 namespace Catch { 3114 3115 struct TagAlias { 3116 TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {} 3117 3118 std::string tag; 3119 SourceLineInfo lineInfo; 3120 }; 3121 3122 struct RegistrarForTagAliases { 3123 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ); 3124 }; 3125 3126 } // end namespace Catch 3127 3128 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } 3129 // #included from: catch_option.hpp 3130 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED 3131 3132 namespace Catch { 3133 3134 // An optional type 3135 template<typename T> 3136 class Option { 3137 public: 3138 Option() : nullableValue( CATCH_NULL ) {} 3139 Option( T const& _value ) 3140 : nullableValue( new( storage ) T( _value ) ) 3141 {} 3142 Option( Option const& _other ) 3143 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL ) 3144 {} 3145 3146 ~Option() { 3147 reset(); 3148 } 3149 3150 Option& operator= ( Option const& _other ) { 3151 if( &_other != this ) { 3152 reset(); 3153 if( _other ) 3154 nullableValue = new( storage ) T( *_other ); 3155 } 3156 return *this; 3157 } 3158 Option& operator = ( T const& _value ) { 3159 reset(); 3160 nullableValue = new( storage ) T( _value ); 3161 return *this; 3162 } 3163 3164 void reset() { 3165 if( nullableValue ) 3166 nullableValue->~T(); 3167 nullableValue = CATCH_NULL; 3168 } 3169 3170 T& operator*() { return *nullableValue; } 3171 T const& operator*() const { return *nullableValue; } 3172 T* operator->() { return nullableValue; } 3173 const T* operator->() const { return nullableValue; } 3174 3175 T valueOr( T const& defaultValue ) const { 3176 return nullableValue ? *nullableValue : defaultValue; 3177 } 3178 3179 bool some() const { return nullableValue != CATCH_NULL; } 3180 bool none() const { return nullableValue == CATCH_NULL; } 3181 3182 bool operator !() const { return nullableValue == CATCH_NULL; } 3183 operator SafeBool::type() const { 3184 return SafeBool::makeSafe( some() ); 3185 } 3186 3187 private: 3188 T *nullableValue; 3189 union { 3190 char storage[sizeof(T)]; 3191 3192 // These are here to force alignment for the storage 3193 long double dummy1; 3194 void (*dummy2)(); 3195 long double dummy3; 3196 #ifdef CATCH_CONFIG_CPP11_LONG_LONG 3197 long long dummy4; 3198 #endif 3199 }; 3200 }; 3201 3202 } // end namespace Catch 3203 3204 namespace Catch { 3205 3206 struct ITagAliasRegistry { 3207 virtual ~ITagAliasRegistry(); 3208 virtual Option<TagAlias> find( std::string const& alias ) const = 0; 3209 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0; 3210 3211 static ITagAliasRegistry const& get(); 3212 }; 3213 3214 } // end namespace Catch 3215 3216 // These files are included here so the single_include script doesn't put them 3217 // in the conditionally compiled sections 3218 // #included from: internal/catch_test_case_info.h 3219 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED 3220 3221 #include <string> 3222 #include <set> 3223 3224 #ifdef __clang__ 3225 # pragma clang diagnostic push 3226 # pragma clang diagnostic ignored "-Wpadded" 3227 #endif 3228 3229 namespace Catch { 3230 3231 struct ITestCase; 3232 3233 struct TestCaseInfo { 3234 enum SpecialProperties{ 3235 None = 0, 3236 IsHidden = 1 << 1, 3237 ShouldFail = 1 << 2, 3238 MayFail = 1 << 3, 3239 Throws = 1 << 4, 3240 NonPortable = 1 << 5 3241 }; 3242 3243 TestCaseInfo( std::string const& _name, 3244 std::string const& _className, 3245 std::string const& _description, 3246 std::set<std::string> const& _tags, 3247 SourceLineInfo const& _lineInfo ); 3248 3249 TestCaseInfo( TestCaseInfo const& other ); 3250 3251 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ); 3252 3253 bool isHidden() const; 3254 bool throws() const; 3255 bool okToFail() const; 3256 bool expectedToFail() const; 3257 3258 std::string name; 3259 std::string className; 3260 std::string description; 3261 std::set<std::string> tags; 3262 std::set<std::string> lcaseTags; 3263 std::string tagsAsString; 3264 SourceLineInfo lineInfo; 3265 SpecialProperties properties; 3266 }; 3267 3268 class TestCase : public TestCaseInfo { 3269 public: 3270 3271 TestCase( ITestCase* testCase, TestCaseInfo const& info ); 3272 TestCase( TestCase const& other ); 3273 3274 TestCase withName( std::string const& _newName ) const; 3275 3276 void invoke() const; 3277 3278 TestCaseInfo const& getTestCaseInfo() const; 3279 3280 void swap( TestCase& other ); 3281 bool operator == ( TestCase const& other ) const; 3282 bool operator < ( TestCase const& other ) const; 3283 TestCase& operator = ( TestCase const& other ); 3284 3285 private: 3286 Ptr<ITestCase> test; 3287 }; 3288 3289 TestCase makeTestCase( ITestCase* testCase, 3290 std::string const& className, 3291 std::string const& name, 3292 std::string const& description, 3293 SourceLineInfo const& lineInfo ); 3294 } 3295 3296 #ifdef __clang__ 3297 # pragma clang diagnostic pop 3298 #endif 3299 3300 3301 #ifdef __OBJC__ 3302 // #included from: internal/catch_objc.hpp 3303 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED 3304 3305 #import <objc/runtime.h> 3306 3307 #include <string> 3308 3309 // NB. Any general catch headers included here must be included 3310 // in catch.hpp first to make sure they are included by the single 3311 // header for non obj-usage 3312 3313 /////////////////////////////////////////////////////////////////////////////// 3314 // This protocol is really only here for (self) documenting purposes, since 3315 // all its methods are optional. 3316 @protocol OcFixture 3317 3318 @optional 3319 3320 -(void) setUp; 3321 -(void) tearDown; 3322 3323 @end 3324 3325 namespace Catch { 3326 3327 class OcMethod : public SharedImpl<ITestCase> { 3328 3329 public: 3330 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {} 3331 3332 virtual void invoke() const { 3333 id obj = [[m_cls alloc] init]; 3334 3335 performOptionalSelector( obj, @selector(setUp) ); 3336 performOptionalSelector( obj, m_sel ); 3337 performOptionalSelector( obj, @selector(tearDown) ); 3338 3339 arcSafeRelease( obj ); 3340 } 3341 private: 3342 virtual ~OcMethod() {} 3343 3344 Class m_cls; 3345 SEL m_sel; 3346 }; 3347 3348 namespace Detail{ 3349 3350 inline std::string getAnnotation( Class cls, 3351 std::string const& annotationName, 3352 std::string const& testCaseName ) { 3353 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()]; 3354 SEL sel = NSSelectorFromString( selStr ); 3355 arcSafeRelease( selStr ); 3356 id value = performOptionalSelector( cls, sel ); 3357 if( value ) 3358 return [(NSString*)value UTF8String]; 3359 return ""; 3360 } 3361 } 3362 3363 inline size_t registerTestMethods() { 3364 size_t noTestMethods = 0; 3365 int noClasses = objc_getClassList( CATCH_NULL, 0 ); 3366 3367 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses); 3368 objc_getClassList( classes, noClasses ); 3369 3370 for( int c = 0; c < noClasses; c++ ) { 3371 Class cls = classes[c]; 3372 { 3373 u_int count; 3374 Method* methods = class_copyMethodList( cls, &count ); 3375 for( u_int m = 0; m < count ; m++ ) { 3376 SEL selector = method_getName(methods[m]); 3377 std::string methodName = sel_getName(selector); 3378 if( startsWith( methodName, "Catch_TestCase_" ) ) { 3379 std::string testCaseName = methodName.substr( 15 ); 3380 std::string name = Detail::getAnnotation( cls, "Name", testCaseName ); 3381 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName ); 3382 const char* className = class_getName( cls ); 3383 3384 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) ); 3385 noTestMethods++; 3386 } 3387 } 3388 free(methods); 3389 } 3390 } 3391 return noTestMethods; 3392 } 3393 3394 namespace Matchers { 3395 namespace Impl { 3396 namespace NSStringMatchers { 3397 3398 struct StringHolder : MatcherBase<NSString*>{ 3399 StringHolder( NSString* substr ) : m_substr( [substr copy] ){} 3400 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){} 3401 StringHolder() { 3402 arcSafeRelease( m_substr ); 3403 } 3404 3405 virtual bool match( NSString* arg ) const CATCH_OVERRIDE { 3406 return false; 3407 } 3408 3409 NSString* m_substr; 3410 }; 3411 3412 struct Equals : StringHolder { 3413 Equals( NSString* substr ) : StringHolder( substr ){} 3414 3415 virtual bool match( NSString* str ) const CATCH_OVERRIDE { 3416 return (str != nil || m_substr == nil ) && 3417 [str isEqualToString:m_substr]; 3418 } 3419 3420 virtual std::string describe() const CATCH_OVERRIDE { 3421 return "equals string: " + Catch::toString( m_substr ); 3422 } 3423 }; 3424 3425 struct Contains : StringHolder { 3426 Contains( NSString* substr ) : StringHolder( substr ){} 3427 3428 virtual bool match( NSString* str ) const { 3429 return (str != nil || m_substr == nil ) && 3430 [str rangeOfString:m_substr].location != NSNotFound; 3431 } 3432 3433 virtual std::string describe() const CATCH_OVERRIDE { 3434 return "contains string: " + Catch::toString( m_substr ); 3435 } 3436 }; 3437 3438 struct StartsWith : StringHolder { 3439 StartsWith( NSString* substr ) : StringHolder( substr ){} 3440 3441 virtual bool match( NSString* str ) const { 3442 return (str != nil || m_substr == nil ) && 3443 [str rangeOfString:m_substr].location == 0; 3444 } 3445 3446 virtual std::string describe() const CATCH_OVERRIDE { 3447 return "starts with: " + Catch::toString( m_substr ); 3448 } 3449 }; 3450 struct EndsWith : StringHolder { 3451 EndsWith( NSString* substr ) : StringHolder( substr ){} 3452 3453 virtual bool match( NSString* str ) const { 3454 return (str != nil || m_substr == nil ) && 3455 [str rangeOfString:m_substr].location == [str length] - [m_substr length]; 3456 } 3457 3458 virtual std::string describe() const CATCH_OVERRIDE { 3459 return "ends with: " + Catch::toString( m_substr ); 3460 } 3461 }; 3462 3463 } // namespace NSStringMatchers 3464 } // namespace Impl 3465 3466 inline Impl::NSStringMatchers::Equals 3467 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); } 3468 3469 inline Impl::NSStringMatchers::Contains 3470 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); } 3471 3472 inline Impl::NSStringMatchers::StartsWith 3473 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); } 3474 3475 inline Impl::NSStringMatchers::EndsWith 3476 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); } 3477 3478 } // namespace Matchers 3479 3480 using namespace Matchers; 3481 3482 } // namespace Catch 3483 3484 /////////////////////////////////////////////////////////////////////////////// 3485 #define OC_TEST_CASE( name, desc )\ 3486 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \ 3487 {\ 3488 return @ name; \ 3489 }\ 3490 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \ 3491 { \ 3492 return @ desc; \ 3493 } \ 3494 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test ) 3495 3496 #endif 3497 3498 #ifdef CATCH_IMPL 3499 3500 // !TBD: Move the leak detector code into a separate header 3501 #ifdef CATCH_CONFIG_WINDOWS_CRTDBG 3502 #include <crtdbg.h> 3503 class LeakDetector { 3504 public: 3505 LeakDetector() { 3506 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); 3507 flag |= _CRTDBG_LEAK_CHECK_DF; 3508 flag |= _CRTDBG_ALLOC_MEM_DF; 3509 _CrtSetDbgFlag(flag); 3510 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG); 3511 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); 3512 // Change this to leaking allocation's number to break there 3513 _CrtSetBreakAlloc(-1); 3514 } 3515 }; 3516 #else 3517 class LeakDetector {}; 3518 #endif 3519 3520 LeakDetector leakDetector; 3521 3522 // #included from: internal/catch_impl.hpp 3523 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED 3524 3525 // Collect all the implementation files together here 3526 // These are the equivalent of what would usually be cpp files 3527 3528 #ifdef __clang__ 3529 # pragma clang diagnostic push 3530 # pragma clang diagnostic ignored "-Wweak-vtables" 3531 #endif 3532 3533 // #included from: ../catch_session.hpp 3534 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED 3535 3536 // #included from: internal/catch_commandline.hpp 3537 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED 3538 3539 // #included from: catch_config.hpp 3540 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED 3541 3542 // #included from: catch_test_spec_parser.hpp 3543 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED 3544 3545 #ifdef __clang__ 3546 # pragma clang diagnostic push 3547 # pragma clang diagnostic ignored "-Wpadded" 3548 #endif 3549 3550 // #included from: catch_test_spec.hpp 3551 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED 3552 3553 #ifdef __clang__ 3554 # pragma clang diagnostic push 3555 # pragma clang diagnostic ignored "-Wpadded" 3556 #endif 3557 3558 // #included from: catch_wildcard_pattern.hpp 3559 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED 3560 3561 #include <stdexcept> 3562 3563 namespace Catch 3564 { 3565 class WildcardPattern { 3566 enum WildcardPosition { 3567 NoWildcard = 0, 3568 WildcardAtStart = 1, 3569 WildcardAtEnd = 2, 3570 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd 3571 }; 3572 3573 public: 3574 3575 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity ) 3576 : m_caseSensitivity( caseSensitivity ), 3577 m_wildcard( NoWildcard ), 3578 m_pattern( adjustCase( pattern ) ) 3579 { 3580 if( startsWith( m_pattern, '*' ) ) { 3581 m_pattern = m_pattern.substr( 1 ); 3582 m_wildcard = WildcardAtStart; 3583 } 3584 if( endsWith( m_pattern, '*' ) ) { 3585 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 ); 3586 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd ); 3587 } 3588 } 3589 virtual ~WildcardPattern(); 3590 virtual bool matches( std::string const& str ) const { 3591 switch( m_wildcard ) { 3592 case NoWildcard: 3593 return m_pattern == adjustCase( str ); 3594 case WildcardAtStart: 3595 return endsWith( adjustCase( str ), m_pattern ); 3596 case WildcardAtEnd: 3597 return startsWith( adjustCase( str ), m_pattern ); 3598 case WildcardAtBothEnds: 3599 return contains( adjustCase( str ), m_pattern ); 3600 } 3601 3602 #ifdef __clang__ 3603 # pragma clang diagnostic push 3604 # pragma clang diagnostic ignored "-Wunreachable-code" 3605 #endif 3606 throw std::logic_error( "Unknown enum" ); 3607 #ifdef __clang__ 3608 # pragma clang diagnostic pop 3609 #endif 3610 } 3611 private: 3612 std::string adjustCase( std::string const& str ) const { 3613 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str; 3614 } 3615 CaseSensitive::Choice m_caseSensitivity; 3616 WildcardPosition m_wildcard; 3617 std::string m_pattern; 3618 }; 3619 } 3620 3621 #include <string> 3622 #include <vector> 3623 3624 namespace Catch { 3625 3626 class TestSpec { 3627 struct Pattern : SharedImpl<> { 3628 virtual ~Pattern(); 3629 virtual bool matches( TestCaseInfo const& testCase ) const = 0; 3630 }; 3631 class NamePattern : public Pattern { 3632 public: 3633 NamePattern( std::string const& name ) 3634 : m_wildcardPattern( toLower( name ), CaseSensitive::No ) 3635 {} 3636 virtual ~NamePattern(); 3637 virtual bool matches( TestCaseInfo const& testCase ) const { 3638 return m_wildcardPattern.matches( toLower( testCase.name ) ); 3639 } 3640 private: 3641 WildcardPattern m_wildcardPattern; 3642 }; 3643 3644 class TagPattern : public Pattern { 3645 public: 3646 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {} 3647 virtual ~TagPattern(); 3648 virtual bool matches( TestCaseInfo const& testCase ) const { 3649 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end(); 3650 } 3651 private: 3652 std::string m_tag; 3653 }; 3654 3655 class ExcludedPattern : public Pattern { 3656 public: 3657 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {} 3658 virtual ~ExcludedPattern(); 3659 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); } 3660 private: 3661 Ptr<Pattern> m_underlyingPattern; 3662 }; 3663 3664 struct Filter { 3665 std::vector<Ptr<Pattern> > m_patterns; 3666 3667 bool matches( TestCaseInfo const& testCase ) const { 3668 // All patterns in a filter must match for the filter to be a match 3669 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) { 3670 if( !(*it)->matches( testCase ) ) 3671 return false; 3672 } 3673 return true; 3674 } 3675 }; 3676 3677 public: 3678 bool hasFilters() const { 3679 return !m_filters.empty(); 3680 } 3681 bool matches( TestCaseInfo const& testCase ) const { 3682 // A TestSpec matches if any filter matches 3683 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it ) 3684 if( it->matches( testCase ) ) 3685 return true; 3686 return false; 3687 } 3688 3689 private: 3690 std::vector<Filter> m_filters; 3691 3692 friend class TestSpecParser; 3693 }; 3694 } 3695 3696 #ifdef __clang__ 3697 # pragma clang diagnostic pop 3698 #endif 3699 3700 namespace Catch { 3701 3702 class TestSpecParser { 3703 enum Mode{ None, Name, QuotedName, Tag, EscapedName }; 3704 Mode m_mode; 3705 bool m_exclusion; 3706 std::size_t m_start, m_pos; 3707 std::string m_arg; 3708 std::vector<std::size_t> m_escapeChars; 3709 TestSpec::Filter m_currentFilter; 3710 TestSpec m_testSpec; 3711 ITagAliasRegistry const* m_tagAliases; 3712 3713 public: 3714 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {} 3715 3716 TestSpecParser& parse( std::string const& arg ) { 3717 m_mode = None; 3718 m_exclusion = false; 3719 m_start = std::string::npos; 3720 m_arg = m_tagAliases->expandAliases( arg ); 3721 m_escapeChars.clear(); 3722 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos ) 3723 visitChar( m_arg[m_pos] ); 3724 if( m_mode == Name ) 3725 addPattern<TestSpec::NamePattern>(); 3726 return *this; 3727 } 3728 TestSpec testSpec() { 3729 addFilter(); 3730 return m_testSpec; 3731 } 3732 private: 3733 void visitChar( char c ) { 3734 if( m_mode == None ) { 3735 switch( c ) { 3736 case ' ': return; 3737 case '~': m_exclusion = true; return; 3738 case '[': return startNewMode( Tag, ++m_pos ); 3739 case '"': return startNewMode( QuotedName, ++m_pos ); 3740 case '\\': return escape(); 3741 default: startNewMode( Name, m_pos ); break; 3742 } 3743 } 3744 if( m_mode == Name ) { 3745 if( c == ',' ) { 3746 addPattern<TestSpec::NamePattern>(); 3747 addFilter(); 3748 } 3749 else if( c == '[' ) { 3750 if( subString() == "exclude:" ) 3751 m_exclusion = true; 3752 else 3753 addPattern<TestSpec::NamePattern>(); 3754 startNewMode( Tag, ++m_pos ); 3755 } 3756 else if( c == '\\' ) 3757 escape(); 3758 } 3759 else if( m_mode == EscapedName ) 3760 m_mode = Name; 3761 else if( m_mode == QuotedName && c == '"' ) 3762 addPattern<TestSpec::NamePattern>(); 3763 else if( m_mode == Tag && c == ']' ) 3764 addPattern<TestSpec::TagPattern>(); 3765 } 3766 void startNewMode( Mode mode, std::size_t start ) { 3767 m_mode = mode; 3768 m_start = start; 3769 } 3770 void escape() { 3771 if( m_mode == None ) 3772 m_start = m_pos; 3773 m_mode = EscapedName; 3774 m_escapeChars.push_back( m_pos ); 3775 } 3776 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); } 3777 template<typename T> 3778 void addPattern() { 3779 std::string token = subString(); 3780 for( size_t i = 0; i < m_escapeChars.size(); ++i ) 3781 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 ); 3782 m_escapeChars.clear(); 3783 if( startsWith( token, "exclude:" ) ) { 3784 m_exclusion = true; 3785 token = token.substr( 8 ); 3786 } 3787 if( !token.empty() ) { 3788 Ptr<TestSpec::Pattern> pattern = new T( token ); 3789 if( m_exclusion ) 3790 pattern = new TestSpec::ExcludedPattern( pattern ); 3791 m_currentFilter.m_patterns.push_back( pattern ); 3792 } 3793 m_exclusion = false; 3794 m_mode = None; 3795 } 3796 void addFilter() { 3797 if( !m_currentFilter.m_patterns.empty() ) { 3798 m_testSpec.m_filters.push_back( m_currentFilter ); 3799 m_currentFilter = TestSpec::Filter(); 3800 } 3801 } 3802 }; 3803 inline TestSpec parseTestSpec( std::string const& arg ) { 3804 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec(); 3805 } 3806 3807 } // namespace Catch 3808 3809 #ifdef __clang__ 3810 # pragma clang diagnostic pop 3811 #endif 3812 3813 // #included from: catch_interfaces_config.h 3814 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED 3815 3816 #include <iosfwd> 3817 #include <string> 3818 #include <vector> 3819 3820 namespace Catch { 3821 3822 struct Verbosity { enum Level { 3823 NoOutput = 0, 3824 Quiet, 3825 Normal 3826 }; }; 3827 3828 struct WarnAbout { enum What { 3829 Nothing = 0x00, 3830 NoAssertions = 0x01 3831 }; }; 3832 3833 struct ShowDurations { enum OrNot { 3834 DefaultForReporter, 3835 Always, 3836 Never 3837 }; }; 3838 struct RunTests { enum InWhatOrder { 3839 InDeclarationOrder, 3840 InLexicographicalOrder, 3841 InRandomOrder 3842 }; }; 3843 struct UseColour { enum YesOrNo { 3844 Auto, 3845 Yes, 3846 No 3847 }; }; 3848 3849 class TestSpec; 3850 3851 struct IConfig : IShared { 3852 3853 virtual ~IConfig(); 3854 3855 virtual bool allowThrows() const = 0; 3856 virtual std::ostream& stream() const = 0; 3857 virtual std::string name() const = 0; 3858 virtual bool includeSuccessfulResults() const = 0; 3859 virtual bool shouldDebugBreak() const = 0; 3860 virtual bool warnAboutMissingAssertions() const = 0; 3861 virtual int abortAfter() const = 0; 3862 virtual bool showInvisibles() const = 0; 3863 virtual ShowDurations::OrNot showDurations() const = 0; 3864 virtual TestSpec const& testSpec() const = 0; 3865 virtual RunTests::InWhatOrder runOrder() const = 0; 3866 virtual unsigned int rngSeed() const = 0; 3867 virtual UseColour::YesOrNo useColour() const = 0; 3868 virtual std::vector<std::string> const& getSectionsToRun() const = 0; 3869 3870 }; 3871 } 3872 3873 // #included from: catch_stream.h 3874 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED 3875 3876 // #included from: catch_streambuf.h 3877 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED 3878 3879 #include <streambuf> 3880 3881 namespace Catch { 3882 3883 class StreamBufBase : public std::streambuf { 3884 public: 3885 virtual ~StreamBufBase() CATCH_NOEXCEPT; 3886 }; 3887 } 3888 3889 #include <streambuf> 3890 #include <ostream> 3891 #include <fstream> 3892 #include <memory> 3893 3894 namespace Catch { 3895 3896 std::ostream& cout(); 3897 std::ostream& cerr(); 3898 3899 struct IStream { 3900 virtual ~IStream() CATCH_NOEXCEPT; 3901 virtual std::ostream& stream() const = 0; 3902 }; 3903 3904 class FileStream : public IStream { 3905 mutable std::ofstream m_ofs; 3906 public: 3907 FileStream( std::string const& filename ); 3908 virtual ~FileStream() CATCH_NOEXCEPT; 3909 public: // IStream 3910 virtual std::ostream& stream() const CATCH_OVERRIDE; 3911 }; 3912 3913 class CoutStream : public IStream { 3914 mutable std::ostream m_os; 3915 public: 3916 CoutStream(); 3917 virtual ~CoutStream() CATCH_NOEXCEPT; 3918 3919 public: // IStream 3920 virtual std::ostream& stream() const CATCH_OVERRIDE; 3921 }; 3922 3923 class DebugOutStream : public IStream { 3924 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf; 3925 mutable std::ostream m_os; 3926 public: 3927 DebugOutStream(); 3928 virtual ~DebugOutStream() CATCH_NOEXCEPT; 3929 3930 public: // IStream 3931 virtual std::ostream& stream() const CATCH_OVERRIDE; 3932 }; 3933 } 3934 3935 #include <memory> 3936 #include <vector> 3937 #include <string> 3938 #include <stdexcept> 3939 3940 #ifndef CATCH_CONFIG_CONSOLE_WIDTH 3941 #define CATCH_CONFIG_CONSOLE_WIDTH 80 3942 #endif 3943 3944 namespace Catch { 3945 3946 struct ConfigData { 3947 3948 ConfigData() 3949 : listTests( false ), 3950 listTags( false ), 3951 listReporters( false ), 3952 listTestNamesOnly( false ), 3953 listExtraInfo( false ), 3954 showSuccessfulTests( false ), 3955 shouldDebugBreak( false ), 3956 noThrow( false ), 3957 showHelp( false ), 3958 showInvisibles( false ), 3959 filenamesAsTags( false ), 3960 abortAfter( -1 ), 3961 rngSeed( 0 ), 3962 verbosity( Verbosity::Normal ), 3963 warnings( WarnAbout::Nothing ), 3964 showDurations( ShowDurations::DefaultForReporter ), 3965 runOrder( RunTests::InDeclarationOrder ), 3966 useColour( UseColour::Auto ) 3967 {} 3968 3969 bool listTests; 3970 bool listTags; 3971 bool listReporters; 3972 bool listTestNamesOnly; 3973 bool listExtraInfo; 3974 3975 bool showSuccessfulTests; 3976 bool shouldDebugBreak; 3977 bool noThrow; 3978 bool showHelp; 3979 bool showInvisibles; 3980 bool filenamesAsTags; 3981 3982 int abortAfter; 3983 unsigned int rngSeed; 3984 3985 Verbosity::Level verbosity; 3986 WarnAbout::What warnings; 3987 ShowDurations::OrNot showDurations; 3988 RunTests::InWhatOrder runOrder; 3989 UseColour::YesOrNo useColour; 3990 3991 std::string outputFilename; 3992 std::string name; 3993 std::string processName; 3994 3995 std::vector<std::string> reporterNames; 3996 std::vector<std::string> testsOrTags; 3997 std::vector<std::string> sectionsToRun; 3998 }; 3999 4000 class Config : public SharedImpl<IConfig> { 4001 private: 4002 Config( Config const& other ); 4003 Config& operator = ( Config const& other ); 4004 virtual void dummy(); 4005 public: 4006 4007 Config() 4008 {} 4009 4010 Config( ConfigData const& data ) 4011 : m_data( data ), 4012 m_stream( openStream() ) 4013 { 4014 if( !data.testsOrTags.empty() ) { 4015 TestSpecParser parser( ITagAliasRegistry::get() ); 4016 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i ) 4017 parser.parse( data.testsOrTags[i] ); 4018 m_testSpec = parser.testSpec(); 4019 } 4020 } 4021 4022 virtual ~Config() {} 4023 4024 std::string const& getFilename() const { 4025 return m_data.outputFilename ; 4026 } 4027 4028 bool listTests() const { return m_data.listTests; } 4029 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; } 4030 bool listTags() const { return m_data.listTags; } 4031 bool listReporters() const { return m_data.listReporters; } 4032 bool listExtraInfo() const { return m_data.listExtraInfo; } 4033 4034 std::string getProcessName() const { return m_data.processName; } 4035 4036 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; } 4037 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; } 4038 4039 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; } 4040 4041 bool showHelp() const { return m_data.showHelp; } 4042 4043 // IConfig interface 4044 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; } 4045 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); } 4046 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; } 4047 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; } 4048 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; } 4049 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; } 4050 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; } 4051 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; } 4052 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; } 4053 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; } 4054 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; } 4055 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; } 4056 4057 private: 4058 4059 IStream const* openStream() { 4060 if( m_data.outputFilename.empty() ) 4061 return new CoutStream(); 4062 else if( m_data.outputFilename[0] == '%' ) { 4063 if( m_data.outputFilename == "%debug" ) 4064 return new DebugOutStream(); 4065 else 4066 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename ); 4067 } 4068 else 4069 return new FileStream( m_data.outputFilename ); 4070 } 4071 ConfigData m_data; 4072 4073 CATCH_AUTO_PTR( IStream const ) m_stream; 4074 TestSpec m_testSpec; 4075 }; 4076 4077 } // end namespace Catch 4078 4079 // #included from: catch_clara.h 4080 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED 4081 4082 // Use Catch's value for console width (store Clara's off to the side, if present) 4083 #ifdef CLARA_CONFIG_CONSOLE_WIDTH 4084 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH 4085 #undef CLARA_CONFIG_CONSOLE_WIDTH 4086 #endif 4087 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH 4088 4089 // Declare Clara inside the Catch namespace 4090 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch { 4091 // #included from: ../external/clara.h 4092 4093 // Version 0.0.2.4 4094 4095 // Only use header guard if we are not using an outer namespace 4096 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE) 4097 4098 #ifndef STITCH_CLARA_OPEN_NAMESPACE 4099 #define TWOBLUECUBES_CLARA_H_INCLUDED 4100 #define STITCH_CLARA_OPEN_NAMESPACE 4101 #define STITCH_CLARA_CLOSE_NAMESPACE 4102 #else 4103 #define STITCH_CLARA_CLOSE_NAMESPACE } 4104 #endif 4105 4106 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE 4107 4108 // ----------- #included from tbc_text_format.h ----------- 4109 4110 // Only use header guard if we are not using an outer namespace 4111 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE) 4112 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE 4113 #define TBC_TEXT_FORMAT_H_INCLUDED 4114 #endif 4115 4116 #include <string> 4117 #include <vector> 4118 #include <sstream> 4119 #include <algorithm> 4120 #include <cctype> 4121 4122 // Use optional outer namespace 4123 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE 4124 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE { 4125 #endif 4126 4127 namespace Tbc { 4128 4129 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH 4130 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; 4131 #else 4132 const unsigned int consoleWidth = 80; 4133 #endif 4134 4135 struct TextAttributes { 4136 TextAttributes() 4137 : initialIndent( std::string::npos ), 4138 indent( 0 ), 4139 width( consoleWidth-1 ), 4140 tabChar( '\t' ) 4141 {} 4142 4143 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } 4144 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } 4145 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } 4146 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; } 4147 4148 std::size_t initialIndent; // indent of first line, or npos 4149 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos 4150 std::size_t width; // maximum width of text, including indent. Longer text will wrap 4151 char tabChar; // If this char is seen the indent is changed to current pos 4152 }; 4153 4154 class Text { 4155 public: 4156 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) 4157 : attr( _attr ) 4158 { 4159 std::string wrappableChars = " [({.,/|\\-"; 4160 std::size_t indent = _attr.initialIndent != std::string::npos 4161 ? _attr.initialIndent 4162 : _attr.indent; 4163 std::string remainder = _str; 4164 4165 while( !remainder.empty() ) { 4166 if( lines.size() >= 1000 ) { 4167 lines.push_back( "... message truncated due to excessive size" ); 4168 return; 4169 } 4170 std::size_t tabPos = std::string::npos; 4171 std::size_t width = (std::min)( remainder.size(), _attr.width - indent ); 4172 std::size_t pos = remainder.find_first_of( '\n' ); 4173 if( pos <= width ) { 4174 width = pos; 4175 } 4176 pos = remainder.find_last_of( _attr.tabChar, width ); 4177 if( pos != std::string::npos ) { 4178 tabPos = pos; 4179 if( remainder[width] == '\n' ) 4180 width--; 4181 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 ); 4182 } 4183 4184 if( width == remainder.size() ) { 4185 spliceLine( indent, remainder, width ); 4186 } 4187 else if( remainder[width] == '\n' ) { 4188 spliceLine( indent, remainder, width ); 4189 if( width <= 1 || remainder.size() != 1 ) 4190 remainder = remainder.substr( 1 ); 4191 indent = _attr.indent; 4192 } 4193 else { 4194 pos = remainder.find_last_of( wrappableChars, width ); 4195 if( pos != std::string::npos && pos > 0 ) { 4196 spliceLine( indent, remainder, pos ); 4197 if( remainder[0] == ' ' ) 4198 remainder = remainder.substr( 1 ); 4199 } 4200 else { 4201 spliceLine( indent, remainder, width-1 ); 4202 lines.back() += "-"; 4203 } 4204 if( lines.size() == 1 ) 4205 indent = _attr.indent; 4206 if( tabPos != std::string::npos ) 4207 indent += tabPos; 4208 } 4209 } 4210 } 4211 4212 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) { 4213 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) ); 4214 _remainder = _remainder.substr( _pos ); 4215 } 4216 4217 typedef std::vector<std::string>::const_iterator const_iterator; 4218 4219 const_iterator begin() const { return lines.begin(); } 4220 const_iterator end() const { return lines.end(); } 4221 std::string const& last() const { return lines.back(); } 4222 std::size_t size() const { return lines.size(); } 4223 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } 4224 std::string toString() const { 4225 std::ostringstream oss; 4226 oss << *this; 4227 return oss.str(); 4228 } 4229 4230 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { 4231 for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); 4232 it != itEnd; ++it ) { 4233 if( it != _text.begin() ) 4234 _stream << "\n"; 4235 _stream << *it; 4236 } 4237 return _stream; 4238 } 4239 4240 private: 4241 std::string str; 4242 TextAttributes attr; 4243 std::vector<std::string> lines; 4244 }; 4245 4246 } // end namespace Tbc 4247 4248 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE 4249 } // end outer namespace 4250 #endif 4251 4252 #endif // TBC_TEXT_FORMAT_H_INCLUDED 4253 4254 // ----------- end of #include from tbc_text_format.h ----------- 4255 // ........... back in clara.h 4256 4257 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE 4258 4259 // ----------- #included from clara_compilers.h ----------- 4260 4261 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED 4262 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED 4263 4264 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler 4265 // The following features are defined: 4266 // 4267 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported? 4268 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported? 4269 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods 4270 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported? 4271 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr) 4272 4273 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported? 4274 4275 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported? 4276 4277 // In general each macro has a _NO_<feature name> form 4278 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature. 4279 // Many features, at point of detection, define an _INTERNAL_ macro, so they 4280 // can be combined, en-mass, with the _NO_ forms later. 4281 4282 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11 4283 4284 #ifdef __clang__ 4285 4286 #if __has_feature(cxx_nullptr) 4287 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR 4288 #endif 4289 4290 #if __has_feature(cxx_noexcept) 4291 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT 4292 #endif 4293 4294 #endif // __clang__ 4295 4296 //////////////////////////////////////////////////////////////////////////////// 4297 // GCC 4298 #ifdef __GNUC__ 4299 4300 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__) 4301 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR 4302 #endif 4303 4304 // - otherwise more recent versions define __cplusplus >= 201103L 4305 // and will get picked up below 4306 4307 #endif // __GNUC__ 4308 4309 //////////////////////////////////////////////////////////////////////////////// 4310 // Visual C++ 4311 #ifdef _MSC_VER 4312 4313 #if (_MSC_VER >= 1600) 4314 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR 4315 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR 4316 #endif 4317 4318 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015)) 4319 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT 4320 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 4321 #endif 4322 4323 #endif // _MSC_VER 4324 4325 //////////////////////////////////////////////////////////////////////////////// 4326 // C++ language feature support 4327 4328 // catch all support for C++11 4329 #if defined(__cplusplus) && __cplusplus >= 201103L 4330 4331 #define CLARA_CPP11_OR_GREATER 4332 4333 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) 4334 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR 4335 #endif 4336 4337 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT 4338 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT 4339 #endif 4340 4341 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 4342 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS 4343 #endif 4344 4345 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) 4346 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE 4347 #endif 4348 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) 4349 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR 4350 #endif 4351 4352 #endif // __cplusplus >= 201103L 4353 4354 // Now set the actual defines based on the above + anything the user has configured 4355 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11) 4356 #define CLARA_CONFIG_CPP11_NULLPTR 4357 #endif 4358 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11) 4359 #define CLARA_CONFIG_CPP11_NOEXCEPT 4360 #endif 4361 #if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11) 4362 #define CLARA_CONFIG_CPP11_GENERATED_METHODS 4363 #endif 4364 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11) 4365 #define CLARA_CONFIG_CPP11_OVERRIDE 4366 #endif 4367 #if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11) 4368 #define CLARA_CONFIG_CPP11_UNIQUE_PTR 4369 #endif 4370 4371 // noexcept support: 4372 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT) 4373 #define CLARA_NOEXCEPT noexcept 4374 # define CLARA_NOEXCEPT_IS(x) noexcept(x) 4375 #else 4376 #define CLARA_NOEXCEPT throw() 4377 # define CLARA_NOEXCEPT_IS(x) 4378 #endif 4379 4380 // nullptr support 4381 #ifdef CLARA_CONFIG_CPP11_NULLPTR 4382 #define CLARA_NULL nullptr 4383 #else 4384 #define CLARA_NULL NULL 4385 #endif 4386 4387 // override support 4388 #ifdef CLARA_CONFIG_CPP11_OVERRIDE 4389 #define CLARA_OVERRIDE override 4390 #else 4391 #define CLARA_OVERRIDE 4392 #endif 4393 4394 // unique_ptr support 4395 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR 4396 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T> 4397 #else 4398 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T> 4399 #endif 4400 4401 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED 4402 4403 // ----------- end of #include from clara_compilers.h ----------- 4404 // ........... back in clara.h 4405 4406 #include <map> 4407 #include <stdexcept> 4408 #include <memory> 4409 4410 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) 4411 #define CLARA_PLATFORM_WINDOWS 4412 #endif 4413 4414 // Use optional outer namespace 4415 #ifdef STITCH_CLARA_OPEN_NAMESPACE 4416 STITCH_CLARA_OPEN_NAMESPACE 4417 #endif 4418 4419 namespace Clara { 4420 4421 struct UnpositionalTag {}; 4422 4423 extern UnpositionalTag _; 4424 4425 #ifdef CLARA_CONFIG_MAIN 4426 UnpositionalTag _; 4427 #endif 4428 4429 namespace Detail { 4430 4431 #ifdef CLARA_CONSOLE_WIDTH 4432 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH; 4433 #else 4434 const unsigned int consoleWidth = 80; 4435 #endif 4436 4437 using namespace Tbc; 4438 4439 inline bool startsWith( std::string const& str, std::string const& prefix ) { 4440 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix; 4441 } 4442 4443 template<typename T> struct RemoveConstRef{ typedef T type; }; 4444 template<typename T> struct RemoveConstRef<T&>{ typedef T type; }; 4445 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; }; 4446 template<typename T> struct RemoveConstRef<T const>{ typedef T type; }; 4447 4448 template<typename T> struct IsBool { static const bool value = false; }; 4449 template<> struct IsBool<bool> { static const bool value = true; }; 4450 4451 template<typename T> 4452 void convertInto( std::string const& _source, T& _dest ) { 4453 std::stringstream ss; 4454 ss << _source; 4455 ss >> _dest; 4456 if( ss.fail() ) 4457 throw std::runtime_error( "Unable to convert " + _source + " to destination type" ); 4458 } 4459 inline void convertInto( std::string const& _source, std::string& _dest ) { 4460 _dest = _source; 4461 } 4462 char toLowerCh(char c) { 4463 return static_cast<char>( std::tolower( c ) ); 4464 } 4465 inline void convertInto( std::string const& _source, bool& _dest ) { 4466 std::string sourceLC = _source; 4467 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh ); 4468 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" ) 4469 _dest = true; 4470 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" ) 4471 _dest = false; 4472 else 4473 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" ); 4474 } 4475 4476 template<typename ConfigT> 4477 struct IArgFunction { 4478 virtual ~IArgFunction() {} 4479 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS 4480 IArgFunction() = default; 4481 IArgFunction( IArgFunction const& ) = default; 4482 #endif 4483 virtual void set( ConfigT& config, std::string const& value ) const = 0; 4484 virtual bool takesArg() const = 0; 4485 virtual IArgFunction* clone() const = 0; 4486 }; 4487 4488 template<typename ConfigT> 4489 class BoundArgFunction { 4490 public: 4491 BoundArgFunction() : functionObj( CLARA_NULL ) {} 4492 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {} 4493 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {} 4494 BoundArgFunction& operator = ( BoundArgFunction const& other ) { 4495 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL; 4496 delete functionObj; 4497 functionObj = newFunctionObj; 4498 return *this; 4499 } 4500 ~BoundArgFunction() { delete functionObj; } 4501 4502 void set( ConfigT& config, std::string const& value ) const { 4503 functionObj->set( config, value ); 4504 } 4505 bool takesArg() const { return functionObj->takesArg(); } 4506 4507 bool isSet() const { 4508 return functionObj != CLARA_NULL; 4509 } 4510 private: 4511 IArgFunction<ConfigT>* functionObj; 4512 }; 4513 4514 template<typename C> 4515 struct NullBinder : IArgFunction<C>{ 4516 virtual void set( C&, std::string const& ) const {} 4517 virtual bool takesArg() const { return true; } 4518 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); } 4519 }; 4520 4521 template<typename C, typename M> 4522 struct BoundDataMember : IArgFunction<C>{ 4523 BoundDataMember( M C::* _member ) : member( _member ) {} 4524 virtual void set( C& p, std::string const& stringValue ) const { 4525 convertInto( stringValue, p.*member ); 4526 } 4527 virtual bool takesArg() const { return !IsBool<M>::value; } 4528 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); } 4529 M C::* member; 4530 }; 4531 template<typename C, typename M> 4532 struct BoundUnaryMethod : IArgFunction<C>{ 4533 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {} 4534 virtual void set( C& p, std::string const& stringValue ) const { 4535 typename RemoveConstRef<M>::type value; 4536 convertInto( stringValue, value ); 4537 (p.*member)( value ); 4538 } 4539 virtual bool takesArg() const { return !IsBool<M>::value; } 4540 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); } 4541 void (C::*member)( M ); 4542 }; 4543 template<typename C> 4544 struct BoundNullaryMethod : IArgFunction<C>{ 4545 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {} 4546 virtual void set( C& p, std::string const& stringValue ) const { 4547 bool value; 4548 convertInto( stringValue, value ); 4549 if( value ) 4550 (p.*member)(); 4551 } 4552 virtual bool takesArg() const { return false; } 4553 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); } 4554 void (C::*member)(); 4555 }; 4556 4557 template<typename C> 4558 struct BoundUnaryFunction : IArgFunction<C>{ 4559 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {} 4560 virtual void set( C& obj, std::string const& stringValue ) const { 4561 bool value; 4562 convertInto( stringValue, value ); 4563 if( value ) 4564 function( obj ); 4565 } 4566 virtual bool takesArg() const { return false; } 4567 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); } 4568 void (*function)( C& ); 4569 }; 4570 4571 template<typename C, typename T> 4572 struct BoundBinaryFunction : IArgFunction<C>{ 4573 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {} 4574 virtual void set( C& obj, std::string const& stringValue ) const { 4575 typename RemoveConstRef<T>::type value; 4576 convertInto( stringValue, value ); 4577 function( obj, value ); 4578 } 4579 virtual bool takesArg() const { return !IsBool<T>::value; } 4580 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); } 4581 void (*function)( C&, T ); 4582 }; 4583 4584 } // namespace Detail 4585 4586 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) { 4587 std::vector<std::string> args( static_cast<std::size_t>( argc ) ); 4588 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i ) 4589 args[i] = argv[i]; 4590 4591 return args; 4592 } 4593 4594 class Parser { 4595 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional }; 4596 Mode mode; 4597 std::size_t from; 4598 bool inQuotes; 4599 public: 4600 4601 struct Token { 4602 enum Type { Positional, ShortOpt, LongOpt }; 4603 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {} 4604 Type type; 4605 std::string data; 4606 }; 4607 4608 Parser() : mode( None ), from( 0 ), inQuotes( false ){} 4609 4610 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) { 4611 const std::string doubleDash = "--"; 4612 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i ) 4613 parseIntoTokens( args[i], tokens); 4614 } 4615 4616 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) { 4617 for( std::size_t i = 0; i < arg.size(); ++i ) { 4618 char c = arg[i]; 4619 if( c == '"' ) 4620 inQuotes = !inQuotes; 4621 mode = handleMode( i, c, arg, tokens ); 4622 } 4623 mode = handleMode( arg.size(), '\0', arg, tokens ); 4624 } 4625 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { 4626 switch( mode ) { 4627 case None: return handleNone( i, c ); 4628 case MaybeShortOpt: return handleMaybeShortOpt( i, c ); 4629 case ShortOpt: 4630 case LongOpt: 4631 case SlashOpt: return handleOpt( i, c, arg, tokens ); 4632 case Positional: return handlePositional( i, c, arg, tokens ); 4633 default: throw std::logic_error( "Unknown mode" ); 4634 } 4635 } 4636 4637 Mode handleNone( std::size_t i, char c ) { 4638 if( inQuotes ) { 4639 from = i; 4640 return Positional; 4641 } 4642 switch( c ) { 4643 case '-': return MaybeShortOpt; 4644 #ifdef CLARA_PLATFORM_WINDOWS 4645 case '/': from = i+1; return SlashOpt; 4646 #endif 4647 default: from = i; return Positional; 4648 } 4649 } 4650 Mode handleMaybeShortOpt( std::size_t i, char c ) { 4651 switch( c ) { 4652 case '-': from = i+1; return LongOpt; 4653 default: from = i; return ShortOpt; 4654 } 4655 } 4656 4657 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { 4658 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos ) 4659 return mode; 4660 4661 std::string optName = arg.substr( from, i-from ); 4662 if( mode == ShortOpt ) 4663 for( std::size_t j = 0; j < optName.size(); ++j ) 4664 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) ); 4665 else if( mode == SlashOpt && optName.size() == 1 ) 4666 tokens.push_back( Token( Token::ShortOpt, optName ) ); 4667 else 4668 tokens.push_back( Token( Token::LongOpt, optName ) ); 4669 return None; 4670 } 4671 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) { 4672 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos ) 4673 return mode; 4674 4675 std::string data = arg.substr( from, i-from ); 4676 tokens.push_back( Token( Token::Positional, data ) ); 4677 return None; 4678 } 4679 }; 4680 4681 template<typename ConfigT> 4682 struct CommonArgProperties { 4683 CommonArgProperties() {} 4684 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {} 4685 4686 Detail::BoundArgFunction<ConfigT> boundField; 4687 std::string description; 4688 std::string detail; 4689 std::string placeholder; // Only value if boundField takes an arg 4690 4691 bool takesArg() const { 4692 return !placeholder.empty(); 4693 } 4694 void validate() const { 4695 if( !boundField.isSet() ) 4696 throw std::logic_error( "option not bound" ); 4697 } 4698 }; 4699 struct OptionArgProperties { 4700 std::vector<std::string> shortNames; 4701 std::string longName; 4702 4703 bool hasShortName( std::string const& shortName ) const { 4704 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end(); 4705 } 4706 bool hasLongName( std::string const& _longName ) const { 4707 return _longName == longName; 4708 } 4709 }; 4710 struct PositionalArgProperties { 4711 PositionalArgProperties() : position( -1 ) {} 4712 int position; // -1 means non-positional (floating) 4713 4714 bool isFixedPositional() const { 4715 return position != -1; 4716 } 4717 }; 4718 4719 template<typename ConfigT> 4720 class CommandLine { 4721 4722 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties { 4723 Arg() {} 4724 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {} 4725 4726 using CommonArgProperties<ConfigT>::placeholder; // !TBD 4727 4728 std::string dbgName() const { 4729 if( !longName.empty() ) 4730 return "--" + longName; 4731 if( !shortNames.empty() ) 4732 return "-" + shortNames[0]; 4733 return "positional args"; 4734 } 4735 std::string commands() const { 4736 std::ostringstream oss; 4737 bool first = true; 4738 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end(); 4739 for(; it != itEnd; ++it ) { 4740 if( first ) 4741 first = false; 4742 else 4743 oss << ", "; 4744 oss << "-" << *it; 4745 } 4746 if( !longName.empty() ) { 4747 if( !first ) 4748 oss << ", "; 4749 oss << "--" << longName; 4750 } 4751 if( !placeholder.empty() ) 4752 oss << " <" << placeholder << ">"; 4753 return oss.str(); 4754 } 4755 }; 4756 4757 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr; 4758 4759 friend void addOptName( Arg& arg, std::string const& optName ) 4760 { 4761 if( optName.empty() ) 4762 return; 4763 if( Detail::startsWith( optName, "--" ) ) { 4764 if( !arg.longName.empty() ) 4765 throw std::logic_error( "Only one long opt may be specified. '" 4766 + arg.longName 4767 + "' already specified, now attempting to add '" 4768 + optName + "'" ); 4769 arg.longName = optName.substr( 2 ); 4770 } 4771 else if( Detail::startsWith( optName, "-" ) ) 4772 arg.shortNames.push_back( optName.substr( 1 ) ); 4773 else 4774 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" ); 4775 } 4776 friend void setPositionalArg( Arg& arg, int position ) 4777 { 4778 arg.position = position; 4779 } 4780 4781 class ArgBuilder { 4782 public: 4783 ArgBuilder( Arg* arg ) : m_arg( arg ) {} 4784 4785 // Bind a non-boolean data member (requires placeholder string) 4786 template<typename C, typename M> 4787 void bind( M C::* field, std::string const& placeholder ) { 4788 m_arg->boundField = new Detail::BoundDataMember<C,M>( field ); 4789 m_arg->placeholder = placeholder; 4790 } 4791 // Bind a boolean data member (no placeholder required) 4792 template<typename C> 4793 void bind( bool C::* field ) { 4794 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field ); 4795 } 4796 4797 // Bind a method taking a single, non-boolean argument (requires a placeholder string) 4798 template<typename C, typename M> 4799 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) { 4800 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod ); 4801 m_arg->placeholder = placeholder; 4802 } 4803 4804 // Bind a method taking a single, boolean argument (no placeholder string required) 4805 template<typename C> 4806 void bind( void (C::* unaryMethod)( bool ) ) { 4807 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod ); 4808 } 4809 4810 // Bind a method that takes no arguments (will be called if opt is present) 4811 template<typename C> 4812 void bind( void (C::* nullaryMethod)() ) { 4813 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod ); 4814 } 4815 4816 // Bind a free function taking a single argument - the object to operate on (no placeholder string required) 4817 template<typename C> 4818 void bind( void (* unaryFunction)( C& ) ) { 4819 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction ); 4820 } 4821 4822 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string) 4823 template<typename C, typename T> 4824 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) { 4825 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction ); 4826 m_arg->placeholder = placeholder; 4827 } 4828 4829 ArgBuilder& describe( std::string const& description ) { 4830 m_arg->description = description; 4831 return *this; 4832 } 4833 ArgBuilder& detail( std::string const& detail ) { 4834 m_arg->detail = detail; 4835 return *this; 4836 } 4837 4838 protected: 4839 Arg* m_arg; 4840 }; 4841 4842 class OptBuilder : public ArgBuilder { 4843 public: 4844 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {} 4845 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {} 4846 4847 OptBuilder& operator[]( std::string const& optName ) { 4848 addOptName( *ArgBuilder::m_arg, optName ); 4849 return *this; 4850 } 4851 }; 4852 4853 public: 4854 4855 CommandLine() 4856 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ), 4857 m_highestSpecifiedArgPosition( 0 ), 4858 m_throwOnUnrecognisedTokens( false ) 4859 {} 4860 CommandLine( CommandLine const& other ) 4861 : m_boundProcessName( other.m_boundProcessName ), 4862 m_options ( other.m_options ), 4863 m_positionalArgs( other.m_positionalArgs ), 4864 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ), 4865 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens ) 4866 { 4867 if( other.m_floatingArg.get() ) 4868 m_floatingArg.reset( new Arg( *other.m_floatingArg ) ); 4869 } 4870 4871 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) { 4872 m_throwOnUnrecognisedTokens = shouldThrow; 4873 return *this; 4874 } 4875 4876 OptBuilder operator[]( std::string const& optName ) { 4877 m_options.push_back( Arg() ); 4878 addOptName( m_options.back(), optName ); 4879 OptBuilder builder( &m_options.back() ); 4880 return builder; 4881 } 4882 4883 ArgBuilder operator[]( int position ) { 4884 m_positionalArgs.insert( std::make_pair( position, Arg() ) ); 4885 if( position > m_highestSpecifiedArgPosition ) 4886 m_highestSpecifiedArgPosition = position; 4887 setPositionalArg( m_positionalArgs[position], position ); 4888 ArgBuilder builder( &m_positionalArgs[position] ); 4889 return builder; 4890 } 4891 4892 // Invoke this with the _ instance 4893 ArgBuilder operator[]( UnpositionalTag ) { 4894 if( m_floatingArg.get() ) 4895 throw std::logic_error( "Only one unpositional argument can be added" ); 4896 m_floatingArg.reset( new Arg() ); 4897 ArgBuilder builder( m_floatingArg.get() ); 4898 return builder; 4899 } 4900 4901 template<typename C, typename M> 4902 void bindProcessName( M C::* field ) { 4903 m_boundProcessName = new Detail::BoundDataMember<C,M>( field ); 4904 } 4905 template<typename C, typename M> 4906 void bindProcessName( void (C::*_unaryMethod)( M ) ) { 4907 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod ); 4908 } 4909 4910 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const { 4911 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it; 4912 std::size_t maxWidth = 0; 4913 for( it = itBegin; it != itEnd; ++it ) 4914 maxWidth = (std::max)( maxWidth, it->commands().size() ); 4915 4916 for( it = itBegin; it != itEnd; ++it ) { 4917 Detail::Text usage( it->commands(), Detail::TextAttributes() 4918 .setWidth( maxWidth+indent ) 4919 .setIndent( indent ) ); 4920 Detail::Text desc( it->description, Detail::TextAttributes() 4921 .setWidth( width - maxWidth - 3 ) ); 4922 4923 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) { 4924 std::string usageCol = i < usage.size() ? usage[i] : ""; 4925 os << usageCol; 4926 4927 if( i < desc.size() && !desc[i].empty() ) 4928 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' ) 4929 << desc[i]; 4930 os << "\n"; 4931 } 4932 } 4933 } 4934 std::string optUsage() const { 4935 std::ostringstream oss; 4936 optUsage( oss ); 4937 return oss.str(); 4938 } 4939 4940 void argSynopsis( std::ostream& os ) const { 4941 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) { 4942 if( i > 1 ) 4943 os << " "; 4944 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i ); 4945 if( it != m_positionalArgs.end() ) 4946 os << "<" << it->second.placeholder << ">"; 4947 else if( m_floatingArg.get() ) 4948 os << "<" << m_floatingArg->placeholder << ">"; 4949 else 4950 throw std::logic_error( "non consecutive positional arguments with no floating args" ); 4951 } 4952 // !TBD No indication of mandatory args 4953 if( m_floatingArg.get() ) { 4954 if( m_highestSpecifiedArgPosition > 1 ) 4955 os << " "; 4956 os << "[<" << m_floatingArg->placeholder << "> ...]"; 4957 } 4958 } 4959 std::string argSynopsis() const { 4960 std::ostringstream oss; 4961 argSynopsis( oss ); 4962 return oss.str(); 4963 } 4964 4965 void usage( std::ostream& os, std::string const& procName ) const { 4966 validate(); 4967 os << "usage:\n " << procName << " "; 4968 argSynopsis( os ); 4969 if( !m_options.empty() ) { 4970 os << " [options]\n\nwhere options are: \n"; 4971 optUsage( os, 2 ); 4972 } 4973 os << "\n"; 4974 } 4975 std::string usage( std::string const& procName ) const { 4976 std::ostringstream oss; 4977 usage( oss, procName ); 4978 return oss.str(); 4979 } 4980 4981 ConfigT parse( std::vector<std::string> const& args ) const { 4982 ConfigT config; 4983 parseInto( args, config ); 4984 return config; 4985 } 4986 4987 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const { 4988 std::string processName = args.empty() ? std::string() : args[0]; 4989 std::size_t lastSlash = processName.find_last_of( "/\\" ); 4990 if( lastSlash != std::string::npos ) 4991 processName = processName.substr( lastSlash+1 ); 4992 m_boundProcessName.set( config, processName ); 4993 std::vector<Parser::Token> tokens; 4994 Parser parser; 4995 parser.parseIntoTokens( args, tokens ); 4996 return populate( tokens, config ); 4997 } 4998 4999 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { 5000 validate(); 5001 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config ); 5002 unusedTokens = populateFixedArgs( unusedTokens, config ); 5003 unusedTokens = populateFloatingArgs( unusedTokens, config ); 5004 return unusedTokens; 5005 } 5006 5007 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { 5008 std::vector<Parser::Token> unusedTokens; 5009 std::vector<std::string> errors; 5010 for( std::size_t i = 0; i < tokens.size(); ++i ) { 5011 Parser::Token const& token = tokens[i]; 5012 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end(); 5013 for(; it != itEnd; ++it ) { 5014 Arg const& arg = *it; 5015 5016 try { 5017 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) || 5018 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) { 5019 if( arg.takesArg() ) { 5020 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional ) 5021 errors.push_back( "Expected argument to option: " + token.data ); 5022 else 5023 arg.boundField.set( config, tokens[++i].data ); 5024 } 5025 else { 5026 arg.boundField.set( config, "true" ); 5027 } 5028 break; 5029 } 5030 } 5031 catch( std::exception& ex ) { 5032 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" ); 5033 } 5034 } 5035 if( it == itEnd ) { 5036 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens ) 5037 unusedTokens.push_back( token ); 5038 else if( errors.empty() && m_throwOnUnrecognisedTokens ) 5039 errors.push_back( "unrecognised option: " + token.data ); 5040 } 5041 } 5042 if( !errors.empty() ) { 5043 std::ostringstream oss; 5044 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end(); 5045 it != itEnd; 5046 ++it ) { 5047 if( it != errors.begin() ) 5048 oss << "\n"; 5049 oss << *it; 5050 } 5051 throw std::runtime_error( oss.str() ); 5052 } 5053 return unusedTokens; 5054 } 5055 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { 5056 std::vector<Parser::Token> unusedTokens; 5057 int position = 1; 5058 for( std::size_t i = 0; i < tokens.size(); ++i ) { 5059 Parser::Token const& token = tokens[i]; 5060 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position ); 5061 if( it != m_positionalArgs.end() ) 5062 it->second.boundField.set( config, token.data ); 5063 else 5064 unusedTokens.push_back( token ); 5065 if( token.type == Parser::Token::Positional ) 5066 position++; 5067 } 5068 return unusedTokens; 5069 } 5070 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const { 5071 if( !m_floatingArg.get() ) 5072 return tokens; 5073 std::vector<Parser::Token> unusedTokens; 5074 for( std::size_t i = 0; i < tokens.size(); ++i ) { 5075 Parser::Token const& token = tokens[i]; 5076 if( token.type == Parser::Token::Positional ) 5077 m_floatingArg->boundField.set( config, token.data ); 5078 else 5079 unusedTokens.push_back( token ); 5080 } 5081 return unusedTokens; 5082 } 5083 5084 void validate() const 5085 { 5086 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() ) 5087 throw std::logic_error( "No options or arguments specified" ); 5088 5089 for( typename std::vector<Arg>::const_iterator it = m_options.begin(), 5090 itEnd = m_options.end(); 5091 it != itEnd; ++it ) 5092 it->validate(); 5093 } 5094 5095 private: 5096 Detail::BoundArgFunction<ConfigT> m_boundProcessName; 5097 std::vector<Arg> m_options; 5098 std::map<int, Arg> m_positionalArgs; 5099 ArgAutoPtr m_floatingArg; 5100 int m_highestSpecifiedArgPosition; 5101 bool m_throwOnUnrecognisedTokens; 5102 }; 5103 5104 } // end namespace Clara 5105 5106 STITCH_CLARA_CLOSE_NAMESPACE 5107 #undef STITCH_CLARA_OPEN_NAMESPACE 5108 #undef STITCH_CLARA_CLOSE_NAMESPACE 5109 5110 #endif // TWOBLUECUBES_CLARA_H_INCLUDED 5111 #undef STITCH_CLARA_OPEN_NAMESPACE 5112 5113 // Restore Clara's value for console width, if present 5114 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 5115 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 5116 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH 5117 #endif 5118 5119 #include <fstream> 5120 #include <ctime> 5121 5122 namespace Catch { 5123 5124 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; } 5125 inline void abortAfterX( ConfigData& config, int x ) { 5126 if( x < 1 ) 5127 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" ); 5128 config.abortAfter = x; 5129 } 5130 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); } 5131 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); } 5132 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); } 5133 5134 inline void addWarning( ConfigData& config, std::string const& _warning ) { 5135 if( _warning == "NoAssertions" ) 5136 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions ); 5137 else 5138 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' ); 5139 } 5140 inline void setOrder( ConfigData& config, std::string const& order ) { 5141 if( startsWith( "declared", order ) ) 5142 config.runOrder = RunTests::InDeclarationOrder; 5143 else if( startsWith( "lexical", order ) ) 5144 config.runOrder = RunTests::InLexicographicalOrder; 5145 else if( startsWith( "random", order ) ) 5146 config.runOrder = RunTests::InRandomOrder; 5147 else 5148 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' ); 5149 } 5150 inline void setRngSeed( ConfigData& config, std::string const& seed ) { 5151 if( seed == "time" ) { 5152 config.rngSeed = static_cast<unsigned int>( std::time(0) ); 5153 } 5154 else { 5155 std::stringstream ss; 5156 ss << seed; 5157 ss >> config.rngSeed; 5158 if( ss.fail() ) 5159 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" ); 5160 } 5161 } 5162 inline void setVerbosity( ConfigData& config, int level ) { 5163 // !TBD: accept strings? 5164 config.verbosity = static_cast<Verbosity::Level>( level ); 5165 } 5166 inline void setShowDurations( ConfigData& config, bool _showDurations ) { 5167 config.showDurations = _showDurations 5168 ? ShowDurations::Always 5169 : ShowDurations::Never; 5170 } 5171 inline void setUseColour( ConfigData& config, std::string const& value ) { 5172 std::string mode = toLower( value ); 5173 5174 if( mode == "yes" ) 5175 config.useColour = UseColour::Yes; 5176 else if( mode == "no" ) 5177 config.useColour = UseColour::No; 5178 else if( mode == "auto" ) 5179 config.useColour = UseColour::Auto; 5180 else 5181 throw std::runtime_error( "colour mode must be one of: auto, yes or no" ); 5182 } 5183 inline void forceColour( ConfigData& config ) { 5184 config.useColour = UseColour::Yes; 5185 } 5186 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) { 5187 std::ifstream f( _filename.c_str() ); 5188 if( !f.is_open() ) 5189 throw std::domain_error( "Unable to load input file: " + _filename ); 5190 5191 std::string line; 5192 while( std::getline( f, line ) ) { 5193 line = trim(line); 5194 if( !line.empty() && !startsWith( line, '#' ) ) { 5195 if( !startsWith( line, '"' ) ) 5196 line = '"' + line + '"'; 5197 addTestOrTags( config, line + ',' ); 5198 } 5199 } 5200 } 5201 5202 inline Clara::CommandLine<ConfigData> makeCommandLineParser() { 5203 5204 using namespace Clara; 5205 CommandLine<ConfigData> cli; 5206 5207 cli.bindProcessName( &ConfigData::processName ); 5208 5209 cli["-?"]["-h"]["--help"] 5210 .describe( "display usage information" ) 5211 .bind( &ConfigData::showHelp ); 5212 5213 cli["-l"]["--list-tests"] 5214 .describe( "list all/matching test cases" ) 5215 .bind( &ConfigData::listTests ); 5216 5217 cli["-t"]["--list-tags"] 5218 .describe( "list all/matching tags" ) 5219 .bind( &ConfigData::listTags ); 5220 5221 cli["-s"]["--success"] 5222 .describe( "include successful tests in output" ) 5223 .bind( &ConfigData::showSuccessfulTests ); 5224 5225 cli["-b"]["--break"] 5226 .describe( "break into debugger on failure" ) 5227 .bind( &ConfigData::shouldDebugBreak ); 5228 5229 cli["-e"]["--nothrow"] 5230 .describe( "skip exception tests" ) 5231 .bind( &ConfigData::noThrow ); 5232 5233 cli["-i"]["--invisibles"] 5234 .describe( "show invisibles (tabs, newlines)" ) 5235 .bind( &ConfigData::showInvisibles ); 5236 5237 cli["-o"]["--out"] 5238 .describe( "output filename" ) 5239 .bind( &ConfigData::outputFilename, "filename" ); 5240 5241 cli["-r"]["--reporter"] 5242 // .placeholder( "name[:filename]" ) 5243 .describe( "reporter to use (defaults to console)" ) 5244 .bind( &addReporterName, "name" ); 5245 5246 cli["-n"]["--name"] 5247 .describe( "suite name" ) 5248 .bind( &ConfigData::name, "name" ); 5249 5250 cli["-a"]["--abort"] 5251 .describe( "abort at first failure" ) 5252 .bind( &abortAfterFirst ); 5253 5254 cli["-x"]["--abortx"] 5255 .describe( "abort after x failures" ) 5256 .bind( &abortAfterX, "no. failures" ); 5257 5258 cli["-w"]["--warn"] 5259 .describe( "enable warnings" ) 5260 .bind( &addWarning, "warning name" ); 5261 5262 // - needs updating if reinstated 5263 // cli.into( &setVerbosity ) 5264 // .describe( "level of verbosity (0=no output)" ) 5265 // .shortOpt( "v") 5266 // .longOpt( "verbosity" ) 5267 // .placeholder( "level" ); 5268 5269 cli[_] 5270 .describe( "which test or tests to use" ) 5271 .bind( &addTestOrTags, "test name, pattern or tags" ); 5272 5273 cli["-d"]["--durations"] 5274 .describe( "show test durations" ) 5275 .bind( &setShowDurations, "yes|no" ); 5276 5277 cli["-f"]["--input-file"] 5278 .describe( "load test names to run from a file" ) 5279 .bind( &loadTestNamesFromFile, "filename" ); 5280 5281 cli["-#"]["--filenames-as-tags"] 5282 .describe( "adds a tag for the filename" ) 5283 .bind( &ConfigData::filenamesAsTags ); 5284 5285 cli["-c"]["--section"] 5286 .describe( "specify section to run" ) 5287 .bind( &addSectionToRun, "section name" ); 5288 5289 // Less common commands which don't have a short form 5290 cli["--list-test-names-only"] 5291 .describe( "list all/matching test cases names only" ) 5292 .bind( &ConfigData::listTestNamesOnly ); 5293 5294 cli["--list-extra-info"] 5295 .describe( "list all/matching test cases with more info" ) 5296 .bind( &ConfigData::listExtraInfo ); 5297 5298 cli["--list-reporters"] 5299 .describe( "list all reporters" ) 5300 .bind( &ConfigData::listReporters ); 5301 5302 cli["--order"] 5303 .describe( "test case order (defaults to decl)" ) 5304 .bind( &setOrder, "decl|lex|rand" ); 5305 5306 cli["--rng-seed"] 5307 .describe( "set a specific seed for random numbers" ) 5308 .bind( &setRngSeed, "'time'|number" ); 5309 5310 cli["--force-colour"] 5311 .describe( "force colourised output (deprecated)" ) 5312 .bind( &forceColour ); 5313 5314 cli["--use-colour"] 5315 .describe( "should output be colourised" ) 5316 .bind( &setUseColour, "yes|no" ); 5317 5318 return cli; 5319 } 5320 5321 } // end namespace Catch 5322 5323 // #included from: internal/catch_list.hpp 5324 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED 5325 5326 // #included from: catch_text.h 5327 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED 5328 5329 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH 5330 5331 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch 5332 // #included from: ../external/tbc_text_format.h 5333 // Only use header guard if we are not using an outer namespace 5334 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE 5335 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED 5336 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED 5337 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED 5338 # endif 5339 # else 5340 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED 5341 # endif 5342 #endif 5343 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED 5344 #include <string> 5345 #include <vector> 5346 #include <sstream> 5347 5348 // Use optional outer namespace 5349 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE 5350 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE { 5351 #endif 5352 5353 namespace Tbc { 5354 5355 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH 5356 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH; 5357 #else 5358 const unsigned int consoleWidth = 80; 5359 #endif 5360 5361 struct TextAttributes { 5362 TextAttributes() 5363 : initialIndent( std::string::npos ), 5364 indent( 0 ), 5365 width( consoleWidth-1 ) 5366 {} 5367 5368 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; } 5369 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; } 5370 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; } 5371 5372 std::size_t initialIndent; // indent of first line, or npos 5373 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos 5374 std::size_t width; // maximum width of text, including indent. Longer text will wrap 5375 }; 5376 5377 class Text { 5378 public: 5379 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() ) 5380 : attr( _attr ) 5381 { 5382 const std::string wrappableBeforeChars = "[({<\t"; 5383 const std::string wrappableAfterChars = "])}>-,./|\\"; 5384 const std::string wrappableInsteadOfChars = " \n\r"; 5385 std::string indent = _attr.initialIndent != std::string::npos 5386 ? std::string( _attr.initialIndent, ' ' ) 5387 : std::string( _attr.indent, ' ' ); 5388 5389 typedef std::string::const_iterator iterator; 5390 iterator it = _str.begin(); 5391 const iterator strEnd = _str.end(); 5392 5393 while( it != strEnd ) { 5394 5395 if( lines.size() >= 1000 ) { 5396 lines.push_back( "... message truncated due to excessive size" ); 5397 return; 5398 } 5399 5400 std::string suffix; 5401 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) ); 5402 iterator itEnd = it+width; 5403 iterator itNext = _str.end(); 5404 5405 iterator itNewLine = std::find( it, itEnd, '\n' ); 5406 if( itNewLine != itEnd ) 5407 itEnd = itNewLine; 5408 5409 if( itEnd != strEnd ) { 5410 bool foundWrapPoint = false; 5411 iterator findIt = itEnd; 5412 do { 5413 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) { 5414 itEnd = findIt+1; 5415 itNext = findIt+1; 5416 foundWrapPoint = true; 5417 } 5418 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) { 5419 itEnd = findIt; 5420 itNext = findIt; 5421 foundWrapPoint = true; 5422 } 5423 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) { 5424 itNext = findIt+1; 5425 itEnd = findIt; 5426 foundWrapPoint = true; 5427 } 5428 if( findIt == it ) 5429 break; 5430 else 5431 --findIt; 5432 } 5433 while( !foundWrapPoint ); 5434 5435 if( !foundWrapPoint ) { 5436 // No good wrap char, so we'll break mid word and add a hyphen 5437 --itEnd; 5438 itNext = itEnd; 5439 suffix = "-"; 5440 } 5441 else { 5442 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos ) 5443 --itEnd; 5444 } 5445 } 5446 lines.push_back( indent + std::string( it, itEnd ) + suffix ); 5447 5448 if( indent.size() != _attr.indent ) 5449 indent = std::string( _attr.indent, ' ' ); 5450 it = itNext; 5451 } 5452 } 5453 5454 typedef std::vector<std::string>::const_iterator const_iterator; 5455 5456 const_iterator begin() const { return lines.begin(); } 5457 const_iterator end() const { return lines.end(); } 5458 std::string const& last() const { return lines.back(); } 5459 std::size_t size() const { return lines.size(); } 5460 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; } 5461 std::string toString() const { 5462 std::ostringstream oss; 5463 oss << *this; 5464 return oss.str(); 5465 } 5466 5467 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) { 5468 for( Text::const_iterator it = _text.begin(), itEnd = _text.end(); 5469 it != itEnd; ++it ) { 5470 if( it != _text.begin() ) 5471 _stream << "\n"; 5472 _stream << *it; 5473 } 5474 return _stream; 5475 } 5476 5477 private: 5478 std::string str; 5479 TextAttributes attr; 5480 std::vector<std::string> lines; 5481 }; 5482 5483 } // end namespace Tbc 5484 5485 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE 5486 } // end outer namespace 5487 #endif 5488 5489 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED 5490 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE 5491 5492 namespace Catch { 5493 using Tbc::Text; 5494 using Tbc::TextAttributes; 5495 } 5496 5497 // #included from: catch_console_colour.hpp 5498 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED 5499 5500 namespace Catch { 5501 5502 struct Colour { 5503 enum Code { 5504 None = 0, 5505 5506 White, 5507 Red, 5508 Green, 5509 Blue, 5510 Cyan, 5511 Yellow, 5512 Grey, 5513 5514 Bright = 0x10, 5515 5516 BrightRed = Bright | Red, 5517 BrightGreen = Bright | Green, 5518 LightGrey = Bright | Grey, 5519 BrightWhite = Bright | White, 5520 5521 // By intention 5522 FileName = LightGrey, 5523 Warning = Yellow, 5524 ResultError = BrightRed, 5525 ResultSuccess = BrightGreen, 5526 ResultExpectedFailure = Warning, 5527 5528 Error = BrightRed, 5529 Success = Green, 5530 5531 OriginalExpression = Cyan, 5532 ReconstructedExpression = Yellow, 5533 5534 SecondaryText = LightGrey, 5535 Headers = White 5536 }; 5537 5538 // Use constructed object for RAII guard 5539 Colour( Code _colourCode ); 5540 Colour( Colour const& other ); 5541 ~Colour(); 5542 5543 // Use static method for one-shot changes 5544 static void use( Code _colourCode ); 5545 5546 private: 5547 bool m_moved; 5548 }; 5549 5550 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; } 5551 5552 } // end namespace Catch 5553 5554 // #included from: catch_interfaces_reporter.h 5555 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED 5556 5557 #include <string> 5558 #include <ostream> 5559 #include <map> 5560 5561 namespace Catch 5562 { 5563 struct ReporterConfig { 5564 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig ) 5565 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {} 5566 5567 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream ) 5568 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {} 5569 5570 std::ostream& stream() const { return *m_stream; } 5571 Ptr<IConfig const> fullConfig() const { return m_fullConfig; } 5572 5573 private: 5574 std::ostream* m_stream; 5575 Ptr<IConfig const> m_fullConfig; 5576 }; 5577 5578 struct ReporterPreferences { 5579 ReporterPreferences() 5580 : shouldRedirectStdOut( false ) 5581 {} 5582 5583 bool shouldRedirectStdOut; 5584 }; 5585 5586 template<typename T> 5587 struct LazyStat : Option<T> { 5588 LazyStat() : used( false ) {} 5589 LazyStat& operator=( T const& _value ) { 5590 Option<T>::operator=( _value ); 5591 used = false; 5592 return *this; 5593 } 5594 void reset() { 5595 Option<T>::reset(); 5596 used = false; 5597 } 5598 bool used; 5599 }; 5600 5601 struct TestRunInfo { 5602 TestRunInfo( std::string const& _name ) : name( _name ) {} 5603 std::string name; 5604 }; 5605 struct GroupInfo { 5606 GroupInfo( std::string const& _name, 5607 std::size_t _groupIndex, 5608 std::size_t _groupsCount ) 5609 : name( _name ), 5610 groupIndex( _groupIndex ), 5611 groupsCounts( _groupsCount ) 5612 {} 5613 5614 std::string name; 5615 std::size_t groupIndex; 5616 std::size_t groupsCounts; 5617 }; 5618 5619 struct AssertionStats { 5620 AssertionStats( AssertionResult const& _assertionResult, 5621 std::vector<MessageInfo> const& _infoMessages, 5622 Totals const& _totals ) 5623 : assertionResult( _assertionResult ), 5624 infoMessages( _infoMessages ), 5625 totals( _totals ) 5626 { 5627 if( assertionResult.hasMessage() ) { 5628 // Copy message into messages list. 5629 // !TBD This should have been done earlier, somewhere 5630 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() ); 5631 builder << assertionResult.getMessage(); 5632 builder.m_info.message = builder.m_stream.str(); 5633 5634 infoMessages.push_back( builder.m_info ); 5635 } 5636 } 5637 virtual ~AssertionStats(); 5638 5639 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 5640 AssertionStats( AssertionStats const& ) = default; 5641 AssertionStats( AssertionStats && ) = default; 5642 AssertionStats& operator = ( AssertionStats const& ) = default; 5643 AssertionStats& operator = ( AssertionStats && ) = default; 5644 # endif 5645 5646 AssertionResult assertionResult; 5647 std::vector<MessageInfo> infoMessages; 5648 Totals totals; 5649 }; 5650 5651 struct SectionStats { 5652 SectionStats( SectionInfo const& _sectionInfo, 5653 Counts const& _assertions, 5654 double _durationInSeconds, 5655 bool _missingAssertions ) 5656 : sectionInfo( _sectionInfo ), 5657 assertions( _assertions ), 5658 durationInSeconds( _durationInSeconds ), 5659 missingAssertions( _missingAssertions ) 5660 {} 5661 virtual ~SectionStats(); 5662 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 5663 SectionStats( SectionStats const& ) = default; 5664 SectionStats( SectionStats && ) = default; 5665 SectionStats& operator = ( SectionStats const& ) = default; 5666 SectionStats& operator = ( SectionStats && ) = default; 5667 # endif 5668 5669 SectionInfo sectionInfo; 5670 Counts assertions; 5671 double durationInSeconds; 5672 bool missingAssertions; 5673 }; 5674 5675 struct TestCaseStats { 5676 TestCaseStats( TestCaseInfo const& _testInfo, 5677 Totals const& _totals, 5678 std::string const& _stdOut, 5679 std::string const& _stdErr, 5680 bool _aborting ) 5681 : testInfo( _testInfo ), 5682 totals( _totals ), 5683 stdOut( _stdOut ), 5684 stdErr( _stdErr ), 5685 aborting( _aborting ) 5686 {} 5687 virtual ~TestCaseStats(); 5688 5689 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 5690 TestCaseStats( TestCaseStats const& ) = default; 5691 TestCaseStats( TestCaseStats && ) = default; 5692 TestCaseStats& operator = ( TestCaseStats const& ) = default; 5693 TestCaseStats& operator = ( TestCaseStats && ) = default; 5694 # endif 5695 5696 TestCaseInfo testInfo; 5697 Totals totals; 5698 std::string stdOut; 5699 std::string stdErr; 5700 bool aborting; 5701 }; 5702 5703 struct TestGroupStats { 5704 TestGroupStats( GroupInfo const& _groupInfo, 5705 Totals const& _totals, 5706 bool _aborting ) 5707 : groupInfo( _groupInfo ), 5708 totals( _totals ), 5709 aborting( _aborting ) 5710 {} 5711 TestGroupStats( GroupInfo const& _groupInfo ) 5712 : groupInfo( _groupInfo ), 5713 aborting( false ) 5714 {} 5715 virtual ~TestGroupStats(); 5716 5717 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS 5718 TestGroupStats( TestGroupStats const& ) = default; 5719 TestGroupStats( TestGroupStats && ) = default; 5720 TestGroupStats& operator = ( TestGroupStats const& ) = default; 5721 TestGroupStats& operator = ( TestGroupStats && ) = default; 5722 # endif 5723 5724 GroupInfo groupInfo; 5725 Totals totals; 5726 bool aborting; 5727 }; 5728 5729 struct TestRunStats { 5730 TestRunStats( TestRunInfo const& _runInfo, 5731 Totals const& _totals, 5732 bool _aborting ) 5733 : runInfo( _runInfo ), 5734 totals( _totals ), 5735 aborting( _aborting ) 5736 {} 5737 virtual ~TestRunStats(); 5738 5739 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS 5740 TestRunStats( TestRunStats const& _other ) 5741 : runInfo( _other.runInfo ), 5742 totals( _other.totals ), 5743 aborting( _other.aborting ) 5744 {} 5745 # else 5746 TestRunStats( TestRunStats const& ) = default; 5747 TestRunStats( TestRunStats && ) = default; 5748 TestRunStats& operator = ( TestRunStats const& ) = default; 5749 TestRunStats& operator = ( TestRunStats && ) = default; 5750 # endif 5751 5752 TestRunInfo runInfo; 5753 Totals totals; 5754 bool aborting; 5755 }; 5756 5757 class MultipleReporters; 5758 5759 struct IStreamingReporter : IShared { 5760 virtual ~IStreamingReporter(); 5761 5762 // Implementing class must also provide the following static method: 5763 // static std::string getDescription(); 5764 5765 virtual ReporterPreferences getPreferences() const = 0; 5766 5767 virtual void noMatchingTestCases( std::string const& spec ) = 0; 5768 5769 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0; 5770 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0; 5771 5772 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0; 5773 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0; 5774 5775 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0; 5776 5777 // The return value indicates if the messages buffer should be cleared: 5778 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0; 5779 5780 virtual void sectionEnded( SectionStats const& sectionStats ) = 0; 5781 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0; 5782 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0; 5783 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0; 5784 5785 virtual void skipTest( TestCaseInfo const& testInfo ) = 0; 5786 5787 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; } 5788 }; 5789 5790 struct IReporterFactory : IShared { 5791 virtual ~IReporterFactory(); 5792 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0; 5793 virtual std::string getDescription() const = 0; 5794 }; 5795 5796 struct IReporterRegistry { 5797 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap; 5798 typedef std::vector<Ptr<IReporterFactory> > Listeners; 5799 5800 virtual ~IReporterRegistry(); 5801 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0; 5802 virtual FactoryMap const& getFactories() const = 0; 5803 virtual Listeners const& getListeners() const = 0; 5804 }; 5805 5806 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ); 5807 5808 } 5809 5810 #include <limits> 5811 #include <algorithm> 5812 5813 namespace Catch { 5814 5815 inline std::size_t listTests( Config const& config ) { 5816 5817 TestSpec testSpec = config.testSpec(); 5818 if( config.testSpec().hasFilters() ) 5819 Catch::cout() << "Matching test cases:\n"; 5820 else { 5821 Catch::cout() << "All available test cases:\n"; 5822 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 5823 } 5824 5825 std::size_t matchedTests = 0; 5826 TextAttributes nameAttr, descAttr, tagsAttr; 5827 nameAttr.setInitialIndent( 2 ).setIndent( 4 ); 5828 descAttr.setIndent( 4 ); 5829 tagsAttr.setIndent( 6 ); 5830 5831 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 5832 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 5833 it != itEnd; 5834 ++it ) { 5835 matchedTests++; 5836 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); 5837 Colour::Code colour = testCaseInfo.isHidden() 5838 ? Colour::SecondaryText 5839 : Colour::None; 5840 Colour colourGuard( colour ); 5841 5842 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl; 5843 if( config.listExtraInfo() ) { 5844 Catch::cout() << " " << testCaseInfo.lineInfo << std::endl; 5845 std::string description = testCaseInfo.description; 5846 if( description.empty() ) 5847 description = "(NO DESCRIPTION)"; 5848 Catch::cout() << Text( description, descAttr ) << std::endl; 5849 } 5850 if( !testCaseInfo.tags.empty() ) 5851 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl; 5852 } 5853 5854 if( !config.testSpec().hasFilters() ) 5855 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl; 5856 else 5857 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl; 5858 return matchedTests; 5859 } 5860 5861 inline std::size_t listTestsNamesOnly( Config const& config ) { 5862 TestSpec testSpec = config.testSpec(); 5863 if( !config.testSpec().hasFilters() ) 5864 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 5865 std::size_t matchedTests = 0; 5866 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 5867 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 5868 it != itEnd; 5869 ++it ) { 5870 matchedTests++; 5871 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo(); 5872 if( startsWith( testCaseInfo.name, '#' ) ) 5873 Catch::cout() << '"' << testCaseInfo.name << '"'; 5874 else 5875 Catch::cout() << testCaseInfo.name; 5876 if ( config.listExtraInfo() ) 5877 Catch::cout() << "\t@" << testCaseInfo.lineInfo; 5878 Catch::cout() << std::endl; 5879 } 5880 return matchedTests; 5881 } 5882 5883 struct TagInfo { 5884 TagInfo() : count ( 0 ) {} 5885 void add( std::string const& spelling ) { 5886 ++count; 5887 spellings.insert( spelling ); 5888 } 5889 std::string all() const { 5890 std::string out; 5891 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end(); 5892 it != itEnd; 5893 ++it ) 5894 out += "[" + *it + "]"; 5895 return out; 5896 } 5897 std::set<std::string> spellings; 5898 std::size_t count; 5899 }; 5900 5901 inline std::size_t listTags( Config const& config ) { 5902 TestSpec testSpec = config.testSpec(); 5903 if( config.testSpec().hasFilters() ) 5904 Catch::cout() << "Tags for matching test cases:\n"; 5905 else { 5906 Catch::cout() << "All available tags:\n"; 5907 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec(); 5908 } 5909 5910 std::map<std::string, TagInfo> tagCounts; 5911 5912 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config ); 5913 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end(); 5914 it != itEnd; 5915 ++it ) { 5916 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(), 5917 tagItEnd = it->getTestCaseInfo().tags.end(); 5918 tagIt != tagItEnd; 5919 ++tagIt ) { 5920 std::string tagName = *tagIt; 5921 std::string lcaseTagName = toLower( tagName ); 5922 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName ); 5923 if( countIt == tagCounts.end() ) 5924 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first; 5925 countIt->second.add( tagName ); 5926 } 5927 } 5928 5929 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(), 5930 countItEnd = tagCounts.end(); 5931 countIt != countItEnd; 5932 ++countIt ) { 5933 std::ostringstream oss; 5934 oss << " " << std::setw(2) << countIt->second.count << " "; 5935 Text wrapper( countIt->second.all(), TextAttributes() 5936 .setInitialIndent( 0 ) 5937 .setIndent( oss.str().size() ) 5938 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) ); 5939 Catch::cout() << oss.str() << wrapper << '\n'; 5940 } 5941 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl; 5942 return tagCounts.size(); 5943 } 5944 5945 inline std::size_t listReporters( Config const& /*config*/ ) { 5946 Catch::cout() << "Available reporters:\n"; 5947 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories(); 5948 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it; 5949 std::size_t maxNameLen = 0; 5950 for(it = itBegin; it != itEnd; ++it ) 5951 maxNameLen = (std::max)( maxNameLen, it->first.size() ); 5952 5953 for(it = itBegin; it != itEnd; ++it ) { 5954 Text wrapper( it->second->getDescription(), TextAttributes() 5955 .setInitialIndent( 0 ) 5956 .setIndent( 7+maxNameLen ) 5957 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) ); 5958 Catch::cout() << " " 5959 << it->first 5960 << ':' 5961 << std::string( maxNameLen - it->first.size() + 2, ' ' ) 5962 << wrapper << '\n'; 5963 } 5964 Catch::cout() << std::endl; 5965 return factories.size(); 5966 } 5967 5968 inline Option<std::size_t> list( Config const& config ) { 5969 Option<std::size_t> listedCount; 5970 if( config.listTests() || ( config.listExtraInfo() && !config.listTestNamesOnly() ) ) 5971 listedCount = listedCount.valueOr(0) + listTests( config ); 5972 if( config.listTestNamesOnly() ) 5973 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config ); 5974 if( config.listTags() ) 5975 listedCount = listedCount.valueOr(0) + listTags( config ); 5976 if( config.listReporters() ) 5977 listedCount = listedCount.valueOr(0) + listReporters( config ); 5978 return listedCount; 5979 } 5980 5981 } // end namespace Catch 5982 5983 // #included from: internal/catch_run_context.hpp 5984 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED 5985 5986 // #included from: catch_test_case_tracker.hpp 5987 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED 5988 5989 #include <algorithm> 5990 #include <string> 5991 #include <assert.h> 5992 #include <vector> 5993 #include <stdexcept> 5994 5995 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS 5996 5997 namespace Catch { 5998 namespace TestCaseTracking { 5999 6000 struct NameAndLocation { 6001 std::string name; 6002 SourceLineInfo location; 6003 6004 NameAndLocation( std::string const& _name, SourceLineInfo const& _location ) 6005 : name( _name ), 6006 location( _location ) 6007 {} 6008 }; 6009 6010 struct ITracker : SharedImpl<> { 6011 virtual ~ITracker(); 6012 6013 // static queries 6014 virtual NameAndLocation const& nameAndLocation() const = 0; 6015 6016 // dynamic queries 6017 virtual bool isComplete() const = 0; // Successfully completed or failed 6018 virtual bool isSuccessfullyCompleted() const = 0; 6019 virtual bool isOpen() const = 0; // Started but not complete 6020 virtual bool hasChildren() const = 0; 6021 6022 virtual ITracker& parent() = 0; 6023 6024 // actions 6025 virtual void close() = 0; // Successfully complete 6026 virtual void fail() = 0; 6027 virtual void markAsNeedingAnotherRun() = 0; 6028 6029 virtual void addChild( Ptr<ITracker> const& child ) = 0; 6030 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0; 6031 virtual void openChild() = 0; 6032 6033 // Debug/ checking 6034 virtual bool isSectionTracker() const = 0; 6035 virtual bool isIndexTracker() const = 0; 6036 }; 6037 6038 class TrackerContext { 6039 6040 enum RunState { 6041 NotStarted, 6042 Executing, 6043 CompletedCycle 6044 }; 6045 6046 Ptr<ITracker> m_rootTracker; 6047 ITracker* m_currentTracker; 6048 RunState m_runState; 6049 6050 public: 6051 6052 static TrackerContext& instance() { 6053 static TrackerContext s_instance; 6054 return s_instance; 6055 } 6056 6057 TrackerContext() 6058 : m_currentTracker( CATCH_NULL ), 6059 m_runState( NotStarted ) 6060 {} 6061 6062 ITracker& startRun(); 6063 6064 void endRun() { 6065 m_rootTracker.reset(); 6066 m_currentTracker = CATCH_NULL; 6067 m_runState = NotStarted; 6068 } 6069 6070 void startCycle() { 6071 m_currentTracker = m_rootTracker.get(); 6072 m_runState = Executing; 6073 } 6074 void completeCycle() { 6075 m_runState = CompletedCycle; 6076 } 6077 6078 bool completedCycle() const { 6079 return m_runState == CompletedCycle; 6080 } 6081 ITracker& currentTracker() { 6082 return *m_currentTracker; 6083 } 6084 void setCurrentTracker( ITracker* tracker ) { 6085 m_currentTracker = tracker; 6086 } 6087 }; 6088 6089 class TrackerBase : public ITracker { 6090 protected: 6091 enum CycleState { 6092 NotStarted, 6093 Executing, 6094 ExecutingChildren, 6095 NeedsAnotherRun, 6096 CompletedSuccessfully, 6097 Failed 6098 }; 6099 class TrackerHasName { 6100 NameAndLocation m_nameAndLocation; 6101 public: 6102 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {} 6103 bool operator ()( Ptr<ITracker> const& tracker ) { 6104 return 6105 tracker->nameAndLocation().name == m_nameAndLocation.name && 6106 tracker->nameAndLocation().location == m_nameAndLocation.location; 6107 } 6108 }; 6109 typedef std::vector<Ptr<ITracker> > Children; 6110 NameAndLocation m_nameAndLocation; 6111 TrackerContext& m_ctx; 6112 ITracker* m_parent; 6113 Children m_children; 6114 CycleState m_runState; 6115 public: 6116 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 6117 : m_nameAndLocation( nameAndLocation ), 6118 m_ctx( ctx ), 6119 m_parent( parent ), 6120 m_runState( NotStarted ) 6121 {} 6122 virtual ~TrackerBase(); 6123 6124 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE { 6125 return m_nameAndLocation; 6126 } 6127 virtual bool isComplete() const CATCH_OVERRIDE { 6128 return m_runState == CompletedSuccessfully || m_runState == Failed; 6129 } 6130 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE { 6131 return m_runState == CompletedSuccessfully; 6132 } 6133 virtual bool isOpen() const CATCH_OVERRIDE { 6134 return m_runState != NotStarted && !isComplete(); 6135 } 6136 virtual bool hasChildren() const CATCH_OVERRIDE { 6137 return !m_children.empty(); 6138 } 6139 6140 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE { 6141 m_children.push_back( child ); 6142 } 6143 6144 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE { 6145 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) ); 6146 return( it != m_children.end() ) 6147 ? it->get() 6148 : CATCH_NULL; 6149 } 6150 virtual ITracker& parent() CATCH_OVERRIDE { 6151 assert( m_parent ); // Should always be non-null except for root 6152 return *m_parent; 6153 } 6154 6155 virtual void openChild() CATCH_OVERRIDE { 6156 if( m_runState != ExecutingChildren ) { 6157 m_runState = ExecutingChildren; 6158 if( m_parent ) 6159 m_parent->openChild(); 6160 } 6161 } 6162 6163 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; } 6164 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; } 6165 6166 void open() { 6167 m_runState = Executing; 6168 moveToThis(); 6169 if( m_parent ) 6170 m_parent->openChild(); 6171 } 6172 6173 virtual void close() CATCH_OVERRIDE { 6174 6175 // Close any still open children (e.g. generators) 6176 while( &m_ctx.currentTracker() != this ) 6177 m_ctx.currentTracker().close(); 6178 6179 switch( m_runState ) { 6180 case NotStarted: 6181 case CompletedSuccessfully: 6182 case Failed: 6183 throw std::logic_error( "Illogical state" ); 6184 6185 case NeedsAnotherRun: 6186 break;; 6187 6188 case Executing: 6189 m_runState = CompletedSuccessfully; 6190 break; 6191 case ExecutingChildren: 6192 if( m_children.empty() || m_children.back()->isComplete() ) 6193 m_runState = CompletedSuccessfully; 6194 break; 6195 6196 default: 6197 throw std::logic_error( "Unexpected state" ); 6198 } 6199 moveToParent(); 6200 m_ctx.completeCycle(); 6201 } 6202 virtual void fail() CATCH_OVERRIDE { 6203 m_runState = Failed; 6204 if( m_parent ) 6205 m_parent->markAsNeedingAnotherRun(); 6206 moveToParent(); 6207 m_ctx.completeCycle(); 6208 } 6209 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE { 6210 m_runState = NeedsAnotherRun; 6211 } 6212 private: 6213 void moveToParent() { 6214 assert( m_parent ); 6215 m_ctx.setCurrentTracker( m_parent ); 6216 } 6217 void moveToThis() { 6218 m_ctx.setCurrentTracker( this ); 6219 } 6220 }; 6221 6222 class SectionTracker : public TrackerBase { 6223 std::vector<std::string> m_filters; 6224 public: 6225 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ) 6226 : TrackerBase( nameAndLocation, ctx, parent ) 6227 { 6228 if( parent ) { 6229 while( !parent->isSectionTracker() ) 6230 parent = &parent->parent(); 6231 6232 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent ); 6233 addNextFilters( parentSection.m_filters ); 6234 } 6235 } 6236 virtual ~SectionTracker(); 6237 6238 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; } 6239 6240 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) { 6241 SectionTracker* section = CATCH_NULL; 6242 6243 ITracker& currentTracker = ctx.currentTracker(); 6244 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { 6245 assert( childTracker ); 6246 assert( childTracker->isSectionTracker() ); 6247 section = static_cast<SectionTracker*>( childTracker ); 6248 } 6249 else { 6250 section = new SectionTracker( nameAndLocation, ctx, ¤tTracker ); 6251 currentTracker.addChild( section ); 6252 } 6253 if( !ctx.completedCycle() ) 6254 section->tryOpen(); 6255 return *section; 6256 } 6257 6258 void tryOpen() { 6259 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) ) 6260 open(); 6261 } 6262 6263 void addInitialFilters( std::vector<std::string> const& filters ) { 6264 if( !filters.empty() ) { 6265 m_filters.push_back(""); // Root - should never be consulted 6266 m_filters.push_back(""); // Test Case - not a section filter 6267 m_filters.insert( m_filters.end(), filters.begin(), filters.end() ); 6268 } 6269 } 6270 void addNextFilters( std::vector<std::string> const& filters ) { 6271 if( filters.size() > 1 ) 6272 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() ); 6273 } 6274 }; 6275 6276 class IndexTracker : public TrackerBase { 6277 int m_size; 6278 int m_index; 6279 public: 6280 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size ) 6281 : TrackerBase( nameAndLocation, ctx, parent ), 6282 m_size( size ), 6283 m_index( -1 ) 6284 {} 6285 virtual ~IndexTracker(); 6286 6287 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; } 6288 6289 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) { 6290 IndexTracker* tracker = CATCH_NULL; 6291 6292 ITracker& currentTracker = ctx.currentTracker(); 6293 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) { 6294 assert( childTracker ); 6295 assert( childTracker->isIndexTracker() ); 6296 tracker = static_cast<IndexTracker*>( childTracker ); 6297 } 6298 else { 6299 tracker = new IndexTracker( nameAndLocation, ctx, ¤tTracker, size ); 6300 currentTracker.addChild( tracker ); 6301 } 6302 6303 if( !ctx.completedCycle() && !tracker->isComplete() ) { 6304 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun ) 6305 tracker->moveNext(); 6306 tracker->open(); 6307 } 6308 6309 return *tracker; 6310 } 6311 6312 int index() const { return m_index; } 6313 6314 void moveNext() { 6315 m_index++; 6316 m_children.clear(); 6317 } 6318 6319 virtual void close() CATCH_OVERRIDE { 6320 TrackerBase::close(); 6321 if( m_runState == CompletedSuccessfully && m_index < m_size-1 ) 6322 m_runState = Executing; 6323 } 6324 }; 6325 6326 inline ITracker& TrackerContext::startRun() { 6327 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL ); 6328 m_currentTracker = CATCH_NULL; 6329 m_runState = Executing; 6330 return *m_rootTracker; 6331 } 6332 6333 } // namespace TestCaseTracking 6334 6335 using TestCaseTracking::ITracker; 6336 using TestCaseTracking::TrackerContext; 6337 using TestCaseTracking::SectionTracker; 6338 using TestCaseTracking::IndexTracker; 6339 6340 } // namespace Catch 6341 6342 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS 6343 6344 // #included from: catch_fatal_condition.hpp 6345 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED 6346 6347 namespace Catch { 6348 6349 // Report the error condition 6350 inline void reportFatal( std::string const& message ) { 6351 IContext& context = Catch::getCurrentContext(); 6352 IResultCapture* resultCapture = context.getResultCapture(); 6353 resultCapture->handleFatalErrorCondition( message ); 6354 } 6355 6356 } // namespace Catch 6357 6358 #if defined ( CATCH_PLATFORM_WINDOWS ) ///////////////////////////////////////// 6359 // #included from: catch_windows_h_proxy.h 6360 6361 #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED 6362 6363 #ifdef CATCH_DEFINES_NOMINMAX 6364 # define NOMINMAX 6365 #endif 6366 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN 6367 # define WIN32_LEAN_AND_MEAN 6368 #endif 6369 6370 #ifdef __AFXDLL 6371 #include <AfxWin.h> 6372 #else 6373 #include <windows.h> 6374 #endif 6375 6376 #ifdef CATCH_DEFINES_NOMINMAX 6377 # undef NOMINMAX 6378 #endif 6379 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN 6380 # undef WIN32_LEAN_AND_MEAN 6381 #endif 6382 6383 6384 # if !defined ( CATCH_CONFIG_WINDOWS_SEH ) 6385 6386 namespace Catch { 6387 struct FatalConditionHandler { 6388 void reset() {} 6389 }; 6390 } 6391 6392 # else // CATCH_CONFIG_WINDOWS_SEH is defined 6393 6394 namespace Catch { 6395 6396 struct SignalDefs { DWORD id; const char* name; }; 6397 extern SignalDefs signalDefs[]; 6398 // There is no 1-1 mapping between signals and windows exceptions. 6399 // Windows can easily distinguish between SO and SigSegV, 6400 // but SigInt, SigTerm, etc are handled differently. 6401 SignalDefs signalDefs[] = { 6402 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" }, 6403 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" }, 6404 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" }, 6405 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" }, 6406 }; 6407 6408 struct FatalConditionHandler { 6409 6410 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) { 6411 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { 6412 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) { 6413 reportFatal(signalDefs[i].name); 6414 } 6415 } 6416 // If its not an exception we care about, pass it along. 6417 // This stops us from eating debugger breaks etc. 6418 return EXCEPTION_CONTINUE_SEARCH; 6419 } 6420 6421 FatalConditionHandler() { 6422 isSet = true; 6423 // 32k seems enough for Catch to handle stack overflow, 6424 // but the value was found experimentally, so there is no strong guarantee 6425 guaranteeSize = 32 * 1024; 6426 exceptionHandlerHandle = CATCH_NULL; 6427 // Register as first handler in current chain 6428 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException); 6429 // Pass in guarantee size to be filled 6430 SetThreadStackGuarantee(&guaranteeSize); 6431 } 6432 6433 static void reset() { 6434 if (isSet) { 6435 // Unregister handler and restore the old guarantee 6436 RemoveVectoredExceptionHandler(exceptionHandlerHandle); 6437 SetThreadStackGuarantee(&guaranteeSize); 6438 exceptionHandlerHandle = CATCH_NULL; 6439 isSet = false; 6440 } 6441 } 6442 6443 ~FatalConditionHandler() { 6444 reset(); 6445 } 6446 private: 6447 static bool isSet; 6448 static ULONG guaranteeSize; 6449 static PVOID exceptionHandlerHandle; 6450 }; 6451 6452 bool FatalConditionHandler::isSet = false; 6453 ULONG FatalConditionHandler::guaranteeSize = 0; 6454 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL; 6455 6456 } // namespace Catch 6457 6458 # endif // CATCH_CONFIG_WINDOWS_SEH 6459 6460 #else // Not Windows - assumed to be POSIX compatible ////////////////////////// 6461 6462 # if !defined(CATCH_CONFIG_POSIX_SIGNALS) 6463 6464 namespace Catch { 6465 struct FatalConditionHandler { 6466 void reset() {} 6467 }; 6468 } 6469 6470 # else // CATCH_CONFIG_POSIX_SIGNALS is defined 6471 6472 #include <signal.h> 6473 6474 namespace Catch { 6475 6476 struct SignalDefs { 6477 int id; 6478 const char* name; 6479 }; 6480 extern SignalDefs signalDefs[]; 6481 SignalDefs signalDefs[] = { 6482 { SIGINT, "SIGINT - Terminal interrupt signal" }, 6483 { SIGILL, "SIGILL - Illegal instruction signal" }, 6484 { SIGFPE, "SIGFPE - Floating point error signal" }, 6485 { SIGSEGV, "SIGSEGV - Segmentation violation signal" }, 6486 { SIGTERM, "SIGTERM - Termination request signal" }, 6487 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" } 6488 }; 6489 6490 struct FatalConditionHandler { 6491 6492 static bool isSet; 6493 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)]; 6494 static stack_t oldSigStack; 6495 static char altStackMem[32768]; 6496 6497 static void handleSignal( int sig ) { 6498 std::string name = "<unknown signal>"; 6499 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) { 6500 SignalDefs &def = signalDefs[i]; 6501 if (sig == def.id) { 6502 name = def.name; 6503 break; 6504 } 6505 } 6506 reset(); 6507 reportFatal(name); 6508 raise( sig ); 6509 } 6510 6511 FatalConditionHandler() { 6512 isSet = true; 6513 stack_t sigStack; 6514 sigStack.ss_sp = altStackMem; 6515 sigStack.ss_size = 32768; 6516 sigStack.ss_flags = 0; 6517 sigaltstack(&sigStack, &oldSigStack); 6518 struct sigaction sa = { 0 }; 6519 6520 sa.sa_handler = handleSignal; 6521 sa.sa_flags = SA_ONSTACK; 6522 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) { 6523 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]); 6524 } 6525 } 6526 6527 ~FatalConditionHandler() { 6528 reset(); 6529 } 6530 static void reset() { 6531 if( isSet ) { 6532 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime 6533 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) { 6534 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL); 6535 } 6536 // Return the old stack 6537 sigaltstack(&oldSigStack, CATCH_NULL); 6538 isSet = false; 6539 } 6540 } 6541 }; 6542 6543 bool FatalConditionHandler::isSet = false; 6544 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {}; 6545 stack_t FatalConditionHandler::oldSigStack = {}; 6546 char FatalConditionHandler::altStackMem[32768] = {}; 6547 6548 } // namespace Catch 6549 6550 # endif // CATCH_CONFIG_POSIX_SIGNALS 6551 6552 #endif // not Windows 6553 6554 #include <set> 6555 #include <string> 6556 6557 namespace Catch { 6558 6559 class StreamRedirect { 6560 6561 public: 6562 StreamRedirect( std::ostream& stream, std::string& targetString ) 6563 : m_stream( stream ), 6564 m_prevBuf( stream.rdbuf() ), 6565 m_targetString( targetString ) 6566 { 6567 stream.rdbuf( m_oss.rdbuf() ); 6568 } 6569 6570 ~StreamRedirect() { 6571 m_targetString += m_oss.str(); 6572 m_stream.rdbuf( m_prevBuf ); 6573 } 6574 6575 private: 6576 std::ostream& m_stream; 6577 std::streambuf* m_prevBuf; 6578 std::ostringstream m_oss; 6579 std::string& m_targetString; 6580 }; 6581 6582 /////////////////////////////////////////////////////////////////////////// 6583 6584 class RunContext : public IResultCapture, public IRunner { 6585 6586 RunContext( RunContext const& ); 6587 void operator =( RunContext const& ); 6588 6589 public: 6590 6591 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter ) 6592 : m_runInfo( _config->name() ), 6593 m_context( getCurrentMutableContext() ), 6594 m_activeTestCase( CATCH_NULL ), 6595 m_config( _config ), 6596 m_reporter( reporter ), 6597 m_shouldReportUnexpected ( true ) 6598 { 6599 m_context.setRunner( this ); 6600 m_context.setConfig( m_config ); 6601 m_context.setResultCapture( this ); 6602 m_reporter->testRunStarting( m_runInfo ); 6603 } 6604 6605 virtual ~RunContext() { 6606 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) ); 6607 } 6608 6609 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) { 6610 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) ); 6611 } 6612 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) { 6613 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) ); 6614 } 6615 6616 Totals runTest( TestCase const& testCase ) { 6617 Totals prevTotals = m_totals; 6618 6619 std::string redirectedCout; 6620 std::string redirectedCerr; 6621 6622 TestCaseInfo testInfo = testCase.getTestCaseInfo(); 6623 6624 m_reporter->testCaseStarting( testInfo ); 6625 6626 m_activeTestCase = &testCase; 6627 6628 do { 6629 ITracker& rootTracker = m_trackerContext.startRun(); 6630 assert( rootTracker.isSectionTracker() ); 6631 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() ); 6632 do { 6633 m_trackerContext.startCycle(); 6634 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) ); 6635 runCurrentTest( redirectedCout, redirectedCerr ); 6636 } 6637 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() ); 6638 } 6639 // !TBD: deprecated - this will be replaced by indexed trackers 6640 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() ); 6641 6642 Totals deltaTotals = m_totals.delta( prevTotals ); 6643 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) { 6644 deltaTotals.assertions.failed++; 6645 deltaTotals.testCases.passed--; 6646 deltaTotals.testCases.failed++; 6647 } 6648 m_totals.testCases += deltaTotals.testCases; 6649 m_reporter->testCaseEnded( TestCaseStats( testInfo, 6650 deltaTotals, 6651 redirectedCout, 6652 redirectedCerr, 6653 aborting() ) ); 6654 6655 m_activeTestCase = CATCH_NULL; 6656 m_testCaseTracker = CATCH_NULL; 6657 6658 return deltaTotals; 6659 } 6660 6661 Ptr<IConfig const> config() const { 6662 return m_config; 6663 } 6664 6665 private: // IResultCapture 6666 6667 virtual void assertionEnded( AssertionResult const& result ) { 6668 if( result.getResultType() == ResultWas::Ok ) { 6669 m_totals.assertions.passed++; 6670 } 6671 else if( !result.isOk() ) { 6672 m_totals.assertions.failed++; 6673 } 6674 6675 // We have no use for the return value (whether messages should be cleared), because messages were made scoped 6676 // and should be let to clear themselves out. 6677 static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals))); 6678 6679 // Reset working state 6680 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition ); 6681 m_lastResult = result; 6682 } 6683 6684 virtual bool sectionStarted ( 6685 SectionInfo const& sectionInfo, 6686 Counts& assertions 6687 ) 6688 { 6689 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) ); 6690 if( !sectionTracker.isOpen() ) 6691 return false; 6692 m_activeSections.push_back( §ionTracker ); 6693 6694 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo; 6695 6696 m_reporter->sectionStarting( sectionInfo ); 6697 6698 assertions = m_totals.assertions; 6699 6700 return true; 6701 } 6702 bool testForMissingAssertions( Counts& assertions ) { 6703 if( assertions.total() != 0 ) 6704 return false; 6705 if( !m_config->warnAboutMissingAssertions() ) 6706 return false; 6707 if( m_trackerContext.currentTracker().hasChildren() ) 6708 return false; 6709 m_totals.assertions.failed++; 6710 assertions.failed++; 6711 return true; 6712 } 6713 6714 virtual void sectionEnded( SectionEndInfo const& endInfo ) { 6715 Counts assertions = m_totals.assertions - endInfo.prevAssertions; 6716 bool missingAssertions = testForMissingAssertions( assertions ); 6717 6718 if( !m_activeSections.empty() ) { 6719 m_activeSections.back()->close(); 6720 m_activeSections.pop_back(); 6721 } 6722 6723 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) ); 6724 m_messages.clear(); 6725 } 6726 6727 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) { 6728 if( m_unfinishedSections.empty() ) 6729 m_activeSections.back()->fail(); 6730 else 6731 m_activeSections.back()->close(); 6732 m_activeSections.pop_back(); 6733 6734 m_unfinishedSections.push_back( endInfo ); 6735 } 6736 6737 virtual void pushScopedMessage( MessageInfo const& message ) { 6738 m_messages.push_back( message ); 6739 } 6740 6741 virtual void popScopedMessage( MessageInfo const& message ) { 6742 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() ); 6743 } 6744 6745 virtual std::string getCurrentTestName() const { 6746 return m_activeTestCase 6747 ? m_activeTestCase->getTestCaseInfo().name 6748 : std::string(); 6749 } 6750 6751 virtual const AssertionResult* getLastResult() const { 6752 return &m_lastResult; 6753 } 6754 6755 virtual void exceptionEarlyReported() { 6756 m_shouldReportUnexpected = false; 6757 } 6758 6759 virtual void handleFatalErrorCondition( std::string const& message ) { 6760 // Don't rebuild the result -- the stringification itself can cause more fatal errors 6761 // Instead, fake a result data. 6762 AssertionResultData tempResult; 6763 tempResult.resultType = ResultWas::FatalErrorCondition; 6764 tempResult.message = message; 6765 AssertionResult result(m_lastAssertionInfo, tempResult); 6766 6767 getResultCapture().assertionEnded(result); 6768 6769 handleUnfinishedSections(); 6770 6771 // Recreate section for test case (as we will lose the one that was in scope) 6772 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 6773 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); 6774 6775 Counts assertions; 6776 assertions.failed = 1; 6777 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false ); 6778 m_reporter->sectionEnded( testCaseSectionStats ); 6779 6780 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo(); 6781 6782 Totals deltaTotals; 6783 deltaTotals.testCases.failed = 1; 6784 m_reporter->testCaseEnded( TestCaseStats( testInfo, 6785 deltaTotals, 6786 std::string(), 6787 std::string(), 6788 false ) ); 6789 m_totals.testCases.failed++; 6790 testGroupEnded( std::string(), m_totals, 1, 1 ); 6791 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) ); 6792 } 6793 6794 public: 6795 // !TBD We need to do this another way! 6796 bool aborting() const { 6797 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() ); 6798 } 6799 6800 private: 6801 6802 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) { 6803 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo(); 6804 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description ); 6805 m_reporter->sectionStarting( testCaseSection ); 6806 Counts prevAssertions = m_totals.assertions; 6807 double duration = 0; 6808 m_shouldReportUnexpected = true; 6809 try { 6810 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal ); 6811 6812 seedRng( *m_config ); 6813 6814 Timer timer; 6815 timer.start(); 6816 if( m_reporter->getPreferences().shouldRedirectStdOut ) { 6817 StreamRedirect coutRedir( Catch::cout(), redirectedCout ); 6818 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr ); 6819 invokeActiveTestCase(); 6820 } 6821 else { 6822 invokeActiveTestCase(); 6823 } 6824 duration = timer.getElapsedSeconds(); 6825 } 6826 catch( TestFailureException& ) { 6827 // This just means the test was aborted due to failure 6828 } 6829 catch(...) { 6830 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions 6831 // are reported without translation at the point of origin. 6832 if (m_shouldReportUnexpected) { 6833 makeUnexpectedResultBuilder().useActiveException(); 6834 } 6835 } 6836 m_testCaseTracker->close(); 6837 handleUnfinishedSections(); 6838 m_messages.clear(); 6839 6840 Counts assertions = m_totals.assertions - prevAssertions; 6841 bool missingAssertions = testForMissingAssertions( assertions ); 6842 6843 if( testCaseInfo.okToFail() ) { 6844 std::swap( assertions.failedButOk, assertions.failed ); 6845 m_totals.assertions.failed -= assertions.failedButOk; 6846 m_totals.assertions.failedButOk += assertions.failedButOk; 6847 } 6848 6849 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions ); 6850 m_reporter->sectionEnded( testCaseSectionStats ); 6851 } 6852 6853 void invokeActiveTestCase() { 6854 FatalConditionHandler fatalConditionHandler; // Handle signals 6855 m_activeTestCase->invoke(); 6856 fatalConditionHandler.reset(); 6857 } 6858 6859 private: 6860 6861 ResultBuilder makeUnexpectedResultBuilder() const { 6862 return ResultBuilder( m_lastAssertionInfo.macroName, 6863 m_lastAssertionInfo.lineInfo, 6864 m_lastAssertionInfo.capturedExpression, 6865 m_lastAssertionInfo.resultDisposition ); 6866 } 6867 6868 void handleUnfinishedSections() { 6869 // If sections ended prematurely due to an exception we stored their 6870 // infos here so we can tear them down outside the unwind process. 6871 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(), 6872 itEnd = m_unfinishedSections.rend(); 6873 it != itEnd; 6874 ++it ) 6875 sectionEnded( *it ); 6876 m_unfinishedSections.clear(); 6877 } 6878 6879 TestRunInfo m_runInfo; 6880 IMutableContext& m_context; 6881 TestCase const* m_activeTestCase; 6882 ITracker* m_testCaseTracker; 6883 ITracker* m_currentSectionTracker; 6884 AssertionResult m_lastResult; 6885 6886 Ptr<IConfig const> m_config; 6887 Totals m_totals; 6888 Ptr<IStreamingReporter> m_reporter; 6889 std::vector<MessageInfo> m_messages; 6890 AssertionInfo m_lastAssertionInfo; 6891 std::vector<SectionEndInfo> m_unfinishedSections; 6892 std::vector<ITracker*> m_activeSections; 6893 TrackerContext m_trackerContext; 6894 bool m_shouldReportUnexpected; 6895 }; 6896 6897 IResultCapture& getResultCapture() { 6898 if( IResultCapture* capture = getCurrentContext().getResultCapture() ) 6899 return *capture; 6900 else 6901 throw std::logic_error( "No result capture instance" ); 6902 } 6903 6904 } // end namespace Catch 6905 6906 // #included from: internal/catch_version.h 6907 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED 6908 6909 namespace Catch { 6910 6911 // Versioning information 6912 struct Version { 6913 Version( unsigned int _majorVersion, 6914 unsigned int _minorVersion, 6915 unsigned int _patchNumber, 6916 char const * const _branchName, 6917 unsigned int _buildNumber ); 6918 6919 unsigned int const majorVersion; 6920 unsigned int const minorVersion; 6921 unsigned int const patchNumber; 6922 6923 // buildNumber is only used if branchName is not null 6924 char const * const branchName; 6925 unsigned int const buildNumber; 6926 6927 friend std::ostream& operator << ( std::ostream& os, Version const& version ); 6928 6929 private: 6930 void operator=( Version const& ); 6931 }; 6932 6933 inline Version libraryVersion(); 6934 } 6935 6936 #include <fstream> 6937 #include <stdlib.h> 6938 #include <limits> 6939 6940 namespace Catch { 6941 6942 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) { 6943 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() ); 6944 if( !reporter ) { 6945 std::ostringstream oss; 6946 oss << "No reporter registered with name: '" << reporterName << "'"; 6947 throw std::domain_error( oss.str() ); 6948 } 6949 return reporter; 6950 } 6951 6952 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) { 6953 std::vector<std::string> reporters = config->getReporterNames(); 6954 if( reporters.empty() ) 6955 reporters.push_back( "console" ); 6956 6957 Ptr<IStreamingReporter> reporter; 6958 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end(); 6959 it != itEnd; 6960 ++it ) 6961 reporter = addReporter( reporter, createReporter( *it, config ) ); 6962 return reporter; 6963 } 6964 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) { 6965 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners(); 6966 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end(); 6967 it != itEnd; 6968 ++it ) 6969 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) ); 6970 return reporters; 6971 } 6972 6973 Totals runTests( Ptr<Config> const& config ) { 6974 6975 Ptr<IConfig const> iconfig = config.get(); 6976 6977 Ptr<IStreamingReporter> reporter = makeReporter( config ); 6978 reporter = addListeners( iconfig, reporter ); 6979 6980 RunContext context( iconfig, reporter ); 6981 6982 Totals totals; 6983 6984 context.testGroupStarting( config->name(), 1, 1 ); 6985 6986 TestSpec testSpec = config->testSpec(); 6987 if( !testSpec.hasFilters() ) 6988 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests 6989 6990 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig ); 6991 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end(); 6992 it != itEnd; 6993 ++it ) { 6994 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) ) 6995 totals += context.runTest( *it ); 6996 else 6997 reporter->skipTest( *it ); 6998 } 6999 7000 context.testGroupEnded( iconfig->name(), totals, 1, 1 ); 7001 return totals; 7002 } 7003 7004 void applyFilenamesAsTags( IConfig const& config ) { 7005 std::vector<TestCase> const& tests = getAllTestCasesSorted( config ); 7006 for(std::size_t i = 0; i < tests.size(); ++i ) { 7007 TestCase& test = const_cast<TestCase&>( tests[i] ); 7008 std::set<std::string> tags = test.tags; 7009 7010 std::string filename = test.lineInfo.file; 7011 std::string::size_type lastSlash = filename.find_last_of( "\\/" ); 7012 if( lastSlash != std::string::npos ) 7013 filename = filename.substr( lastSlash+1 ); 7014 7015 std::string::size_type lastDot = filename.find_last_of( "." ); 7016 if( lastDot != std::string::npos ) 7017 filename = filename.substr( 0, lastDot ); 7018 7019 tags.insert( "#" + filename ); 7020 setTags( test, tags ); 7021 } 7022 } 7023 7024 class Session : NonCopyable { 7025 static bool alreadyInstantiated; 7026 7027 public: 7028 7029 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; }; 7030 7031 Session() 7032 : m_cli( makeCommandLineParser() ) { 7033 if( alreadyInstantiated ) { 7034 std::string msg = "Only one instance of Catch::Session can ever be used"; 7035 Catch::cerr() << msg << std::endl; 7036 throw std::logic_error( msg ); 7037 } 7038 alreadyInstantiated = true; 7039 } 7040 ~Session() { 7041 Catch::cleanUp(); 7042 } 7043 7044 void showHelp( std::string const& processName ) { 7045 Catch::cout() << "\nCatch v" << libraryVersion() << "\n"; 7046 7047 m_cli.usage( Catch::cout(), processName ); 7048 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl; 7049 } 7050 7051 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) { 7052 try { 7053 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail ); 7054 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData ); 7055 if( m_configData.showHelp ) 7056 showHelp( m_configData.processName ); 7057 m_config.reset(); 7058 } 7059 catch( std::exception& ex ) { 7060 { 7061 Colour colourGuard( Colour::Red ); 7062 Catch::cerr() 7063 << "\nError(s) in input:\n" 7064 << Text( ex.what(), TextAttributes().setIndent(2) ) 7065 << "\n\n"; 7066 } 7067 m_cli.usage( Catch::cout(), m_configData.processName ); 7068 return (std::numeric_limits<int>::max)(); 7069 } 7070 return 0; 7071 } 7072 7073 void useConfigData( ConfigData const& _configData ) { 7074 m_configData = _configData; 7075 m_config.reset(); 7076 } 7077 7078 int run( int argc, char const* const* const argv ) { 7079 7080 int returnCode = applyCommandLine( argc, argv ); 7081 if( returnCode == 0 ) 7082 returnCode = run(); 7083 return returnCode; 7084 } 7085 7086 #if defined(WIN32) && defined(UNICODE) 7087 int run( int argc, wchar_t const* const* const argv ) { 7088 7089 char **utf8Argv = new char *[ argc ]; 7090 7091 for ( int i = 0; i < argc; ++i ) { 7092 int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, NULL, 0, NULL, NULL ); 7093 7094 utf8Argv[ i ] = new char[ bufSize ]; 7095 7096 WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, NULL, NULL ); 7097 } 7098 7099 int returnCode = applyCommandLine( argc, utf8Argv ); 7100 if( returnCode == 0 ) 7101 returnCode = run(); 7102 7103 for ( int i = 0; i < argc; ++i ) 7104 delete [] utf8Argv[ i ]; 7105 7106 delete [] utf8Argv; 7107 7108 return returnCode; 7109 } 7110 #endif 7111 7112 int run() { 7113 if( m_configData.showHelp ) 7114 return 0; 7115 7116 try 7117 { 7118 config(); // Force config to be constructed 7119 7120 seedRng( *m_config ); 7121 7122 if( m_configData.filenamesAsTags ) 7123 applyFilenamesAsTags( *m_config ); 7124 7125 // Handle list request 7126 if( Option<std::size_t> listed = list( config() ) ) 7127 return static_cast<int>( *listed ); 7128 7129 return static_cast<int>( runTests( m_config ).assertions.failed ); 7130 } 7131 catch( std::exception& ex ) { 7132 Catch::cerr() << ex.what() << std::endl; 7133 return (std::numeric_limits<int>::max)(); 7134 } 7135 } 7136 7137 Clara::CommandLine<ConfigData> const& cli() const { 7138 return m_cli; 7139 } 7140 std::vector<Clara::Parser::Token> const& unusedTokens() const { 7141 return m_unusedTokens; 7142 } 7143 ConfigData& configData() { 7144 return m_configData; 7145 } 7146 Config& config() { 7147 if( !m_config ) 7148 m_config = new Config( m_configData ); 7149 return *m_config; 7150 } 7151 private: 7152 Clara::CommandLine<ConfigData> m_cli; 7153 std::vector<Clara::Parser::Token> m_unusedTokens; 7154 ConfigData m_configData; 7155 Ptr<Config> m_config; 7156 }; 7157 7158 bool Session::alreadyInstantiated = false; 7159 7160 } // end namespace Catch 7161 7162 // #included from: catch_registry_hub.hpp 7163 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED 7164 7165 // #included from: catch_test_case_registry_impl.hpp 7166 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED 7167 7168 #include <vector> 7169 #include <set> 7170 #include <sstream> 7171 #include <algorithm> 7172 7173 namespace Catch { 7174 7175 struct RandomNumberGenerator { 7176 typedef std::ptrdiff_t result_type; 7177 7178 result_type operator()( result_type n ) const { return rand() % n; } 7179 7180 #ifdef CATCH_CONFIG_CPP11_SHUFFLE 7181 static constexpr result_type min() { return 0; } 7182 static constexpr result_type max() { return 1000000; } 7183 result_type operator()() const { return rand() % max(); } 7184 #endif 7185 template<typename V> 7186 static void shuffle( V& vector ) { 7187 RandomNumberGenerator rng; 7188 #ifdef CATCH_CONFIG_CPP11_SHUFFLE 7189 std::shuffle( vector.begin(), vector.end(), rng ); 7190 #else 7191 random_shuffle( vector.begin(), vector.end(), rng ); 7192 #endif 7193 } 7194 }; 7195 7196 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) { 7197 7198 std::vector<TestCase> sorted = unsortedTestCases; 7199 7200 switch( config.runOrder() ) { 7201 case RunTests::InLexicographicalOrder: 7202 std::sort( sorted.begin(), sorted.end() ); 7203 break; 7204 case RunTests::InRandomOrder: 7205 { 7206 seedRng( config ); 7207 RandomNumberGenerator::shuffle( sorted ); 7208 } 7209 break; 7210 case RunTests::InDeclarationOrder: 7211 // already in declaration order 7212 break; 7213 } 7214 return sorted; 7215 } 7216 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) { 7217 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() ); 7218 } 7219 7220 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) { 7221 std::set<TestCase> seenFunctions; 7222 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end(); 7223 it != itEnd; 7224 ++it ) { 7225 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it ); 7226 if( !prev.second ) { 7227 std::ostringstream ss; 7228 7229 ss << Colour( Colour::Red ) 7230 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n" 7231 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n' 7232 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl; 7233 7234 throw std::runtime_error(ss.str()); 7235 } 7236 } 7237 } 7238 7239 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) { 7240 std::vector<TestCase> filtered; 7241 filtered.reserve( testCases.size() ); 7242 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end(); 7243 it != itEnd; 7244 ++it ) 7245 if( matchTest( *it, testSpec, config ) ) 7246 filtered.push_back( *it ); 7247 return filtered; 7248 } 7249 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) { 7250 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config ); 7251 } 7252 7253 class TestRegistry : public ITestCaseRegistry { 7254 public: 7255 TestRegistry() 7256 : m_currentSortOrder( RunTests::InDeclarationOrder ), 7257 m_unnamedCount( 0 ) 7258 {} 7259 virtual ~TestRegistry(); 7260 7261 virtual void registerTest( TestCase const& testCase ) { 7262 std::string name = testCase.getTestCaseInfo().name; 7263 if( name.empty() ) { 7264 std::ostringstream oss; 7265 oss << "Anonymous test case " << ++m_unnamedCount; 7266 return registerTest( testCase.withName( oss.str() ) ); 7267 } 7268 m_functions.push_back( testCase ); 7269 } 7270 7271 virtual std::vector<TestCase> const& getAllTests() const { 7272 return m_functions; 7273 } 7274 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const { 7275 if( m_sortedFunctions.empty() ) 7276 enforceNoDuplicateTestCases( m_functions ); 7277 7278 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) { 7279 m_sortedFunctions = sortTests( config, m_functions ); 7280 m_currentSortOrder = config.runOrder(); 7281 } 7282 return m_sortedFunctions; 7283 } 7284 7285 private: 7286 std::vector<TestCase> m_functions; 7287 mutable RunTests::InWhatOrder m_currentSortOrder; 7288 mutable std::vector<TestCase> m_sortedFunctions; 7289 size_t m_unnamedCount; 7290 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised 7291 }; 7292 7293 /////////////////////////////////////////////////////////////////////////// 7294 7295 class FreeFunctionTestCase : public SharedImpl<ITestCase> { 7296 public: 7297 7298 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {} 7299 7300 virtual void invoke() const { 7301 m_fun(); 7302 } 7303 7304 private: 7305 virtual ~FreeFunctionTestCase(); 7306 7307 TestFunction m_fun; 7308 }; 7309 7310 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) { 7311 std::string className = classOrQualifiedMethodName; 7312 if( startsWith( className, '&' ) ) 7313 { 7314 std::size_t lastColons = className.rfind( "::" ); 7315 std::size_t penultimateColons = className.rfind( "::", lastColons-1 ); 7316 if( penultimateColons == std::string::npos ) 7317 penultimateColons = 1; 7318 className = className.substr( penultimateColons, lastColons-penultimateColons ); 7319 } 7320 return className; 7321 } 7322 7323 void registerTestCase 7324 ( ITestCase* testCase, 7325 char const* classOrQualifiedMethodName, 7326 NameAndDesc const& nameAndDesc, 7327 SourceLineInfo const& lineInfo ) { 7328 7329 getMutableRegistryHub().registerTest 7330 ( makeTestCase 7331 ( testCase, 7332 extractClassName( classOrQualifiedMethodName ), 7333 nameAndDesc.name, 7334 nameAndDesc.description, 7335 lineInfo ) ); 7336 } 7337 void registerTestCaseFunction 7338 ( TestFunction function, 7339 SourceLineInfo const& lineInfo, 7340 NameAndDesc const& nameAndDesc ) { 7341 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo ); 7342 } 7343 7344 /////////////////////////////////////////////////////////////////////////// 7345 7346 AutoReg::AutoReg 7347 ( TestFunction function, 7348 SourceLineInfo const& lineInfo, 7349 NameAndDesc const& nameAndDesc ) { 7350 registerTestCaseFunction( function, lineInfo, nameAndDesc ); 7351 } 7352 7353 AutoReg::~AutoReg() {} 7354 7355 } // end namespace Catch 7356 7357 // #included from: catch_reporter_registry.hpp 7358 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED 7359 7360 #include <map> 7361 7362 namespace Catch { 7363 7364 class ReporterRegistry : public IReporterRegistry { 7365 7366 public: 7367 7368 virtual ~ReporterRegistry() CATCH_OVERRIDE {} 7369 7370 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE { 7371 FactoryMap::const_iterator it = m_factories.find( name ); 7372 if( it == m_factories.end() ) 7373 return CATCH_NULL; 7374 return it->second->create( ReporterConfig( config ) ); 7375 } 7376 7377 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) { 7378 m_factories.insert( std::make_pair( name, factory ) ); 7379 } 7380 void registerListener( Ptr<IReporterFactory> const& factory ) { 7381 m_listeners.push_back( factory ); 7382 } 7383 7384 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE { 7385 return m_factories; 7386 } 7387 virtual Listeners const& getListeners() const CATCH_OVERRIDE { 7388 return m_listeners; 7389 } 7390 7391 private: 7392 FactoryMap m_factories; 7393 Listeners m_listeners; 7394 }; 7395 } 7396 7397 // #included from: catch_exception_translator_registry.hpp 7398 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED 7399 7400 #ifdef __OBJC__ 7401 #import "Foundation/Foundation.h" 7402 #endif 7403 7404 namespace Catch { 7405 7406 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry { 7407 public: 7408 ~ExceptionTranslatorRegistry() { 7409 deleteAll( m_translators ); 7410 } 7411 7412 virtual void registerTranslator( const IExceptionTranslator* translator ) { 7413 m_translators.push_back( translator ); 7414 } 7415 7416 virtual std::string translateActiveException() const { 7417 try { 7418 #ifdef __OBJC__ 7419 // In Objective-C try objective-c exceptions first 7420 @try { 7421 return tryTranslators(); 7422 } 7423 @catch (NSException *exception) { 7424 return Catch::toString( [exception description] ); 7425 } 7426 #else 7427 return tryTranslators(); 7428 #endif 7429 } 7430 catch( TestFailureException& ) { 7431 throw; 7432 } 7433 catch( std::exception& ex ) { 7434 return ex.what(); 7435 } 7436 catch( std::string& msg ) { 7437 return msg; 7438 } 7439 catch( const char* msg ) { 7440 return msg; 7441 } 7442 catch(...) { 7443 return "Unknown exception"; 7444 } 7445 } 7446 7447 std::string tryTranslators() const { 7448 if( m_translators.empty() ) 7449 throw; 7450 else 7451 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() ); 7452 } 7453 7454 private: 7455 std::vector<const IExceptionTranslator*> m_translators; 7456 }; 7457 } 7458 7459 // #included from: catch_tag_alias_registry.h 7460 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED 7461 7462 #include <map> 7463 7464 namespace Catch { 7465 7466 class TagAliasRegistry : public ITagAliasRegistry { 7467 public: 7468 virtual ~TagAliasRegistry(); 7469 virtual Option<TagAlias> find( std::string const& alias ) const; 7470 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const; 7471 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ); 7472 7473 private: 7474 std::map<std::string, TagAlias> m_registry; 7475 }; 7476 7477 } // end namespace Catch 7478 7479 namespace Catch { 7480 7481 namespace { 7482 7483 class RegistryHub : public IRegistryHub, public IMutableRegistryHub { 7484 7485 RegistryHub( RegistryHub const& ); 7486 void operator=( RegistryHub const& ); 7487 7488 public: // IRegistryHub 7489 RegistryHub() { 7490 } 7491 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE { 7492 return m_reporterRegistry; 7493 } 7494 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE { 7495 return m_testCaseRegistry; 7496 } 7497 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE { 7498 return m_exceptionTranslatorRegistry; 7499 } 7500 virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE { 7501 return m_tagAliasRegistry; 7502 } 7503 7504 public: // IMutableRegistryHub 7505 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { 7506 m_reporterRegistry.registerReporter( name, factory ); 7507 } 7508 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE { 7509 m_reporterRegistry.registerListener( factory ); 7510 } 7511 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE { 7512 m_testCaseRegistry.registerTest( testInfo ); 7513 } 7514 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE { 7515 m_exceptionTranslatorRegistry.registerTranslator( translator ); 7516 } 7517 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE { 7518 m_tagAliasRegistry.add( alias, tag, lineInfo ); 7519 } 7520 7521 private: 7522 TestRegistry m_testCaseRegistry; 7523 ReporterRegistry m_reporterRegistry; 7524 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry; 7525 TagAliasRegistry m_tagAliasRegistry; 7526 }; 7527 7528 // Single, global, instance 7529 inline RegistryHub*& getTheRegistryHub() { 7530 static RegistryHub* theRegistryHub = CATCH_NULL; 7531 if( !theRegistryHub ) 7532 theRegistryHub = new RegistryHub(); 7533 return theRegistryHub; 7534 } 7535 } 7536 7537 IRegistryHub& getRegistryHub() { 7538 return *getTheRegistryHub(); 7539 } 7540 IMutableRegistryHub& getMutableRegistryHub() { 7541 return *getTheRegistryHub(); 7542 } 7543 void cleanUp() { 7544 delete getTheRegistryHub(); 7545 getTheRegistryHub() = CATCH_NULL; 7546 cleanUpContext(); 7547 } 7548 std::string translateActiveException() { 7549 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException(); 7550 } 7551 7552 } // end namespace Catch 7553 7554 // #included from: catch_notimplemented_exception.hpp 7555 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED 7556 7557 #include <sstream> 7558 7559 namespace Catch { 7560 7561 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo ) 7562 : m_lineInfo( lineInfo ) { 7563 std::ostringstream oss; 7564 oss << lineInfo << ": function "; 7565 oss << "not implemented"; 7566 m_what = oss.str(); 7567 } 7568 7569 const char* NotImplementedException::what() const CATCH_NOEXCEPT { 7570 return m_what.c_str(); 7571 } 7572 7573 } // end namespace Catch 7574 7575 // #included from: catch_context_impl.hpp 7576 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED 7577 7578 // #included from: catch_stream.hpp 7579 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED 7580 7581 #include <stdexcept> 7582 #include <cstdio> 7583 #include <iostream> 7584 7585 namespace Catch { 7586 7587 template<typename WriterF, size_t bufferSize=256> 7588 class StreamBufImpl : public StreamBufBase { 7589 char data[bufferSize]; 7590 WriterF m_writer; 7591 7592 public: 7593 StreamBufImpl() { 7594 setp( data, data + sizeof(data) ); 7595 } 7596 7597 ~StreamBufImpl() CATCH_NOEXCEPT { 7598 sync(); 7599 } 7600 7601 private: 7602 int overflow( int c ) { 7603 sync(); 7604 7605 if( c != EOF ) { 7606 if( pbase() == epptr() ) 7607 m_writer( std::string( 1, static_cast<char>( c ) ) ); 7608 else 7609 sputc( static_cast<char>( c ) ); 7610 } 7611 return 0; 7612 } 7613 7614 int sync() { 7615 if( pbase() != pptr() ) { 7616 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) ); 7617 setp( pbase(), epptr() ); 7618 } 7619 return 0; 7620 } 7621 }; 7622 7623 /////////////////////////////////////////////////////////////////////////// 7624 7625 FileStream::FileStream( std::string const& filename ) { 7626 m_ofs.open( filename.c_str() ); 7627 if( m_ofs.fail() ) { 7628 std::ostringstream oss; 7629 oss << "Unable to open file: '" << filename << '\''; 7630 throw std::domain_error( oss.str() ); 7631 } 7632 } 7633 7634 std::ostream& FileStream::stream() const { 7635 return m_ofs; 7636 } 7637 7638 struct OutputDebugWriter { 7639 7640 void operator()( std::string const&str ) { 7641 writeToDebugConsole( str ); 7642 } 7643 }; 7644 7645 DebugOutStream::DebugOutStream() 7646 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ), 7647 m_os( m_streamBuf.get() ) 7648 {} 7649 7650 std::ostream& DebugOutStream::stream() const { 7651 return m_os; 7652 } 7653 7654 // Store the streambuf from cout up-front because 7655 // cout may get redirected when running tests 7656 CoutStream::CoutStream() 7657 : m_os( Catch::cout().rdbuf() ) 7658 {} 7659 7660 std::ostream& CoutStream::stream() const { 7661 return m_os; 7662 } 7663 7664 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions 7665 std::ostream& cout() { 7666 return std::cout; 7667 } 7668 std::ostream& cerr() { 7669 return std::cerr; 7670 } 7671 #endif 7672 } 7673 7674 namespace Catch { 7675 7676 class Context : public IMutableContext { 7677 7678 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {} 7679 Context( Context const& ); 7680 void operator=( Context const& ); 7681 7682 public: 7683 virtual ~Context() { 7684 deleteAllValues( m_generatorsByTestName ); 7685 } 7686 7687 public: // IContext 7688 virtual IResultCapture* getResultCapture() { 7689 return m_resultCapture; 7690 } 7691 virtual IRunner* getRunner() { 7692 return m_runner; 7693 } 7694 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) { 7695 return getGeneratorsForCurrentTest() 7696 .getGeneratorInfo( fileInfo, totalSize ) 7697 .getCurrentIndex(); 7698 } 7699 virtual bool advanceGeneratorsForCurrentTest() { 7700 IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); 7701 return generators && generators->moveNext(); 7702 } 7703 7704 virtual Ptr<IConfig const> getConfig() const { 7705 return m_config; 7706 } 7707 7708 public: // IMutableContext 7709 virtual void setResultCapture( IResultCapture* resultCapture ) { 7710 m_resultCapture = resultCapture; 7711 } 7712 virtual void setRunner( IRunner* runner ) { 7713 m_runner = runner; 7714 } 7715 virtual void setConfig( Ptr<IConfig const> const& config ) { 7716 m_config = config; 7717 } 7718 7719 friend IMutableContext& getCurrentMutableContext(); 7720 7721 private: 7722 IGeneratorsForTest* findGeneratorsForCurrentTest() { 7723 std::string testName = getResultCapture()->getCurrentTestName(); 7724 7725 std::map<std::string, IGeneratorsForTest*>::const_iterator it = 7726 m_generatorsByTestName.find( testName ); 7727 return it != m_generatorsByTestName.end() 7728 ? it->second 7729 : CATCH_NULL; 7730 } 7731 7732 IGeneratorsForTest& getGeneratorsForCurrentTest() { 7733 IGeneratorsForTest* generators = findGeneratorsForCurrentTest(); 7734 if( !generators ) { 7735 std::string testName = getResultCapture()->getCurrentTestName(); 7736 generators = createGeneratorsForTest(); 7737 m_generatorsByTestName.insert( std::make_pair( testName, generators ) ); 7738 } 7739 return *generators; 7740 } 7741 7742 private: 7743 Ptr<IConfig const> m_config; 7744 IRunner* m_runner; 7745 IResultCapture* m_resultCapture; 7746 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName; 7747 }; 7748 7749 namespace { 7750 Context* currentContext = CATCH_NULL; 7751 } 7752 IMutableContext& getCurrentMutableContext() { 7753 if( !currentContext ) 7754 currentContext = new Context(); 7755 return *currentContext; 7756 } 7757 IContext& getCurrentContext() { 7758 return getCurrentMutableContext(); 7759 } 7760 7761 void cleanUpContext() { 7762 delete currentContext; 7763 currentContext = CATCH_NULL; 7764 } 7765 } 7766 7767 // #included from: catch_console_colour_impl.hpp 7768 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED 7769 7770 // #included from: catch_errno_guard.hpp 7771 #define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED 7772 7773 #include <cerrno> 7774 7775 namespace Catch { 7776 7777 class ErrnoGuard { 7778 public: 7779 ErrnoGuard():m_oldErrno(errno){} 7780 ~ErrnoGuard() { errno = m_oldErrno; } 7781 private: 7782 int m_oldErrno; 7783 }; 7784 7785 } 7786 7787 namespace Catch { 7788 namespace { 7789 7790 struct IColourImpl { 7791 virtual ~IColourImpl() {} 7792 virtual void use( Colour::Code _colourCode ) = 0; 7793 }; 7794 7795 struct NoColourImpl : IColourImpl { 7796 void use( Colour::Code ) {} 7797 7798 static IColourImpl* instance() { 7799 static NoColourImpl s_instance; 7800 return &s_instance; 7801 } 7802 }; 7803 7804 } // anon namespace 7805 } // namespace Catch 7806 7807 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI ) 7808 # ifdef CATCH_PLATFORM_WINDOWS 7809 # define CATCH_CONFIG_COLOUR_WINDOWS 7810 # else 7811 # define CATCH_CONFIG_COLOUR_ANSI 7812 # endif 7813 #endif 7814 7815 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) ///////////////////////////////////////// 7816 7817 namespace Catch { 7818 namespace { 7819 7820 class Win32ColourImpl : public IColourImpl { 7821 public: 7822 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) ) 7823 { 7824 CONSOLE_SCREEN_BUFFER_INFO csbiInfo; 7825 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo ); 7826 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY ); 7827 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY ); 7828 } 7829 7830 virtual void use( Colour::Code _colourCode ) { 7831 switch( _colourCode ) { 7832 case Colour::None: return setTextAttribute( originalForegroundAttributes ); 7833 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 7834 case Colour::Red: return setTextAttribute( FOREGROUND_RED ); 7835 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN ); 7836 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE ); 7837 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN ); 7838 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN ); 7839 case Colour::Grey: return setTextAttribute( 0 ); 7840 7841 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY ); 7842 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED ); 7843 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN ); 7844 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE ); 7845 7846 case Colour::Bright: throw std::logic_error( "not a colour" ); 7847 } 7848 } 7849 7850 private: 7851 void setTextAttribute( WORD _textAttribute ) { 7852 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes ); 7853 } 7854 HANDLE stdoutHandle; 7855 WORD originalForegroundAttributes; 7856 WORD originalBackgroundAttributes; 7857 }; 7858 7859 IColourImpl* platformColourInstance() { 7860 static Win32ColourImpl s_instance; 7861 7862 Ptr<IConfig const> config = getCurrentContext().getConfig(); 7863 UseColour::YesOrNo colourMode = config 7864 ? config->useColour() 7865 : UseColour::Auto; 7866 if( colourMode == UseColour::Auto ) 7867 colourMode = !isDebuggerActive() 7868 ? UseColour::Yes 7869 : UseColour::No; 7870 return colourMode == UseColour::Yes 7871 ? &s_instance 7872 : NoColourImpl::instance(); 7873 } 7874 7875 } // end anon namespace 7876 } // end namespace Catch 7877 7878 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) ////////////////////////////////////// 7879 7880 #include <unistd.h> 7881 7882 namespace Catch { 7883 namespace { 7884 7885 // use POSIX/ ANSI console terminal codes 7886 // Thanks to Adam Strzelecki for original contribution 7887 // (http://github.com/nanoant) 7888 // https://github.com/philsquared/Catch/pull/131 7889 class PosixColourImpl : public IColourImpl { 7890 public: 7891 virtual void use( Colour::Code _colourCode ) { 7892 switch( _colourCode ) { 7893 case Colour::None: 7894 case Colour::White: return setColour( "[0m" ); 7895 case Colour::Red: return setColour( "[0;31m" ); 7896 case Colour::Green: return setColour( "[0;32m" ); 7897 case Colour::Blue: return setColour( "[0;34m" ); 7898 case Colour::Cyan: return setColour( "[0;36m" ); 7899 case Colour::Yellow: return setColour( "[0;33m" ); 7900 case Colour::Grey: return setColour( "[1;30m" ); 7901 7902 case Colour::LightGrey: return setColour( "[0;37m" ); 7903 case Colour::BrightRed: return setColour( "[1;31m" ); 7904 case Colour::BrightGreen: return setColour( "[1;32m" ); 7905 case Colour::BrightWhite: return setColour( "[1;37m" ); 7906 7907 case Colour::Bright: throw std::logic_error( "not a colour" ); 7908 } 7909 } 7910 static IColourImpl* instance() { 7911 static PosixColourImpl s_instance; 7912 return &s_instance; 7913 } 7914 7915 private: 7916 void setColour( const char* _escapeCode ) { 7917 Catch::cout() << '\033' << _escapeCode; 7918 } 7919 }; 7920 7921 IColourImpl* platformColourInstance() { 7922 ErrnoGuard guard; 7923 Ptr<IConfig const> config = getCurrentContext().getConfig(); 7924 UseColour::YesOrNo colourMode = config 7925 ? config->useColour() 7926 : UseColour::Auto; 7927 if( colourMode == UseColour::Auto ) 7928 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) ) 7929 ? UseColour::Yes 7930 : UseColour::No; 7931 return colourMode == UseColour::Yes 7932 ? PosixColourImpl::instance() 7933 : NoColourImpl::instance(); 7934 } 7935 7936 } // end anon namespace 7937 } // end namespace Catch 7938 7939 #else // not Windows or ANSI /////////////////////////////////////////////// 7940 7941 namespace Catch { 7942 7943 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); } 7944 7945 } // end namespace Catch 7946 7947 #endif // Windows/ ANSI/ None 7948 7949 namespace Catch { 7950 7951 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); } 7952 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; } 7953 Colour::~Colour(){ if( !m_moved ) use( None ); } 7954 7955 void Colour::use( Code _colourCode ) { 7956 static IColourImpl* impl = platformColourInstance(); 7957 impl->use( _colourCode ); 7958 } 7959 7960 } // end namespace Catch 7961 7962 // #included from: catch_generators_impl.hpp 7963 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED 7964 7965 #include <vector> 7966 #include <string> 7967 #include <map> 7968 7969 namespace Catch { 7970 7971 struct GeneratorInfo : IGeneratorInfo { 7972 7973 GeneratorInfo( std::size_t size ) 7974 : m_size( size ), 7975 m_currentIndex( 0 ) 7976 {} 7977 7978 bool moveNext() { 7979 if( ++m_currentIndex == m_size ) { 7980 m_currentIndex = 0; 7981 return false; 7982 } 7983 return true; 7984 } 7985 7986 std::size_t getCurrentIndex() const { 7987 return m_currentIndex; 7988 } 7989 7990 std::size_t m_size; 7991 std::size_t m_currentIndex; 7992 }; 7993 7994 /////////////////////////////////////////////////////////////////////////// 7995 7996 class GeneratorsForTest : public IGeneratorsForTest { 7997 7998 public: 7999 ~GeneratorsForTest() { 8000 deleteAll( m_generatorsInOrder ); 8001 } 8002 8003 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) { 8004 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo ); 8005 if( it == m_generatorsByName.end() ) { 8006 IGeneratorInfo* info = new GeneratorInfo( size ); 8007 m_generatorsByName.insert( std::make_pair( fileInfo, info ) ); 8008 m_generatorsInOrder.push_back( info ); 8009 return *info; 8010 } 8011 return *it->second; 8012 } 8013 8014 bool moveNext() { 8015 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin(); 8016 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end(); 8017 for(; it != itEnd; ++it ) { 8018 if( (*it)->moveNext() ) 8019 return true; 8020 } 8021 return false; 8022 } 8023 8024 private: 8025 std::map<std::string, IGeneratorInfo*> m_generatorsByName; 8026 std::vector<IGeneratorInfo*> m_generatorsInOrder; 8027 }; 8028 8029 IGeneratorsForTest* createGeneratorsForTest() 8030 { 8031 return new GeneratorsForTest(); 8032 } 8033 8034 } // end namespace Catch 8035 8036 // #included from: catch_assertionresult.hpp 8037 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED 8038 8039 namespace Catch { 8040 8041 AssertionInfo::AssertionInfo( char const * _macroName, 8042 SourceLineInfo const& _lineInfo, 8043 char const * _capturedExpression, 8044 ResultDisposition::Flags _resultDisposition, 8045 char const * _secondArg) 8046 : macroName( _macroName ), 8047 lineInfo( _lineInfo ), 8048 capturedExpression( _capturedExpression ), 8049 resultDisposition( _resultDisposition ), 8050 secondArg( _secondArg ) 8051 {} 8052 8053 AssertionResult::AssertionResult() {} 8054 8055 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data ) 8056 : m_info( info ), 8057 m_resultData( data ) 8058 {} 8059 8060 AssertionResult::~AssertionResult() {} 8061 8062 // Result was a success 8063 bool AssertionResult::succeeded() const { 8064 return Catch::isOk( m_resultData.resultType ); 8065 } 8066 8067 // Result was a success, or failure is suppressed 8068 bool AssertionResult::isOk() const { 8069 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition ); 8070 } 8071 8072 ResultWas::OfType AssertionResult::getResultType() const { 8073 return m_resultData.resultType; 8074 } 8075 8076 bool AssertionResult::hasExpression() const { 8077 return m_info.capturedExpression[0] != 0; 8078 } 8079 8080 bool AssertionResult::hasMessage() const { 8081 return !m_resultData.message.empty(); 8082 } 8083 8084 std::string capturedExpressionWithSecondArgument( char const * capturedExpression, char const * secondArg ) { 8085 return (secondArg[0] == 0 || secondArg[0] == '"' && secondArg[1] == '"') 8086 ? capturedExpression 8087 : std::string(capturedExpression) + ", " + secondArg; 8088 } 8089 8090 std::string AssertionResult::getExpression() const { 8091 if( isFalseTest( m_info.resultDisposition ) ) 8092 return '!' + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); 8093 else 8094 return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); 8095 } 8096 std::string AssertionResult::getExpressionInMacro() const { 8097 if( m_info.macroName[0] == 0 ) 8098 return capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg); 8099 else 8100 return std::string(m_info.macroName) + "( " + capturedExpressionWithSecondArgument(m_info.capturedExpression, m_info.secondArg) + " )"; 8101 } 8102 8103 bool AssertionResult::hasExpandedExpression() const { 8104 return hasExpression() && getExpandedExpression() != getExpression(); 8105 } 8106 8107 std::string AssertionResult::getExpandedExpression() const { 8108 return m_resultData.reconstructExpression(); 8109 } 8110 8111 std::string AssertionResult::getMessage() const { 8112 return m_resultData.message; 8113 } 8114 SourceLineInfo AssertionResult::getSourceInfo() const { 8115 return m_info.lineInfo; 8116 } 8117 8118 std::string AssertionResult::getTestMacroName() const { 8119 return m_info.macroName; 8120 } 8121 8122 void AssertionResult::discardDecomposedExpression() const { 8123 m_resultData.decomposedExpression = CATCH_NULL; 8124 } 8125 8126 void AssertionResult::expandDecomposedExpression() const { 8127 m_resultData.reconstructExpression(); 8128 } 8129 8130 } // end namespace Catch 8131 8132 // #included from: catch_test_case_info.hpp 8133 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED 8134 8135 #include <cctype> 8136 8137 namespace Catch { 8138 8139 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) { 8140 if( startsWith( tag, '.' ) || 8141 tag == "hide" || 8142 tag == "!hide" ) 8143 return TestCaseInfo::IsHidden; 8144 else if( tag == "!throws" ) 8145 return TestCaseInfo::Throws; 8146 else if( tag == "!shouldfail" ) 8147 return TestCaseInfo::ShouldFail; 8148 else if( tag == "!mayfail" ) 8149 return TestCaseInfo::MayFail; 8150 else if( tag == "!nonportable" ) 8151 return TestCaseInfo::NonPortable; 8152 else 8153 return TestCaseInfo::None; 8154 } 8155 inline bool isReservedTag( std::string const& tag ) { 8156 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] ); 8157 } 8158 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) { 8159 if( isReservedTag( tag ) ) { 8160 std::ostringstream ss; 8161 ss << Colour(Colour::Red) 8162 << "Tag name [" << tag << "] not allowed.\n" 8163 << "Tag names starting with non alpha-numeric characters are reserved\n" 8164 << Colour(Colour::FileName) 8165 << _lineInfo << '\n'; 8166 throw std::runtime_error(ss.str()); 8167 } 8168 } 8169 8170 TestCase makeTestCase( ITestCase* _testCase, 8171 std::string const& _className, 8172 std::string const& _name, 8173 std::string const& _descOrTags, 8174 SourceLineInfo const& _lineInfo ) 8175 { 8176 bool isHidden( startsWith( _name, "./" ) ); // Legacy support 8177 8178 // Parse out tags 8179 std::set<std::string> tags; 8180 std::string desc, tag; 8181 bool inTag = false; 8182 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) { 8183 char c = _descOrTags[i]; 8184 if( !inTag ) { 8185 if( c == '[' ) 8186 inTag = true; 8187 else 8188 desc += c; 8189 } 8190 else { 8191 if( c == ']' ) { 8192 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag ); 8193 if( prop == TestCaseInfo::IsHidden ) 8194 isHidden = true; 8195 else if( prop == TestCaseInfo::None ) 8196 enforceNotReservedTag( tag, _lineInfo ); 8197 8198 tags.insert( tag ); 8199 tag.clear(); 8200 inTag = false; 8201 } 8202 else 8203 tag += c; 8204 } 8205 } 8206 if( isHidden ) { 8207 tags.insert( "hide" ); 8208 tags.insert( "." ); 8209 } 8210 8211 TestCaseInfo info( _name, _className, desc, tags, _lineInfo ); 8212 return TestCase( _testCase, info ); 8213 } 8214 8215 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags ) 8216 { 8217 testCaseInfo.tags = tags; 8218 testCaseInfo.lcaseTags.clear(); 8219 8220 std::ostringstream oss; 8221 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) { 8222 oss << '[' << *it << ']'; 8223 std::string lcaseTag = toLower( *it ); 8224 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) ); 8225 testCaseInfo.lcaseTags.insert( lcaseTag ); 8226 } 8227 testCaseInfo.tagsAsString = oss.str(); 8228 } 8229 8230 TestCaseInfo::TestCaseInfo( std::string const& _name, 8231 std::string const& _className, 8232 std::string const& _description, 8233 std::set<std::string> const& _tags, 8234 SourceLineInfo const& _lineInfo ) 8235 : name( _name ), 8236 className( _className ), 8237 description( _description ), 8238 lineInfo( _lineInfo ), 8239 properties( None ) 8240 { 8241 setTags( *this, _tags ); 8242 } 8243 8244 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other ) 8245 : name( other.name ), 8246 className( other.className ), 8247 description( other.description ), 8248 tags( other.tags ), 8249 lcaseTags( other.lcaseTags ), 8250 tagsAsString( other.tagsAsString ), 8251 lineInfo( other.lineInfo ), 8252 properties( other.properties ) 8253 {} 8254 8255 bool TestCaseInfo::isHidden() const { 8256 return ( properties & IsHidden ) != 0; 8257 } 8258 bool TestCaseInfo::throws() const { 8259 return ( properties & Throws ) != 0; 8260 } 8261 bool TestCaseInfo::okToFail() const { 8262 return ( properties & (ShouldFail | MayFail ) ) != 0; 8263 } 8264 bool TestCaseInfo::expectedToFail() const { 8265 return ( properties & (ShouldFail ) ) != 0; 8266 } 8267 8268 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {} 8269 8270 TestCase::TestCase( TestCase const& other ) 8271 : TestCaseInfo( other ), 8272 test( other.test ) 8273 {} 8274 8275 TestCase TestCase::withName( std::string const& _newName ) const { 8276 TestCase other( *this ); 8277 other.name = _newName; 8278 return other; 8279 } 8280 8281 void TestCase::swap( TestCase& other ) { 8282 test.swap( other.test ); 8283 name.swap( other.name ); 8284 className.swap( other.className ); 8285 description.swap( other.description ); 8286 tags.swap( other.tags ); 8287 lcaseTags.swap( other.lcaseTags ); 8288 tagsAsString.swap( other.tagsAsString ); 8289 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties ); 8290 std::swap( lineInfo, other.lineInfo ); 8291 } 8292 8293 void TestCase::invoke() const { 8294 test->invoke(); 8295 } 8296 8297 bool TestCase::operator == ( TestCase const& other ) const { 8298 return test.get() == other.test.get() && 8299 name == other.name && 8300 className == other.className; 8301 } 8302 8303 bool TestCase::operator < ( TestCase const& other ) const { 8304 return name < other.name; 8305 } 8306 TestCase& TestCase::operator = ( TestCase const& other ) { 8307 TestCase temp( other ); 8308 swap( temp ); 8309 return *this; 8310 } 8311 8312 TestCaseInfo const& TestCase::getTestCaseInfo() const 8313 { 8314 return *this; 8315 } 8316 8317 } // end namespace Catch 8318 8319 // #included from: catch_version.hpp 8320 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED 8321 8322 namespace Catch { 8323 8324 Version::Version 8325 ( unsigned int _majorVersion, 8326 unsigned int _minorVersion, 8327 unsigned int _patchNumber, 8328 char const * const _branchName, 8329 unsigned int _buildNumber ) 8330 : majorVersion( _majorVersion ), 8331 minorVersion( _minorVersion ), 8332 patchNumber( _patchNumber ), 8333 branchName( _branchName ), 8334 buildNumber( _buildNumber ) 8335 {} 8336 8337 std::ostream& operator << ( std::ostream& os, Version const& version ) { 8338 os << version.majorVersion << '.' 8339 << version.minorVersion << '.' 8340 << version.patchNumber; 8341 // branchName is never null -> 0th char is \0 if it is empty 8342 if (version.branchName[0]) { 8343 os << '-' << version.branchName 8344 << '.' << version.buildNumber; 8345 } 8346 return os; 8347 } 8348 8349 inline Version libraryVersion() { 8350 static Version version( 1, 9, 6, "", 0 ); 8351 return version; 8352 } 8353 8354 } 8355 8356 // #included from: catch_message.hpp 8357 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED 8358 8359 namespace Catch { 8360 8361 MessageInfo::MessageInfo( std::string const& _macroName, 8362 SourceLineInfo const& _lineInfo, 8363 ResultWas::OfType _type ) 8364 : macroName( _macroName ), 8365 lineInfo( _lineInfo ), 8366 type( _type ), 8367 sequence( ++globalCount ) 8368 {} 8369 8370 // This may need protecting if threading support is added 8371 unsigned int MessageInfo::globalCount = 0; 8372 8373 //////////////////////////////////////////////////////////////////////////// 8374 8375 ScopedMessage::ScopedMessage( MessageBuilder const& builder ) 8376 : m_info( builder.m_info ) 8377 { 8378 m_info.message = builder.m_stream.str(); 8379 getResultCapture().pushScopedMessage( m_info ); 8380 } 8381 ScopedMessage::ScopedMessage( ScopedMessage const& other ) 8382 : m_info( other.m_info ) 8383 {} 8384 8385 ScopedMessage::~ScopedMessage() { 8386 if ( !std::uncaught_exception() ){ 8387 getResultCapture().popScopedMessage(m_info); 8388 } 8389 } 8390 8391 } // end namespace Catch 8392 8393 // #included from: catch_legacy_reporter_adapter.hpp 8394 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED 8395 8396 // #included from: catch_legacy_reporter_adapter.h 8397 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED 8398 8399 namespace Catch 8400 { 8401 // Deprecated 8402 struct IReporter : IShared { 8403 virtual ~IReporter(); 8404 8405 virtual bool shouldRedirectStdout() const = 0; 8406 8407 virtual void StartTesting() = 0; 8408 virtual void EndTesting( Totals const& totals ) = 0; 8409 virtual void StartGroup( std::string const& groupName ) = 0; 8410 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0; 8411 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0; 8412 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0; 8413 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0; 8414 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0; 8415 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0; 8416 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0; 8417 virtual void Aborted() = 0; 8418 virtual void Result( AssertionResult const& result ) = 0; 8419 }; 8420 8421 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter> 8422 { 8423 public: 8424 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ); 8425 virtual ~LegacyReporterAdapter(); 8426 8427 virtual ReporterPreferences getPreferences() const; 8428 virtual void noMatchingTestCases( std::string const& ); 8429 virtual void testRunStarting( TestRunInfo const& ); 8430 virtual void testGroupStarting( GroupInfo const& groupInfo ); 8431 virtual void testCaseStarting( TestCaseInfo const& testInfo ); 8432 virtual void sectionStarting( SectionInfo const& sectionInfo ); 8433 virtual void assertionStarting( AssertionInfo const& ); 8434 virtual bool assertionEnded( AssertionStats const& assertionStats ); 8435 virtual void sectionEnded( SectionStats const& sectionStats ); 8436 virtual void testCaseEnded( TestCaseStats const& testCaseStats ); 8437 virtual void testGroupEnded( TestGroupStats const& testGroupStats ); 8438 virtual void testRunEnded( TestRunStats const& testRunStats ); 8439 virtual void skipTest( TestCaseInfo const& ); 8440 8441 private: 8442 Ptr<IReporter> m_legacyReporter; 8443 }; 8444 } 8445 8446 namespace Catch 8447 { 8448 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter ) 8449 : m_legacyReporter( legacyReporter ) 8450 {} 8451 LegacyReporterAdapter::~LegacyReporterAdapter() {} 8452 8453 ReporterPreferences LegacyReporterAdapter::getPreferences() const { 8454 ReporterPreferences prefs; 8455 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout(); 8456 return prefs; 8457 } 8458 8459 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {} 8460 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) { 8461 m_legacyReporter->StartTesting(); 8462 } 8463 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) { 8464 m_legacyReporter->StartGroup( groupInfo.name ); 8465 } 8466 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) { 8467 m_legacyReporter->StartTestCase( testInfo ); 8468 } 8469 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) { 8470 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description ); 8471 } 8472 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) { 8473 // Not on legacy interface 8474 } 8475 8476 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) { 8477 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) { 8478 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); 8479 it != itEnd; 8480 ++it ) { 8481 if( it->type == ResultWas::Info ) { 8482 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal ); 8483 rb << it->message; 8484 rb.setResultType( ResultWas::Info ); 8485 AssertionResult result = rb.build(); 8486 m_legacyReporter->Result( result ); 8487 } 8488 } 8489 } 8490 m_legacyReporter->Result( assertionStats.assertionResult ); 8491 return true; 8492 } 8493 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) { 8494 if( sectionStats.missingAssertions ) 8495 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name ); 8496 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions ); 8497 } 8498 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) { 8499 m_legacyReporter->EndTestCase 8500 ( testCaseStats.testInfo, 8501 testCaseStats.totals, 8502 testCaseStats.stdOut, 8503 testCaseStats.stdErr ); 8504 } 8505 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) { 8506 if( testGroupStats.aborting ) 8507 m_legacyReporter->Aborted(); 8508 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals ); 8509 } 8510 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) { 8511 m_legacyReporter->EndTesting( testRunStats.totals ); 8512 } 8513 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) { 8514 } 8515 } 8516 8517 // #included from: catch_timer.hpp 8518 8519 #ifdef __clang__ 8520 # pragma clang diagnostic push 8521 # pragma clang diagnostic ignored "-Wc++11-long-long" 8522 #endif 8523 8524 #ifdef CATCH_PLATFORM_WINDOWS 8525 8526 #else 8527 8528 #include <sys/time.h> 8529 8530 #endif 8531 8532 namespace Catch { 8533 8534 namespace { 8535 #ifdef CATCH_PLATFORM_WINDOWS 8536 UInt64 getCurrentTicks() { 8537 static UInt64 hz=0, hzo=0; 8538 if (!hz) { 8539 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) ); 8540 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) ); 8541 } 8542 UInt64 t; 8543 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) ); 8544 return ((t-hzo)*1000000)/hz; 8545 } 8546 #else 8547 UInt64 getCurrentTicks() { 8548 timeval t; 8549 gettimeofday(&t,CATCH_NULL); 8550 return static_cast<UInt64>( t.tv_sec ) * 1000000ull + static_cast<UInt64>( t.tv_usec ); 8551 } 8552 #endif 8553 } 8554 8555 void Timer::start() { 8556 m_ticks = getCurrentTicks(); 8557 } 8558 unsigned int Timer::getElapsedMicroseconds() const { 8559 return static_cast<unsigned int>(getCurrentTicks() - m_ticks); 8560 } 8561 unsigned int Timer::getElapsedMilliseconds() const { 8562 return static_cast<unsigned int>(getElapsedMicroseconds()/1000); 8563 } 8564 double Timer::getElapsedSeconds() const { 8565 return getElapsedMicroseconds()/1000000.0; 8566 } 8567 8568 } // namespace Catch 8569 8570 #ifdef __clang__ 8571 # pragma clang diagnostic pop 8572 #endif 8573 // #included from: catch_common.hpp 8574 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED 8575 8576 #include <cstring> 8577 #include <cctype> 8578 8579 namespace Catch { 8580 8581 bool startsWith( std::string const& s, std::string const& prefix ) { 8582 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin()); 8583 } 8584 bool startsWith( std::string const& s, char prefix ) { 8585 return !s.empty() && s[0] == prefix; 8586 } 8587 bool endsWith( std::string const& s, std::string const& suffix ) { 8588 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin()); 8589 } 8590 bool endsWith( std::string const& s, char suffix ) { 8591 return !s.empty() && s[s.size()-1] == suffix; 8592 } 8593 bool contains( std::string const& s, std::string const& infix ) { 8594 return s.find( infix ) != std::string::npos; 8595 } 8596 char toLowerCh(char c) { 8597 return static_cast<char>( std::tolower( c ) ); 8598 } 8599 void toLowerInPlace( std::string& s ) { 8600 std::transform( s.begin(), s.end(), s.begin(), toLowerCh ); 8601 } 8602 std::string toLower( std::string const& s ) { 8603 std::string lc = s; 8604 toLowerInPlace( lc ); 8605 return lc; 8606 } 8607 std::string trim( std::string const& str ) { 8608 static char const* whitespaceChars = "\n\r\t "; 8609 std::string::size_type start = str.find_first_not_of( whitespaceChars ); 8610 std::string::size_type end = str.find_last_not_of( whitespaceChars ); 8611 8612 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string(); 8613 } 8614 8615 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) { 8616 bool replaced = false; 8617 std::size_t i = str.find( replaceThis ); 8618 while( i != std::string::npos ) { 8619 replaced = true; 8620 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() ); 8621 if( i < str.size()-withThis.size() ) 8622 i = str.find( replaceThis, i+withThis.size() ); 8623 else 8624 i = std::string::npos; 8625 } 8626 return replaced; 8627 } 8628 8629 pluralise::pluralise( std::size_t count, std::string const& label ) 8630 : m_count( count ), 8631 m_label( label ) 8632 {} 8633 8634 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) { 8635 os << pluraliser.m_count << ' ' << pluraliser.m_label; 8636 if( pluraliser.m_count != 1 ) 8637 os << 's'; 8638 return os; 8639 } 8640 8641 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){} 8642 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line ) 8643 : file( _file ), 8644 line( _line ) 8645 {} 8646 bool SourceLineInfo::empty() const { 8647 return file[0] == '\0'; 8648 } 8649 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const { 8650 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0); 8651 } 8652 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const { 8653 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0)); 8654 } 8655 8656 void seedRng( IConfig const& config ) { 8657 if( config.rngSeed() != 0 ) 8658 srand( config.rngSeed() ); 8659 } 8660 unsigned int rngSeed() { 8661 return getCurrentContext().getConfig()->rngSeed(); 8662 } 8663 8664 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) { 8665 #ifndef __GNUG__ 8666 os << info.file << '(' << info.line << ')'; 8667 #else 8668 os << info.file << ':' << info.line; 8669 #endif 8670 return os; 8671 } 8672 8673 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) { 8674 std::ostringstream oss; 8675 oss << locationInfo << ": Internal Catch error: '" << message << '\''; 8676 if( alwaysTrue() ) 8677 throw std::logic_error( oss.str() ); 8678 } 8679 } 8680 8681 // #included from: catch_section.hpp 8682 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED 8683 8684 namespace Catch { 8685 8686 SectionInfo::SectionInfo 8687 ( SourceLineInfo const& _lineInfo, 8688 std::string const& _name, 8689 std::string const& _description ) 8690 : name( _name ), 8691 description( _description ), 8692 lineInfo( _lineInfo ) 8693 {} 8694 8695 Section::Section( SectionInfo const& info ) 8696 : m_info( info ), 8697 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) ) 8698 { 8699 m_timer.start(); 8700 } 8701 8702 #if defined(_MSC_VER) 8703 # pragma warning(push) 8704 # pragma warning(disable:4996) // std::uncaught_exception is deprecated in C++17 8705 #endif 8706 Section::~Section() { 8707 if( m_sectionIncluded ) { 8708 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() ); 8709 if( std::uncaught_exception() ) 8710 getResultCapture().sectionEndedEarly( endInfo ); 8711 else 8712 getResultCapture().sectionEnded( endInfo ); 8713 } 8714 } 8715 #if defined(_MSC_VER) 8716 # pragma warning(pop) 8717 #endif 8718 8719 // This indicates whether the section should be executed or not 8720 Section::operator bool() const { 8721 return m_sectionIncluded; 8722 } 8723 8724 } // end namespace Catch 8725 8726 // #included from: catch_debugger.hpp 8727 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED 8728 8729 #ifdef CATCH_PLATFORM_MAC 8730 8731 #include <assert.h> 8732 #include <stdbool.h> 8733 #include <sys/types.h> 8734 #include <unistd.h> 8735 #include <sys/sysctl.h> 8736 8737 namespace Catch{ 8738 8739 // The following function is taken directly from the following technical note: 8740 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html 8741 8742 // Returns true if the current process is being debugged (either 8743 // running under the debugger or has a debugger attached post facto). 8744 bool isDebuggerActive(){ 8745 8746 int mib[4]; 8747 struct kinfo_proc info; 8748 size_t size; 8749 8750 // Initialize the flags so that, if sysctl fails for some bizarre 8751 // reason, we get a predictable result. 8752 8753 info.kp_proc.p_flag = 0; 8754 8755 // Initialize mib, which tells sysctl the info we want, in this case 8756 // we're looking for information about a specific process ID. 8757 8758 mib[0] = CTL_KERN; 8759 mib[1] = KERN_PROC; 8760 mib[2] = KERN_PROC_PID; 8761 mib[3] = getpid(); 8762 8763 // Call sysctl. 8764 8765 size = sizeof(info); 8766 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) { 8767 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl; 8768 return false; 8769 } 8770 8771 // We're being debugged if the P_TRACED flag is set. 8772 8773 return ( (info.kp_proc.p_flag & P_TRACED) != 0 ); 8774 } 8775 } // namespace Catch 8776 8777 #elif defined(CATCH_PLATFORM_LINUX) 8778 #include <fstream> 8779 #include <string> 8780 8781 namespace Catch{ 8782 // The standard POSIX way of detecting a debugger is to attempt to 8783 // ptrace() the process, but this needs to be done from a child and not 8784 // this process itself to still allow attaching to this process later 8785 // if wanted, so is rather heavy. Under Linux we have the PID of the 8786 // "debugger" (which doesn't need to be gdb, of course, it could also 8787 // be strace, for example) in /proc/$PID/status, so just get it from 8788 // there instead. 8789 bool isDebuggerActive(){ 8790 // Libstdc++ has a bug, where std::ifstream sets errno to 0 8791 // This way our users can properly assert over errno values 8792 ErrnoGuard guard; 8793 std::ifstream in("/proc/self/status"); 8794 for( std::string line; std::getline(in, line); ) { 8795 static const int PREFIX_LEN = 11; 8796 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) { 8797 // We're traced if the PID is not 0 and no other PID starts 8798 // with 0 digit, so it's enough to check for just a single 8799 // character. 8800 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0'; 8801 } 8802 } 8803 8804 return false; 8805 } 8806 } // namespace Catch 8807 #elif defined(_MSC_VER) 8808 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 8809 namespace Catch { 8810 bool isDebuggerActive() { 8811 return IsDebuggerPresent() != 0; 8812 } 8813 } 8814 #elif defined(__MINGW32__) 8815 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent(); 8816 namespace Catch { 8817 bool isDebuggerActive() { 8818 return IsDebuggerPresent() != 0; 8819 } 8820 } 8821 #else 8822 namespace Catch { 8823 inline bool isDebuggerActive() { return false; } 8824 } 8825 #endif // Platform 8826 8827 #ifdef CATCH_PLATFORM_WINDOWS 8828 8829 namespace Catch { 8830 void writeToDebugConsole( std::string const& text ) { 8831 ::OutputDebugStringA( text.c_str() ); 8832 } 8833 } 8834 #else 8835 namespace Catch { 8836 void writeToDebugConsole( std::string const& text ) { 8837 // !TBD: Need a version for Mac/ XCode and other IDEs 8838 Catch::cout() << text; 8839 } 8840 } 8841 #endif // Platform 8842 8843 // #included from: catch_tostring.hpp 8844 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED 8845 8846 namespace Catch { 8847 8848 namespace Detail { 8849 8850 const std::string unprintableString = "{?}"; 8851 8852 namespace { 8853 const int hexThreshold = 255; 8854 8855 struct Endianness { 8856 enum Arch { Big, Little }; 8857 8858 static Arch which() { 8859 union _{ 8860 int asInt; 8861 char asChar[sizeof (int)]; 8862 } u; 8863 8864 u.asInt = 1; 8865 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little; 8866 } 8867 }; 8868 } 8869 8870 std::string rawMemoryToString( const void *object, std::size_t size ) 8871 { 8872 // Reverse order for little endian architectures 8873 int i = 0, end = static_cast<int>( size ), inc = 1; 8874 if( Endianness::which() == Endianness::Little ) { 8875 i = end-1; 8876 end = inc = -1; 8877 } 8878 8879 unsigned char const *bytes = static_cast<unsigned char const *>(object); 8880 std::ostringstream os; 8881 os << "0x" << std::setfill('0') << std::hex; 8882 for( ; i != end; i += inc ) 8883 os << std::setw(2) << static_cast<unsigned>(bytes[i]); 8884 return os.str(); 8885 } 8886 } 8887 8888 std::string toString( std::string const& value ) { 8889 std::string s = value; 8890 if( getCurrentContext().getConfig()->showInvisibles() ) { 8891 for(size_t i = 0; i < s.size(); ++i ) { 8892 std::string subs; 8893 switch( s[i] ) { 8894 case '\n': subs = "\\n"; break; 8895 case '\t': subs = "\\t"; break; 8896 default: break; 8897 } 8898 if( !subs.empty() ) { 8899 s = s.substr( 0, i ) + subs + s.substr( i+1 ); 8900 ++i; 8901 } 8902 } 8903 } 8904 return '"' + s + '"'; 8905 } 8906 std::string toString( std::wstring const& value ) { 8907 8908 std::string s; 8909 s.reserve( value.size() ); 8910 for(size_t i = 0; i < value.size(); ++i ) 8911 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?'; 8912 return Catch::toString( s ); 8913 } 8914 8915 std::string toString( const char* const value ) { 8916 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" ); 8917 } 8918 8919 std::string toString( char* const value ) { 8920 return Catch::toString( static_cast<const char*>( value ) ); 8921 } 8922 8923 std::string toString( const wchar_t* const value ) 8924 { 8925 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" ); 8926 } 8927 8928 std::string toString( wchar_t* const value ) 8929 { 8930 return Catch::toString( static_cast<const wchar_t*>( value ) ); 8931 } 8932 8933 std::string toString( int value ) { 8934 std::ostringstream oss; 8935 oss << value; 8936 if( value > Detail::hexThreshold ) 8937 oss << " (0x" << std::hex << value << ')'; 8938 return oss.str(); 8939 } 8940 8941 std::string toString( unsigned long value ) { 8942 std::ostringstream oss; 8943 oss << value; 8944 if( value > Detail::hexThreshold ) 8945 oss << " (0x" << std::hex << value << ')'; 8946 return oss.str(); 8947 } 8948 8949 std::string toString( unsigned int value ) { 8950 return Catch::toString( static_cast<unsigned long>( value ) ); 8951 } 8952 8953 template<typename T> 8954 std::string fpToString( T value, int precision ) { 8955 std::ostringstream oss; 8956 oss << std::setprecision( precision ) 8957 << std::fixed 8958 << value; 8959 std::string d = oss.str(); 8960 std::size_t i = d.find_last_not_of( '0' ); 8961 if( i != std::string::npos && i != d.size()-1 ) { 8962 if( d[i] == '.' ) 8963 i++; 8964 d = d.substr( 0, i+1 ); 8965 } 8966 return d; 8967 } 8968 8969 std::string toString( const double value ) { 8970 return fpToString( value, 10 ); 8971 } 8972 std::string toString( const float value ) { 8973 return fpToString( value, 5 ) + 'f'; 8974 } 8975 8976 std::string toString( bool value ) { 8977 return value ? "true" : "false"; 8978 } 8979 8980 std::string toString( char value ) { 8981 if ( value == '\r' ) 8982 return "'\\r'"; 8983 if ( value == '\f' ) 8984 return "'\\f'"; 8985 if ( value == '\n' ) 8986 return "'\\n'"; 8987 if ( value == '\t' ) 8988 return "'\\t'"; 8989 if ( '\0' <= value && value < ' ' ) 8990 return toString( static_cast<unsigned int>( value ) ); 8991 char chstr[] = "' '"; 8992 chstr[1] = value; 8993 return chstr; 8994 } 8995 8996 std::string toString( signed char value ) { 8997 return toString( static_cast<char>( value ) ); 8998 } 8999 9000 std::string toString( unsigned char value ) { 9001 return toString( static_cast<char>( value ) ); 9002 } 9003 9004 #ifdef CATCH_CONFIG_CPP11_LONG_LONG 9005 std::string toString( long long value ) { 9006 std::ostringstream oss; 9007 oss << value; 9008 if( value > Detail::hexThreshold ) 9009 oss << " (0x" << std::hex << value << ')'; 9010 return oss.str(); 9011 } 9012 std::string toString( unsigned long long value ) { 9013 std::ostringstream oss; 9014 oss << value; 9015 if( value > Detail::hexThreshold ) 9016 oss << " (0x" << std::hex << value << ')'; 9017 return oss.str(); 9018 } 9019 #endif 9020 9021 #ifdef CATCH_CONFIG_CPP11_NULLPTR 9022 std::string toString( std::nullptr_t ) { 9023 return "nullptr"; 9024 } 9025 #endif 9026 9027 #ifdef __OBJC__ 9028 std::string toString( NSString const * const& nsstring ) { 9029 if( !nsstring ) 9030 return "nil"; 9031 return "@" + toString([nsstring UTF8String]); 9032 } 9033 std::string toString( NSString * CATCH_ARC_STRONG & nsstring ) { 9034 if( !nsstring ) 9035 return "nil"; 9036 return "@" + toString([nsstring UTF8String]); 9037 } 9038 std::string toString( NSObject* const& nsObject ) { 9039 return toString( [nsObject description] ); 9040 } 9041 #endif 9042 9043 } // end namespace Catch 9044 9045 // #included from: catch_result_builder.hpp 9046 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED 9047 9048 namespace Catch { 9049 9050 ResultBuilder::ResultBuilder( char const* macroName, 9051 SourceLineInfo const& lineInfo, 9052 char const* capturedExpression, 9053 ResultDisposition::Flags resultDisposition, 9054 char const* secondArg ) 9055 : m_assertionInfo( macroName, lineInfo, capturedExpression, resultDisposition, secondArg ), 9056 m_shouldDebugBreak( false ), 9057 m_shouldThrow( false ), 9058 m_guardException( false ) 9059 { 9060 m_stream().oss.str(""); 9061 } 9062 9063 ResultBuilder::~ResultBuilder() { 9064 #if defined(CATCH_CONFIG_FAST_COMPILE) 9065 if ( m_guardException ) { 9066 m_stream().oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE"; 9067 captureResult( ResultWas::ThrewException ); 9068 getCurrentContext().getResultCapture()->exceptionEarlyReported(); 9069 } 9070 #endif 9071 } 9072 9073 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) { 9074 m_data.resultType = result; 9075 return *this; 9076 } 9077 ResultBuilder& ResultBuilder::setResultType( bool result ) { 9078 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed; 9079 return *this; 9080 } 9081 9082 void ResultBuilder::endExpression( DecomposedExpression const& expr ) { 9083 AssertionResult result = build( expr ); 9084 handleResult( result ); 9085 } 9086 9087 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) { 9088 m_assertionInfo.resultDisposition = resultDisposition; 9089 m_stream().oss << Catch::translateActiveException(); 9090 captureResult( ResultWas::ThrewException ); 9091 } 9092 9093 void ResultBuilder::captureResult( ResultWas::OfType resultType ) { 9094 setResultType( resultType ); 9095 captureExpression(); 9096 } 9097 9098 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) { 9099 if( expectedMessage.empty() ) 9100 captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() ); 9101 else 9102 captureExpectedException( Matchers::Equals( expectedMessage ) ); 9103 } 9104 9105 void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) { 9106 9107 assert( !isFalseTest( m_assertionInfo.resultDisposition ) ); 9108 AssertionResultData data = m_data; 9109 data.resultType = ResultWas::Ok; 9110 data.reconstructedExpression = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); 9111 9112 std::string actualMessage = Catch::translateActiveException(); 9113 if( !matcher.match( actualMessage ) ) { 9114 data.resultType = ResultWas::ExpressionFailed; 9115 data.reconstructedExpression = actualMessage; 9116 } 9117 AssertionResult result( m_assertionInfo, data ); 9118 handleResult( result ); 9119 } 9120 9121 void ResultBuilder::captureExpression() { 9122 AssertionResult result = build(); 9123 handleResult( result ); 9124 } 9125 9126 void ResultBuilder::handleResult( AssertionResult const& result ) 9127 { 9128 getResultCapture().assertionEnded( result ); 9129 9130 if( !result.isOk() ) { 9131 if( getCurrentContext().getConfig()->shouldDebugBreak() ) 9132 m_shouldDebugBreak = true; 9133 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) ) 9134 m_shouldThrow = true; 9135 } 9136 } 9137 9138 void ResultBuilder::react() { 9139 #if defined(CATCH_CONFIG_FAST_COMPILE) 9140 if (m_shouldDebugBreak) { 9141 /////////////////////////////////////////////////////////////////// 9142 // To inspect the state during test, you need to go one level up the callstack 9143 // To go back to the test and change execution, jump over the throw statement 9144 /////////////////////////////////////////////////////////////////// 9145 CATCH_BREAK_INTO_DEBUGGER(); 9146 } 9147 #endif 9148 if( m_shouldThrow ) 9149 throw Catch::TestFailureException(); 9150 } 9151 9152 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; } 9153 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); } 9154 9155 AssertionResult ResultBuilder::build() const 9156 { 9157 return build( *this ); 9158 } 9159 9160 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr, 9161 // a temporary DecomposedExpression, which in turn holds references to 9162 // operands, possibly temporary as well. 9163 // It should immediately be passed to handleResult; if the expression 9164 // needs to be reported, its string expansion must be composed before 9165 // the temporaries are destroyed. 9166 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const 9167 { 9168 assert( m_data.resultType != ResultWas::Unknown ); 9169 AssertionResultData data = m_data; 9170 9171 // Flip bool results if FalseTest flag is set 9172 if( isFalseTest( m_assertionInfo.resultDisposition ) ) { 9173 data.negate( expr.isBinaryExpression() ); 9174 } 9175 9176 data.message = m_stream().oss.str(); 9177 data.decomposedExpression = &expr; // for lazy reconstruction 9178 return AssertionResult( m_assertionInfo, data ); 9179 } 9180 9181 void ResultBuilder::reconstructExpression( std::string& dest ) const { 9182 dest = capturedExpressionWithSecondArgument(m_assertionInfo.capturedExpression, m_assertionInfo.secondArg); 9183 } 9184 9185 void ResultBuilder::setExceptionGuard() { 9186 m_guardException = true; 9187 } 9188 void ResultBuilder::unsetExceptionGuard() { 9189 m_guardException = false; 9190 } 9191 9192 } // end namespace Catch 9193 9194 // #included from: catch_tag_alias_registry.hpp 9195 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED 9196 9197 namespace Catch { 9198 9199 TagAliasRegistry::~TagAliasRegistry() {} 9200 9201 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const { 9202 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias ); 9203 if( it != m_registry.end() ) 9204 return it->second; 9205 else 9206 return Option<TagAlias>(); 9207 } 9208 9209 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const { 9210 std::string expandedTestSpec = unexpandedTestSpec; 9211 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end(); 9212 it != itEnd; 9213 ++it ) { 9214 std::size_t pos = expandedTestSpec.find( it->first ); 9215 if( pos != std::string::npos ) { 9216 expandedTestSpec = expandedTestSpec.substr( 0, pos ) + 9217 it->second.tag + 9218 expandedTestSpec.substr( pos + it->first.size() ); 9219 } 9220 } 9221 return expandedTestSpec; 9222 } 9223 9224 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) { 9225 9226 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) { 9227 std::ostringstream oss; 9228 oss << Colour( Colour::Red ) 9229 << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" 9230 << Colour( Colour::FileName ) 9231 << lineInfo << '\n'; 9232 throw std::domain_error( oss.str().c_str() ); 9233 } 9234 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) { 9235 std::ostringstream oss; 9236 oss << Colour( Colour::Red ) 9237 << "error: tag alias, \"" << alias << "\" already registered.\n" 9238 << "\tFirst seen at " 9239 << Colour( Colour::Red ) << find(alias)->lineInfo << '\n' 9240 << Colour( Colour::Red ) << "\tRedefined at " 9241 << Colour( Colour::FileName) << lineInfo << '\n'; 9242 throw std::domain_error( oss.str().c_str() ); 9243 } 9244 } 9245 9246 ITagAliasRegistry::~ITagAliasRegistry() {} 9247 9248 ITagAliasRegistry const& ITagAliasRegistry::get() { 9249 return getRegistryHub().getTagAliasRegistry(); 9250 } 9251 9252 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) { 9253 getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo ); 9254 } 9255 9256 } // end namespace Catch 9257 9258 // #included from: catch_matchers_string.hpp 9259 9260 namespace Catch { 9261 namespace Matchers { 9262 9263 namespace StdString { 9264 9265 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity ) 9266 : m_caseSensitivity( caseSensitivity ), 9267 m_str( adjustString( str ) ) 9268 {} 9269 std::string CasedString::adjustString( std::string const& str ) const { 9270 return m_caseSensitivity == CaseSensitive::No 9271 ? toLower( str ) 9272 : str; 9273 } 9274 std::string CasedString::caseSensitivitySuffix() const { 9275 return m_caseSensitivity == CaseSensitive::No 9276 ? " (case insensitive)" 9277 : std::string(); 9278 } 9279 9280 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator ) 9281 : m_comparator( comparator ), 9282 m_operation( operation ) { 9283 } 9284 9285 std::string StringMatcherBase::describe() const { 9286 std::string description; 9287 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() + 9288 m_comparator.caseSensitivitySuffix().size()); 9289 description += m_operation; 9290 description += ": \""; 9291 description += m_comparator.m_str; 9292 description += "\""; 9293 description += m_comparator.caseSensitivitySuffix(); 9294 return description; 9295 } 9296 9297 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {} 9298 9299 bool EqualsMatcher::match( std::string const& source ) const { 9300 return m_comparator.adjustString( source ) == m_comparator.m_str; 9301 } 9302 9303 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {} 9304 9305 bool ContainsMatcher::match( std::string const& source ) const { 9306 return contains( m_comparator.adjustString( source ), m_comparator.m_str ); 9307 } 9308 9309 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {} 9310 9311 bool StartsWithMatcher::match( std::string const& source ) const { 9312 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 9313 } 9314 9315 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {} 9316 9317 bool EndsWithMatcher::match( std::string const& source ) const { 9318 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str ); 9319 } 9320 9321 } // namespace StdString 9322 9323 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9324 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) ); 9325 } 9326 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9327 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) ); 9328 } 9329 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9330 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 9331 } 9332 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) { 9333 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) ); 9334 } 9335 9336 } // namespace Matchers 9337 } // namespace Catch 9338 // #included from: ../reporters/catch_reporter_multi.hpp 9339 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED 9340 9341 namespace Catch { 9342 9343 class MultipleReporters : public SharedImpl<IStreamingReporter> { 9344 typedef std::vector<Ptr<IStreamingReporter> > Reporters; 9345 Reporters m_reporters; 9346 9347 public: 9348 void add( Ptr<IStreamingReporter> const& reporter ) { 9349 m_reporters.push_back( reporter ); 9350 } 9351 9352 public: // IStreamingReporter 9353 9354 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { 9355 return m_reporters[0]->getPreferences(); 9356 } 9357 9358 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { 9359 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9360 it != itEnd; 9361 ++it ) 9362 (*it)->noMatchingTestCases( spec ); 9363 } 9364 9365 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE { 9366 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9367 it != itEnd; 9368 ++it ) 9369 (*it)->testRunStarting( testRunInfo ); 9370 } 9371 9372 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { 9373 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9374 it != itEnd; 9375 ++it ) 9376 (*it)->testGroupStarting( groupInfo ); 9377 } 9378 9379 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { 9380 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9381 it != itEnd; 9382 ++it ) 9383 (*it)->testCaseStarting( testInfo ); 9384 } 9385 9386 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { 9387 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9388 it != itEnd; 9389 ++it ) 9390 (*it)->sectionStarting( sectionInfo ); 9391 } 9392 9393 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE { 9394 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9395 it != itEnd; 9396 ++it ) 9397 (*it)->assertionStarting( assertionInfo ); 9398 } 9399 9400 // The return value indicates if the messages buffer should be cleared: 9401 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { 9402 bool clearBuffer = false; 9403 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9404 it != itEnd; 9405 ++it ) 9406 clearBuffer |= (*it)->assertionEnded( assertionStats ); 9407 return clearBuffer; 9408 } 9409 9410 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { 9411 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9412 it != itEnd; 9413 ++it ) 9414 (*it)->sectionEnded( sectionStats ); 9415 } 9416 9417 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { 9418 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9419 it != itEnd; 9420 ++it ) 9421 (*it)->testCaseEnded( testCaseStats ); 9422 } 9423 9424 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { 9425 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9426 it != itEnd; 9427 ++it ) 9428 (*it)->testGroupEnded( testGroupStats ); 9429 } 9430 9431 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { 9432 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9433 it != itEnd; 9434 ++it ) 9435 (*it)->testRunEnded( testRunStats ); 9436 } 9437 9438 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { 9439 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end(); 9440 it != itEnd; 9441 ++it ) 9442 (*it)->skipTest( testInfo ); 9443 } 9444 9445 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE { 9446 return this; 9447 } 9448 9449 }; 9450 9451 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) { 9452 Ptr<IStreamingReporter> resultingReporter; 9453 9454 if( existingReporter ) { 9455 MultipleReporters* multi = existingReporter->tryAsMulti(); 9456 if( !multi ) { 9457 multi = new MultipleReporters; 9458 resultingReporter = Ptr<IStreamingReporter>( multi ); 9459 if( existingReporter ) 9460 multi->add( existingReporter ); 9461 } 9462 else 9463 resultingReporter = existingReporter; 9464 multi->add( additionalReporter ); 9465 } 9466 else 9467 resultingReporter = additionalReporter; 9468 9469 return resultingReporter; 9470 } 9471 9472 } // end namespace Catch 9473 9474 // #included from: ../reporters/catch_reporter_xml.hpp 9475 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED 9476 9477 // #included from: catch_reporter_bases.hpp 9478 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED 9479 9480 #include <cstring> 9481 #include <cfloat> 9482 #include <cstdio> 9483 #include <assert.h> 9484 9485 namespace Catch { 9486 9487 namespace { 9488 // Because formatting using c++ streams is stateful, drop down to C is required 9489 // Alternatively we could use stringstream, but its performance is... not good. 9490 std::string getFormattedDuration( double duration ) { 9491 // Max exponent + 1 is required to represent the whole part 9492 // + 1 for decimal point 9493 // + 3 for the 3 decimal places 9494 // + 1 for null terminator 9495 const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1; 9496 char buffer[maxDoubleSize]; 9497 9498 // Save previous errno, to prevent sprintf from overwriting it 9499 ErrnoGuard guard; 9500 #ifdef _MSC_VER 9501 sprintf_s(buffer, "%.3f", duration); 9502 #else 9503 sprintf(buffer, "%.3f", duration); 9504 #endif 9505 return std::string(buffer); 9506 } 9507 } 9508 9509 struct StreamingReporterBase : SharedImpl<IStreamingReporter> { 9510 9511 StreamingReporterBase( ReporterConfig const& _config ) 9512 : m_config( _config.fullConfig() ), 9513 stream( _config.stream() ) 9514 { 9515 m_reporterPrefs.shouldRedirectStdOut = false; 9516 } 9517 9518 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { 9519 return m_reporterPrefs; 9520 } 9521 9522 virtual ~StreamingReporterBase() CATCH_OVERRIDE; 9523 9524 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {} 9525 9526 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE { 9527 currentTestRunInfo = _testRunInfo; 9528 } 9529 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE { 9530 currentGroupInfo = _groupInfo; 9531 } 9532 9533 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE { 9534 currentTestCaseInfo = _testInfo; 9535 } 9536 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { 9537 m_sectionStack.push_back( _sectionInfo ); 9538 } 9539 9540 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE { 9541 m_sectionStack.pop_back(); 9542 } 9543 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE { 9544 currentTestCaseInfo.reset(); 9545 } 9546 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE { 9547 currentGroupInfo.reset(); 9548 } 9549 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE { 9550 currentTestCaseInfo.reset(); 9551 currentGroupInfo.reset(); 9552 currentTestRunInfo.reset(); 9553 } 9554 9555 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE { 9556 // Don't do anything with this by default. 9557 // It can optionally be overridden in the derived class. 9558 } 9559 9560 Ptr<IConfig const> m_config; 9561 std::ostream& stream; 9562 9563 LazyStat<TestRunInfo> currentTestRunInfo; 9564 LazyStat<GroupInfo> currentGroupInfo; 9565 LazyStat<TestCaseInfo> currentTestCaseInfo; 9566 9567 std::vector<SectionInfo> m_sectionStack; 9568 ReporterPreferences m_reporterPrefs; 9569 }; 9570 9571 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> { 9572 template<typename T, typename ChildNodeT> 9573 struct Node : SharedImpl<> { 9574 explicit Node( T const& _value ) : value( _value ) {} 9575 virtual ~Node() {} 9576 9577 typedef std::vector<Ptr<ChildNodeT> > ChildNodes; 9578 T value; 9579 ChildNodes children; 9580 }; 9581 struct SectionNode : SharedImpl<> { 9582 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {} 9583 virtual ~SectionNode(); 9584 9585 bool operator == ( SectionNode const& other ) const { 9586 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo; 9587 } 9588 bool operator == ( Ptr<SectionNode> const& other ) const { 9589 return operator==( *other ); 9590 } 9591 9592 SectionStats stats; 9593 typedef std::vector<Ptr<SectionNode> > ChildSections; 9594 typedef std::vector<AssertionStats> Assertions; 9595 ChildSections childSections; 9596 Assertions assertions; 9597 std::string stdOut; 9598 std::string stdErr; 9599 }; 9600 9601 struct BySectionInfo { 9602 BySectionInfo( SectionInfo const& other ) : m_other( other ) {} 9603 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {} 9604 bool operator() ( Ptr<SectionNode> const& node ) const { 9605 return node->stats.sectionInfo.lineInfo == m_other.lineInfo; 9606 } 9607 private: 9608 void operator=( BySectionInfo const& ); 9609 SectionInfo const& m_other; 9610 }; 9611 9612 typedef Node<TestCaseStats, SectionNode> TestCaseNode; 9613 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode; 9614 typedef Node<TestRunStats, TestGroupNode> TestRunNode; 9615 9616 CumulativeReporterBase( ReporterConfig const& _config ) 9617 : m_config( _config.fullConfig() ), 9618 stream( _config.stream() ) 9619 { 9620 m_reporterPrefs.shouldRedirectStdOut = false; 9621 } 9622 ~CumulativeReporterBase(); 9623 9624 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE { 9625 return m_reporterPrefs; 9626 } 9627 9628 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {} 9629 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {} 9630 9631 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {} 9632 9633 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { 9634 SectionStats incompleteStats( sectionInfo, Counts(), 0, false ); 9635 Ptr<SectionNode> node; 9636 if( m_sectionStack.empty() ) { 9637 if( !m_rootSection ) 9638 m_rootSection = new SectionNode( incompleteStats ); 9639 node = m_rootSection; 9640 } 9641 else { 9642 SectionNode& parentNode = *m_sectionStack.back(); 9643 SectionNode::ChildSections::const_iterator it = 9644 std::find_if( parentNode.childSections.begin(), 9645 parentNode.childSections.end(), 9646 BySectionInfo( sectionInfo ) ); 9647 if( it == parentNode.childSections.end() ) { 9648 node = new SectionNode( incompleteStats ); 9649 parentNode.childSections.push_back( node ); 9650 } 9651 else 9652 node = *it; 9653 } 9654 m_sectionStack.push_back( node ); 9655 m_deepestSection = node; 9656 } 9657 9658 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} 9659 9660 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { 9661 assert( !m_sectionStack.empty() ); 9662 SectionNode& sectionNode = *m_sectionStack.back(); 9663 sectionNode.assertions.push_back( assertionStats ); 9664 // AssertionResult holds a pointer to a temporary DecomposedExpression, 9665 // which getExpandedExpression() calls to build the expression string. 9666 // Our section stack copy of the assertionResult will likely outlive the 9667 // temporary, so it must be expanded or discarded now to avoid calling 9668 // a destroyed object later. 9669 prepareExpandedExpression( sectionNode.assertions.back().assertionResult ); 9670 return true; 9671 } 9672 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { 9673 assert( !m_sectionStack.empty() ); 9674 SectionNode& node = *m_sectionStack.back(); 9675 node.stats = sectionStats; 9676 m_sectionStack.pop_back(); 9677 } 9678 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { 9679 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats ); 9680 assert( m_sectionStack.size() == 0 ); 9681 node->children.push_back( m_rootSection ); 9682 m_testCases.push_back( node ); 9683 m_rootSection.reset(); 9684 9685 assert( m_deepestSection ); 9686 m_deepestSection->stdOut = testCaseStats.stdOut; 9687 m_deepestSection->stdErr = testCaseStats.stdErr; 9688 } 9689 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { 9690 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats ); 9691 node->children.swap( m_testCases ); 9692 m_testGroups.push_back( node ); 9693 } 9694 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { 9695 Ptr<TestRunNode> node = new TestRunNode( testRunStats ); 9696 node->children.swap( m_testGroups ); 9697 m_testRuns.push_back( node ); 9698 testRunEndedCumulative(); 9699 } 9700 virtual void testRunEndedCumulative() = 0; 9701 9702 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {} 9703 9704 virtual void prepareExpandedExpression( AssertionResult& result ) const { 9705 if( result.isOk() ) 9706 result.discardDecomposedExpression(); 9707 else 9708 result.expandDecomposedExpression(); 9709 } 9710 9711 Ptr<IConfig const> m_config; 9712 std::ostream& stream; 9713 std::vector<AssertionStats> m_assertions; 9714 std::vector<std::vector<Ptr<SectionNode> > > m_sections; 9715 std::vector<Ptr<TestCaseNode> > m_testCases; 9716 std::vector<Ptr<TestGroupNode> > m_testGroups; 9717 9718 std::vector<Ptr<TestRunNode> > m_testRuns; 9719 9720 Ptr<SectionNode> m_rootSection; 9721 Ptr<SectionNode> m_deepestSection; 9722 std::vector<Ptr<SectionNode> > m_sectionStack; 9723 ReporterPreferences m_reporterPrefs; 9724 9725 }; 9726 9727 template<char C> 9728 char const* getLineOfChars() { 9729 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0}; 9730 if( !*line ) { 9731 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 ); 9732 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0; 9733 } 9734 return line; 9735 } 9736 9737 struct TestEventListenerBase : StreamingReporterBase { 9738 TestEventListenerBase( ReporterConfig const& _config ) 9739 : StreamingReporterBase( _config ) 9740 {} 9741 9742 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {} 9743 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE { 9744 return false; 9745 } 9746 }; 9747 9748 } // end namespace Catch 9749 9750 // #included from: ../internal/catch_reporter_registrars.hpp 9751 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED 9752 9753 namespace Catch { 9754 9755 template<typename T> 9756 class LegacyReporterRegistrar { 9757 9758 class ReporterFactory : public IReporterFactory { 9759 virtual IStreamingReporter* create( ReporterConfig const& config ) const { 9760 return new LegacyReporterAdapter( new T( config ) ); 9761 } 9762 9763 virtual std::string getDescription() const { 9764 return T::getDescription(); 9765 } 9766 }; 9767 9768 public: 9769 9770 LegacyReporterRegistrar( std::string const& name ) { 9771 getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); 9772 } 9773 }; 9774 9775 template<typename T> 9776 class ReporterRegistrar { 9777 9778 class ReporterFactory : public SharedImpl<IReporterFactory> { 9779 9780 // *** Please Note ***: 9781 // - If you end up here looking at a compiler error because it's trying to register 9782 // your custom reporter class be aware that the native reporter interface has changed 9783 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via 9784 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter. 9785 // However please consider updating to the new interface as the old one is now 9786 // deprecated and will probably be removed quite soon! 9787 // Please contact me via github if you have any questions at all about this. 9788 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have 9789 // no idea who is actually using custom reporters at all (possibly no-one!). 9790 // The new interface is designed to minimise exposure to interface changes in the future. 9791 virtual IStreamingReporter* create( ReporterConfig const& config ) const { 9792 return new T( config ); 9793 } 9794 9795 virtual std::string getDescription() const { 9796 return T::getDescription(); 9797 } 9798 }; 9799 9800 public: 9801 9802 ReporterRegistrar( std::string const& name ) { 9803 getMutableRegistryHub().registerReporter( name, new ReporterFactory() ); 9804 } 9805 }; 9806 9807 template<typename T> 9808 class ListenerRegistrar { 9809 9810 class ListenerFactory : public SharedImpl<IReporterFactory> { 9811 9812 virtual IStreamingReporter* create( ReporterConfig const& config ) const { 9813 return new T( config ); 9814 } 9815 virtual std::string getDescription() const { 9816 return std::string(); 9817 } 9818 }; 9819 9820 public: 9821 9822 ListenerRegistrar() { 9823 getMutableRegistryHub().registerListener( new ListenerFactory() ); 9824 } 9825 }; 9826 } 9827 9828 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \ 9829 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } 9830 9831 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \ 9832 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } 9833 9834 // Deprecated - use the form without INTERNAL_ 9835 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \ 9836 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } 9837 9838 #define CATCH_REGISTER_LISTENER( listenerType ) \ 9839 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } 9840 9841 // #included from: ../internal/catch_xmlwriter.hpp 9842 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED 9843 9844 #include <sstream> 9845 #include <string> 9846 #include <vector> 9847 #include <iomanip> 9848 9849 namespace Catch { 9850 9851 class XmlEncode { 9852 public: 9853 enum ForWhat { ForTextNodes, ForAttributes }; 9854 9855 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes ) 9856 : m_str( str ), 9857 m_forWhat( forWhat ) 9858 {} 9859 9860 void encodeTo( std::ostream& os ) const { 9861 9862 // Apostrophe escaping not necessary if we always use " to write attributes 9863 // (see: http://www.w3.org/TR/xml/#syntax) 9864 9865 for( std::size_t i = 0; i < m_str.size(); ++ i ) { 9866 char c = m_str[i]; 9867 switch( c ) { 9868 case '<': os << "<"; break; 9869 case '&': os << "&"; break; 9870 9871 case '>': 9872 // See: http://www.w3.org/TR/xml/#syntax 9873 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' ) 9874 os << ">"; 9875 else 9876 os << c; 9877 break; 9878 9879 case '\"': 9880 if( m_forWhat == ForAttributes ) 9881 os << """; 9882 else 9883 os << c; 9884 break; 9885 9886 default: 9887 // Escape control chars - based on contribution by @espenalb in PR #465 and 9888 // by @mrpi PR #588 9889 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) { 9890 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0 9891 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) 9892 << static_cast<int>( c ); 9893 } 9894 else 9895 os << c; 9896 } 9897 } 9898 } 9899 9900 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) { 9901 xmlEncode.encodeTo( os ); 9902 return os; 9903 } 9904 9905 private: 9906 std::string m_str; 9907 ForWhat m_forWhat; 9908 }; 9909 9910 class XmlWriter { 9911 public: 9912 9913 class ScopedElement { 9914 public: 9915 ScopedElement( XmlWriter* writer ) 9916 : m_writer( writer ) 9917 {} 9918 9919 ScopedElement( ScopedElement const& other ) 9920 : m_writer( other.m_writer ){ 9921 other.m_writer = CATCH_NULL; 9922 } 9923 9924 ~ScopedElement() { 9925 if( m_writer ) 9926 m_writer->endElement(); 9927 } 9928 9929 ScopedElement& writeText( std::string const& text, bool indent = true ) { 9930 m_writer->writeText( text, indent ); 9931 return *this; 9932 } 9933 9934 template<typename T> 9935 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) { 9936 m_writer->writeAttribute( name, attribute ); 9937 return *this; 9938 } 9939 9940 private: 9941 mutable XmlWriter* m_writer; 9942 }; 9943 9944 XmlWriter() 9945 : m_tagIsOpen( false ), 9946 m_needsNewline( false ), 9947 m_os( Catch::cout() ) 9948 { 9949 writeDeclaration(); 9950 } 9951 9952 XmlWriter( std::ostream& os ) 9953 : m_tagIsOpen( false ), 9954 m_needsNewline( false ), 9955 m_os( os ) 9956 { 9957 writeDeclaration(); 9958 } 9959 9960 ~XmlWriter() { 9961 while( !m_tags.empty() ) 9962 endElement(); 9963 } 9964 9965 XmlWriter& startElement( std::string const& name ) { 9966 ensureTagClosed(); 9967 newlineIfNecessary(); 9968 m_os << m_indent << '<' << name; 9969 m_tags.push_back( name ); 9970 m_indent += " "; 9971 m_tagIsOpen = true; 9972 return *this; 9973 } 9974 9975 ScopedElement scopedElement( std::string const& name ) { 9976 ScopedElement scoped( this ); 9977 startElement( name ); 9978 return scoped; 9979 } 9980 9981 XmlWriter& endElement() { 9982 newlineIfNecessary(); 9983 m_indent = m_indent.substr( 0, m_indent.size()-2 ); 9984 if( m_tagIsOpen ) { 9985 m_os << "/>"; 9986 m_tagIsOpen = false; 9987 } 9988 else { 9989 m_os << m_indent << "</" << m_tags.back() << ">"; 9990 } 9991 m_os << std::endl; 9992 m_tags.pop_back(); 9993 return *this; 9994 } 9995 9996 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) { 9997 if( !name.empty() && !attribute.empty() ) 9998 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"'; 9999 return *this; 10000 } 10001 10002 XmlWriter& writeAttribute( std::string const& name, bool attribute ) { 10003 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"'; 10004 return *this; 10005 } 10006 10007 template<typename T> 10008 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) { 10009 std::ostringstream oss; 10010 oss << attribute; 10011 return writeAttribute( name, oss.str() ); 10012 } 10013 10014 XmlWriter& writeText( std::string const& text, bool indent = true ) { 10015 if( !text.empty() ){ 10016 bool tagWasOpen = m_tagIsOpen; 10017 ensureTagClosed(); 10018 if( tagWasOpen && indent ) 10019 m_os << m_indent; 10020 m_os << XmlEncode( text ); 10021 m_needsNewline = true; 10022 } 10023 return *this; 10024 } 10025 10026 XmlWriter& writeComment( std::string const& text ) { 10027 ensureTagClosed(); 10028 m_os << m_indent << "<!--" << text << "-->"; 10029 m_needsNewline = true; 10030 return *this; 10031 } 10032 10033 void writeStylesheetRef( std::string const& url ) { 10034 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n"; 10035 } 10036 10037 XmlWriter& writeBlankLine() { 10038 ensureTagClosed(); 10039 m_os << '\n'; 10040 return *this; 10041 } 10042 10043 void ensureTagClosed() { 10044 if( m_tagIsOpen ) { 10045 m_os << ">" << std::endl; 10046 m_tagIsOpen = false; 10047 } 10048 } 10049 10050 private: 10051 XmlWriter( XmlWriter const& ); 10052 void operator=( XmlWriter const& ); 10053 10054 void writeDeclaration() { 10055 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; 10056 } 10057 10058 void newlineIfNecessary() { 10059 if( m_needsNewline ) { 10060 m_os << std::endl; 10061 m_needsNewline = false; 10062 } 10063 } 10064 10065 bool m_tagIsOpen; 10066 bool m_needsNewline; 10067 std::vector<std::string> m_tags; 10068 std::string m_indent; 10069 std::ostream& m_os; 10070 }; 10071 10072 } 10073 10074 namespace Catch { 10075 class XmlReporter : public StreamingReporterBase { 10076 public: 10077 XmlReporter( ReporterConfig const& _config ) 10078 : StreamingReporterBase( _config ), 10079 m_xml(_config.stream()), 10080 m_sectionDepth( 0 ) 10081 { 10082 m_reporterPrefs.shouldRedirectStdOut = true; 10083 } 10084 10085 virtual ~XmlReporter() CATCH_OVERRIDE; 10086 10087 static std::string getDescription() { 10088 return "Reports test results as an XML document"; 10089 } 10090 10091 virtual std::string getStylesheetRef() const { 10092 return std::string(); 10093 } 10094 10095 void writeSourceInfo( SourceLineInfo const& sourceInfo ) { 10096 m_xml 10097 .writeAttribute( "filename", sourceInfo.file ) 10098 .writeAttribute( "line", sourceInfo.line ); 10099 } 10100 10101 public: // StreamingReporterBase 10102 10103 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE { 10104 StreamingReporterBase::noMatchingTestCases( s ); 10105 } 10106 10107 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE { 10108 StreamingReporterBase::testRunStarting( testInfo ); 10109 std::string stylesheetRef = getStylesheetRef(); 10110 if( !stylesheetRef.empty() ) 10111 m_xml.writeStylesheetRef( stylesheetRef ); 10112 m_xml.startElement( "Catch" ); 10113 if( !m_config->name().empty() ) 10114 m_xml.writeAttribute( "name", m_config->name() ); 10115 } 10116 10117 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { 10118 StreamingReporterBase::testGroupStarting( groupInfo ); 10119 m_xml.startElement( "Group" ) 10120 .writeAttribute( "name", groupInfo.name ); 10121 } 10122 10123 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE { 10124 StreamingReporterBase::testCaseStarting(testInfo); 10125 m_xml.startElement( "TestCase" ) 10126 .writeAttribute( "name", trim( testInfo.name ) ) 10127 .writeAttribute( "description", testInfo.description ) 10128 .writeAttribute( "tags", testInfo.tagsAsString ); 10129 10130 writeSourceInfo( testInfo.lineInfo ); 10131 10132 if ( m_config->showDurations() == ShowDurations::Always ) 10133 m_testCaseTimer.start(); 10134 m_xml.ensureTagClosed(); 10135 } 10136 10137 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE { 10138 StreamingReporterBase::sectionStarting( sectionInfo ); 10139 if( m_sectionDepth++ > 0 ) { 10140 m_xml.startElement( "Section" ) 10141 .writeAttribute( "name", trim( sectionInfo.name ) ) 10142 .writeAttribute( "description", sectionInfo.description ); 10143 writeSourceInfo( sectionInfo.lineInfo ); 10144 m_xml.ensureTagClosed(); 10145 } 10146 } 10147 10148 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { } 10149 10150 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { 10151 10152 AssertionResult const& result = assertionStats.assertionResult; 10153 10154 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 10155 10156 if( includeResults ) { 10157 // Print any info messages in <Info> tags. 10158 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end(); 10159 it != itEnd; 10160 ++it ) { 10161 if( it->type == ResultWas::Info ) { 10162 m_xml.scopedElement( "Info" ) 10163 .writeText( it->message ); 10164 } else if ( it->type == ResultWas::Warning ) { 10165 m_xml.scopedElement( "Warning" ) 10166 .writeText( it->message ); 10167 } 10168 } 10169 } 10170 10171 // Drop out if result was successful but we're not printing them. 10172 if( !includeResults && result.getResultType() != ResultWas::Warning ) 10173 return true; 10174 10175 // Print the expression if there is one. 10176 if( result.hasExpression() ) { 10177 m_xml.startElement( "Expression" ) 10178 .writeAttribute( "success", result.succeeded() ) 10179 .writeAttribute( "type", result.getTestMacroName() ); 10180 10181 writeSourceInfo( result.getSourceInfo() ); 10182 10183 m_xml.scopedElement( "Original" ) 10184 .writeText( result.getExpression() ); 10185 m_xml.scopedElement( "Expanded" ) 10186 .writeText( result.getExpandedExpression() ); 10187 } 10188 10189 // And... Print a result applicable to each result type. 10190 switch( result.getResultType() ) { 10191 case ResultWas::ThrewException: 10192 m_xml.startElement( "Exception" ); 10193 writeSourceInfo( result.getSourceInfo() ); 10194 m_xml.writeText( result.getMessage() ); 10195 m_xml.endElement(); 10196 break; 10197 case ResultWas::FatalErrorCondition: 10198 m_xml.startElement( "FatalErrorCondition" ); 10199 writeSourceInfo( result.getSourceInfo() ); 10200 m_xml.writeText( result.getMessage() ); 10201 m_xml.endElement(); 10202 break; 10203 case ResultWas::Info: 10204 m_xml.scopedElement( "Info" ) 10205 .writeText( result.getMessage() ); 10206 break; 10207 case ResultWas::Warning: 10208 // Warning will already have been written 10209 break; 10210 case ResultWas::ExplicitFailure: 10211 m_xml.startElement( "Failure" ); 10212 writeSourceInfo( result.getSourceInfo() ); 10213 m_xml.writeText( result.getMessage() ); 10214 m_xml.endElement(); 10215 break; 10216 default: 10217 break; 10218 } 10219 10220 if( result.hasExpression() ) 10221 m_xml.endElement(); 10222 10223 return true; 10224 } 10225 10226 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE { 10227 StreamingReporterBase::sectionEnded( sectionStats ); 10228 if( --m_sectionDepth > 0 ) { 10229 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" ); 10230 e.writeAttribute( "successes", sectionStats.assertions.passed ); 10231 e.writeAttribute( "failures", sectionStats.assertions.failed ); 10232 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk ); 10233 10234 if ( m_config->showDurations() == ShowDurations::Always ) 10235 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds ); 10236 10237 m_xml.endElement(); 10238 } 10239 } 10240 10241 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { 10242 StreamingReporterBase::testCaseEnded( testCaseStats ); 10243 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" ); 10244 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() ); 10245 10246 if ( m_config->showDurations() == ShowDurations::Always ) 10247 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() ); 10248 10249 if( !testCaseStats.stdOut.empty() ) 10250 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false ); 10251 if( !testCaseStats.stdErr.empty() ) 10252 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false ); 10253 10254 m_xml.endElement(); 10255 } 10256 10257 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { 10258 StreamingReporterBase::testGroupEnded( testGroupStats ); 10259 // TODO: Check testGroupStats.aborting and act accordingly. 10260 m_xml.scopedElement( "OverallResults" ) 10261 .writeAttribute( "successes", testGroupStats.totals.assertions.passed ) 10262 .writeAttribute( "failures", testGroupStats.totals.assertions.failed ) 10263 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk ); 10264 m_xml.endElement(); 10265 } 10266 10267 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE { 10268 StreamingReporterBase::testRunEnded( testRunStats ); 10269 m_xml.scopedElement( "OverallResults" ) 10270 .writeAttribute( "successes", testRunStats.totals.assertions.passed ) 10271 .writeAttribute( "failures", testRunStats.totals.assertions.failed ) 10272 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk ); 10273 m_xml.endElement(); 10274 } 10275 10276 private: 10277 Timer m_testCaseTimer; 10278 XmlWriter m_xml; 10279 int m_sectionDepth; 10280 }; 10281 10282 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter ) 10283 10284 } // end namespace Catch 10285 10286 // #included from: ../reporters/catch_reporter_junit.hpp 10287 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED 10288 10289 #include <assert.h> 10290 10291 namespace Catch { 10292 10293 namespace { 10294 std::string getCurrentTimestamp() { 10295 // Beware, this is not reentrant because of backward compatibility issues 10296 // Also, UTC only, again because of backward compatibility (%z is C++11) 10297 time_t rawtime; 10298 std::time(&rawtime); 10299 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z"); 10300 10301 #ifdef _MSC_VER 10302 std::tm timeInfo = {}; 10303 gmtime_s(&timeInfo, &rawtime); 10304 #else 10305 std::tm* timeInfo; 10306 timeInfo = std::gmtime(&rawtime); 10307 #endif 10308 10309 char timeStamp[timeStampSize]; 10310 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ"; 10311 10312 #ifdef _MSC_VER 10313 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo); 10314 #else 10315 std::strftime(timeStamp, timeStampSize, fmt, timeInfo); 10316 #endif 10317 return std::string(timeStamp); 10318 } 10319 10320 } 10321 10322 class JunitReporter : public CumulativeReporterBase { 10323 public: 10324 JunitReporter( ReporterConfig const& _config ) 10325 : CumulativeReporterBase( _config ), 10326 xml( _config.stream() ), 10327 m_okToFail( false ) 10328 { 10329 m_reporterPrefs.shouldRedirectStdOut = true; 10330 } 10331 10332 virtual ~JunitReporter() CATCH_OVERRIDE; 10333 10334 static std::string getDescription() { 10335 return "Reports test results in an XML format that looks like Ant's junitreport target"; 10336 } 10337 10338 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {} 10339 10340 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE { 10341 CumulativeReporterBase::testRunStarting( runInfo ); 10342 xml.startElement( "testsuites" ); 10343 } 10344 10345 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE { 10346 suiteTimer.start(); 10347 stdOutForSuite.str(""); 10348 stdErrForSuite.str(""); 10349 unexpectedExceptions = 0; 10350 CumulativeReporterBase::testGroupStarting( groupInfo ); 10351 } 10352 10353 virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE { 10354 m_okToFail = testCaseInfo.okToFail(); 10355 } 10356 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE { 10357 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail ) 10358 unexpectedExceptions++; 10359 return CumulativeReporterBase::assertionEnded( assertionStats ); 10360 } 10361 10362 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE { 10363 stdOutForSuite << testCaseStats.stdOut; 10364 stdErrForSuite << testCaseStats.stdErr; 10365 CumulativeReporterBase::testCaseEnded( testCaseStats ); 10366 } 10367 10368 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE { 10369 double suiteTime = suiteTimer.getElapsedSeconds(); 10370 CumulativeReporterBase::testGroupEnded( testGroupStats ); 10371 writeGroup( *m_testGroups.back(), suiteTime ); 10372 } 10373 10374 virtual void testRunEndedCumulative() CATCH_OVERRIDE { 10375 xml.endElement(); 10376 } 10377 10378 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) { 10379 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" ); 10380 TestGroupStats const& stats = groupNode.value; 10381 xml.writeAttribute( "name", stats.groupInfo.name ); 10382 xml.writeAttribute( "errors", unexpectedExceptions ); 10383 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions ); 10384 xml.writeAttribute( "tests", stats.totals.assertions.total() ); 10385 xml.writeAttribute( "hostname", "tbd" ); // !TBD 10386 if( m_config->showDurations() == ShowDurations::Never ) 10387 xml.writeAttribute( "time", "" ); 10388 else 10389 xml.writeAttribute( "time", suiteTime ); 10390 xml.writeAttribute( "timestamp", getCurrentTimestamp() ); 10391 10392 // Write test cases 10393 for( TestGroupNode::ChildNodes::const_iterator 10394 it = groupNode.children.begin(), itEnd = groupNode.children.end(); 10395 it != itEnd; 10396 ++it ) 10397 writeTestCase( **it ); 10398 10399 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false ); 10400 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false ); 10401 } 10402 10403 void writeTestCase( TestCaseNode const& testCaseNode ) { 10404 TestCaseStats const& stats = testCaseNode.value; 10405 10406 // All test cases have exactly one section - which represents the 10407 // test case itself. That section may have 0-n nested sections 10408 assert( testCaseNode.children.size() == 1 ); 10409 SectionNode const& rootSection = *testCaseNode.children.front(); 10410 10411 std::string className = stats.testInfo.className; 10412 10413 if( className.empty() ) { 10414 if( rootSection.childSections.empty() ) 10415 className = "global"; 10416 } 10417 writeSection( className, "", rootSection ); 10418 } 10419 10420 void writeSection( std::string const& className, 10421 std::string const& rootName, 10422 SectionNode const& sectionNode ) { 10423 std::string name = trim( sectionNode.stats.sectionInfo.name ); 10424 if( !rootName.empty() ) 10425 name = rootName + '/' + name; 10426 10427 if( !sectionNode.assertions.empty() || 10428 !sectionNode.stdOut.empty() || 10429 !sectionNode.stdErr.empty() ) { 10430 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" ); 10431 if( className.empty() ) { 10432 xml.writeAttribute( "classname", name ); 10433 xml.writeAttribute( "name", "root" ); 10434 } 10435 else { 10436 xml.writeAttribute( "classname", className ); 10437 xml.writeAttribute( "name", name ); 10438 } 10439 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) ); 10440 10441 writeAssertions( sectionNode ); 10442 10443 if( !sectionNode.stdOut.empty() ) 10444 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false ); 10445 if( !sectionNode.stdErr.empty() ) 10446 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false ); 10447 } 10448 for( SectionNode::ChildSections::const_iterator 10449 it = sectionNode.childSections.begin(), 10450 itEnd = sectionNode.childSections.end(); 10451 it != itEnd; 10452 ++it ) 10453 if( className.empty() ) 10454 writeSection( name, "", **it ); 10455 else 10456 writeSection( className, name, **it ); 10457 } 10458 10459 void writeAssertions( SectionNode const& sectionNode ) { 10460 for( SectionNode::Assertions::const_iterator 10461 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end(); 10462 it != itEnd; 10463 ++it ) 10464 writeAssertion( *it ); 10465 } 10466 void writeAssertion( AssertionStats const& stats ) { 10467 AssertionResult const& result = stats.assertionResult; 10468 if( !result.isOk() ) { 10469 std::string elementName; 10470 switch( result.getResultType() ) { 10471 case ResultWas::ThrewException: 10472 case ResultWas::FatalErrorCondition: 10473 elementName = "error"; 10474 break; 10475 case ResultWas::ExplicitFailure: 10476 elementName = "failure"; 10477 break; 10478 case ResultWas::ExpressionFailed: 10479 elementName = "failure"; 10480 break; 10481 case ResultWas::DidntThrowException: 10482 elementName = "failure"; 10483 break; 10484 10485 // We should never see these here: 10486 case ResultWas::Info: 10487 case ResultWas::Warning: 10488 case ResultWas::Ok: 10489 case ResultWas::Unknown: 10490 case ResultWas::FailureBit: 10491 case ResultWas::Exception: 10492 elementName = "internalError"; 10493 break; 10494 } 10495 10496 XmlWriter::ScopedElement e = xml.scopedElement( elementName ); 10497 10498 xml.writeAttribute( "message", result.getExpandedExpression() ); 10499 xml.writeAttribute( "type", result.getTestMacroName() ); 10500 10501 std::ostringstream oss; 10502 if( !result.getMessage().empty() ) 10503 oss << result.getMessage() << '\n'; 10504 for( std::vector<MessageInfo>::const_iterator 10505 it = stats.infoMessages.begin(), 10506 itEnd = stats.infoMessages.end(); 10507 it != itEnd; 10508 ++it ) 10509 if( it->type == ResultWas::Info ) 10510 oss << it->message << '\n'; 10511 10512 oss << "at " << result.getSourceInfo(); 10513 xml.writeText( oss.str(), false ); 10514 } 10515 } 10516 10517 XmlWriter xml; 10518 Timer suiteTimer; 10519 std::ostringstream stdOutForSuite; 10520 std::ostringstream stdErrForSuite; 10521 unsigned int unexpectedExceptions; 10522 bool m_okToFail; 10523 }; 10524 10525 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter ) 10526 10527 } // end namespace Catch 10528 10529 // #included from: ../reporters/catch_reporter_console.hpp 10530 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED 10531 10532 #include <cfloat> 10533 #include <cstdio> 10534 10535 namespace Catch { 10536 10537 struct ConsoleReporter : StreamingReporterBase { 10538 ConsoleReporter( ReporterConfig const& _config ) 10539 : StreamingReporterBase( _config ), 10540 m_headerPrinted( false ) 10541 {} 10542 10543 virtual ~ConsoleReporter() CATCH_OVERRIDE; 10544 static std::string getDescription() { 10545 return "Reports test results as plain lines of text"; 10546 } 10547 10548 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE { 10549 stream << "No test cases matched '" << spec << '\'' << std::endl; 10550 } 10551 10552 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { 10553 } 10554 10555 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE { 10556 AssertionResult const& result = _assertionStats.assertionResult; 10557 10558 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk(); 10559 10560 // Drop out if result was successful but we're not printing them. 10561 if( !includeResults && result.getResultType() != ResultWas::Warning ) 10562 return false; 10563 10564 lazyPrint(); 10565 10566 AssertionPrinter printer( stream, _assertionStats, includeResults ); 10567 printer.print(); 10568 stream << std::endl; 10569 return true; 10570 } 10571 10572 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE { 10573 m_headerPrinted = false; 10574 StreamingReporterBase::sectionStarting( _sectionInfo ); 10575 } 10576 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE { 10577 if( _sectionStats.missingAssertions ) { 10578 lazyPrint(); 10579 Colour colour( Colour::ResultError ); 10580 if( m_sectionStack.size() > 1 ) 10581 stream << "\nNo assertions in section"; 10582 else 10583 stream << "\nNo assertions in test case"; 10584 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl; 10585 } 10586 if( m_config->showDurations() == ShowDurations::Always ) { 10587 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 10588 } 10589 if( m_headerPrinted ) { 10590 m_headerPrinted = false; 10591 } 10592 StreamingReporterBase::sectionEnded( _sectionStats ); 10593 } 10594 10595 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE { 10596 StreamingReporterBase::testCaseEnded( _testCaseStats ); 10597 m_headerPrinted = false; 10598 } 10599 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE { 10600 if( currentGroupInfo.used ) { 10601 printSummaryDivider(); 10602 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n"; 10603 printTotals( _testGroupStats.totals ); 10604 stream << '\n' << std::endl; 10605 } 10606 StreamingReporterBase::testGroupEnded( _testGroupStats ); 10607 } 10608 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE { 10609 printTotalsDivider( _testRunStats.totals ); 10610 printTotals( _testRunStats.totals ); 10611 stream << std::endl; 10612 StreamingReporterBase::testRunEnded( _testRunStats ); 10613 } 10614 10615 private: 10616 10617 class AssertionPrinter { 10618 void operator= ( AssertionPrinter const& ); 10619 public: 10620 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) 10621 : stream( _stream ), 10622 stats( _stats ), 10623 result( _stats.assertionResult ), 10624 colour( Colour::None ), 10625 message( result.getMessage() ), 10626 messages( _stats.infoMessages ), 10627 printInfoMessages( _printInfoMessages ) 10628 { 10629 switch( result.getResultType() ) { 10630 case ResultWas::Ok: 10631 colour = Colour::Success; 10632 passOrFail = "PASSED"; 10633 //if( result.hasMessage() ) 10634 if( _stats.infoMessages.size() == 1 ) 10635 messageLabel = "with message"; 10636 if( _stats.infoMessages.size() > 1 ) 10637 messageLabel = "with messages"; 10638 break; 10639 case ResultWas::ExpressionFailed: 10640 if( result.isOk() ) { 10641 colour = Colour::Success; 10642 passOrFail = "FAILED - but was ok"; 10643 } 10644 else { 10645 colour = Colour::Error; 10646 passOrFail = "FAILED"; 10647 } 10648 if( _stats.infoMessages.size() == 1 ) 10649 messageLabel = "with message"; 10650 if( _stats.infoMessages.size() > 1 ) 10651 messageLabel = "with messages"; 10652 break; 10653 case ResultWas::ThrewException: 10654 colour = Colour::Error; 10655 passOrFail = "FAILED"; 10656 messageLabel = "due to unexpected exception with "; 10657 if (_stats.infoMessages.size() == 1) 10658 messageLabel += "message"; 10659 if (_stats.infoMessages.size() > 1) 10660 messageLabel += "messages"; 10661 break; 10662 case ResultWas::FatalErrorCondition: 10663 colour = Colour::Error; 10664 passOrFail = "FAILED"; 10665 messageLabel = "due to a fatal error condition"; 10666 break; 10667 case ResultWas::DidntThrowException: 10668 colour = Colour::Error; 10669 passOrFail = "FAILED"; 10670 messageLabel = "because no exception was thrown where one was expected"; 10671 break; 10672 case ResultWas::Info: 10673 messageLabel = "info"; 10674 break; 10675 case ResultWas::Warning: 10676 messageLabel = "warning"; 10677 break; 10678 case ResultWas::ExplicitFailure: 10679 passOrFail = "FAILED"; 10680 colour = Colour::Error; 10681 if( _stats.infoMessages.size() == 1 ) 10682 messageLabel = "explicitly with message"; 10683 if( _stats.infoMessages.size() > 1 ) 10684 messageLabel = "explicitly with messages"; 10685 break; 10686 // These cases are here to prevent compiler warnings 10687 case ResultWas::Unknown: 10688 case ResultWas::FailureBit: 10689 case ResultWas::Exception: 10690 passOrFail = "** internal error **"; 10691 colour = Colour::Error; 10692 break; 10693 } 10694 } 10695 10696 void print() const { 10697 printSourceInfo(); 10698 if( stats.totals.assertions.total() > 0 ) { 10699 if( result.isOk() ) 10700 stream << '\n'; 10701 printResultType(); 10702 printOriginalExpression(); 10703 printReconstructedExpression(); 10704 } 10705 else { 10706 stream << '\n'; 10707 } 10708 printMessage(); 10709 } 10710 10711 private: 10712 void printResultType() const { 10713 if( !passOrFail.empty() ) { 10714 Colour colourGuard( colour ); 10715 stream << passOrFail << ":\n"; 10716 } 10717 } 10718 void printOriginalExpression() const { 10719 if( result.hasExpression() ) { 10720 Colour colourGuard( Colour::OriginalExpression ); 10721 stream << " "; 10722 stream << result.getExpressionInMacro(); 10723 stream << '\n'; 10724 } 10725 } 10726 void printReconstructedExpression() const { 10727 if( result.hasExpandedExpression() ) { 10728 stream << "with expansion:\n"; 10729 Colour colourGuard( Colour::ReconstructedExpression ); 10730 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n'; 10731 } 10732 } 10733 void printMessage() const { 10734 if( !messageLabel.empty() ) 10735 stream << messageLabel << ':' << '\n'; 10736 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end(); 10737 it != itEnd; 10738 ++it ) { 10739 // If this assertion is a warning ignore any INFO messages 10740 if( printInfoMessages || it->type != ResultWas::Info ) 10741 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n'; 10742 } 10743 } 10744 void printSourceInfo() const { 10745 Colour colourGuard( Colour::FileName ); 10746 stream << result.getSourceInfo() << ": "; 10747 } 10748 10749 std::ostream& stream; 10750 AssertionStats const& stats; 10751 AssertionResult const& result; 10752 Colour::Code colour; 10753 std::string passOrFail; 10754 std::string messageLabel; 10755 std::string message; 10756 std::vector<MessageInfo> messages; 10757 bool printInfoMessages; 10758 }; 10759 10760 void lazyPrint() { 10761 10762 if( !currentTestRunInfo.used ) 10763 lazyPrintRunInfo(); 10764 if( !currentGroupInfo.used ) 10765 lazyPrintGroupInfo(); 10766 10767 if( !m_headerPrinted ) { 10768 printTestCaseAndSectionHeader(); 10769 m_headerPrinted = true; 10770 } 10771 } 10772 void lazyPrintRunInfo() { 10773 stream << '\n' << getLineOfChars<'~'>() << '\n'; 10774 Colour colour( Colour::SecondaryText ); 10775 stream << currentTestRunInfo->name 10776 << " is a Catch v" << libraryVersion() << " host application.\n" 10777 << "Run with -? for options\n\n"; 10778 10779 if( m_config->rngSeed() != 0 ) 10780 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n"; 10781 10782 currentTestRunInfo.used = true; 10783 } 10784 void lazyPrintGroupInfo() { 10785 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) { 10786 printClosedHeader( "Group: " + currentGroupInfo->name ); 10787 currentGroupInfo.used = true; 10788 } 10789 } 10790 void printTestCaseAndSectionHeader() { 10791 assert( !m_sectionStack.empty() ); 10792 printOpenHeader( currentTestCaseInfo->name ); 10793 10794 if( m_sectionStack.size() > 1 ) { 10795 Colour colourGuard( Colour::Headers ); 10796 10797 std::vector<SectionInfo>::const_iterator 10798 it = m_sectionStack.begin()+1, // Skip first section (test case) 10799 itEnd = m_sectionStack.end(); 10800 for( ; it != itEnd; ++it ) 10801 printHeaderString( it->name, 2 ); 10802 } 10803 10804 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo; 10805 10806 if( !lineInfo.empty() ){ 10807 stream << getLineOfChars<'-'>() << '\n'; 10808 Colour colourGuard( Colour::FileName ); 10809 stream << lineInfo << '\n'; 10810 } 10811 stream << getLineOfChars<'.'>() << '\n' << std::endl; 10812 } 10813 10814 void printClosedHeader( std::string const& _name ) { 10815 printOpenHeader( _name ); 10816 stream << getLineOfChars<'.'>() << '\n'; 10817 } 10818 void printOpenHeader( std::string const& _name ) { 10819 stream << getLineOfChars<'-'>() << '\n'; 10820 { 10821 Colour colourGuard( Colour::Headers ); 10822 printHeaderString( _name ); 10823 } 10824 } 10825 10826 // if string has a : in first line will set indent to follow it on 10827 // subsequent lines 10828 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) { 10829 std::size_t i = _string.find( ": " ); 10830 if( i != std::string::npos ) 10831 i+=2; 10832 else 10833 i = 0; 10834 stream << Text( _string, TextAttributes() 10835 .setIndent( indent+i) 10836 .setInitialIndent( indent ) ) << '\n'; 10837 } 10838 10839 struct SummaryColumn { 10840 10841 SummaryColumn( std::string const& _label, Colour::Code _colour ) 10842 : label( _label ), 10843 colour( _colour ) 10844 {} 10845 SummaryColumn addRow( std::size_t count ) { 10846 std::ostringstream oss; 10847 oss << count; 10848 std::string row = oss.str(); 10849 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) { 10850 while( it->size() < row.size() ) 10851 *it = ' ' + *it; 10852 while( it->size() > row.size() ) 10853 row = ' ' + row; 10854 } 10855 rows.push_back( row ); 10856 return *this; 10857 } 10858 10859 std::string label; 10860 Colour::Code colour; 10861 std::vector<std::string> rows; 10862 10863 }; 10864 10865 void printTotals( Totals const& totals ) { 10866 if( totals.testCases.total() == 0 ) { 10867 stream << Colour( Colour::Warning ) << "No tests ran\n"; 10868 } 10869 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) { 10870 stream << Colour( Colour::ResultSuccess ) << "All tests passed"; 10871 stream << " (" 10872 << pluralise( totals.assertions.passed, "assertion" ) << " in " 10873 << pluralise( totals.testCases.passed, "test case" ) << ')' 10874 << '\n'; 10875 } 10876 else { 10877 10878 std::vector<SummaryColumn> columns; 10879 columns.push_back( SummaryColumn( "", Colour::None ) 10880 .addRow( totals.testCases.total() ) 10881 .addRow( totals.assertions.total() ) ); 10882 columns.push_back( SummaryColumn( "passed", Colour::Success ) 10883 .addRow( totals.testCases.passed ) 10884 .addRow( totals.assertions.passed ) ); 10885 columns.push_back( SummaryColumn( "failed", Colour::ResultError ) 10886 .addRow( totals.testCases.failed ) 10887 .addRow( totals.assertions.failed ) ); 10888 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure ) 10889 .addRow( totals.testCases.failedButOk ) 10890 .addRow( totals.assertions.failedButOk ) ); 10891 10892 printSummaryRow( "test cases", columns, 0 ); 10893 printSummaryRow( "assertions", columns, 1 ); 10894 } 10895 } 10896 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) { 10897 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) { 10898 std::string value = it->rows[row]; 10899 if( it->label.empty() ) { 10900 stream << label << ": "; 10901 if( value != "0" ) 10902 stream << value; 10903 else 10904 stream << Colour( Colour::Warning ) << "- none -"; 10905 } 10906 else if( value != "0" ) { 10907 stream << Colour( Colour::LightGrey ) << " | "; 10908 stream << Colour( it->colour ) 10909 << value << ' ' << it->label; 10910 } 10911 } 10912 stream << '\n'; 10913 } 10914 10915 static std::size_t makeRatio( std::size_t number, std::size_t total ) { 10916 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0; 10917 return ( ratio == 0 && number > 0 ) ? 1 : ratio; 10918 } 10919 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) { 10920 if( i > j && i > k ) 10921 return i; 10922 else if( j > k ) 10923 return j; 10924 else 10925 return k; 10926 } 10927 10928 void printTotalsDivider( Totals const& totals ) { 10929 if( totals.testCases.total() > 0 ) { 10930 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() ); 10931 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() ); 10932 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() ); 10933 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 ) 10934 findMax( failedRatio, failedButOkRatio, passedRatio )++; 10935 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 ) 10936 findMax( failedRatio, failedButOkRatio, passedRatio )--; 10937 10938 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' ); 10939 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' ); 10940 if( totals.testCases.allPassed() ) 10941 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' ); 10942 else 10943 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' ); 10944 } 10945 else { 10946 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' ); 10947 } 10948 stream << '\n'; 10949 } 10950 void printSummaryDivider() { 10951 stream << getLineOfChars<'-'>() << '\n'; 10952 } 10953 10954 private: 10955 bool m_headerPrinted; 10956 }; 10957 10958 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter ) 10959 10960 } // end namespace Catch 10961 10962 // #included from: ../reporters/catch_reporter_compact.hpp 10963 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED 10964 10965 namespace Catch { 10966 10967 struct CompactReporter : StreamingReporterBase { 10968 10969 CompactReporter( ReporterConfig const& _config ) 10970 : StreamingReporterBase( _config ) 10971 {} 10972 10973 virtual ~CompactReporter(); 10974 10975 static std::string getDescription() { 10976 return "Reports test results on a single line, suitable for IDEs"; 10977 } 10978 10979 virtual ReporterPreferences getPreferences() const { 10980 ReporterPreferences prefs; 10981 prefs.shouldRedirectStdOut = false; 10982 return prefs; 10983 } 10984 10985 virtual void noMatchingTestCases( std::string const& spec ) { 10986 stream << "No test cases matched '" << spec << '\'' << std::endl; 10987 } 10988 10989 virtual void assertionStarting( AssertionInfo const& ) {} 10990 10991 virtual bool assertionEnded( AssertionStats const& _assertionStats ) { 10992 AssertionResult const& result = _assertionStats.assertionResult; 10993 10994 bool printInfoMessages = true; 10995 10996 // Drop out if result was successful and we're not printing those 10997 if( !m_config->includeSuccessfulResults() && result.isOk() ) { 10998 if( result.getResultType() != ResultWas::Warning ) 10999 return false; 11000 printInfoMessages = false; 11001 } 11002 11003 AssertionPrinter printer( stream, _assertionStats, printInfoMessages ); 11004 printer.print(); 11005 11006 stream << std::endl; 11007 return true; 11008 } 11009 11010 virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE { 11011 if (m_config->showDurations() == ShowDurations::Always) { 11012 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl; 11013 } 11014 } 11015 11016 virtual void testRunEnded( TestRunStats const& _testRunStats ) { 11017 printTotals( _testRunStats.totals ); 11018 stream << '\n' << std::endl; 11019 StreamingReporterBase::testRunEnded( _testRunStats ); 11020 } 11021 11022 private: 11023 class AssertionPrinter { 11024 void operator= ( AssertionPrinter const& ); 11025 public: 11026 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages ) 11027 : stream( _stream ) 11028 , stats( _stats ) 11029 , result( _stats.assertionResult ) 11030 , messages( _stats.infoMessages ) 11031 , itMessage( _stats.infoMessages.begin() ) 11032 , printInfoMessages( _printInfoMessages ) 11033 {} 11034 11035 void print() { 11036 printSourceInfo(); 11037 11038 itMessage = messages.begin(); 11039 11040 switch( result.getResultType() ) { 11041 case ResultWas::Ok: 11042 printResultType( Colour::ResultSuccess, passedString() ); 11043 printOriginalExpression(); 11044 printReconstructedExpression(); 11045 if ( ! result.hasExpression() ) 11046 printRemainingMessages( Colour::None ); 11047 else 11048 printRemainingMessages(); 11049 break; 11050 case ResultWas::ExpressionFailed: 11051 if( result.isOk() ) 11052 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) ); 11053 else 11054 printResultType( Colour::Error, failedString() ); 11055 printOriginalExpression(); 11056 printReconstructedExpression(); 11057 printRemainingMessages(); 11058 break; 11059 case ResultWas::ThrewException: 11060 printResultType( Colour::Error, failedString() ); 11061 printIssue( "unexpected exception with message:" ); 11062 printMessage(); 11063 printExpressionWas(); 11064 printRemainingMessages(); 11065 break; 11066 case ResultWas::FatalErrorCondition: 11067 printResultType( Colour::Error, failedString() ); 11068 printIssue( "fatal error condition with message:" ); 11069 printMessage(); 11070 printExpressionWas(); 11071 printRemainingMessages(); 11072 break; 11073 case ResultWas::DidntThrowException: 11074 printResultType( Colour::Error, failedString() ); 11075 printIssue( "expected exception, got none" ); 11076 printExpressionWas(); 11077 printRemainingMessages(); 11078 break; 11079 case ResultWas::Info: 11080 printResultType( Colour::None, "info" ); 11081 printMessage(); 11082 printRemainingMessages(); 11083 break; 11084 case ResultWas::Warning: 11085 printResultType( Colour::None, "warning" ); 11086 printMessage(); 11087 printRemainingMessages(); 11088 break; 11089 case ResultWas::ExplicitFailure: 11090 printResultType( Colour::Error, failedString() ); 11091 printIssue( "explicitly" ); 11092 printRemainingMessages( Colour::None ); 11093 break; 11094 // These cases are here to prevent compiler warnings 11095 case ResultWas::Unknown: 11096 case ResultWas::FailureBit: 11097 case ResultWas::Exception: 11098 printResultType( Colour::Error, "** internal error **" ); 11099 break; 11100 } 11101 } 11102 11103 private: 11104 // Colour::LightGrey 11105 11106 static Colour::Code dimColour() { return Colour::FileName; } 11107 11108 #ifdef CATCH_PLATFORM_MAC 11109 static const char* failedString() { return "FAILED"; } 11110 static const char* passedString() { return "PASSED"; } 11111 #else 11112 static const char* failedString() { return "failed"; } 11113 static const char* passedString() { return "passed"; } 11114 #endif 11115 11116 void printSourceInfo() const { 11117 Colour colourGuard( Colour::FileName ); 11118 stream << result.getSourceInfo() << ':'; 11119 } 11120 11121 void printResultType( Colour::Code colour, std::string const& passOrFail ) const { 11122 if( !passOrFail.empty() ) { 11123 { 11124 Colour colourGuard( colour ); 11125 stream << ' ' << passOrFail; 11126 } 11127 stream << ':'; 11128 } 11129 } 11130 11131 void printIssue( std::string const& issue ) const { 11132 stream << ' ' << issue; 11133 } 11134 11135 void printExpressionWas() { 11136 if( result.hasExpression() ) { 11137 stream << ';'; 11138 { 11139 Colour colour( dimColour() ); 11140 stream << " expression was:"; 11141 } 11142 printOriginalExpression(); 11143 } 11144 } 11145 11146 void printOriginalExpression() const { 11147 if( result.hasExpression() ) { 11148 stream << ' ' << result.getExpression(); 11149 } 11150 } 11151 11152 void printReconstructedExpression() const { 11153 if( result.hasExpandedExpression() ) { 11154 { 11155 Colour colour( dimColour() ); 11156 stream << " for: "; 11157 } 11158 stream << result.getExpandedExpression(); 11159 } 11160 } 11161 11162 void printMessage() { 11163 if ( itMessage != messages.end() ) { 11164 stream << " '" << itMessage->message << '\''; 11165 ++itMessage; 11166 } 11167 } 11168 11169 void printRemainingMessages( Colour::Code colour = dimColour() ) { 11170 if ( itMessage == messages.end() ) 11171 return; 11172 11173 // using messages.end() directly yields compilation error: 11174 std::vector<MessageInfo>::const_iterator itEnd = messages.end(); 11175 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) ); 11176 11177 { 11178 Colour colourGuard( colour ); 11179 stream << " with " << pluralise( N, "message" ) << ':'; 11180 } 11181 11182 for(; itMessage != itEnd; ) { 11183 // If this assertion is a warning ignore any INFO messages 11184 if( printInfoMessages || itMessage->type != ResultWas::Info ) { 11185 stream << " '" << itMessage->message << '\''; 11186 if ( ++itMessage != itEnd ) { 11187 Colour colourGuard( dimColour() ); 11188 stream << " and"; 11189 } 11190 } 11191 } 11192 } 11193 11194 private: 11195 std::ostream& stream; 11196 AssertionStats const& stats; 11197 AssertionResult const& result; 11198 std::vector<MessageInfo> messages; 11199 std::vector<MessageInfo>::const_iterator itMessage; 11200 bool printInfoMessages; 11201 }; 11202 11203 // Colour, message variants: 11204 // - white: No tests ran. 11205 // - red: Failed [both/all] N test cases, failed [both/all] M assertions. 11206 // - white: Passed [both/all] N test cases (no assertions). 11207 // - red: Failed N tests cases, failed M assertions. 11208 // - green: Passed [both/all] N tests cases with M assertions. 11209 11210 std::string bothOrAll( std::size_t count ) const { 11211 return count == 1 ? std::string() : count == 2 ? "both " : "all " ; 11212 } 11213 11214 void printTotals( const Totals& totals ) const { 11215 if( totals.testCases.total() == 0 ) { 11216 stream << "No tests ran."; 11217 } 11218 else if( totals.testCases.failed == totals.testCases.total() ) { 11219 Colour colour( Colour::ResultError ); 11220 const std::string qualify_assertions_failed = 11221 totals.assertions.failed == totals.assertions.total() ? 11222 bothOrAll( totals.assertions.failed ) : std::string(); 11223 stream << 11224 "Failed " << bothOrAll( totals.testCases.failed ) 11225 << pluralise( totals.testCases.failed, "test case" ) << ", " 11226 "failed " << qualify_assertions_failed << 11227 pluralise( totals.assertions.failed, "assertion" ) << '.'; 11228 } 11229 else if( totals.assertions.total() == 0 ) { 11230 stream << 11231 "Passed " << bothOrAll( totals.testCases.total() ) 11232 << pluralise( totals.testCases.total(), "test case" ) 11233 << " (no assertions)."; 11234 } 11235 else if( totals.assertions.failed ) { 11236 Colour colour( Colour::ResultError ); 11237 stream << 11238 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", " 11239 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.'; 11240 } 11241 else { 11242 Colour colour( Colour::ResultSuccess ); 11243 stream << 11244 "Passed " << bothOrAll( totals.testCases.passed ) 11245 << pluralise( totals.testCases.passed, "test case" ) << 11246 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.'; 11247 } 11248 } 11249 }; 11250 11251 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter ) 11252 11253 } // end namespace Catch 11254 11255 namespace Catch { 11256 // These are all here to avoid warnings about not having any out of line 11257 // virtual methods 11258 NonCopyable::~NonCopyable() {} 11259 IShared::~IShared() {} 11260 IStream::~IStream() CATCH_NOEXCEPT {} 11261 FileStream::~FileStream() CATCH_NOEXCEPT {} 11262 CoutStream::~CoutStream() CATCH_NOEXCEPT {} 11263 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {} 11264 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {} 11265 IContext::~IContext() {} 11266 IResultCapture::~IResultCapture() {} 11267 ITestCase::~ITestCase() {} 11268 ITestCaseRegistry::~ITestCaseRegistry() {} 11269 IRegistryHub::~IRegistryHub() {} 11270 IMutableRegistryHub::~IMutableRegistryHub() {} 11271 IExceptionTranslator::~IExceptionTranslator() {} 11272 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {} 11273 IReporter::~IReporter() {} 11274 IReporterFactory::~IReporterFactory() {} 11275 IReporterRegistry::~IReporterRegistry() {} 11276 IStreamingReporter::~IStreamingReporter() {} 11277 AssertionStats::~AssertionStats() {} 11278 SectionStats::~SectionStats() {} 11279 TestCaseStats::~TestCaseStats() {} 11280 TestGroupStats::~TestGroupStats() {} 11281 TestRunStats::~TestRunStats() {} 11282 CumulativeReporterBase::SectionNode::~SectionNode() {} 11283 CumulativeReporterBase::~CumulativeReporterBase() {} 11284 11285 StreamingReporterBase::~StreamingReporterBase() {} 11286 ConsoleReporter::~ConsoleReporter() {} 11287 CompactReporter::~CompactReporter() {} 11288 IRunner::~IRunner() {} 11289 IMutableContext::~IMutableContext() {} 11290 IConfig::~IConfig() {} 11291 XmlReporter::~XmlReporter() {} 11292 JunitReporter::~JunitReporter() {} 11293 TestRegistry::~TestRegistry() {} 11294 FreeFunctionTestCase::~FreeFunctionTestCase() {} 11295 IGeneratorInfo::~IGeneratorInfo() {} 11296 IGeneratorsForTest::~IGeneratorsForTest() {} 11297 WildcardPattern::~WildcardPattern() {} 11298 TestSpec::Pattern::~Pattern() {} 11299 TestSpec::NamePattern::~NamePattern() {} 11300 TestSpec::TagPattern::~TagPattern() {} 11301 TestSpec::ExcludedPattern::~ExcludedPattern() {} 11302 Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {} 11303 11304 void Config::dummy() {} 11305 11306 namespace TestCaseTracking { 11307 ITracker::~ITracker() {} 11308 TrackerBase::~TrackerBase() {} 11309 SectionTracker::~SectionTracker() {} 11310 IndexTracker::~IndexTracker() {} 11311 } 11312 } 11313 11314 #ifdef __clang__ 11315 # pragma clang diagnostic pop 11316 #endif 11317 11318 #endif 11319 11320 #ifdef CATCH_CONFIG_MAIN 11321 // #included from: internal/catch_default_main.hpp 11322 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED 11323 11324 #ifndef __OBJC__ 11325 11326 #if defined(WIN32) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN) 11327 // Standard C/C++ Win32 Unicode wmain entry point 11328 extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) { 11329 #else 11330 // Standard C/C++ main entry point 11331 int main (int argc, char * argv[]) { 11332 #endif 11333 11334 int result = Catch::Session().run( argc, argv ); 11335 return ( result < 0xff ? result : 0xff ); 11336 } 11337 11338 #else // __OBJC__ 11339 11340 // Objective-C entry point 11341 int main (int argc, char * const argv[]) { 11342 #if !CATCH_ARC_ENABLED 11343 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 11344 #endif 11345 11346 Catch::registerTestMethods(); 11347 int result = Catch::Session().run( argc, (char* const*)argv ); 11348 11349 #if !CATCH_ARC_ENABLED 11350 [pool drain]; 11351 #endif 11352 11353 return ( result < 0xff ? result : 0xff ); 11354 } 11355 11356 #endif // __OBJC__ 11357 11358 #endif 11359 11360 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED 11361 # undef CLARA_CONFIG_MAIN 11362 #endif 11363 11364 ////// 11365 11366 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_ 11367 #ifdef CATCH_CONFIG_PREFIX_ALL 11368 11369 #if defined(CATCH_CONFIG_FAST_COMPILE) 11370 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) 11371 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) 11372 #else 11373 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr ) 11374 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) 11375 #endif 11376 11377 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) 11378 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 11379 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 11380 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) 11381 11382 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) 11383 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) 11384 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) 11385 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) 11386 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) 11387 11388 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) 11389 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 11390 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11391 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) 11392 11393 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 11394 11395 #if defined(CATCH_CONFIG_FAST_COMPILE) 11396 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11397 #else 11398 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11399 #endif 11400 11401 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 11402 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 11403 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg ) 11404 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) 11405 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) ) 11406 11407 #ifdef CATCH_CONFIG_VARIADIC_MACROS 11408 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 11409 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 11410 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 11411 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 11412 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 11413 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 11414 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 11415 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 11416 #else 11417 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) 11418 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) 11419 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) 11420 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description ) 11421 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) 11422 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) 11423 #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) 11424 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) 11425 #endif 11426 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) 11427 11428 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) 11429 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) 11430 11431 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) 11432 11433 // "BDD-style" convenience wrappers 11434 #ifdef CATCH_CONFIG_VARIADIC_MACROS 11435 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ ) 11436 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 11437 #else 11438 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags ) 11439 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) 11440 #endif 11441 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" ) 11442 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" ) 11443 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) 11444 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" ) 11445 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" ) 11446 11447 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required 11448 #else 11449 11450 #if defined(CATCH_CONFIG_FAST_COMPILE) 11451 #define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr ) 11452 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) 11453 11454 #else 11455 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr ) 11456 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr ) 11457 #endif 11458 11459 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr ) 11460 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr ) 11461 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr ) 11462 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr ) 11463 11464 #define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr ) 11465 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr ) 11466 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr ) 11467 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr ) 11468 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr ) 11469 11470 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr ) 11471 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr ) 11472 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr ) 11473 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr ) 11474 11475 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg ) 11476 11477 #if defined(CATCH_CONFIG_FAST_COMPILE) 11478 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11479 #else 11480 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg ) 11481 #endif 11482 11483 #define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 11484 #define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg ) 11485 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg ) 11486 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) 11487 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) ) 11488 11489 #ifdef CATCH_CONFIG_VARIADIC_MACROS 11490 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ ) 11491 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ ) 11492 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ ) 11493 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ ) 11494 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ ) 11495 #define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ ) 11496 #define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 11497 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ ) 11498 #else 11499 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description ) 11500 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description ) 11501 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description ) 11502 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description ) 11503 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description ) 11504 #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg ) 11505 #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg ) 11506 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg ) 11507 #endif 11508 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" ) 11509 11510 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) 11511 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) 11512 11513 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr ) 11514 11515 #endif 11516 11517 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) 11518 11519 // "BDD-style" convenience wrappers 11520 #ifdef CATCH_CONFIG_VARIADIC_MACROS 11521 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ ) 11522 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ ) 11523 #else 11524 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags ) 11525 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags ) 11526 #endif 11527 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" ) 11528 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" ) 11529 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" ) 11530 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" ) 11531 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" ) 11532 11533 using Catch::Detail::Approx; 11534 11535 // #included from: internal/catch_reenable_warnings.h 11536 11537 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED 11538 11539 #ifdef __clang__ 11540 # ifdef __ICC // icpc defines the __clang__ macro 11541 # pragma warning(pop) 11542 # else 11543 # pragma clang diagnostic pop 11544 # endif 11545 #elif defined __GNUC__ 11546 # pragma GCC diagnostic pop 11547 #endif 11548 11549 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED 11550