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