annotate ext/catch/catch.hpp @ 189:6859f35cb4f8

Manually bring in Catch for testing.
author Lucas Thompson <dev@lucas.im>
date Tue, 07 Feb 2017 10:25:15 +0000
parents
children
rev   line source
dev@189 1 /*
dev@189 2 * Catch v1.7.1
dev@189 3 * Generated: 2017-02-07 09:44:56.263047
dev@189 4 * ----------------------------------------------------------
dev@189 5 * This file has been merged from multiple headers. Please don't edit it directly
dev@189 6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
dev@189 7 *
dev@189 8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
dev@189 9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
dev@189 10 */
dev@189 11 #ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
dev@189 12 #define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
dev@189 13
dev@189 14 #define TWOBLUECUBES_CATCH_HPP_INCLUDED
dev@189 15
dev@189 16 #ifdef __clang__
dev@189 17 # pragma clang system_header
dev@189 18 #elif defined __GNUC__
dev@189 19 # pragma GCC system_header
dev@189 20 #endif
dev@189 21
dev@189 22 // #included from: internal/catch_suppress_warnings.h
dev@189 23
dev@189 24 #ifdef __clang__
dev@189 25 # ifdef __ICC // icpc defines the __clang__ macro
dev@189 26 # pragma warning(push)
dev@189 27 # pragma warning(disable: 161 1682)
dev@189 28 # else // __ICC
dev@189 29 # pragma clang diagnostic ignored "-Wglobal-constructors"
dev@189 30 # pragma clang diagnostic ignored "-Wvariadic-macros"
dev@189 31 # pragma clang diagnostic ignored "-Wc99-extensions"
dev@189 32 # pragma clang diagnostic ignored "-Wunused-variable"
dev@189 33 # pragma clang diagnostic push
dev@189 34 # pragma clang diagnostic ignored "-Wpadded"
dev@189 35 # pragma clang diagnostic ignored "-Wc++98-compat"
dev@189 36 # pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
dev@189 37 # pragma clang diagnostic ignored "-Wswitch-enum"
dev@189 38 # pragma clang diagnostic ignored "-Wcovered-switch-default"
dev@189 39 # endif
dev@189 40 #elif defined __GNUC__
dev@189 41 # pragma GCC diagnostic ignored "-Wvariadic-macros"
dev@189 42 # pragma GCC diagnostic ignored "-Wunused-variable"
dev@189 43 # pragma GCC diagnostic push
dev@189 44 # pragma GCC diagnostic ignored "-Wpadded"
dev@189 45 #endif
dev@189 46 #if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
dev@189 47 # define CATCH_IMPL
dev@189 48 #endif
dev@189 49
dev@189 50 #ifdef CATCH_IMPL
dev@189 51 # ifndef CLARA_CONFIG_MAIN
dev@189 52 # define CLARA_CONFIG_MAIN_NOT_DEFINED
dev@189 53 # define CLARA_CONFIG_MAIN
dev@189 54 # endif
dev@189 55 #endif
dev@189 56
dev@189 57 // #included from: internal/catch_notimplemented_exception.h
dev@189 58 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
dev@189 59
dev@189 60 // #included from: catch_common.h
dev@189 61 #define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
dev@189 62
dev@189 63 // #included from: catch_compiler_capabilities.h
dev@189 64 #define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
dev@189 65
dev@189 66 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
dev@189 67 // The following features are defined:
dev@189 68 //
dev@189 69 // CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
dev@189 70 // CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
dev@189 71 // CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
dev@189 72 // CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
dev@189 73 // CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
dev@189 74 // CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
dev@189 75 // CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
dev@189 76 // CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
dev@189 77 // CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
dev@189 78 // CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
dev@189 79
dev@189 80 // CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
dev@189 81
dev@189 82 // CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
dev@189 83 // CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
dev@189 84 // CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
dev@189 85 // ****************
dev@189 86 // Note to maintainers: if new toggles are added please document them
dev@189 87 // in configuration.md, too
dev@189 88 // ****************
dev@189 89
dev@189 90 // In general each macro has a _NO_<feature name> form
dev@189 91 // (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
dev@189 92 // Many features, at point of detection, define an _INTERNAL_ macro, so they
dev@189 93 // can be combined, en-mass, with the _NO_ forms later.
dev@189 94
dev@189 95 // All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
dev@189 96
dev@189 97 #ifdef __cplusplus
dev@189 98
dev@189 99 # if __cplusplus >= 201103L
dev@189 100 # define CATCH_CPP11_OR_GREATER
dev@189 101 # endif
dev@189 102
dev@189 103 # if __cplusplus >= 201402L
dev@189 104 # define CATCH_CPP14_OR_GREATER
dev@189 105 # endif
dev@189 106
dev@189 107 #endif
dev@189 108
dev@189 109 #ifdef __clang__
dev@189 110
dev@189 111 # if __has_feature(cxx_nullptr)
dev@189 112 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 113 # endif
dev@189 114
dev@189 115 # if __has_feature(cxx_noexcept)
dev@189 116 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 117 # endif
dev@189 118
dev@189 119 # if defined(CATCH_CPP11_OR_GREATER)
dev@189 120 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
dev@189 121 # endif
dev@189 122
dev@189 123 #endif // __clang__
dev@189 124
dev@189 125 ////////////////////////////////////////////////////////////////////////////////
dev@189 126 // Borland
dev@189 127 #ifdef __BORLANDC__
dev@189 128
dev@189 129 #endif // __BORLANDC__
dev@189 130
dev@189 131 ////////////////////////////////////////////////////////////////////////////////
dev@189 132 // EDG
dev@189 133 #ifdef __EDG_VERSION__
dev@189 134
dev@189 135 #endif // __EDG_VERSION__
dev@189 136
dev@189 137 ////////////////////////////////////////////////////////////////////////////////
dev@189 138 // Digital Mars
dev@189 139 #ifdef __DMC__
dev@189 140
dev@189 141 #endif // __DMC__
dev@189 142
dev@189 143 ////////////////////////////////////////////////////////////////////////////////
dev@189 144 // GCC
dev@189 145 #ifdef __GNUC__
dev@189 146
dev@189 147 # if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
dev@189 148 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 149 # endif
dev@189 150
dev@189 151 # if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
dev@189 152 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
dev@189 153 # endif
dev@189 154
dev@189 155 // - otherwise more recent versions define __cplusplus >= 201103L
dev@189 156 // and will get picked up below
dev@189 157
dev@189 158 #endif // __GNUC__
dev@189 159
dev@189 160 ////////////////////////////////////////////////////////////////////////////////
dev@189 161 // Visual C++
dev@189 162 #ifdef _MSC_VER
dev@189 163
dev@189 164 #define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
dev@189 165
dev@189 166 #if (_MSC_VER >= 1600)
dev@189 167 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 168 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
dev@189 169 #endif
dev@189 170
dev@189 171 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
dev@189 172 #define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 173 #define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 174 #define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
dev@189 175 #define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
dev@189 176 #endif
dev@189 177
dev@189 178 #endif // _MSC_VER
dev@189 179
dev@189 180 ////////////////////////////////////////////////////////////////////////////////
dev@189 181
dev@189 182 // Use variadic macros if the compiler supports them
dev@189 183 #if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
dev@189 184 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
dev@189 185 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
dev@189 186 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
dev@189 187
dev@189 188 #define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
dev@189 189
dev@189 190 #endif
dev@189 191
dev@189 192 // Use __COUNTER__ if the compiler supports it
dev@189 193 #if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
dev@189 194 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
dev@189 195 ( defined __clang__ && __clang_major__ >= 3 )
dev@189 196
dev@189 197 #define CATCH_INTERNAL_CONFIG_COUNTER
dev@189 198
dev@189 199 #endif
dev@189 200
dev@189 201 ////////////////////////////////////////////////////////////////////////////////
dev@189 202 // C++ language feature support
dev@189 203
dev@189 204 // catch all support for C++11
dev@189 205 #if defined(CATCH_CPP11_OR_GREATER)
dev@189 206
dev@189 207 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
dev@189 208 # define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 209 # endif
dev@189 210
dev@189 211 # ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 212 # define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 213 # endif
dev@189 214
dev@189 215 # ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 216 # define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 217 # endif
dev@189 218
dev@189 219 # ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
dev@189 220 # define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
dev@189 221 # endif
dev@189 222
dev@189 223 # ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
dev@189 224 # define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
dev@189 225 # endif
dev@189 226
dev@189 227 # ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
dev@189 228 # define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
dev@189 229 # endif
dev@189 230
dev@189 231 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
dev@189 232 # define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
dev@189 233 # endif
dev@189 234
dev@189 235 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
dev@189 236 # define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
dev@189 237 # endif
dev@189 238 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
dev@189 239 # define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
dev@189 240 # endif
dev@189 241 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
dev@189 242 # define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
dev@189 243 # endif
dev@189 244 # if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
dev@189 245 # define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
dev@189 246 # endif
dev@189 247
dev@189 248 #endif // __cplusplus >= 201103L
dev@189 249
dev@189 250 // Now set the actual defines based on the above + anything the user has configured
dev@189 251 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 252 # define CATCH_CONFIG_CPP11_NULLPTR
dev@189 253 #endif
dev@189 254 #if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 255 # define CATCH_CONFIG_CPP11_NOEXCEPT
dev@189 256 #endif
dev@189 257 #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)
dev@189 258 # define CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 259 #endif
dev@189 260 #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)
dev@189 261 # define CATCH_CONFIG_CPP11_IS_ENUM
dev@189 262 #endif
dev@189 263 #if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 264 # define CATCH_CONFIG_CPP11_TUPLE
dev@189 265 #endif
dev@189 266 #if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
dev@189 267 # define CATCH_CONFIG_VARIADIC_MACROS
dev@189 268 #endif
dev@189 269 #if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 270 # define CATCH_CONFIG_CPP11_LONG_LONG
dev@189 271 #endif
dev@189 272 #if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 273 # define CATCH_CONFIG_CPP11_OVERRIDE
dev@189 274 #endif
dev@189 275 #if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 276 # define CATCH_CONFIG_CPP11_UNIQUE_PTR
dev@189 277 #endif
dev@189 278 // Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
dev@189 279 // analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
dev@189 280 // This does not affect compilation
dev@189 281 #if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
dev@189 282 # define CATCH_CONFIG_COUNTER
dev@189 283 #endif
dev@189 284 #if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 285 # define CATCH_CONFIG_CPP11_SHUFFLE
dev@189 286 #endif
dev@189 287 # if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
dev@189 288 # define CATCH_CONFIG_CPP11_TYPE_TRAITS
dev@189 289 # endif
dev@189 290 #if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
dev@189 291 # define CATCH_CONFIG_WINDOWS_SEH
dev@189 292 #endif
dev@189 293
dev@189 294 #if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
dev@189 295 # define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
dev@189 296 #endif
dev@189 297
dev@189 298 // noexcept support:
dev@189 299 #if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
dev@189 300 # define CATCH_NOEXCEPT noexcept
dev@189 301 # define CATCH_NOEXCEPT_IS(x) noexcept(x)
dev@189 302 #else
dev@189 303 # define CATCH_NOEXCEPT throw()
dev@189 304 # define CATCH_NOEXCEPT_IS(x)
dev@189 305 #endif
dev@189 306
dev@189 307 // nullptr support
dev@189 308 #ifdef CATCH_CONFIG_CPP11_NULLPTR
dev@189 309 # define CATCH_NULL nullptr
dev@189 310 #else
dev@189 311 # define CATCH_NULL NULL
dev@189 312 #endif
dev@189 313
dev@189 314 // override support
dev@189 315 #ifdef CATCH_CONFIG_CPP11_OVERRIDE
dev@189 316 # define CATCH_OVERRIDE override
dev@189 317 #else
dev@189 318 # define CATCH_OVERRIDE
dev@189 319 #endif
dev@189 320
dev@189 321 // unique_ptr support
dev@189 322 #ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
dev@189 323 # define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
dev@189 324 #else
dev@189 325 # define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
dev@189 326 #endif
dev@189 327
dev@189 328 #define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
dev@189 329 #define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
dev@189 330 #ifdef CATCH_CONFIG_COUNTER
dev@189 331 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
dev@189 332 #else
dev@189 333 # define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
dev@189 334 #endif
dev@189 335
dev@189 336 #define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
dev@189 337 #define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
dev@189 338
dev@189 339 #include <sstream>
dev@189 340 #include <stdexcept>
dev@189 341 #include <algorithm>
dev@189 342
dev@189 343 namespace Catch {
dev@189 344
dev@189 345 struct IConfig;
dev@189 346
dev@189 347 struct CaseSensitive { enum Choice {
dev@189 348 Yes,
dev@189 349 No
dev@189 350 }; };
dev@189 351
dev@189 352 class NonCopyable {
dev@189 353 #ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 354 NonCopyable( NonCopyable const& ) = delete;
dev@189 355 NonCopyable( NonCopyable && ) = delete;
dev@189 356 NonCopyable& operator = ( NonCopyable const& ) = delete;
dev@189 357 NonCopyable& operator = ( NonCopyable && ) = delete;
dev@189 358 #else
dev@189 359 NonCopyable( NonCopyable const& info );
dev@189 360 NonCopyable& operator = ( NonCopyable const& );
dev@189 361 #endif
dev@189 362
dev@189 363 protected:
dev@189 364 NonCopyable() {}
dev@189 365 virtual ~NonCopyable();
dev@189 366 };
dev@189 367
dev@189 368 class SafeBool {
dev@189 369 public:
dev@189 370 typedef void (SafeBool::*type)() const;
dev@189 371
dev@189 372 static type makeSafe( bool value ) {
dev@189 373 return value ? &SafeBool::trueValue : 0;
dev@189 374 }
dev@189 375 private:
dev@189 376 void trueValue() const {}
dev@189 377 };
dev@189 378
dev@189 379 template<typename ContainerT>
dev@189 380 inline void deleteAll( ContainerT& container ) {
dev@189 381 typename ContainerT::const_iterator it = container.begin();
dev@189 382 typename ContainerT::const_iterator itEnd = container.end();
dev@189 383 for(; it != itEnd; ++it )
dev@189 384 delete *it;
dev@189 385 }
dev@189 386 template<typename AssociativeContainerT>
dev@189 387 inline void deleteAllValues( AssociativeContainerT& container ) {
dev@189 388 typename AssociativeContainerT::const_iterator it = container.begin();
dev@189 389 typename AssociativeContainerT::const_iterator itEnd = container.end();
dev@189 390 for(; it != itEnd; ++it )
dev@189 391 delete it->second;
dev@189 392 }
dev@189 393
dev@189 394 bool startsWith( std::string const& s, std::string const& prefix );
dev@189 395 bool startsWith( std::string const& s, char prefix );
dev@189 396 bool endsWith( std::string const& s, std::string const& suffix );
dev@189 397 bool endsWith( std::string const& s, char suffix );
dev@189 398 bool contains( std::string const& s, std::string const& infix );
dev@189 399 bool contains( std::string const& s, std::string const& infix );
dev@189 400 void toLowerInPlace( std::string& s );
dev@189 401 std::string toLower( std::string const& s );
dev@189 402 std::string trim( std::string const& str );
dev@189 403 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
dev@189 404
dev@189 405 struct pluralise {
dev@189 406 pluralise( std::size_t count, std::string const& label );
dev@189 407
dev@189 408 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
dev@189 409
dev@189 410 std::size_t m_count;
dev@189 411 std::string m_label;
dev@189 412 };
dev@189 413
dev@189 414 struct SourceLineInfo {
dev@189 415
dev@189 416 SourceLineInfo();
dev@189 417 SourceLineInfo( char const* _file, std::size_t _line );
dev@189 418 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 419 SourceLineInfo(SourceLineInfo const& other) = default;
dev@189 420 SourceLineInfo( SourceLineInfo && ) = default;
dev@189 421 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
dev@189 422 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
dev@189 423 # endif
dev@189 424 bool empty() const;
dev@189 425 bool operator == ( SourceLineInfo const& other ) const;
dev@189 426 bool operator < ( SourceLineInfo const& other ) const;
dev@189 427
dev@189 428 char const* file;
dev@189 429 std::size_t line;
dev@189 430 };
dev@189 431
dev@189 432 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
dev@189 433
dev@189 434 // This is just here to avoid compiler warnings with macro constants and boolean literals
dev@189 435 inline bool isTrue( bool value ){ return value; }
dev@189 436 inline bool alwaysTrue() { return true; }
dev@189 437 inline bool alwaysFalse() { return false; }
dev@189 438
dev@189 439 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
dev@189 440
dev@189 441 void seedRng( IConfig const& config );
dev@189 442 unsigned int rngSeed();
dev@189 443
dev@189 444 // Use this in variadic streaming macros to allow
dev@189 445 // >> +StreamEndStop
dev@189 446 // as well as
dev@189 447 // >> stuff +StreamEndStop
dev@189 448 struct StreamEndStop {
dev@189 449 std::string operator+() {
dev@189 450 return std::string();
dev@189 451 }
dev@189 452 };
dev@189 453 template<typename T>
dev@189 454 T const& operator + ( T const& value, StreamEndStop ) {
dev@189 455 return value;
dev@189 456 }
dev@189 457 }
dev@189 458
dev@189 459 #define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
dev@189 460 #define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
dev@189 461
dev@189 462 #include <ostream>
dev@189 463
dev@189 464 namespace Catch {
dev@189 465
dev@189 466 class NotImplementedException : public std::exception
dev@189 467 {
dev@189 468 public:
dev@189 469 NotImplementedException( SourceLineInfo const& lineInfo );
dev@189 470 NotImplementedException( NotImplementedException const& ) {}
dev@189 471
dev@189 472 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
dev@189 473
dev@189 474 virtual const char* what() const CATCH_NOEXCEPT;
dev@189 475
dev@189 476 private:
dev@189 477 std::string m_what;
dev@189 478 SourceLineInfo m_lineInfo;
dev@189 479 };
dev@189 480
dev@189 481 } // end namespace Catch
dev@189 482
dev@189 483 ///////////////////////////////////////////////////////////////////////////////
dev@189 484 #define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
dev@189 485
dev@189 486 // #included from: internal/catch_context.h
dev@189 487 #define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
dev@189 488
dev@189 489 // #included from: catch_interfaces_generators.h
dev@189 490 #define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
dev@189 491
dev@189 492 #include <string>
dev@189 493
dev@189 494 namespace Catch {
dev@189 495
dev@189 496 struct IGeneratorInfo {
dev@189 497 virtual ~IGeneratorInfo();
dev@189 498 virtual bool moveNext() = 0;
dev@189 499 virtual std::size_t getCurrentIndex() const = 0;
dev@189 500 };
dev@189 501
dev@189 502 struct IGeneratorsForTest {
dev@189 503 virtual ~IGeneratorsForTest();
dev@189 504
dev@189 505 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
dev@189 506 virtual bool moveNext() = 0;
dev@189 507 };
dev@189 508
dev@189 509 IGeneratorsForTest* createGeneratorsForTest();
dev@189 510
dev@189 511 } // end namespace Catch
dev@189 512
dev@189 513 // #included from: catch_ptr.hpp
dev@189 514 #define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
dev@189 515
dev@189 516 #ifdef __clang__
dev@189 517 #pragma clang diagnostic push
dev@189 518 #pragma clang diagnostic ignored "-Wpadded"
dev@189 519 #endif
dev@189 520
dev@189 521 namespace Catch {
dev@189 522
dev@189 523 // An intrusive reference counting smart pointer.
dev@189 524 // T must implement addRef() and release() methods
dev@189 525 // typically implementing the IShared interface
dev@189 526 template<typename T>
dev@189 527 class Ptr {
dev@189 528 public:
dev@189 529 Ptr() : m_p( CATCH_NULL ){}
dev@189 530 Ptr( T* p ) : m_p( p ){
dev@189 531 if( m_p )
dev@189 532 m_p->addRef();
dev@189 533 }
dev@189 534 Ptr( Ptr const& other ) : m_p( other.m_p ){
dev@189 535 if( m_p )
dev@189 536 m_p->addRef();
dev@189 537 }
dev@189 538 ~Ptr(){
dev@189 539 if( m_p )
dev@189 540 m_p->release();
dev@189 541 }
dev@189 542 void reset() {
dev@189 543 if( m_p )
dev@189 544 m_p->release();
dev@189 545 m_p = CATCH_NULL;
dev@189 546 }
dev@189 547 Ptr& operator = ( T* p ){
dev@189 548 Ptr temp( p );
dev@189 549 swap( temp );
dev@189 550 return *this;
dev@189 551 }
dev@189 552 Ptr& operator = ( Ptr const& other ){
dev@189 553 Ptr temp( other );
dev@189 554 swap( temp );
dev@189 555 return *this;
dev@189 556 }
dev@189 557 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
dev@189 558 T* get() const{ return m_p; }
dev@189 559 T& operator*() const { return *m_p; }
dev@189 560 T* operator->() const { return m_p; }
dev@189 561 bool operator !() const { return m_p == CATCH_NULL; }
dev@189 562 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
dev@189 563
dev@189 564 private:
dev@189 565 T* m_p;
dev@189 566 };
dev@189 567
dev@189 568 struct IShared : NonCopyable {
dev@189 569 virtual ~IShared();
dev@189 570 virtual void addRef() const = 0;
dev@189 571 virtual void release() const = 0;
dev@189 572 };
dev@189 573
dev@189 574 template<typename T = IShared>
dev@189 575 struct SharedImpl : T {
dev@189 576
dev@189 577 SharedImpl() : m_rc( 0 ){}
dev@189 578
dev@189 579 virtual void addRef() const {
dev@189 580 ++m_rc;
dev@189 581 }
dev@189 582 virtual void release() const {
dev@189 583 if( --m_rc == 0 )
dev@189 584 delete this;
dev@189 585 }
dev@189 586
dev@189 587 mutable unsigned int m_rc;
dev@189 588 };
dev@189 589
dev@189 590 } // end namespace Catch
dev@189 591
dev@189 592 #ifdef __clang__
dev@189 593 #pragma clang diagnostic pop
dev@189 594 #endif
dev@189 595
dev@189 596 #include <memory>
dev@189 597 #include <vector>
dev@189 598 #include <stdlib.h>
dev@189 599
dev@189 600 namespace Catch {
dev@189 601
dev@189 602 class TestCase;
dev@189 603 class Stream;
dev@189 604 struct IResultCapture;
dev@189 605 struct IRunner;
dev@189 606 struct IGeneratorsForTest;
dev@189 607 struct IConfig;
dev@189 608
dev@189 609 struct IContext
dev@189 610 {
dev@189 611 virtual ~IContext();
dev@189 612
dev@189 613 virtual IResultCapture* getResultCapture() = 0;
dev@189 614 virtual IRunner* getRunner() = 0;
dev@189 615 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
dev@189 616 virtual bool advanceGeneratorsForCurrentTest() = 0;
dev@189 617 virtual Ptr<IConfig const> getConfig() const = 0;
dev@189 618 };
dev@189 619
dev@189 620 struct IMutableContext : IContext
dev@189 621 {
dev@189 622 virtual ~IMutableContext();
dev@189 623 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
dev@189 624 virtual void setRunner( IRunner* runner ) = 0;
dev@189 625 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
dev@189 626 };
dev@189 627
dev@189 628 IContext& getCurrentContext();
dev@189 629 IMutableContext& getCurrentMutableContext();
dev@189 630 void cleanUpContext();
dev@189 631 Stream createStream( std::string const& streamName );
dev@189 632
dev@189 633 }
dev@189 634
dev@189 635 // #included from: internal/catch_test_registry.hpp
dev@189 636 #define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
dev@189 637
dev@189 638 // #included from: catch_interfaces_testcase.h
dev@189 639 #define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
dev@189 640
dev@189 641 #include <vector>
dev@189 642
dev@189 643 namespace Catch {
dev@189 644
dev@189 645 class TestSpec;
dev@189 646
dev@189 647 struct ITestCase : IShared {
dev@189 648 virtual void invoke () const = 0;
dev@189 649 protected:
dev@189 650 virtual ~ITestCase();
dev@189 651 };
dev@189 652
dev@189 653 class TestCase;
dev@189 654 struct IConfig;
dev@189 655
dev@189 656 struct ITestCaseRegistry {
dev@189 657 virtual ~ITestCaseRegistry();
dev@189 658 virtual std::vector<TestCase> const& getAllTests() const = 0;
dev@189 659 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
dev@189 660 };
dev@189 661
dev@189 662 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
dev@189 663 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
dev@189 664 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
dev@189 665
dev@189 666 }
dev@189 667
dev@189 668 namespace Catch {
dev@189 669
dev@189 670 template<typename C>
dev@189 671 class MethodTestCase : public SharedImpl<ITestCase> {
dev@189 672
dev@189 673 public:
dev@189 674 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
dev@189 675
dev@189 676 virtual void invoke() const {
dev@189 677 C obj;
dev@189 678 (obj.*m_method)();
dev@189 679 }
dev@189 680
dev@189 681 private:
dev@189 682 virtual ~MethodTestCase() {}
dev@189 683
dev@189 684 void (C::*m_method)();
dev@189 685 };
dev@189 686
dev@189 687 typedef void(*TestFunction)();
dev@189 688
dev@189 689 struct NameAndDesc {
dev@189 690 NameAndDesc( const char* _name = "", const char* _description= "" )
dev@189 691 : name( _name ), description( _description )
dev@189 692 {}
dev@189 693
dev@189 694 const char* name;
dev@189 695 const char* description;
dev@189 696 };
dev@189 697
dev@189 698 void registerTestCase
dev@189 699 ( ITestCase* testCase,
dev@189 700 char const* className,
dev@189 701 NameAndDesc const& nameAndDesc,
dev@189 702 SourceLineInfo const& lineInfo );
dev@189 703
dev@189 704 struct AutoReg {
dev@189 705
dev@189 706 AutoReg
dev@189 707 ( TestFunction function,
dev@189 708 SourceLineInfo const& lineInfo,
dev@189 709 NameAndDesc const& nameAndDesc );
dev@189 710
dev@189 711 template<typename C>
dev@189 712 AutoReg
dev@189 713 ( void (C::*method)(),
dev@189 714 char const* className,
dev@189 715 NameAndDesc const& nameAndDesc,
dev@189 716 SourceLineInfo const& lineInfo ) {
dev@189 717
dev@189 718 registerTestCase
dev@189 719 ( new MethodTestCase<C>( method ),
dev@189 720 className,
dev@189 721 nameAndDesc,
dev@189 722 lineInfo );
dev@189 723 }
dev@189 724
dev@189 725 ~AutoReg();
dev@189 726
dev@189 727 private:
dev@189 728 AutoReg( AutoReg const& );
dev@189 729 void operator= ( AutoReg const& );
dev@189 730 };
dev@189 731
dev@189 732 void registerTestCaseFunction
dev@189 733 ( TestFunction function,
dev@189 734 SourceLineInfo const& lineInfo,
dev@189 735 NameAndDesc const& nameAndDesc );
dev@189 736
dev@189 737 } // end namespace Catch
dev@189 738
dev@189 739 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 740 ///////////////////////////////////////////////////////////////////////////////
dev@189 741 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
dev@189 742 static void TestName(); \
dev@189 743 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
dev@189 744 static void TestName()
dev@189 745 #define INTERNAL_CATCH_TESTCASE( ... ) \
dev@189 746 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
dev@189 747
dev@189 748 ///////////////////////////////////////////////////////////////////////////////
dev@189 749 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
dev@189 750 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
dev@189 751
dev@189 752 ///////////////////////////////////////////////////////////////////////////////
dev@189 753 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
dev@189 754 namespace{ \
dev@189 755 struct TestName : ClassName{ \
dev@189 756 void test(); \
dev@189 757 }; \
dev@189 758 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
dev@189 759 } \
dev@189 760 void TestName::test()
dev@189 761 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
dev@189 762 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
dev@189 763
dev@189 764 ///////////////////////////////////////////////////////////////////////////////
dev@189 765 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
dev@189 766 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
dev@189 767
dev@189 768 #else
dev@189 769 ///////////////////////////////////////////////////////////////////////////////
dev@189 770 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
dev@189 771 static void TestName(); \
dev@189 772 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
dev@189 773 static void TestName()
dev@189 774 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
dev@189 775 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
dev@189 776
dev@189 777 ///////////////////////////////////////////////////////////////////////////////
dev@189 778 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
dev@189 779 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
dev@189 780
dev@189 781 ///////////////////////////////////////////////////////////////////////////////
dev@189 782 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
dev@189 783 namespace{ \
dev@189 784 struct TestCaseName : ClassName{ \
dev@189 785 void test(); \
dev@189 786 }; \
dev@189 787 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
dev@189 788 } \
dev@189 789 void TestCaseName::test()
dev@189 790 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
dev@189 791 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
dev@189 792
dev@189 793 ///////////////////////////////////////////////////////////////////////////////
dev@189 794 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
dev@189 795 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
dev@189 796 #endif
dev@189 797
dev@189 798 // #included from: internal/catch_capture.hpp
dev@189 799 #define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
dev@189 800
dev@189 801 // #included from: catch_result_builder.h
dev@189 802 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
dev@189 803
dev@189 804 // #included from: catch_result_type.h
dev@189 805 #define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
dev@189 806
dev@189 807 namespace Catch {
dev@189 808
dev@189 809 // ResultWas::OfType enum
dev@189 810 struct ResultWas { enum OfType {
dev@189 811 Unknown = -1,
dev@189 812 Ok = 0,
dev@189 813 Info = 1,
dev@189 814 Warning = 2,
dev@189 815
dev@189 816 FailureBit = 0x10,
dev@189 817
dev@189 818 ExpressionFailed = FailureBit | 1,
dev@189 819 ExplicitFailure = FailureBit | 2,
dev@189 820
dev@189 821 Exception = 0x100 | FailureBit,
dev@189 822
dev@189 823 ThrewException = Exception | 1,
dev@189 824 DidntThrowException = Exception | 2,
dev@189 825
dev@189 826 FatalErrorCondition = 0x200 | FailureBit
dev@189 827
dev@189 828 }; };
dev@189 829
dev@189 830 inline bool isOk( ResultWas::OfType resultType ) {
dev@189 831 return ( resultType & ResultWas::FailureBit ) == 0;
dev@189 832 }
dev@189 833 inline bool isJustInfo( int flags ) {
dev@189 834 return flags == ResultWas::Info;
dev@189 835 }
dev@189 836
dev@189 837 // ResultDisposition::Flags enum
dev@189 838 struct ResultDisposition { enum Flags {
dev@189 839 Normal = 0x01,
dev@189 840
dev@189 841 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
dev@189 842 FalseTest = 0x04, // Prefix expression with !
dev@189 843 SuppressFail = 0x08 // Failures are reported but do not fail the test
dev@189 844 }; };
dev@189 845
dev@189 846 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
dev@189 847 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
dev@189 848 }
dev@189 849
dev@189 850 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
dev@189 851 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
dev@189 852 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
dev@189 853
dev@189 854 } // end namespace Catch
dev@189 855
dev@189 856 // #included from: catch_assertionresult.h
dev@189 857 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
dev@189 858
dev@189 859 #include <string>
dev@189 860
dev@189 861 namespace Catch {
dev@189 862
dev@189 863 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
dev@189 864
dev@189 865 struct DecomposedExpression
dev@189 866 {
dev@189 867 virtual ~DecomposedExpression() {}
dev@189 868 virtual bool isBinaryExpression() const {
dev@189 869 return false;
dev@189 870 }
dev@189 871 virtual void reconstructExpression( std::string& dest ) const = 0;
dev@189 872
dev@189 873 // Only simple binary comparisons can be decomposed.
dev@189 874 // If more complex check is required then wrap sub-expressions in parentheses.
dev@189 875 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
dev@189 876 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
dev@189 877 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
dev@189 878 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
dev@189 879 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
dev@189 880 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
dev@189 881 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
dev@189 882 };
dev@189 883
dev@189 884 struct AssertionInfo
dev@189 885 {
dev@189 886 AssertionInfo() {}
dev@189 887 AssertionInfo( std::string const& _macroName,
dev@189 888 SourceLineInfo const& _lineInfo,
dev@189 889 std::string const& _capturedExpression,
dev@189 890 ResultDisposition::Flags _resultDisposition );
dev@189 891
dev@189 892 std::string macroName;
dev@189 893 SourceLineInfo lineInfo;
dev@189 894 std::string capturedExpression;
dev@189 895 ResultDisposition::Flags resultDisposition;
dev@189 896 };
dev@189 897
dev@189 898 struct AssertionResultData
dev@189 899 {
dev@189 900 AssertionResultData() : decomposedExpression( CATCH_NULL )
dev@189 901 , resultType( ResultWas::Unknown )
dev@189 902 , negated( false )
dev@189 903 , parenthesized( false ) {}
dev@189 904
dev@189 905 void negate( bool parenthesize ) {
dev@189 906 negated = !negated;
dev@189 907 parenthesized = parenthesize;
dev@189 908 if( resultType == ResultWas::Ok )
dev@189 909 resultType = ResultWas::ExpressionFailed;
dev@189 910 else if( resultType == ResultWas::ExpressionFailed )
dev@189 911 resultType = ResultWas::Ok;
dev@189 912 }
dev@189 913
dev@189 914 std::string const& reconstructExpression() const {
dev@189 915 if( decomposedExpression != CATCH_NULL ) {
dev@189 916 decomposedExpression->reconstructExpression( reconstructedExpression );
dev@189 917 if( parenthesized ) {
dev@189 918 reconstructedExpression.insert( 0, 1, '(' );
dev@189 919 reconstructedExpression.append( 1, ')' );
dev@189 920 }
dev@189 921 if( negated ) {
dev@189 922 reconstructedExpression.insert( 0, 1, '!' );
dev@189 923 }
dev@189 924 decomposedExpression = CATCH_NULL;
dev@189 925 }
dev@189 926 return reconstructedExpression;
dev@189 927 }
dev@189 928
dev@189 929 mutable DecomposedExpression const* decomposedExpression;
dev@189 930 mutable std::string reconstructedExpression;
dev@189 931 std::string message;
dev@189 932 ResultWas::OfType resultType;
dev@189 933 bool negated;
dev@189 934 bool parenthesized;
dev@189 935 };
dev@189 936
dev@189 937 class AssertionResult {
dev@189 938 public:
dev@189 939 AssertionResult();
dev@189 940 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
dev@189 941 ~AssertionResult();
dev@189 942 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 943 AssertionResult( AssertionResult const& ) = default;
dev@189 944 AssertionResult( AssertionResult && ) = default;
dev@189 945 AssertionResult& operator = ( AssertionResult const& ) = default;
dev@189 946 AssertionResult& operator = ( AssertionResult && ) = default;
dev@189 947 # endif
dev@189 948
dev@189 949 bool isOk() const;
dev@189 950 bool succeeded() const;
dev@189 951 ResultWas::OfType getResultType() const;
dev@189 952 bool hasExpression() const;
dev@189 953 bool hasMessage() const;
dev@189 954 std::string getExpression() const;
dev@189 955 std::string getExpressionInMacro() const;
dev@189 956 bool hasExpandedExpression() const;
dev@189 957 std::string getExpandedExpression() const;
dev@189 958 std::string getMessage() const;
dev@189 959 SourceLineInfo getSourceInfo() const;
dev@189 960 std::string getTestMacroName() const;
dev@189 961 void discardDecomposedExpression() const;
dev@189 962 void expandDecomposedExpression() const;
dev@189 963
dev@189 964 protected:
dev@189 965 AssertionInfo m_info;
dev@189 966 AssertionResultData m_resultData;
dev@189 967 };
dev@189 968
dev@189 969 } // end namespace Catch
dev@189 970
dev@189 971 // #included from: catch_matchers.hpp
dev@189 972 #define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
dev@189 973
dev@189 974 namespace Catch {
dev@189 975 namespace Matchers {
dev@189 976 namespace Impl {
dev@189 977
dev@189 978 namespace Generic {
dev@189 979 template<typename ExpressionT> class AllOf;
dev@189 980 template<typename ExpressionT> class AnyOf;
dev@189 981 template<typename ExpressionT> class Not;
dev@189 982 }
dev@189 983
dev@189 984 template<typename ExpressionT>
dev@189 985 struct Matcher : SharedImpl<IShared>
dev@189 986 {
dev@189 987 typedef ExpressionT ExpressionType;
dev@189 988
dev@189 989 virtual ~Matcher() {}
dev@189 990 virtual Ptr<Matcher> clone() const = 0;
dev@189 991 virtual bool match( ExpressionT const& expr ) const = 0;
dev@189 992 virtual std::string toString() const = 0;
dev@189 993
dev@189 994 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
dev@189 995 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
dev@189 996 Generic::Not<ExpressionT> operator ! () const;
dev@189 997 };
dev@189 998
dev@189 999 template<typename DerivedT, typename ExpressionT>
dev@189 1000 struct MatcherImpl : Matcher<ExpressionT> {
dev@189 1001
dev@189 1002 virtual Ptr<Matcher<ExpressionT> > clone() const {
dev@189 1003 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
dev@189 1004 }
dev@189 1005 };
dev@189 1006
dev@189 1007 namespace Generic {
dev@189 1008 template<typename ExpressionT>
dev@189 1009 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
dev@189 1010 public:
dev@189 1011 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
dev@189 1012 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
dev@189 1013
dev@189 1014 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
dev@189 1015 return !m_matcher->match( expr );
dev@189 1016 }
dev@189 1017
dev@189 1018 virtual std::string toString() const CATCH_OVERRIDE {
dev@189 1019 return "not " + m_matcher->toString();
dev@189 1020 }
dev@189 1021 private:
dev@189 1022 Ptr< Matcher<ExpressionT> > m_matcher;
dev@189 1023 };
dev@189 1024
dev@189 1025 template<typename ExpressionT>
dev@189 1026 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
dev@189 1027 public:
dev@189 1028
dev@189 1029 AllOf() {}
dev@189 1030 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
dev@189 1031
dev@189 1032 AllOf& add( Matcher<ExpressionT> const& matcher ) {
dev@189 1033 m_matchers.push_back( matcher.clone() );
dev@189 1034 return *this;
dev@189 1035 }
dev@189 1036 virtual bool match( ExpressionT const& expr ) const
dev@189 1037 {
dev@189 1038 for( std::size_t i = 0; i < m_matchers.size(); ++i )
dev@189 1039 if( !m_matchers[i]->match( expr ) )
dev@189 1040 return false;
dev@189 1041 return true;
dev@189 1042 }
dev@189 1043 virtual std::string toString() const {
dev@189 1044 std::ostringstream oss;
dev@189 1045 oss << "( ";
dev@189 1046 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
dev@189 1047 if( i != 0 )
dev@189 1048 oss << " and ";
dev@189 1049 oss << m_matchers[i]->toString();
dev@189 1050 }
dev@189 1051 oss << " )";
dev@189 1052 return oss.str();
dev@189 1053 }
dev@189 1054
dev@189 1055 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
dev@189 1056 AllOf allOfExpr( *this );
dev@189 1057 allOfExpr.add( other );
dev@189 1058 return allOfExpr;
dev@189 1059 }
dev@189 1060
dev@189 1061 private:
dev@189 1062 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
dev@189 1063 };
dev@189 1064
dev@189 1065 template<typename ExpressionT>
dev@189 1066 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
dev@189 1067 public:
dev@189 1068
dev@189 1069 AnyOf() {}
dev@189 1070 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
dev@189 1071
dev@189 1072 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
dev@189 1073 m_matchers.push_back( matcher.clone() );
dev@189 1074 return *this;
dev@189 1075 }
dev@189 1076 virtual bool match( ExpressionT const& expr ) const
dev@189 1077 {
dev@189 1078 for( std::size_t i = 0; i < m_matchers.size(); ++i )
dev@189 1079 if( m_matchers[i]->match( expr ) )
dev@189 1080 return true;
dev@189 1081 return false;
dev@189 1082 }
dev@189 1083 virtual std::string toString() const {
dev@189 1084 std::ostringstream oss;
dev@189 1085 oss << "( ";
dev@189 1086 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
dev@189 1087 if( i != 0 )
dev@189 1088 oss << " or ";
dev@189 1089 oss << m_matchers[i]->toString();
dev@189 1090 }
dev@189 1091 oss << " )";
dev@189 1092 return oss.str();
dev@189 1093 }
dev@189 1094
dev@189 1095 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
dev@189 1096 AnyOf anyOfExpr( *this );
dev@189 1097 anyOfExpr.add( other );
dev@189 1098 return anyOfExpr;
dev@189 1099 }
dev@189 1100
dev@189 1101 private:
dev@189 1102 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
dev@189 1103 };
dev@189 1104
dev@189 1105 } // namespace Generic
dev@189 1106
dev@189 1107 template<typename ExpressionT>
dev@189 1108 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
dev@189 1109 Generic::AllOf<ExpressionT> allOfExpr;
dev@189 1110 allOfExpr.add( *this );
dev@189 1111 allOfExpr.add( other );
dev@189 1112 return allOfExpr;
dev@189 1113 }
dev@189 1114
dev@189 1115 template<typename ExpressionT>
dev@189 1116 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
dev@189 1117 Generic::AnyOf<ExpressionT> anyOfExpr;
dev@189 1118 anyOfExpr.add( *this );
dev@189 1119 anyOfExpr.add( other );
dev@189 1120 return anyOfExpr;
dev@189 1121 }
dev@189 1122
dev@189 1123 template<typename ExpressionT>
dev@189 1124 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
dev@189 1125 return Generic::Not<ExpressionT>( *this );
dev@189 1126 }
dev@189 1127
dev@189 1128 namespace StdString {
dev@189 1129
dev@189 1130 inline std::string makeString( std::string const& str ) { return str; }
dev@189 1131 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
dev@189 1132
dev@189 1133 struct CasedString
dev@189 1134 {
dev@189 1135 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
dev@189 1136 : m_caseSensitivity( caseSensitivity ),
dev@189 1137 m_str( adjustString( str ) )
dev@189 1138 {}
dev@189 1139 std::string adjustString( std::string const& str ) const {
dev@189 1140 return m_caseSensitivity == CaseSensitive::No
dev@189 1141 ? toLower( str )
dev@189 1142 : str;
dev@189 1143
dev@189 1144 }
dev@189 1145 std::string toStringSuffix() const
dev@189 1146 {
dev@189 1147 return m_caseSensitivity == CaseSensitive::No
dev@189 1148 ? " (case insensitive)"
dev@189 1149 : std::string();
dev@189 1150 }
dev@189 1151 CaseSensitive::Choice m_caseSensitivity;
dev@189 1152 std::string m_str;
dev@189 1153 };
dev@189 1154
dev@189 1155 struct Equals : MatcherImpl<Equals, std::string> {
dev@189 1156 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
dev@189 1157 : m_data( str, caseSensitivity )
dev@189 1158 {}
dev@189 1159 Equals( Equals const& other ) : m_data( other.m_data ){}
dev@189 1160
dev@189 1161 virtual ~Equals();
dev@189 1162
dev@189 1163 virtual bool match( std::string const& expr ) const {
dev@189 1164 return m_data.m_str == m_data.adjustString( expr );;
dev@189 1165 }
dev@189 1166 virtual std::string toString() const {
dev@189 1167 return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
dev@189 1168 }
dev@189 1169
dev@189 1170 CasedString m_data;
dev@189 1171 };
dev@189 1172
dev@189 1173 struct Contains : MatcherImpl<Contains, std::string> {
dev@189 1174 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
dev@189 1175 : m_data( substr, caseSensitivity ){}
dev@189 1176 Contains( Contains const& other ) : m_data( other.m_data ){}
dev@189 1177
dev@189 1178 virtual ~Contains();
dev@189 1179
dev@189 1180 virtual bool match( std::string const& expr ) const {
dev@189 1181 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
dev@189 1182 }
dev@189 1183 virtual std::string toString() const {
dev@189 1184 return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
dev@189 1185 }
dev@189 1186
dev@189 1187 CasedString m_data;
dev@189 1188 };
dev@189 1189
dev@189 1190 struct StartsWith : MatcherImpl<StartsWith, std::string> {
dev@189 1191 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
dev@189 1192 : m_data( substr, caseSensitivity ){}
dev@189 1193
dev@189 1194 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
dev@189 1195
dev@189 1196 virtual ~StartsWith();
dev@189 1197
dev@189 1198 virtual bool match( std::string const& expr ) const {
dev@189 1199 return startsWith( m_data.adjustString( expr ), m_data.m_str );
dev@189 1200 }
dev@189 1201 virtual std::string toString() const {
dev@189 1202 return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
dev@189 1203 }
dev@189 1204
dev@189 1205 CasedString m_data;
dev@189 1206 };
dev@189 1207
dev@189 1208 struct EndsWith : MatcherImpl<EndsWith, std::string> {
dev@189 1209 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
dev@189 1210 : m_data( substr, caseSensitivity ){}
dev@189 1211 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
dev@189 1212
dev@189 1213 virtual ~EndsWith();
dev@189 1214
dev@189 1215 virtual bool match( std::string const& expr ) const {
dev@189 1216 return endsWith( m_data.adjustString( expr ), m_data.m_str );
dev@189 1217 }
dev@189 1218 virtual std::string toString() const {
dev@189 1219 return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
dev@189 1220 }
dev@189 1221
dev@189 1222 CasedString m_data;
dev@189 1223 };
dev@189 1224 } // namespace StdString
dev@189 1225 } // namespace Impl
dev@189 1226
dev@189 1227 // The following functions create the actual matcher objects.
dev@189 1228 // This allows the types to be inferred
dev@189 1229 template<typename ExpressionT>
dev@189 1230 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
dev@189 1231 return Impl::Generic::Not<ExpressionT>( m );
dev@189 1232 }
dev@189 1233
dev@189 1234 template<typename ExpressionT>
dev@189 1235 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
dev@189 1236 Impl::Matcher<ExpressionT> const& m2 ) {
dev@189 1237 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
dev@189 1238 }
dev@189 1239 template<typename ExpressionT>
dev@189 1240 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
dev@189 1241 Impl::Matcher<ExpressionT> const& m2,
dev@189 1242 Impl::Matcher<ExpressionT> const& m3 ) {
dev@189 1243 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
dev@189 1244 }
dev@189 1245 template<typename ExpressionT>
dev@189 1246 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
dev@189 1247 Impl::Matcher<ExpressionT> const& m2 ) {
dev@189 1248 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
dev@189 1249 }
dev@189 1250 template<typename ExpressionT>
dev@189 1251 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
dev@189 1252 Impl::Matcher<ExpressionT> const& m2,
dev@189 1253 Impl::Matcher<ExpressionT> const& m3 ) {
dev@189 1254 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
dev@189 1255 }
dev@189 1256
dev@189 1257 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
dev@189 1258 return Impl::StdString::Equals( str, caseSensitivity );
dev@189 1259 }
dev@189 1260 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
dev@189 1261 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
dev@189 1262 }
dev@189 1263 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
dev@189 1264 return Impl::StdString::Contains( substr, caseSensitivity );
dev@189 1265 }
dev@189 1266 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
dev@189 1267 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
dev@189 1268 }
dev@189 1269 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
dev@189 1270 return Impl::StdString::StartsWith( substr );
dev@189 1271 }
dev@189 1272 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
dev@189 1273 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
dev@189 1274 }
dev@189 1275 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
dev@189 1276 return Impl::StdString::EndsWith( substr );
dev@189 1277 }
dev@189 1278 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
dev@189 1279 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
dev@189 1280 }
dev@189 1281
dev@189 1282 } // namespace Matchers
dev@189 1283
dev@189 1284 using namespace Matchers;
dev@189 1285
dev@189 1286 } // namespace Catch
dev@189 1287
dev@189 1288 namespace Catch {
dev@189 1289
dev@189 1290 struct TestFailureException{};
dev@189 1291
dev@189 1292 template<typename T> class ExpressionLhs;
dev@189 1293
dev@189 1294 struct CopyableStream {
dev@189 1295 CopyableStream() {}
dev@189 1296 CopyableStream( CopyableStream const& other ) {
dev@189 1297 oss << other.oss.str();
dev@189 1298 }
dev@189 1299 CopyableStream& operator=( CopyableStream const& other ) {
dev@189 1300 oss.str(std::string());
dev@189 1301 oss << other.oss.str();
dev@189 1302 return *this;
dev@189 1303 }
dev@189 1304 std::ostringstream oss;
dev@189 1305 };
dev@189 1306
dev@189 1307 class ResultBuilder : public DecomposedExpression {
dev@189 1308 public:
dev@189 1309 ResultBuilder( char const* macroName,
dev@189 1310 SourceLineInfo const& lineInfo,
dev@189 1311 char const* capturedExpression,
dev@189 1312 ResultDisposition::Flags resultDisposition,
dev@189 1313 char const* secondArg = "" );
dev@189 1314
dev@189 1315 template<typename T>
dev@189 1316 ExpressionLhs<T const&> operator <= ( T const& operand );
dev@189 1317 ExpressionLhs<bool> operator <= ( bool value );
dev@189 1318
dev@189 1319 template<typename T>
dev@189 1320 ResultBuilder& operator << ( T const& value ) {
dev@189 1321 m_stream.oss << value;
dev@189 1322 return *this;
dev@189 1323 }
dev@189 1324
dev@189 1325 ResultBuilder& setResultType( ResultWas::OfType result );
dev@189 1326 ResultBuilder& setResultType( bool result );
dev@189 1327
dev@189 1328 void endExpression( DecomposedExpression const& expr );
dev@189 1329
dev@189 1330 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
dev@189 1331
dev@189 1332 AssertionResult build() const;
dev@189 1333 AssertionResult build( DecomposedExpression const& expr ) const;
dev@189 1334
dev@189 1335 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
dev@189 1336 void captureResult( ResultWas::OfType resultType );
dev@189 1337 void captureExpression();
dev@189 1338 void captureExpectedException( std::string const& expectedMessage );
dev@189 1339 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
dev@189 1340 void handleResult( AssertionResult const& result );
dev@189 1341 void react();
dev@189 1342 bool shouldDebugBreak() const;
dev@189 1343 bool allowThrows() const;
dev@189 1344
dev@189 1345 template<typename ArgT, typename MatcherT>
dev@189 1346 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
dev@189 1347
dev@189 1348 private:
dev@189 1349 AssertionInfo m_assertionInfo;
dev@189 1350 AssertionResultData m_data;
dev@189 1351 CopyableStream m_stream;
dev@189 1352
dev@189 1353 bool m_shouldDebugBreak;
dev@189 1354 bool m_shouldThrow;
dev@189 1355 };
dev@189 1356
dev@189 1357 } // namespace Catch
dev@189 1358
dev@189 1359 // Include after due to circular dependency:
dev@189 1360 // #included from: catch_expression_lhs.hpp
dev@189 1361 #define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
dev@189 1362
dev@189 1363 // #included from: catch_evaluate.hpp
dev@189 1364 #define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
dev@189 1365
dev@189 1366 #ifdef _MSC_VER
dev@189 1367 #pragma warning(push)
dev@189 1368 #pragma warning(disable:4389) // '==' : signed/unsigned mismatch
dev@189 1369 #endif
dev@189 1370
dev@189 1371 #include <cstddef>
dev@189 1372
dev@189 1373 namespace Catch {
dev@189 1374 namespace Internal {
dev@189 1375
dev@189 1376 enum Operator {
dev@189 1377 IsEqualTo,
dev@189 1378 IsNotEqualTo,
dev@189 1379 IsLessThan,
dev@189 1380 IsGreaterThan,
dev@189 1381 IsLessThanOrEqualTo,
dev@189 1382 IsGreaterThanOrEqualTo
dev@189 1383 };
dev@189 1384
dev@189 1385 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
dev@189 1386 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
dev@189 1387 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
dev@189 1388 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
dev@189 1389 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
dev@189 1390 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
dev@189 1391 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
dev@189 1392
dev@189 1393 template<typename T>
dev@189 1394 inline T& opCast(T const& t) { return const_cast<T&>(t); }
dev@189 1395
dev@189 1396 // nullptr_t support based on pull request #154 from Konstantin Baumann
dev@189 1397 #ifdef CATCH_CONFIG_CPP11_NULLPTR
dev@189 1398 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
dev@189 1399 #endif // CATCH_CONFIG_CPP11_NULLPTR
dev@189 1400
dev@189 1401 // So the compare overloads can be operator agnostic we convey the operator as a template
dev@189 1402 // enum, which is used to specialise an Evaluator for doing the comparison.
dev@189 1403 template<typename T1, typename T2, Operator Op>
dev@189 1404 class Evaluator{};
dev@189 1405
dev@189 1406 template<typename T1, typename T2>
dev@189 1407 struct Evaluator<T1, T2, IsEqualTo> {
dev@189 1408 static bool evaluate( T1 const& lhs, T2 const& rhs) {
dev@189 1409 return bool( opCast( lhs ) == opCast( rhs ) );
dev@189 1410 }
dev@189 1411 };
dev@189 1412 template<typename T1, typename T2>
dev@189 1413 struct Evaluator<T1, T2, IsNotEqualTo> {
dev@189 1414 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
dev@189 1415 return bool( opCast( lhs ) != opCast( rhs ) );
dev@189 1416 }
dev@189 1417 };
dev@189 1418 template<typename T1, typename T2>
dev@189 1419 struct Evaluator<T1, T2, IsLessThan> {
dev@189 1420 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
dev@189 1421 return bool( opCast( lhs ) < opCast( rhs ) );
dev@189 1422 }
dev@189 1423 };
dev@189 1424 template<typename T1, typename T2>
dev@189 1425 struct Evaluator<T1, T2, IsGreaterThan> {
dev@189 1426 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
dev@189 1427 return bool( opCast( lhs ) > opCast( rhs ) );
dev@189 1428 }
dev@189 1429 };
dev@189 1430 template<typename T1, typename T2>
dev@189 1431 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
dev@189 1432 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
dev@189 1433 return bool( opCast( lhs ) >= opCast( rhs ) );
dev@189 1434 }
dev@189 1435 };
dev@189 1436 template<typename T1, typename T2>
dev@189 1437 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
dev@189 1438 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
dev@189 1439 return bool( opCast( lhs ) <= opCast( rhs ) );
dev@189 1440 }
dev@189 1441 };
dev@189 1442
dev@189 1443 template<Operator Op, typename T1, typename T2>
dev@189 1444 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
dev@189 1445 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
dev@189 1446 }
dev@189 1447
dev@189 1448 // This level of indirection allows us to specialise for integer types
dev@189 1449 // to avoid signed/ unsigned warnings
dev@189 1450
dev@189 1451 // "base" overload
dev@189 1452 template<Operator Op, typename T1, typename T2>
dev@189 1453 bool compare( T1 const& lhs, T2 const& rhs ) {
dev@189 1454 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
dev@189 1455 }
dev@189 1456
dev@189 1457 // unsigned X to int
dev@189 1458 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
dev@189 1459 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
dev@189 1460 }
dev@189 1461 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
dev@189 1462 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
dev@189 1463 }
dev@189 1464 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
dev@189 1465 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
dev@189 1466 }
dev@189 1467
dev@189 1468 // unsigned X to long
dev@189 1469 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
dev@189 1470 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
dev@189 1471 }
dev@189 1472 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
dev@189 1473 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
dev@189 1474 }
dev@189 1475 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
dev@189 1476 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
dev@189 1477 }
dev@189 1478
dev@189 1479 // int to unsigned X
dev@189 1480 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
dev@189 1481 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
dev@189 1482 }
dev@189 1483 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
dev@189 1484 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
dev@189 1485 }
dev@189 1486 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
dev@189 1487 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
dev@189 1488 }
dev@189 1489
dev@189 1490 // long to unsigned X
dev@189 1491 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
dev@189 1492 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1493 }
dev@189 1494 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
dev@189 1495 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1496 }
dev@189 1497 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
dev@189 1498 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1499 }
dev@189 1500
dev@189 1501 // pointer to long (when comparing against NULL)
dev@189 1502 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
dev@189 1503 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
dev@189 1504 }
dev@189 1505 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
dev@189 1506 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
dev@189 1507 }
dev@189 1508
dev@189 1509 // pointer to int (when comparing against NULL)
dev@189 1510 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
dev@189 1511 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
dev@189 1512 }
dev@189 1513 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
dev@189 1514 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
dev@189 1515 }
dev@189 1516
dev@189 1517 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
dev@189 1518 // long long to unsigned X
dev@189 1519 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
dev@189 1520 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1521 }
dev@189 1522 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
dev@189 1523 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1524 }
dev@189 1525 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
dev@189 1526 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1527 }
dev@189 1528 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
dev@189 1529 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
dev@189 1530 }
dev@189 1531
dev@189 1532 // unsigned long long to X
dev@189 1533 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
dev@189 1534 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
dev@189 1535 }
dev@189 1536 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
dev@189 1537 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
dev@189 1538 }
dev@189 1539 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
dev@189 1540 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
dev@189 1541 }
dev@189 1542 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
dev@189 1543 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
dev@189 1544 }
dev@189 1545
dev@189 1546 // pointer to long long (when comparing against NULL)
dev@189 1547 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
dev@189 1548 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
dev@189 1549 }
dev@189 1550 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
dev@189 1551 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
dev@189 1552 }
dev@189 1553 #endif // CATCH_CONFIG_CPP11_LONG_LONG
dev@189 1554
dev@189 1555 #ifdef CATCH_CONFIG_CPP11_NULLPTR
dev@189 1556 // pointer to nullptr_t (when comparing against nullptr)
dev@189 1557 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
dev@189 1558 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
dev@189 1559 }
dev@189 1560 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
dev@189 1561 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
dev@189 1562 }
dev@189 1563 #endif // CATCH_CONFIG_CPP11_NULLPTR
dev@189 1564
dev@189 1565 } // end of namespace Internal
dev@189 1566 } // end of namespace Catch
dev@189 1567
dev@189 1568 #ifdef _MSC_VER
dev@189 1569 #pragma warning(pop)
dev@189 1570 #endif
dev@189 1571
dev@189 1572 // #included from: catch_tostring.h
dev@189 1573 #define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
dev@189 1574
dev@189 1575 #include <sstream>
dev@189 1576 #include <iomanip>
dev@189 1577 #include <limits>
dev@189 1578 #include <vector>
dev@189 1579 #include <cstddef>
dev@189 1580
dev@189 1581 #ifdef __OBJC__
dev@189 1582 // #included from: catch_objc_arc.hpp
dev@189 1583 #define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
dev@189 1584
dev@189 1585 #import <Foundation/Foundation.h>
dev@189 1586
dev@189 1587 #ifdef __has_feature
dev@189 1588 #define CATCH_ARC_ENABLED __has_feature(objc_arc)
dev@189 1589 #else
dev@189 1590 #define CATCH_ARC_ENABLED 0
dev@189 1591 #endif
dev@189 1592
dev@189 1593 void arcSafeRelease( NSObject* obj );
dev@189 1594 id performOptionalSelector( id obj, SEL sel );
dev@189 1595
dev@189 1596 #if !CATCH_ARC_ENABLED
dev@189 1597 inline void arcSafeRelease( NSObject* obj ) {
dev@189 1598 [obj release];
dev@189 1599 }
dev@189 1600 inline id performOptionalSelector( id obj, SEL sel ) {
dev@189 1601 if( [obj respondsToSelector: sel] )
dev@189 1602 return [obj performSelector: sel];
dev@189 1603 return nil;
dev@189 1604 }
dev@189 1605 #define CATCH_UNSAFE_UNRETAINED
dev@189 1606 #define CATCH_ARC_STRONG
dev@189 1607 #else
dev@189 1608 inline void arcSafeRelease( NSObject* ){}
dev@189 1609 inline id performOptionalSelector( id obj, SEL sel ) {
dev@189 1610 #ifdef __clang__
dev@189 1611 #pragma clang diagnostic push
dev@189 1612 #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
dev@189 1613 #endif
dev@189 1614 if( [obj respondsToSelector: sel] )
dev@189 1615 return [obj performSelector: sel];
dev@189 1616 #ifdef __clang__
dev@189 1617 #pragma clang diagnostic pop
dev@189 1618 #endif
dev@189 1619 return nil;
dev@189 1620 }
dev@189 1621 #define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
dev@189 1622 #define CATCH_ARC_STRONG __strong
dev@189 1623 #endif
dev@189 1624
dev@189 1625 #endif
dev@189 1626
dev@189 1627 #ifdef CATCH_CONFIG_CPP11_TUPLE
dev@189 1628 #include <tuple>
dev@189 1629 #endif
dev@189 1630
dev@189 1631 #ifdef CATCH_CONFIG_CPP11_IS_ENUM
dev@189 1632 #include <type_traits>
dev@189 1633 #endif
dev@189 1634
dev@189 1635 namespace Catch {
dev@189 1636
dev@189 1637 // Why we're here.
dev@189 1638 template<typename T>
dev@189 1639 std::string toString( T const& value );
dev@189 1640
dev@189 1641 // Built in overloads
dev@189 1642
dev@189 1643 std::string toString( std::string const& value );
dev@189 1644 std::string toString( std::wstring const& value );
dev@189 1645 std::string toString( const char* const value );
dev@189 1646 std::string toString( char* const value );
dev@189 1647 std::string toString( const wchar_t* const value );
dev@189 1648 std::string toString( wchar_t* const value );
dev@189 1649 std::string toString( int value );
dev@189 1650 std::string toString( unsigned long value );
dev@189 1651 std::string toString( unsigned int value );
dev@189 1652 std::string toString( const double value );
dev@189 1653 std::string toString( const float value );
dev@189 1654 std::string toString( bool value );
dev@189 1655 std::string toString( char value );
dev@189 1656 std::string toString( signed char value );
dev@189 1657 std::string toString( unsigned char value );
dev@189 1658
dev@189 1659 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
dev@189 1660 std::string toString( long long value );
dev@189 1661 std::string toString( unsigned long long value );
dev@189 1662 #endif
dev@189 1663
dev@189 1664 #ifdef CATCH_CONFIG_CPP11_NULLPTR
dev@189 1665 std::string toString( std::nullptr_t );
dev@189 1666 #endif
dev@189 1667
dev@189 1668 #ifdef __OBJC__
dev@189 1669 std::string toString( NSString const * const& nsstring );
dev@189 1670 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
dev@189 1671 std::string toString( NSObject* const& nsObject );
dev@189 1672 #endif
dev@189 1673
dev@189 1674 namespace Detail {
dev@189 1675
dev@189 1676 extern const std::string unprintableString;
dev@189 1677
dev@189 1678 struct BorgType {
dev@189 1679 template<typename T> BorgType( T const& );
dev@189 1680 };
dev@189 1681
dev@189 1682 struct TrueType { char sizer[1]; };
dev@189 1683 struct FalseType { char sizer[2]; };
dev@189 1684
dev@189 1685 TrueType& testStreamable( std::ostream& );
dev@189 1686 FalseType testStreamable( FalseType );
dev@189 1687
dev@189 1688 FalseType operator<<( std::ostream const&, BorgType const& );
dev@189 1689
dev@189 1690 template<typename T>
dev@189 1691 struct IsStreamInsertable {
dev@189 1692 static std::ostream &s;
dev@189 1693 static T const&t;
dev@189 1694 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
dev@189 1695 };
dev@189 1696
dev@189 1697 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
dev@189 1698 template<typename T,
dev@189 1699 bool IsEnum = std::is_enum<T>::value
dev@189 1700 >
dev@189 1701 struct EnumStringMaker
dev@189 1702 {
dev@189 1703 static std::string convert( T const& ) { return unprintableString; }
dev@189 1704 };
dev@189 1705
dev@189 1706 template<typename T>
dev@189 1707 struct EnumStringMaker<T,true>
dev@189 1708 {
dev@189 1709 static std::string convert( T const& v )
dev@189 1710 {
dev@189 1711 return ::Catch::toString(
dev@189 1712 static_cast<typename std::underlying_type<T>::type>(v)
dev@189 1713 );
dev@189 1714 }
dev@189 1715 };
dev@189 1716 #endif
dev@189 1717 template<bool C>
dev@189 1718 struct StringMakerBase {
dev@189 1719 #if defined(CATCH_CONFIG_CPP11_IS_ENUM)
dev@189 1720 template<typename T>
dev@189 1721 static std::string convert( T const& v )
dev@189 1722 {
dev@189 1723 return EnumStringMaker<T>::convert( v );
dev@189 1724 }
dev@189 1725 #else
dev@189 1726 template<typename T>
dev@189 1727 static std::string convert( T const& ) { return unprintableString; }
dev@189 1728 #endif
dev@189 1729 };
dev@189 1730
dev@189 1731 template<>
dev@189 1732 struct StringMakerBase<true> {
dev@189 1733 template<typename T>
dev@189 1734 static std::string convert( T const& _value ) {
dev@189 1735 std::ostringstream oss;
dev@189 1736 oss << _value;
dev@189 1737 return oss.str();
dev@189 1738 }
dev@189 1739 };
dev@189 1740
dev@189 1741 std::string rawMemoryToString( const void *object, std::size_t size );
dev@189 1742
dev@189 1743 template<typename T>
dev@189 1744 inline std::string rawMemoryToString( const T& object ) {
dev@189 1745 return rawMemoryToString( &object, sizeof(object) );
dev@189 1746 }
dev@189 1747
dev@189 1748 } // end namespace Detail
dev@189 1749
dev@189 1750 template<typename T>
dev@189 1751 struct StringMaker :
dev@189 1752 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
dev@189 1753
dev@189 1754 template<typename T>
dev@189 1755 struct StringMaker<T*> {
dev@189 1756 template<typename U>
dev@189 1757 static std::string convert( U* p ) {
dev@189 1758 if( !p )
dev@189 1759 return "NULL";
dev@189 1760 else
dev@189 1761 return Detail::rawMemoryToString( p );
dev@189 1762 }
dev@189 1763 };
dev@189 1764
dev@189 1765 template<typename R, typename C>
dev@189 1766 struct StringMaker<R C::*> {
dev@189 1767 static std::string convert( R C::* p ) {
dev@189 1768 if( !p )
dev@189 1769 return "NULL";
dev@189 1770 else
dev@189 1771 return Detail::rawMemoryToString( p );
dev@189 1772 }
dev@189 1773 };
dev@189 1774
dev@189 1775 namespace Detail {
dev@189 1776 template<typename InputIterator>
dev@189 1777 std::string rangeToString( InputIterator first, InputIterator last );
dev@189 1778 }
dev@189 1779
dev@189 1780 //template<typename T, typename Allocator>
dev@189 1781 //struct StringMaker<std::vector<T, Allocator> > {
dev@189 1782 // static std::string convert( std::vector<T,Allocator> const& v ) {
dev@189 1783 // return Detail::rangeToString( v.begin(), v.end() );
dev@189 1784 // }
dev@189 1785 //};
dev@189 1786
dev@189 1787 template<typename T, typename Allocator>
dev@189 1788 std::string toString( std::vector<T,Allocator> const& v ) {
dev@189 1789 return Detail::rangeToString( v.begin(), v.end() );
dev@189 1790 }
dev@189 1791
dev@189 1792 #ifdef CATCH_CONFIG_CPP11_TUPLE
dev@189 1793
dev@189 1794 // toString for tuples
dev@189 1795 namespace TupleDetail {
dev@189 1796 template<
dev@189 1797 typename Tuple,
dev@189 1798 std::size_t N = 0,
dev@189 1799 bool = (N < std::tuple_size<Tuple>::value)
dev@189 1800 >
dev@189 1801 struct ElementPrinter {
dev@189 1802 static void print( const Tuple& tuple, std::ostream& os )
dev@189 1803 {
dev@189 1804 os << ( N ? ", " : " " )
dev@189 1805 << Catch::toString(std::get<N>(tuple));
dev@189 1806 ElementPrinter<Tuple,N+1>::print(tuple,os);
dev@189 1807 }
dev@189 1808 };
dev@189 1809
dev@189 1810 template<
dev@189 1811 typename Tuple,
dev@189 1812 std::size_t N
dev@189 1813 >
dev@189 1814 struct ElementPrinter<Tuple,N,false> {
dev@189 1815 static void print( const Tuple&, std::ostream& ) {}
dev@189 1816 };
dev@189 1817
dev@189 1818 }
dev@189 1819
dev@189 1820 template<typename ...Types>
dev@189 1821 struct StringMaker<std::tuple<Types...>> {
dev@189 1822
dev@189 1823 static std::string convert( const std::tuple<Types...>& tuple )
dev@189 1824 {
dev@189 1825 std::ostringstream os;
dev@189 1826 os << '{';
dev@189 1827 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
dev@189 1828 os << " }";
dev@189 1829 return os.str();
dev@189 1830 }
dev@189 1831 };
dev@189 1832 #endif // CATCH_CONFIG_CPP11_TUPLE
dev@189 1833
dev@189 1834 namespace Detail {
dev@189 1835 template<typename T>
dev@189 1836 std::string makeString( T const& value ) {
dev@189 1837 return StringMaker<T>::convert( value );
dev@189 1838 }
dev@189 1839 } // end namespace Detail
dev@189 1840
dev@189 1841 /// \brief converts any type to a string
dev@189 1842 ///
dev@189 1843 /// The default template forwards on to ostringstream - except when an
dev@189 1844 /// ostringstream overload does not exist - in which case it attempts to detect
dev@189 1845 /// that and writes {?}.
dev@189 1846 /// Overload (not specialise) this template for custom typs that you don't want
dev@189 1847 /// to provide an ostream overload for.
dev@189 1848 template<typename T>
dev@189 1849 std::string toString( T const& value ) {
dev@189 1850 return StringMaker<T>::convert( value );
dev@189 1851 }
dev@189 1852
dev@189 1853 namespace Detail {
dev@189 1854 template<typename InputIterator>
dev@189 1855 std::string rangeToString( InputIterator first, InputIterator last ) {
dev@189 1856 std::ostringstream oss;
dev@189 1857 oss << "{ ";
dev@189 1858 if( first != last ) {
dev@189 1859 oss << Catch::toString( *first );
dev@189 1860 for( ++first ; first != last ; ++first )
dev@189 1861 oss << ", " << Catch::toString( *first );
dev@189 1862 }
dev@189 1863 oss << " }";
dev@189 1864 return oss.str();
dev@189 1865 }
dev@189 1866 }
dev@189 1867
dev@189 1868 } // end namespace Catch
dev@189 1869
dev@189 1870 namespace Catch {
dev@189 1871
dev@189 1872 template<typename LhsT, Internal::Operator Op, typename RhsT>
dev@189 1873 class BinaryExpression;
dev@189 1874
dev@189 1875 template<typename ArgT, typename MatcherT>
dev@189 1876 class MatchExpression;
dev@189 1877
dev@189 1878 // Wraps the LHS of an expression and overloads comparison operators
dev@189 1879 // for also capturing those and RHS (if any)
dev@189 1880 template<typename T>
dev@189 1881 class ExpressionLhs : public DecomposedExpression {
dev@189 1882 public:
dev@189 1883 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
dev@189 1884
dev@189 1885 template<typename RhsT>
dev@189 1886 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
dev@189 1887 operator == ( RhsT const& rhs ) {
dev@189 1888 return captureExpression<Internal::IsEqualTo>( rhs );
dev@189 1889 }
dev@189 1890
dev@189 1891 template<typename RhsT>
dev@189 1892 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
dev@189 1893 operator != ( RhsT const& rhs ) {
dev@189 1894 return captureExpression<Internal::IsNotEqualTo>( rhs );
dev@189 1895 }
dev@189 1896
dev@189 1897 template<typename RhsT>
dev@189 1898 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
dev@189 1899 operator < ( RhsT const& rhs ) {
dev@189 1900 return captureExpression<Internal::IsLessThan>( rhs );
dev@189 1901 }
dev@189 1902
dev@189 1903 template<typename RhsT>
dev@189 1904 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
dev@189 1905 operator > ( RhsT const& rhs ) {
dev@189 1906 return captureExpression<Internal::IsGreaterThan>( rhs );
dev@189 1907 }
dev@189 1908
dev@189 1909 template<typename RhsT>
dev@189 1910 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
dev@189 1911 operator <= ( RhsT const& rhs ) {
dev@189 1912 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
dev@189 1913 }
dev@189 1914
dev@189 1915 template<typename RhsT>
dev@189 1916 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
dev@189 1917 operator >= ( RhsT const& rhs ) {
dev@189 1918 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
dev@189 1919 }
dev@189 1920
dev@189 1921 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
dev@189 1922 return captureExpression<Internal::IsEqualTo>( rhs );
dev@189 1923 }
dev@189 1924
dev@189 1925 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
dev@189 1926 return captureExpression<Internal::IsNotEqualTo>( rhs );
dev@189 1927 }
dev@189 1928
dev@189 1929 void endExpression() {
dev@189 1930 m_truthy = m_lhs ? true : false;
dev@189 1931 m_rb
dev@189 1932 .setResultType( m_truthy )
dev@189 1933 .endExpression( *this );
dev@189 1934 }
dev@189 1935
dev@189 1936 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dev@189 1937 dest = Catch::toString( m_truthy );
dev@189 1938 }
dev@189 1939
dev@189 1940 private:
dev@189 1941 template<Internal::Operator Op, typename RhsT>
dev@189 1942 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
dev@189 1943 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
dev@189 1944 }
dev@189 1945
dev@189 1946 template<Internal::Operator Op>
dev@189 1947 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
dev@189 1948 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
dev@189 1949 }
dev@189 1950
dev@189 1951 private:
dev@189 1952 ResultBuilder& m_rb;
dev@189 1953 T m_lhs;
dev@189 1954 bool m_truthy;
dev@189 1955 };
dev@189 1956
dev@189 1957 template<typename LhsT, Internal::Operator Op, typename RhsT>
dev@189 1958 class BinaryExpression : public DecomposedExpression {
dev@189 1959 public:
dev@189 1960 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
dev@189 1961 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
dev@189 1962
dev@189 1963 void endExpression() const {
dev@189 1964 m_rb
dev@189 1965 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
dev@189 1966 .endExpression( *this );
dev@189 1967 }
dev@189 1968
dev@189 1969 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
dev@189 1970 return true;
dev@189 1971 }
dev@189 1972
dev@189 1973 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dev@189 1974 std::string lhs = Catch::toString( m_lhs );
dev@189 1975 std::string rhs = Catch::toString( m_rhs );
dev@189 1976 char delim = lhs.size() + rhs.size() < 40 &&
dev@189 1977 lhs.find('\n') == std::string::npos &&
dev@189 1978 rhs.find('\n') == std::string::npos ? ' ' : '\n';
dev@189 1979 dest.reserve( 7 + lhs.size() + rhs.size() );
dev@189 1980 // 2 for spaces around operator
dev@189 1981 // 2 for operator
dev@189 1982 // 2 for parentheses (conditionally added later)
dev@189 1983 // 1 for negation (conditionally added later)
dev@189 1984 dest = lhs;
dev@189 1985 dest += delim;
dev@189 1986 dest += Internal::OperatorTraits<Op>::getName();
dev@189 1987 dest += delim;
dev@189 1988 dest += rhs;
dev@189 1989 }
dev@189 1990
dev@189 1991 private:
dev@189 1992 ResultBuilder& m_rb;
dev@189 1993 LhsT m_lhs;
dev@189 1994 RhsT m_rhs;
dev@189 1995 };
dev@189 1996
dev@189 1997 template<typename ArgT, typename MatcherT>
dev@189 1998 class MatchExpression : public DecomposedExpression {
dev@189 1999 public:
dev@189 2000 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
dev@189 2001 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
dev@189 2002
dev@189 2003 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
dev@189 2004 return true;
dev@189 2005 }
dev@189 2006
dev@189 2007 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
dev@189 2008 std::string matcherAsString = m_matcher.toString();
dev@189 2009 dest = Catch::toString( m_arg );
dev@189 2010 dest += ' ';
dev@189 2011 if( matcherAsString == Detail::unprintableString )
dev@189 2012 dest += m_matcherString;
dev@189 2013 else
dev@189 2014 dest += matcherAsString;
dev@189 2015 }
dev@189 2016
dev@189 2017 private:
dev@189 2018 ArgT m_arg;
dev@189 2019 MatcherT m_matcher;
dev@189 2020 char const* m_matcherString;
dev@189 2021 };
dev@189 2022
dev@189 2023 } // end namespace Catch
dev@189 2024
dev@189 2025
dev@189 2026 namespace Catch {
dev@189 2027
dev@189 2028 template<typename T>
dev@189 2029 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
dev@189 2030 return ExpressionLhs<T const&>( *this, operand );
dev@189 2031 }
dev@189 2032
dev@189 2033 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
dev@189 2034 return ExpressionLhs<bool>( *this, value );
dev@189 2035 }
dev@189 2036
dev@189 2037 template<typename ArgT, typename MatcherT>
dev@189 2038 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
dev@189 2039 char const* matcherString ) {
dev@189 2040 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
dev@189 2041 setResultType( matcher.match( arg ) );
dev@189 2042 endExpression( expr );
dev@189 2043 }
dev@189 2044
dev@189 2045 } // namespace Catch
dev@189 2046
dev@189 2047 // #included from: catch_message.h
dev@189 2048 #define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
dev@189 2049
dev@189 2050 #include <string>
dev@189 2051
dev@189 2052 namespace Catch {
dev@189 2053
dev@189 2054 struct MessageInfo {
dev@189 2055 MessageInfo( std::string const& _macroName,
dev@189 2056 SourceLineInfo const& _lineInfo,
dev@189 2057 ResultWas::OfType _type );
dev@189 2058
dev@189 2059 std::string macroName;
dev@189 2060 SourceLineInfo lineInfo;
dev@189 2061 ResultWas::OfType type;
dev@189 2062 std::string message;
dev@189 2063 unsigned int sequence;
dev@189 2064
dev@189 2065 bool operator == ( MessageInfo const& other ) const {
dev@189 2066 return sequence == other.sequence;
dev@189 2067 }
dev@189 2068 bool operator < ( MessageInfo const& other ) const {
dev@189 2069 return sequence < other.sequence;
dev@189 2070 }
dev@189 2071 private:
dev@189 2072 static unsigned int globalCount;
dev@189 2073 };
dev@189 2074
dev@189 2075 struct MessageBuilder {
dev@189 2076 MessageBuilder( std::string const& macroName,
dev@189 2077 SourceLineInfo const& lineInfo,
dev@189 2078 ResultWas::OfType type )
dev@189 2079 : m_info( macroName, lineInfo, type )
dev@189 2080 {}
dev@189 2081
dev@189 2082 template<typename T>
dev@189 2083 MessageBuilder& operator << ( T const& value ) {
dev@189 2084 m_stream << value;
dev@189 2085 return *this;
dev@189 2086 }
dev@189 2087
dev@189 2088 MessageInfo m_info;
dev@189 2089 std::ostringstream m_stream;
dev@189 2090 };
dev@189 2091
dev@189 2092 class ScopedMessage {
dev@189 2093 public:
dev@189 2094 ScopedMessage( MessageBuilder const& builder );
dev@189 2095 ScopedMessage( ScopedMessage const& other );
dev@189 2096 ~ScopedMessage();
dev@189 2097
dev@189 2098 MessageInfo m_info;
dev@189 2099 };
dev@189 2100
dev@189 2101 } // end namespace Catch
dev@189 2102
dev@189 2103 // #included from: catch_interfaces_capture.h
dev@189 2104 #define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
dev@189 2105
dev@189 2106 #include <string>
dev@189 2107
dev@189 2108 namespace Catch {
dev@189 2109
dev@189 2110 class TestCase;
dev@189 2111 class AssertionResult;
dev@189 2112 struct AssertionInfo;
dev@189 2113 struct SectionInfo;
dev@189 2114 struct SectionEndInfo;
dev@189 2115 struct MessageInfo;
dev@189 2116 class ScopedMessageBuilder;
dev@189 2117 struct Counts;
dev@189 2118
dev@189 2119 struct IResultCapture {
dev@189 2120
dev@189 2121 virtual ~IResultCapture();
dev@189 2122
dev@189 2123 virtual void assertionEnded( AssertionResult const& result ) = 0;
dev@189 2124 virtual bool sectionStarted( SectionInfo const& sectionInfo,
dev@189 2125 Counts& assertions ) = 0;
dev@189 2126 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
dev@189 2127 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
dev@189 2128 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
dev@189 2129 virtual void popScopedMessage( MessageInfo const& message ) = 0;
dev@189 2130
dev@189 2131 virtual std::string getCurrentTestName() const = 0;
dev@189 2132 virtual const AssertionResult* getLastResult() const = 0;
dev@189 2133
dev@189 2134 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
dev@189 2135 };
dev@189 2136
dev@189 2137 IResultCapture& getResultCapture();
dev@189 2138 }
dev@189 2139
dev@189 2140 // #included from: catch_debugger.h
dev@189 2141 #define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
dev@189 2142
dev@189 2143 // #included from: catch_platform.h
dev@189 2144 #define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
dev@189 2145
dev@189 2146 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
dev@189 2147 # define CATCH_PLATFORM_MAC
dev@189 2148 #elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
dev@189 2149 # define CATCH_PLATFORM_IPHONE
dev@189 2150 #elif defined(linux) || defined(__linux) || defined(__linux__)
dev@189 2151 # define CATCH_PLATFORM_LINUX
dev@189 2152 #elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
dev@189 2153 # define CATCH_PLATFORM_WINDOWS
dev@189 2154 # if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
dev@189 2155 # define CATCH_DEFINES_NOMINMAX
dev@189 2156 # endif
dev@189 2157 # if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
dev@189 2158 # define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
dev@189 2159 # endif
dev@189 2160 #endif
dev@189 2161
dev@189 2162 #include <string>
dev@189 2163
dev@189 2164 namespace Catch{
dev@189 2165
dev@189 2166 bool isDebuggerActive();
dev@189 2167 void writeToDebugConsole( std::string const& text );
dev@189 2168 }
dev@189 2169
dev@189 2170 #ifdef CATCH_PLATFORM_MAC
dev@189 2171
dev@189 2172 // The following code snippet based on:
dev@189 2173 // http://cocoawithlove.com/2008/03/break-into-debugger.html
dev@189 2174 #if defined(__ppc64__) || defined(__ppc__)
dev@189 2175 #define CATCH_TRAP() \
dev@189 2176 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
dev@189 2177 : : : "memory","r0","r3","r4" )
dev@189 2178 #else
dev@189 2179 #define CATCH_TRAP() __asm__("int $3\n" : : )
dev@189 2180 #endif
dev@189 2181
dev@189 2182 #elif defined(CATCH_PLATFORM_LINUX)
dev@189 2183 // If we can use inline assembler, do it because this allows us to break
dev@189 2184 // directly at the location of the failing check instead of breaking inside
dev@189 2185 // raise() called from it, i.e. one stack frame below.
dev@189 2186 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
dev@189 2187 #define CATCH_TRAP() asm volatile ("int $3")
dev@189 2188 #else // Fall back to the generic way.
dev@189 2189 #include <signal.h>
dev@189 2190
dev@189 2191 #define CATCH_TRAP() raise(SIGTRAP)
dev@189 2192 #endif
dev@189 2193 #elif defined(_MSC_VER)
dev@189 2194 #define CATCH_TRAP() __debugbreak()
dev@189 2195 #elif defined(__MINGW32__)
dev@189 2196 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
dev@189 2197 #define CATCH_TRAP() DebugBreak()
dev@189 2198 #endif
dev@189 2199
dev@189 2200 #ifdef CATCH_TRAP
dev@189 2201 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
dev@189 2202 #else
dev@189 2203 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
dev@189 2204 #endif
dev@189 2205
dev@189 2206 // #included from: catch_interfaces_runner.h
dev@189 2207 #define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
dev@189 2208
dev@189 2209 namespace Catch {
dev@189 2210 class TestCase;
dev@189 2211
dev@189 2212 struct IRunner {
dev@189 2213 virtual ~IRunner();
dev@189 2214 virtual bool aborting() const = 0;
dev@189 2215 };
dev@189 2216 }
dev@189 2217
dev@189 2218 ///////////////////////////////////////////////////////////////////////////////
dev@189 2219 // In the event of a failure works out if the debugger needs to be invoked
dev@189 2220 // and/or an exception thrown and takes appropriate action.
dev@189 2221 // This needs to be done as a macro so the debugger will stop in the user
dev@189 2222 // source code rather than in Catch library code
dev@189 2223 #define INTERNAL_CATCH_REACT( resultBuilder ) \
dev@189 2224 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
dev@189 2225 resultBuilder.react();
dev@189 2226
dev@189 2227 ///////////////////////////////////////////////////////////////////////////////
dev@189 2228 #define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
dev@189 2229 do { \
dev@189 2230 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
dev@189 2231 try { \
dev@189 2232 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
dev@189 2233 ( __catchResult <= expr ).endExpression(); \
dev@189 2234 } \
dev@189 2235 catch( ... ) { \
dev@189 2236 __catchResult.useActiveException( resultDisposition ); \
dev@189 2237 } \
dev@189 2238 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2239 } 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
dev@189 2240 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
dev@189 2241
dev@189 2242 ///////////////////////////////////////////////////////////////////////////////
dev@189 2243 #define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
dev@189 2244 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
dev@189 2245 if( Catch::getResultCapture().getLastResult()->succeeded() )
dev@189 2246
dev@189 2247 ///////////////////////////////////////////////////////////////////////////////
dev@189 2248 #define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
dev@189 2249 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
dev@189 2250 if( !Catch::getResultCapture().getLastResult()->succeeded() )
dev@189 2251
dev@189 2252 ///////////////////////////////////////////////////////////////////////////////
dev@189 2253 #define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
dev@189 2254 do { \
dev@189 2255 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
dev@189 2256 try { \
dev@189 2257 static_cast<void>(expr); \
dev@189 2258 __catchResult.captureResult( Catch::ResultWas::Ok ); \
dev@189 2259 } \
dev@189 2260 catch( ... ) { \
dev@189 2261 __catchResult.useActiveException( resultDisposition ); \
dev@189 2262 } \
dev@189 2263 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2264 } while( Catch::alwaysFalse() )
dev@189 2265
dev@189 2266 ///////////////////////////////////////////////////////////////////////////////
dev@189 2267 #define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
dev@189 2268 do { \
dev@189 2269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
dev@189 2270 if( __catchResult.allowThrows() ) \
dev@189 2271 try { \
dev@189 2272 static_cast<void>(expr); \
dev@189 2273 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
dev@189 2274 } \
dev@189 2275 catch( ... ) { \
dev@189 2276 __catchResult.captureExpectedException( matcher ); \
dev@189 2277 } \
dev@189 2278 else \
dev@189 2279 __catchResult.captureResult( Catch::ResultWas::Ok ); \
dev@189 2280 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2281 } while( Catch::alwaysFalse() )
dev@189 2282
dev@189 2283 ///////////////////////////////////////////////////////////////////////////////
dev@189 2284 #define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
dev@189 2285 do { \
dev@189 2286 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
dev@189 2287 if( __catchResult.allowThrows() ) \
dev@189 2288 try { \
dev@189 2289 static_cast<void>(expr); \
dev@189 2290 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
dev@189 2291 } \
dev@189 2292 catch( exceptionType ) { \
dev@189 2293 __catchResult.captureResult( Catch::ResultWas::Ok ); \
dev@189 2294 } \
dev@189 2295 catch( ... ) { \
dev@189 2296 __catchResult.useActiveException( resultDisposition ); \
dev@189 2297 } \
dev@189 2298 else \
dev@189 2299 __catchResult.captureResult( Catch::ResultWas::Ok ); \
dev@189 2300 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2301 } while( Catch::alwaysFalse() )
dev@189 2302
dev@189 2303 ///////////////////////////////////////////////////////////////////////////////
dev@189 2304 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 2305 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
dev@189 2306 do { \
dev@189 2307 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
dev@189 2308 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
dev@189 2309 __catchResult.captureResult( messageType ); \
dev@189 2310 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2311 } while( Catch::alwaysFalse() )
dev@189 2312 #else
dev@189 2313 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
dev@189 2314 do { \
dev@189 2315 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
dev@189 2316 __catchResult << log + ::Catch::StreamEndStop(); \
dev@189 2317 __catchResult.captureResult( messageType ); \
dev@189 2318 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2319 } while( Catch::alwaysFalse() )
dev@189 2320 #endif
dev@189 2321
dev@189 2322 ///////////////////////////////////////////////////////////////////////////////
dev@189 2323 #define INTERNAL_CATCH_INFO( log, macroName ) \
dev@189 2324 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
dev@189 2325
dev@189 2326 ///////////////////////////////////////////////////////////////////////////////
dev@189 2327 #define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
dev@189 2328 do { \
dev@189 2329 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
dev@189 2330 try { \
dev@189 2331 __catchResult.captureMatch( arg, matcher, #matcher ); \
dev@189 2332 } catch( ... ) { \
dev@189 2333 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
dev@189 2334 } \
dev@189 2335 INTERNAL_CATCH_REACT( __catchResult ) \
dev@189 2336 } while( Catch::alwaysFalse() )
dev@189 2337
dev@189 2338 // #included from: internal/catch_section.h
dev@189 2339 #define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
dev@189 2340
dev@189 2341 // #included from: catch_section_info.h
dev@189 2342 #define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
dev@189 2343
dev@189 2344 // #included from: catch_totals.hpp
dev@189 2345 #define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
dev@189 2346
dev@189 2347 #include <cstddef>
dev@189 2348
dev@189 2349 namespace Catch {
dev@189 2350
dev@189 2351 struct Counts {
dev@189 2352 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
dev@189 2353
dev@189 2354 Counts operator - ( Counts const& other ) const {
dev@189 2355 Counts diff;
dev@189 2356 diff.passed = passed - other.passed;
dev@189 2357 diff.failed = failed - other.failed;
dev@189 2358 diff.failedButOk = failedButOk - other.failedButOk;
dev@189 2359 return diff;
dev@189 2360 }
dev@189 2361 Counts& operator += ( Counts const& other ) {
dev@189 2362 passed += other.passed;
dev@189 2363 failed += other.failed;
dev@189 2364 failedButOk += other.failedButOk;
dev@189 2365 return *this;
dev@189 2366 }
dev@189 2367
dev@189 2368 std::size_t total() const {
dev@189 2369 return passed + failed + failedButOk;
dev@189 2370 }
dev@189 2371 bool allPassed() const {
dev@189 2372 return failed == 0 && failedButOk == 0;
dev@189 2373 }
dev@189 2374 bool allOk() const {
dev@189 2375 return failed == 0;
dev@189 2376 }
dev@189 2377
dev@189 2378 std::size_t passed;
dev@189 2379 std::size_t failed;
dev@189 2380 std::size_t failedButOk;
dev@189 2381 };
dev@189 2382
dev@189 2383 struct Totals {
dev@189 2384
dev@189 2385 Totals operator - ( Totals const& other ) const {
dev@189 2386 Totals diff;
dev@189 2387 diff.assertions = assertions - other.assertions;
dev@189 2388 diff.testCases = testCases - other.testCases;
dev@189 2389 return diff;
dev@189 2390 }
dev@189 2391
dev@189 2392 Totals delta( Totals const& prevTotals ) const {
dev@189 2393 Totals diff = *this - prevTotals;
dev@189 2394 if( diff.assertions.failed > 0 )
dev@189 2395 ++diff.testCases.failed;
dev@189 2396 else if( diff.assertions.failedButOk > 0 )
dev@189 2397 ++diff.testCases.failedButOk;
dev@189 2398 else
dev@189 2399 ++diff.testCases.passed;
dev@189 2400 return diff;
dev@189 2401 }
dev@189 2402
dev@189 2403 Totals& operator += ( Totals const& other ) {
dev@189 2404 assertions += other.assertions;
dev@189 2405 testCases += other.testCases;
dev@189 2406 return *this;
dev@189 2407 }
dev@189 2408
dev@189 2409 Counts assertions;
dev@189 2410 Counts testCases;
dev@189 2411 };
dev@189 2412 }
dev@189 2413
dev@189 2414 namespace Catch {
dev@189 2415
dev@189 2416 struct SectionInfo {
dev@189 2417 SectionInfo
dev@189 2418 ( SourceLineInfo const& _lineInfo,
dev@189 2419 std::string const& _name,
dev@189 2420 std::string const& _description = std::string() );
dev@189 2421
dev@189 2422 std::string name;
dev@189 2423 std::string description;
dev@189 2424 SourceLineInfo lineInfo;
dev@189 2425 };
dev@189 2426
dev@189 2427 struct SectionEndInfo {
dev@189 2428 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
dev@189 2429 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
dev@189 2430 {}
dev@189 2431
dev@189 2432 SectionInfo sectionInfo;
dev@189 2433 Counts prevAssertions;
dev@189 2434 double durationInSeconds;
dev@189 2435 };
dev@189 2436
dev@189 2437 } // end namespace Catch
dev@189 2438
dev@189 2439 // #included from: catch_timer.h
dev@189 2440 #define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
dev@189 2441
dev@189 2442 #ifdef CATCH_PLATFORM_WINDOWS
dev@189 2443 typedef unsigned long long uint64_t;
dev@189 2444 #else
dev@189 2445 #include <stdint.h>
dev@189 2446 #endif
dev@189 2447
dev@189 2448 namespace Catch {
dev@189 2449
dev@189 2450 class Timer {
dev@189 2451 public:
dev@189 2452 Timer() : m_ticks( 0 ) {}
dev@189 2453 void start();
dev@189 2454 unsigned int getElapsedMicroseconds() const;
dev@189 2455 unsigned int getElapsedMilliseconds() const;
dev@189 2456 double getElapsedSeconds() const;
dev@189 2457
dev@189 2458 private:
dev@189 2459 uint64_t m_ticks;
dev@189 2460 };
dev@189 2461
dev@189 2462 } // namespace Catch
dev@189 2463
dev@189 2464 #include <string>
dev@189 2465
dev@189 2466 namespace Catch {
dev@189 2467
dev@189 2468 class Section : NonCopyable {
dev@189 2469 public:
dev@189 2470 Section( SectionInfo const& info );
dev@189 2471 ~Section();
dev@189 2472
dev@189 2473 // This indicates whether the section should be executed or not
dev@189 2474 operator bool() const;
dev@189 2475
dev@189 2476 private:
dev@189 2477 SectionInfo m_info;
dev@189 2478
dev@189 2479 std::string m_name;
dev@189 2480 Counts m_assertions;
dev@189 2481 bool m_sectionIncluded;
dev@189 2482 Timer m_timer;
dev@189 2483 };
dev@189 2484
dev@189 2485 } // end namespace Catch
dev@189 2486
dev@189 2487 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 2488 #define INTERNAL_CATCH_SECTION( ... ) \
dev@189 2489 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
dev@189 2490 #else
dev@189 2491 #define INTERNAL_CATCH_SECTION( name, desc ) \
dev@189 2492 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
dev@189 2493 #endif
dev@189 2494
dev@189 2495 // #included from: internal/catch_generators.hpp
dev@189 2496 #define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
dev@189 2497
dev@189 2498 #include <iterator>
dev@189 2499 #include <vector>
dev@189 2500 #include <string>
dev@189 2501 #include <stdlib.h>
dev@189 2502
dev@189 2503 namespace Catch {
dev@189 2504
dev@189 2505 template<typename T>
dev@189 2506 struct IGenerator {
dev@189 2507 virtual ~IGenerator() {}
dev@189 2508 virtual T getValue( std::size_t index ) const = 0;
dev@189 2509 virtual std::size_t size () const = 0;
dev@189 2510 };
dev@189 2511
dev@189 2512 template<typename T>
dev@189 2513 class BetweenGenerator : public IGenerator<T> {
dev@189 2514 public:
dev@189 2515 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
dev@189 2516
dev@189 2517 virtual T getValue( std::size_t index ) const {
dev@189 2518 return m_from+static_cast<int>( index );
dev@189 2519 }
dev@189 2520
dev@189 2521 virtual std::size_t size() const {
dev@189 2522 return static_cast<std::size_t>( 1+m_to-m_from );
dev@189 2523 }
dev@189 2524
dev@189 2525 private:
dev@189 2526
dev@189 2527 T m_from;
dev@189 2528 T m_to;
dev@189 2529 };
dev@189 2530
dev@189 2531 template<typename T>
dev@189 2532 class ValuesGenerator : public IGenerator<T> {
dev@189 2533 public:
dev@189 2534 ValuesGenerator(){}
dev@189 2535
dev@189 2536 void add( T value ) {
dev@189 2537 m_values.push_back( value );
dev@189 2538 }
dev@189 2539
dev@189 2540 virtual T getValue( std::size_t index ) const {
dev@189 2541 return m_values[index];
dev@189 2542 }
dev@189 2543
dev@189 2544 virtual std::size_t size() const {
dev@189 2545 return m_values.size();
dev@189 2546 }
dev@189 2547
dev@189 2548 private:
dev@189 2549 std::vector<T> m_values;
dev@189 2550 };
dev@189 2551
dev@189 2552 template<typename T>
dev@189 2553 class CompositeGenerator {
dev@189 2554 public:
dev@189 2555 CompositeGenerator() : m_totalSize( 0 ) {}
dev@189 2556
dev@189 2557 // *** Move semantics, similar to auto_ptr ***
dev@189 2558 CompositeGenerator( CompositeGenerator& other )
dev@189 2559 : m_fileInfo( other.m_fileInfo ),
dev@189 2560 m_totalSize( 0 )
dev@189 2561 {
dev@189 2562 move( other );
dev@189 2563 }
dev@189 2564
dev@189 2565 CompositeGenerator& setFileInfo( const char* fileInfo ) {
dev@189 2566 m_fileInfo = fileInfo;
dev@189 2567 return *this;
dev@189 2568 }
dev@189 2569
dev@189 2570 ~CompositeGenerator() {
dev@189 2571 deleteAll( m_composed );
dev@189 2572 }
dev@189 2573
dev@189 2574 operator T () const {
dev@189 2575 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
dev@189 2576
dev@189 2577 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
dev@189 2578 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
dev@189 2579 for( size_t index = 0; it != itEnd; ++it )
dev@189 2580 {
dev@189 2581 const IGenerator<T>* generator = *it;
dev@189 2582 if( overallIndex >= index && overallIndex < index + generator->size() )
dev@189 2583 {
dev@189 2584 return generator->getValue( overallIndex-index );
dev@189 2585 }
dev@189 2586 index += generator->size();
dev@189 2587 }
dev@189 2588 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
dev@189 2589 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
dev@189 2590 }
dev@189 2591
dev@189 2592 void add( const IGenerator<T>* generator ) {
dev@189 2593 m_totalSize += generator->size();
dev@189 2594 m_composed.push_back( generator );
dev@189 2595 }
dev@189 2596
dev@189 2597 CompositeGenerator& then( CompositeGenerator& other ) {
dev@189 2598 move( other );
dev@189 2599 return *this;
dev@189 2600 }
dev@189 2601
dev@189 2602 CompositeGenerator& then( T value ) {
dev@189 2603 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
dev@189 2604 valuesGen->add( value );
dev@189 2605 add( valuesGen );
dev@189 2606 return *this;
dev@189 2607 }
dev@189 2608
dev@189 2609 private:
dev@189 2610
dev@189 2611 void move( CompositeGenerator& other ) {
dev@189 2612 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
dev@189 2613 m_totalSize += other.m_totalSize;
dev@189 2614 other.m_composed.clear();
dev@189 2615 }
dev@189 2616
dev@189 2617 std::vector<const IGenerator<T>*> m_composed;
dev@189 2618 std::string m_fileInfo;
dev@189 2619 size_t m_totalSize;
dev@189 2620 };
dev@189 2621
dev@189 2622 namespace Generators
dev@189 2623 {
dev@189 2624 template<typename T>
dev@189 2625 CompositeGenerator<T> between( T from, T to ) {
dev@189 2626 CompositeGenerator<T> generators;
dev@189 2627 generators.add( new BetweenGenerator<T>( from, to ) );
dev@189 2628 return generators;
dev@189 2629 }
dev@189 2630
dev@189 2631 template<typename T>
dev@189 2632 CompositeGenerator<T> values( T val1, T val2 ) {
dev@189 2633 CompositeGenerator<T> generators;
dev@189 2634 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
dev@189 2635 valuesGen->add( val1 );
dev@189 2636 valuesGen->add( val2 );
dev@189 2637 generators.add( valuesGen );
dev@189 2638 return generators;
dev@189 2639 }
dev@189 2640
dev@189 2641 template<typename T>
dev@189 2642 CompositeGenerator<T> values( T val1, T val2, T val3 ){
dev@189 2643 CompositeGenerator<T> generators;
dev@189 2644 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
dev@189 2645 valuesGen->add( val1 );
dev@189 2646 valuesGen->add( val2 );
dev@189 2647 valuesGen->add( val3 );
dev@189 2648 generators.add( valuesGen );
dev@189 2649 return generators;
dev@189 2650 }
dev@189 2651
dev@189 2652 template<typename T>
dev@189 2653 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
dev@189 2654 CompositeGenerator<T> generators;
dev@189 2655 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
dev@189 2656 valuesGen->add( val1 );
dev@189 2657 valuesGen->add( val2 );
dev@189 2658 valuesGen->add( val3 );
dev@189 2659 valuesGen->add( val4 );
dev@189 2660 generators.add( valuesGen );
dev@189 2661 return generators;
dev@189 2662 }
dev@189 2663
dev@189 2664 } // end namespace Generators
dev@189 2665
dev@189 2666 using namespace Generators;
dev@189 2667
dev@189 2668 } // end namespace Catch
dev@189 2669
dev@189 2670 #define INTERNAL_CATCH_LINESTR2( line ) #line
dev@189 2671 #define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
dev@189 2672
dev@189 2673 #define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
dev@189 2674
dev@189 2675 // #included from: internal/catch_interfaces_exception.h
dev@189 2676 #define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
dev@189 2677
dev@189 2678 #include <string>
dev@189 2679 #include <vector>
dev@189 2680
dev@189 2681 // #included from: catch_interfaces_registry_hub.h
dev@189 2682 #define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
dev@189 2683
dev@189 2684 #include <string>
dev@189 2685
dev@189 2686 namespace Catch {
dev@189 2687
dev@189 2688 class TestCase;
dev@189 2689 struct ITestCaseRegistry;
dev@189 2690 struct IExceptionTranslatorRegistry;
dev@189 2691 struct IExceptionTranslator;
dev@189 2692 struct IReporterRegistry;
dev@189 2693 struct IReporterFactory;
dev@189 2694
dev@189 2695 struct IRegistryHub {
dev@189 2696 virtual ~IRegistryHub();
dev@189 2697
dev@189 2698 virtual IReporterRegistry const& getReporterRegistry() const = 0;
dev@189 2699 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
dev@189 2700 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
dev@189 2701 };
dev@189 2702
dev@189 2703 struct IMutableRegistryHub {
dev@189 2704 virtual ~IMutableRegistryHub();
dev@189 2705 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
dev@189 2706 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
dev@189 2707 virtual void registerTest( TestCase const& testInfo ) = 0;
dev@189 2708 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
dev@189 2709 };
dev@189 2710
dev@189 2711 IRegistryHub& getRegistryHub();
dev@189 2712 IMutableRegistryHub& getMutableRegistryHub();
dev@189 2713 void cleanUp();
dev@189 2714 std::string translateActiveException();
dev@189 2715
dev@189 2716 }
dev@189 2717
dev@189 2718 namespace Catch {
dev@189 2719
dev@189 2720 typedef std::string(*exceptionTranslateFunction)();
dev@189 2721
dev@189 2722 struct IExceptionTranslator;
dev@189 2723 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
dev@189 2724
dev@189 2725 struct IExceptionTranslator {
dev@189 2726 virtual ~IExceptionTranslator();
dev@189 2727 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
dev@189 2728 };
dev@189 2729
dev@189 2730 struct IExceptionTranslatorRegistry {
dev@189 2731 virtual ~IExceptionTranslatorRegistry();
dev@189 2732
dev@189 2733 virtual std::string translateActiveException() const = 0;
dev@189 2734 };
dev@189 2735
dev@189 2736 class ExceptionTranslatorRegistrar {
dev@189 2737 template<typename T>
dev@189 2738 class ExceptionTranslator : public IExceptionTranslator {
dev@189 2739 public:
dev@189 2740
dev@189 2741 ExceptionTranslator( std::string(*translateFunction)( T& ) )
dev@189 2742 : m_translateFunction( translateFunction )
dev@189 2743 {}
dev@189 2744
dev@189 2745 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
dev@189 2746 try {
dev@189 2747 if( it == itEnd )
dev@189 2748 throw;
dev@189 2749 else
dev@189 2750 return (*it)->translate( it+1, itEnd );
dev@189 2751 }
dev@189 2752 catch( T& ex ) {
dev@189 2753 return m_translateFunction( ex );
dev@189 2754 }
dev@189 2755 }
dev@189 2756
dev@189 2757 protected:
dev@189 2758 std::string(*m_translateFunction)( T& );
dev@189 2759 };
dev@189 2760
dev@189 2761 public:
dev@189 2762 template<typename T>
dev@189 2763 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
dev@189 2764 getMutableRegistryHub().registerTranslator
dev@189 2765 ( new ExceptionTranslator<T>( translateFunction ) );
dev@189 2766 }
dev@189 2767 };
dev@189 2768 }
dev@189 2769
dev@189 2770 ///////////////////////////////////////////////////////////////////////////////
dev@189 2771 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
dev@189 2772 static std::string translatorName( signature ); \
dev@189 2773 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
dev@189 2774 static std::string translatorName( signature )
dev@189 2775
dev@189 2776 #define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
dev@189 2777
dev@189 2778 // #included from: internal/catch_approx.hpp
dev@189 2779 #define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
dev@189 2780
dev@189 2781 #include <cmath>
dev@189 2782 #include <limits>
dev@189 2783
dev@189 2784 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
dev@189 2785 #include <type_traits>
dev@189 2786 #endif
dev@189 2787
dev@189 2788 namespace Catch {
dev@189 2789 namespace Detail {
dev@189 2790
dev@189 2791 class Approx {
dev@189 2792 public:
dev@189 2793 explicit Approx ( double value )
dev@189 2794 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
dev@189 2795 m_scale( 1.0 ),
dev@189 2796 m_value( value )
dev@189 2797 {}
dev@189 2798
dev@189 2799 Approx( Approx const& other )
dev@189 2800 : m_epsilon( other.m_epsilon ),
dev@189 2801 m_scale( other.m_scale ),
dev@189 2802 m_value( other.m_value )
dev@189 2803 {}
dev@189 2804
dev@189 2805 static Approx custom() {
dev@189 2806 return Approx( 0 );
dev@189 2807 }
dev@189 2808
dev@189 2809 Approx operator()( double value ) {
dev@189 2810 Approx approx( value );
dev@189 2811 approx.epsilon( m_epsilon );
dev@189 2812 approx.scale( m_scale );
dev@189 2813 return approx;
dev@189 2814 }
dev@189 2815
dev@189 2816 #if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
dev@189 2817 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2818 friend bool operator == ( const T& lhs, Approx const& rhs ) {
dev@189 2819 // Thanks to Richard Harris for his help refining this formula
dev@189 2820 auto lhs_v = double(lhs);
dev@189 2821 return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) );
dev@189 2822 }
dev@189 2823
dev@189 2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2825 friend bool operator == ( Approx const& lhs, const T& rhs ) {
dev@189 2826 return operator==( rhs, lhs );
dev@189 2827 }
dev@189 2828
dev@189 2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2830 friend bool operator != ( T lhs, Approx const& rhs ) {
dev@189 2831 return !operator==( lhs, rhs );
dev@189 2832 }
dev@189 2833
dev@189 2834 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2835 friend bool operator != ( Approx const& lhs, T rhs ) {
dev@189 2836 return !operator==( rhs, lhs );
dev@189 2837 }
dev@189 2838
dev@189 2839 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2840 friend bool operator <= ( T lhs, Approx const& rhs )
dev@189 2841 {
dev@189 2842 return double(lhs) < rhs.m_value || lhs == rhs;
dev@189 2843 }
dev@189 2844
dev@189 2845 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2846 friend bool operator <= ( Approx const& lhs, T rhs )
dev@189 2847 {
dev@189 2848 return lhs.m_value < double(rhs) || lhs == rhs;
dev@189 2849 }
dev@189 2850
dev@189 2851 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2852 friend bool operator >= ( T lhs, Approx const& rhs )
dev@189 2853 {
dev@189 2854 return double(lhs) > rhs.m_value || lhs == rhs;
dev@189 2855 }
dev@189 2856
dev@189 2857 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
dev@189 2858 friend bool operator >= ( Approx const& lhs, T rhs )
dev@189 2859 {
dev@189 2860 return lhs.m_value > double(rhs) || lhs == rhs;
dev@189 2861 }
dev@189 2862 #else
dev@189 2863 friend bool operator == ( double lhs, Approx const& rhs ) {
dev@189 2864 // Thanks to Richard Harris for his help refining this formula
dev@189 2865 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
dev@189 2866 }
dev@189 2867
dev@189 2868 friend bool operator == ( Approx const& lhs, double rhs ) {
dev@189 2869 return operator==( rhs, lhs );
dev@189 2870 }
dev@189 2871
dev@189 2872 friend bool operator != ( double lhs, Approx const& rhs ) {
dev@189 2873 return !operator==( lhs, rhs );
dev@189 2874 }
dev@189 2875
dev@189 2876 friend bool operator != ( Approx const& lhs, double rhs ) {
dev@189 2877 return !operator==( rhs, lhs );
dev@189 2878 }
dev@189 2879
dev@189 2880 friend bool operator <= ( double lhs, Approx const& rhs )
dev@189 2881 {
dev@189 2882 return lhs < rhs.m_value || lhs == rhs;
dev@189 2883 }
dev@189 2884
dev@189 2885 friend bool operator <= ( Approx const& lhs, double rhs )
dev@189 2886 {
dev@189 2887 return lhs.m_value < rhs || lhs == rhs;
dev@189 2888 }
dev@189 2889
dev@189 2890 friend bool operator >= ( double lhs, Approx const& rhs )
dev@189 2891 {
dev@189 2892 return lhs > rhs.m_value || lhs == rhs;
dev@189 2893 }
dev@189 2894
dev@189 2895 friend bool operator >= ( Approx const& lhs, double rhs )
dev@189 2896 {
dev@189 2897 return lhs.m_value > rhs || lhs == rhs;
dev@189 2898 }
dev@189 2899 #endif
dev@189 2900
dev@189 2901 Approx& epsilon( double newEpsilon ) {
dev@189 2902 m_epsilon = newEpsilon;
dev@189 2903 return *this;
dev@189 2904 }
dev@189 2905
dev@189 2906 Approx& scale( double newScale ) {
dev@189 2907 m_scale = newScale;
dev@189 2908 return *this;
dev@189 2909 }
dev@189 2910
dev@189 2911 std::string toString() const {
dev@189 2912 std::ostringstream oss;
dev@189 2913 oss << "Approx( " << Catch::toString( m_value ) << " )";
dev@189 2914 return oss.str();
dev@189 2915 }
dev@189 2916
dev@189 2917 private:
dev@189 2918 double m_epsilon;
dev@189 2919 double m_scale;
dev@189 2920 double m_value;
dev@189 2921 };
dev@189 2922 }
dev@189 2923
dev@189 2924 template<>
dev@189 2925 inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
dev@189 2926 return value.toString();
dev@189 2927 }
dev@189 2928
dev@189 2929 } // end namespace Catch
dev@189 2930
dev@189 2931 // #included from: internal/catch_interfaces_tag_alias_registry.h
dev@189 2932 #define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
dev@189 2933
dev@189 2934 // #included from: catch_tag_alias.h
dev@189 2935 #define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
dev@189 2936
dev@189 2937 #include <string>
dev@189 2938
dev@189 2939 namespace Catch {
dev@189 2940
dev@189 2941 struct TagAlias {
dev@189 2942 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
dev@189 2943
dev@189 2944 std::string tag;
dev@189 2945 SourceLineInfo lineInfo;
dev@189 2946 };
dev@189 2947
dev@189 2948 struct RegistrarForTagAliases {
dev@189 2949 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
dev@189 2950 };
dev@189 2951
dev@189 2952 } // end namespace Catch
dev@189 2953
dev@189 2954 #define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
dev@189 2955 // #included from: catch_option.hpp
dev@189 2956 #define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
dev@189 2957
dev@189 2958 namespace Catch {
dev@189 2959
dev@189 2960 // An optional type
dev@189 2961 template<typename T>
dev@189 2962 class Option {
dev@189 2963 public:
dev@189 2964 Option() : nullableValue( CATCH_NULL ) {}
dev@189 2965 Option( T const& _value )
dev@189 2966 : nullableValue( new( storage ) T( _value ) )
dev@189 2967 {}
dev@189 2968 Option( Option const& _other )
dev@189 2969 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
dev@189 2970 {}
dev@189 2971
dev@189 2972 ~Option() {
dev@189 2973 reset();
dev@189 2974 }
dev@189 2975
dev@189 2976 Option& operator= ( Option const& _other ) {
dev@189 2977 if( &_other != this ) {
dev@189 2978 reset();
dev@189 2979 if( _other )
dev@189 2980 nullableValue = new( storage ) T( *_other );
dev@189 2981 }
dev@189 2982 return *this;
dev@189 2983 }
dev@189 2984 Option& operator = ( T const& _value ) {
dev@189 2985 reset();
dev@189 2986 nullableValue = new( storage ) T( _value );
dev@189 2987 return *this;
dev@189 2988 }
dev@189 2989
dev@189 2990 void reset() {
dev@189 2991 if( nullableValue )
dev@189 2992 nullableValue->~T();
dev@189 2993 nullableValue = CATCH_NULL;
dev@189 2994 }
dev@189 2995
dev@189 2996 T& operator*() { return *nullableValue; }
dev@189 2997 T const& operator*() const { return *nullableValue; }
dev@189 2998 T* operator->() { return nullableValue; }
dev@189 2999 const T* operator->() const { return nullableValue; }
dev@189 3000
dev@189 3001 T valueOr( T const& defaultValue ) const {
dev@189 3002 return nullableValue ? *nullableValue : defaultValue;
dev@189 3003 }
dev@189 3004
dev@189 3005 bool some() const { return nullableValue != CATCH_NULL; }
dev@189 3006 bool none() const { return nullableValue == CATCH_NULL; }
dev@189 3007
dev@189 3008 bool operator !() const { return nullableValue == CATCH_NULL; }
dev@189 3009 operator SafeBool::type() const {
dev@189 3010 return SafeBool::makeSafe( some() );
dev@189 3011 }
dev@189 3012
dev@189 3013 private:
dev@189 3014 T* nullableValue;
dev@189 3015 char storage[sizeof(T)];
dev@189 3016 };
dev@189 3017
dev@189 3018 } // end namespace Catch
dev@189 3019
dev@189 3020 namespace Catch {
dev@189 3021
dev@189 3022 struct ITagAliasRegistry {
dev@189 3023 virtual ~ITagAliasRegistry();
dev@189 3024 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
dev@189 3025 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
dev@189 3026
dev@189 3027 static ITagAliasRegistry const& get();
dev@189 3028 };
dev@189 3029
dev@189 3030 } // end namespace Catch
dev@189 3031
dev@189 3032 // These files are included here so the single_include script doesn't put them
dev@189 3033 // in the conditionally compiled sections
dev@189 3034 // #included from: internal/catch_test_case_info.h
dev@189 3035 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
dev@189 3036
dev@189 3037 #include <string>
dev@189 3038 #include <set>
dev@189 3039
dev@189 3040 #ifdef __clang__
dev@189 3041 #pragma clang diagnostic push
dev@189 3042 #pragma clang diagnostic ignored "-Wpadded"
dev@189 3043 #endif
dev@189 3044
dev@189 3045 namespace Catch {
dev@189 3046
dev@189 3047 struct ITestCase;
dev@189 3048
dev@189 3049 struct TestCaseInfo {
dev@189 3050 enum SpecialProperties{
dev@189 3051 None = 0,
dev@189 3052 IsHidden = 1 << 1,
dev@189 3053 ShouldFail = 1 << 2,
dev@189 3054 MayFail = 1 << 3,
dev@189 3055 Throws = 1 << 4,
dev@189 3056 NonPortable = 1 << 5
dev@189 3057 };
dev@189 3058
dev@189 3059 TestCaseInfo( std::string const& _name,
dev@189 3060 std::string const& _className,
dev@189 3061 std::string const& _description,
dev@189 3062 std::set<std::string> const& _tags,
dev@189 3063 SourceLineInfo const& _lineInfo );
dev@189 3064
dev@189 3065 TestCaseInfo( TestCaseInfo const& other );
dev@189 3066
dev@189 3067 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
dev@189 3068
dev@189 3069 bool isHidden() const;
dev@189 3070 bool throws() const;
dev@189 3071 bool okToFail() const;
dev@189 3072 bool expectedToFail() const;
dev@189 3073
dev@189 3074 std::string name;
dev@189 3075 std::string className;
dev@189 3076 std::string description;
dev@189 3077 std::set<std::string> tags;
dev@189 3078 std::set<std::string> lcaseTags;
dev@189 3079 std::string tagsAsString;
dev@189 3080 SourceLineInfo lineInfo;
dev@189 3081 SpecialProperties properties;
dev@189 3082 };
dev@189 3083
dev@189 3084 class TestCase : public TestCaseInfo {
dev@189 3085 public:
dev@189 3086
dev@189 3087 TestCase( ITestCase* testCase, TestCaseInfo const& info );
dev@189 3088 TestCase( TestCase const& other );
dev@189 3089
dev@189 3090 TestCase withName( std::string const& _newName ) const;
dev@189 3091
dev@189 3092 void invoke() const;
dev@189 3093
dev@189 3094 TestCaseInfo const& getTestCaseInfo() const;
dev@189 3095
dev@189 3096 void swap( TestCase& other );
dev@189 3097 bool operator == ( TestCase const& other ) const;
dev@189 3098 bool operator < ( TestCase const& other ) const;
dev@189 3099 TestCase& operator = ( TestCase const& other );
dev@189 3100
dev@189 3101 private:
dev@189 3102 Ptr<ITestCase> test;
dev@189 3103 };
dev@189 3104
dev@189 3105 TestCase makeTestCase( ITestCase* testCase,
dev@189 3106 std::string const& className,
dev@189 3107 std::string const& name,
dev@189 3108 std::string const& description,
dev@189 3109 SourceLineInfo const& lineInfo );
dev@189 3110 }
dev@189 3111
dev@189 3112 #ifdef __clang__
dev@189 3113 #pragma clang diagnostic pop
dev@189 3114 #endif
dev@189 3115
dev@189 3116
dev@189 3117 #ifdef __OBJC__
dev@189 3118 // #included from: internal/catch_objc.hpp
dev@189 3119 #define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
dev@189 3120
dev@189 3121 #import <objc/runtime.h>
dev@189 3122
dev@189 3123 #include <string>
dev@189 3124
dev@189 3125 // NB. Any general catch headers included here must be included
dev@189 3126 // in catch.hpp first to make sure they are included by the single
dev@189 3127 // header for non obj-usage
dev@189 3128
dev@189 3129 ///////////////////////////////////////////////////////////////////////////////
dev@189 3130 // This protocol is really only here for (self) documenting purposes, since
dev@189 3131 // all its methods are optional.
dev@189 3132 @protocol OcFixture
dev@189 3133
dev@189 3134 @optional
dev@189 3135
dev@189 3136 -(void) setUp;
dev@189 3137 -(void) tearDown;
dev@189 3138
dev@189 3139 @end
dev@189 3140
dev@189 3141 namespace Catch {
dev@189 3142
dev@189 3143 class OcMethod : public SharedImpl<ITestCase> {
dev@189 3144
dev@189 3145 public:
dev@189 3146 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
dev@189 3147
dev@189 3148 virtual void invoke() const {
dev@189 3149 id obj = [[m_cls alloc] init];
dev@189 3150
dev@189 3151 performOptionalSelector( obj, @selector(setUp) );
dev@189 3152 performOptionalSelector( obj, m_sel );
dev@189 3153 performOptionalSelector( obj, @selector(tearDown) );
dev@189 3154
dev@189 3155 arcSafeRelease( obj );
dev@189 3156 }
dev@189 3157 private:
dev@189 3158 virtual ~OcMethod() {}
dev@189 3159
dev@189 3160 Class m_cls;
dev@189 3161 SEL m_sel;
dev@189 3162 };
dev@189 3163
dev@189 3164 namespace Detail{
dev@189 3165
dev@189 3166 inline std::string getAnnotation( Class cls,
dev@189 3167 std::string const& annotationName,
dev@189 3168 std::string const& testCaseName ) {
dev@189 3169 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
dev@189 3170 SEL sel = NSSelectorFromString( selStr );
dev@189 3171 arcSafeRelease( selStr );
dev@189 3172 id value = performOptionalSelector( cls, sel );
dev@189 3173 if( value )
dev@189 3174 return [(NSString*)value UTF8String];
dev@189 3175 return "";
dev@189 3176 }
dev@189 3177 }
dev@189 3178
dev@189 3179 inline size_t registerTestMethods() {
dev@189 3180 size_t noTestMethods = 0;
dev@189 3181 int noClasses = objc_getClassList( CATCH_NULL, 0 );
dev@189 3182
dev@189 3183 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
dev@189 3184 objc_getClassList( classes, noClasses );
dev@189 3185
dev@189 3186 for( int c = 0; c < noClasses; c++ ) {
dev@189 3187 Class cls = classes[c];
dev@189 3188 {
dev@189 3189 u_int count;
dev@189 3190 Method* methods = class_copyMethodList( cls, &count );
dev@189 3191 for( u_int m = 0; m < count ; m++ ) {
dev@189 3192 SEL selector = method_getName(methods[m]);
dev@189 3193 std::string methodName = sel_getName(selector);
dev@189 3194 if( startsWith( methodName, "Catch_TestCase_" ) ) {
dev@189 3195 std::string testCaseName = methodName.substr( 15 );
dev@189 3196 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
dev@189 3197 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
dev@189 3198 const char* className = class_getName( cls );
dev@189 3199
dev@189 3200 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
dev@189 3201 noTestMethods++;
dev@189 3202 }
dev@189 3203 }
dev@189 3204 free(methods);
dev@189 3205 }
dev@189 3206 }
dev@189 3207 return noTestMethods;
dev@189 3208 }
dev@189 3209
dev@189 3210 namespace Matchers {
dev@189 3211 namespace Impl {
dev@189 3212 namespace NSStringMatchers {
dev@189 3213
dev@189 3214 template<typename MatcherT>
dev@189 3215 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
dev@189 3216 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
dev@189 3217 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
dev@189 3218 StringHolder() {
dev@189 3219 arcSafeRelease( m_substr );
dev@189 3220 }
dev@189 3221
dev@189 3222 NSString* m_substr;
dev@189 3223 };
dev@189 3224
dev@189 3225 struct Equals : StringHolder<Equals> {
dev@189 3226 Equals( NSString* substr ) : StringHolder( substr ){}
dev@189 3227
dev@189 3228 virtual bool match( ExpressionType const& str ) const {
dev@189 3229 return (str != nil || m_substr == nil ) &&
dev@189 3230 [str isEqualToString:m_substr];
dev@189 3231 }
dev@189 3232
dev@189 3233 virtual std::string toString() const {
dev@189 3234 return "equals string: " + Catch::toString( m_substr );
dev@189 3235 }
dev@189 3236 };
dev@189 3237
dev@189 3238 struct Contains : StringHolder<Contains> {
dev@189 3239 Contains( NSString* substr ) : StringHolder( substr ){}
dev@189 3240
dev@189 3241 virtual bool match( ExpressionType const& str ) const {
dev@189 3242 return (str != nil || m_substr == nil ) &&
dev@189 3243 [str rangeOfString:m_substr].location != NSNotFound;
dev@189 3244 }
dev@189 3245
dev@189 3246 virtual std::string toString() const {
dev@189 3247 return "contains string: " + Catch::toString( m_substr );
dev@189 3248 }
dev@189 3249 };
dev@189 3250
dev@189 3251 struct StartsWith : StringHolder<StartsWith> {
dev@189 3252 StartsWith( NSString* substr ) : StringHolder( substr ){}
dev@189 3253
dev@189 3254 virtual bool match( ExpressionType const& str ) const {
dev@189 3255 return (str != nil || m_substr == nil ) &&
dev@189 3256 [str rangeOfString:m_substr].location == 0;
dev@189 3257 }
dev@189 3258
dev@189 3259 virtual std::string toString() const {
dev@189 3260 return "starts with: " + Catch::toString( m_substr );
dev@189 3261 }
dev@189 3262 };
dev@189 3263 struct EndsWith : StringHolder<EndsWith> {
dev@189 3264 EndsWith( NSString* substr ) : StringHolder( substr ){}
dev@189 3265
dev@189 3266 virtual bool match( ExpressionType const& str ) const {
dev@189 3267 return (str != nil || m_substr == nil ) &&
dev@189 3268 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
dev@189 3269 }
dev@189 3270
dev@189 3271 virtual std::string toString() const {
dev@189 3272 return "ends with: " + Catch::toString( m_substr );
dev@189 3273 }
dev@189 3274 };
dev@189 3275
dev@189 3276 } // namespace NSStringMatchers
dev@189 3277 } // namespace Impl
dev@189 3278
dev@189 3279 inline Impl::NSStringMatchers::Equals
dev@189 3280 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
dev@189 3281
dev@189 3282 inline Impl::NSStringMatchers::Contains
dev@189 3283 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
dev@189 3284
dev@189 3285 inline Impl::NSStringMatchers::StartsWith
dev@189 3286 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
dev@189 3287
dev@189 3288 inline Impl::NSStringMatchers::EndsWith
dev@189 3289 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
dev@189 3290
dev@189 3291 } // namespace Matchers
dev@189 3292
dev@189 3293 using namespace Matchers;
dev@189 3294
dev@189 3295 } // namespace Catch
dev@189 3296
dev@189 3297 ///////////////////////////////////////////////////////////////////////////////
dev@189 3298 #define OC_TEST_CASE( name, desc )\
dev@189 3299 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
dev@189 3300 {\
dev@189 3301 return @ name; \
dev@189 3302 }\
dev@189 3303 +(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
dev@189 3304 { \
dev@189 3305 return @ desc; \
dev@189 3306 } \
dev@189 3307 -(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
dev@189 3308
dev@189 3309 #endif
dev@189 3310
dev@189 3311 #ifdef CATCH_IMPL
dev@189 3312 // #included from: internal/catch_impl.hpp
dev@189 3313 #define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
dev@189 3314
dev@189 3315 // Collect all the implementation files together here
dev@189 3316 // These are the equivalent of what would usually be cpp files
dev@189 3317
dev@189 3318 #ifdef __clang__
dev@189 3319 #pragma clang diagnostic push
dev@189 3320 #pragma clang diagnostic ignored "-Wweak-vtables"
dev@189 3321 #endif
dev@189 3322
dev@189 3323 // #included from: ../catch_session.hpp
dev@189 3324 #define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
dev@189 3325
dev@189 3326 // #included from: internal/catch_commandline.hpp
dev@189 3327 #define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
dev@189 3328
dev@189 3329 // #included from: catch_config.hpp
dev@189 3330 #define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
dev@189 3331
dev@189 3332 // #included from: catch_test_spec_parser.hpp
dev@189 3333 #define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
dev@189 3334
dev@189 3335 #ifdef __clang__
dev@189 3336 #pragma clang diagnostic push
dev@189 3337 #pragma clang diagnostic ignored "-Wpadded"
dev@189 3338 #endif
dev@189 3339
dev@189 3340 // #included from: catch_test_spec.hpp
dev@189 3341 #define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
dev@189 3342
dev@189 3343 #ifdef __clang__
dev@189 3344 #pragma clang diagnostic push
dev@189 3345 #pragma clang diagnostic ignored "-Wpadded"
dev@189 3346 #endif
dev@189 3347
dev@189 3348 // #included from: catch_wildcard_pattern.hpp
dev@189 3349 #define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
dev@189 3350
dev@189 3351 namespace Catch
dev@189 3352 {
dev@189 3353 class WildcardPattern {
dev@189 3354 enum WildcardPosition {
dev@189 3355 NoWildcard = 0,
dev@189 3356 WildcardAtStart = 1,
dev@189 3357 WildcardAtEnd = 2,
dev@189 3358 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
dev@189 3359 };
dev@189 3360
dev@189 3361 public:
dev@189 3362
dev@189 3363 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
dev@189 3364 : m_caseSensitivity( caseSensitivity ),
dev@189 3365 m_wildcard( NoWildcard ),
dev@189 3366 m_pattern( adjustCase( pattern ) )
dev@189 3367 {
dev@189 3368 if( startsWith( m_pattern, '*' ) ) {
dev@189 3369 m_pattern = m_pattern.substr( 1 );
dev@189 3370 m_wildcard = WildcardAtStart;
dev@189 3371 }
dev@189 3372 if( endsWith( m_pattern, '*' ) ) {
dev@189 3373 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
dev@189 3374 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
dev@189 3375 }
dev@189 3376 }
dev@189 3377 virtual ~WildcardPattern();
dev@189 3378 virtual bool matches( std::string const& str ) const {
dev@189 3379 switch( m_wildcard ) {
dev@189 3380 case NoWildcard:
dev@189 3381 return m_pattern == adjustCase( str );
dev@189 3382 case WildcardAtStart:
dev@189 3383 return endsWith( adjustCase( str ), m_pattern );
dev@189 3384 case WildcardAtEnd:
dev@189 3385 return startsWith( adjustCase( str ), m_pattern );
dev@189 3386 case WildcardAtBothEnds:
dev@189 3387 return contains( adjustCase( str ), m_pattern );
dev@189 3388 }
dev@189 3389
dev@189 3390 #ifdef __clang__
dev@189 3391 #pragma clang diagnostic push
dev@189 3392 #pragma clang diagnostic ignored "-Wunreachable-code"
dev@189 3393 #endif
dev@189 3394 throw std::logic_error( "Unknown enum" );
dev@189 3395 #ifdef __clang__
dev@189 3396 #pragma clang diagnostic pop
dev@189 3397 #endif
dev@189 3398 }
dev@189 3399 private:
dev@189 3400 std::string adjustCase( std::string const& str ) const {
dev@189 3401 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
dev@189 3402 }
dev@189 3403 CaseSensitive::Choice m_caseSensitivity;
dev@189 3404 WildcardPosition m_wildcard;
dev@189 3405 std::string m_pattern;
dev@189 3406 };
dev@189 3407 }
dev@189 3408
dev@189 3409 #include <string>
dev@189 3410 #include <vector>
dev@189 3411
dev@189 3412 namespace Catch {
dev@189 3413
dev@189 3414 class TestSpec {
dev@189 3415 struct Pattern : SharedImpl<> {
dev@189 3416 virtual ~Pattern();
dev@189 3417 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
dev@189 3418 };
dev@189 3419 class NamePattern : public Pattern {
dev@189 3420 public:
dev@189 3421 NamePattern( std::string const& name )
dev@189 3422 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
dev@189 3423 {}
dev@189 3424 virtual ~NamePattern();
dev@189 3425 virtual bool matches( TestCaseInfo const& testCase ) const {
dev@189 3426 return m_wildcardPattern.matches( toLower( testCase.name ) );
dev@189 3427 }
dev@189 3428 private:
dev@189 3429 WildcardPattern m_wildcardPattern;
dev@189 3430 };
dev@189 3431
dev@189 3432 class TagPattern : public Pattern {
dev@189 3433 public:
dev@189 3434 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
dev@189 3435 virtual ~TagPattern();
dev@189 3436 virtual bool matches( TestCaseInfo const& testCase ) const {
dev@189 3437 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
dev@189 3438 }
dev@189 3439 private:
dev@189 3440 std::string m_tag;
dev@189 3441 };
dev@189 3442
dev@189 3443 class ExcludedPattern : public Pattern {
dev@189 3444 public:
dev@189 3445 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
dev@189 3446 virtual ~ExcludedPattern();
dev@189 3447 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
dev@189 3448 private:
dev@189 3449 Ptr<Pattern> m_underlyingPattern;
dev@189 3450 };
dev@189 3451
dev@189 3452 struct Filter {
dev@189 3453 std::vector<Ptr<Pattern> > m_patterns;
dev@189 3454
dev@189 3455 bool matches( TestCaseInfo const& testCase ) const {
dev@189 3456 // All patterns in a filter must match for the filter to be a match
dev@189 3457 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
dev@189 3458 if( !(*it)->matches( testCase ) )
dev@189 3459 return false;
dev@189 3460 }
dev@189 3461 return true;
dev@189 3462 }
dev@189 3463 };
dev@189 3464
dev@189 3465 public:
dev@189 3466 bool hasFilters() const {
dev@189 3467 return !m_filters.empty();
dev@189 3468 }
dev@189 3469 bool matches( TestCaseInfo const& testCase ) const {
dev@189 3470 // A TestSpec matches if any filter matches
dev@189 3471 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
dev@189 3472 if( it->matches( testCase ) )
dev@189 3473 return true;
dev@189 3474 return false;
dev@189 3475 }
dev@189 3476
dev@189 3477 private:
dev@189 3478 std::vector<Filter> m_filters;
dev@189 3479
dev@189 3480 friend class TestSpecParser;
dev@189 3481 };
dev@189 3482 }
dev@189 3483
dev@189 3484 #ifdef __clang__
dev@189 3485 #pragma clang diagnostic pop
dev@189 3486 #endif
dev@189 3487
dev@189 3488 namespace Catch {
dev@189 3489
dev@189 3490 class TestSpecParser {
dev@189 3491 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
dev@189 3492 Mode m_mode;
dev@189 3493 bool m_exclusion;
dev@189 3494 std::size_t m_start, m_pos;
dev@189 3495 std::string m_arg;
dev@189 3496 std::vector<std::size_t> m_escapeChars;
dev@189 3497 TestSpec::Filter m_currentFilter;
dev@189 3498 TestSpec m_testSpec;
dev@189 3499 ITagAliasRegistry const* m_tagAliases;
dev@189 3500
dev@189 3501 public:
dev@189 3502 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
dev@189 3503
dev@189 3504 TestSpecParser& parse( std::string const& arg ) {
dev@189 3505 m_mode = None;
dev@189 3506 m_exclusion = false;
dev@189 3507 m_start = std::string::npos;
dev@189 3508 m_arg = m_tagAliases->expandAliases( arg );
dev@189 3509 m_escapeChars.clear();
dev@189 3510 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
dev@189 3511 visitChar( m_arg[m_pos] );
dev@189 3512 if( m_mode == Name )
dev@189 3513 addPattern<TestSpec::NamePattern>();
dev@189 3514 return *this;
dev@189 3515 }
dev@189 3516 TestSpec testSpec() {
dev@189 3517 addFilter();
dev@189 3518 return m_testSpec;
dev@189 3519 }
dev@189 3520 private:
dev@189 3521 void visitChar( char c ) {
dev@189 3522 if( m_mode == None ) {
dev@189 3523 switch( c ) {
dev@189 3524 case ' ': return;
dev@189 3525 case '~': m_exclusion = true; return;
dev@189 3526 case '[': return startNewMode( Tag, ++m_pos );
dev@189 3527 case '"': return startNewMode( QuotedName, ++m_pos );
dev@189 3528 case '\\': return escape();
dev@189 3529 default: startNewMode( Name, m_pos ); break;
dev@189 3530 }
dev@189 3531 }
dev@189 3532 if( m_mode == Name ) {
dev@189 3533 if( c == ',' ) {
dev@189 3534 addPattern<TestSpec::NamePattern>();
dev@189 3535 addFilter();
dev@189 3536 }
dev@189 3537 else if( c == '[' ) {
dev@189 3538 if( subString() == "exclude:" )
dev@189 3539 m_exclusion = true;
dev@189 3540 else
dev@189 3541 addPattern<TestSpec::NamePattern>();
dev@189 3542 startNewMode( Tag, ++m_pos );
dev@189 3543 }
dev@189 3544 else if( c == '\\' )
dev@189 3545 escape();
dev@189 3546 }
dev@189 3547 else if( m_mode == EscapedName )
dev@189 3548 m_mode = Name;
dev@189 3549 else if( m_mode == QuotedName && c == '"' )
dev@189 3550 addPattern<TestSpec::NamePattern>();
dev@189 3551 else if( m_mode == Tag && c == ']' )
dev@189 3552 addPattern<TestSpec::TagPattern>();
dev@189 3553 }
dev@189 3554 void startNewMode( Mode mode, std::size_t start ) {
dev@189 3555 m_mode = mode;
dev@189 3556 m_start = start;
dev@189 3557 }
dev@189 3558 void escape() {
dev@189 3559 if( m_mode == None )
dev@189 3560 m_start = m_pos;
dev@189 3561 m_mode = EscapedName;
dev@189 3562 m_escapeChars.push_back( m_pos );
dev@189 3563 }
dev@189 3564 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
dev@189 3565 template<typename T>
dev@189 3566 void addPattern() {
dev@189 3567 std::string token = subString();
dev@189 3568 for( size_t i = 0; i < m_escapeChars.size(); ++i )
dev@189 3569 token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i );
dev@189 3570 m_escapeChars.clear();
dev@189 3571 if( startsWith( token, "exclude:" ) ) {
dev@189 3572 m_exclusion = true;
dev@189 3573 token = token.substr( 8 );
dev@189 3574 }
dev@189 3575 if( !token.empty() ) {
dev@189 3576 Ptr<TestSpec::Pattern> pattern = new T( token );
dev@189 3577 if( m_exclusion )
dev@189 3578 pattern = new TestSpec::ExcludedPattern( pattern );
dev@189 3579 m_currentFilter.m_patterns.push_back( pattern );
dev@189 3580 }
dev@189 3581 m_exclusion = false;
dev@189 3582 m_mode = None;
dev@189 3583 }
dev@189 3584 void addFilter() {
dev@189 3585 if( !m_currentFilter.m_patterns.empty() ) {
dev@189 3586 m_testSpec.m_filters.push_back( m_currentFilter );
dev@189 3587 m_currentFilter = TestSpec::Filter();
dev@189 3588 }
dev@189 3589 }
dev@189 3590 };
dev@189 3591 inline TestSpec parseTestSpec( std::string const& arg ) {
dev@189 3592 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
dev@189 3593 }
dev@189 3594
dev@189 3595 } // namespace Catch
dev@189 3596
dev@189 3597 #ifdef __clang__
dev@189 3598 #pragma clang diagnostic pop
dev@189 3599 #endif
dev@189 3600
dev@189 3601 // #included from: catch_interfaces_config.h
dev@189 3602 #define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
dev@189 3603
dev@189 3604 #include <iostream>
dev@189 3605 #include <string>
dev@189 3606 #include <vector>
dev@189 3607
dev@189 3608 namespace Catch {
dev@189 3609
dev@189 3610 struct Verbosity { enum Level {
dev@189 3611 NoOutput = 0,
dev@189 3612 Quiet,
dev@189 3613 Normal
dev@189 3614 }; };
dev@189 3615
dev@189 3616 struct WarnAbout { enum What {
dev@189 3617 Nothing = 0x00,
dev@189 3618 NoAssertions = 0x01
dev@189 3619 }; };
dev@189 3620
dev@189 3621 struct ShowDurations { enum OrNot {
dev@189 3622 DefaultForReporter,
dev@189 3623 Always,
dev@189 3624 Never
dev@189 3625 }; };
dev@189 3626 struct RunTests { enum InWhatOrder {
dev@189 3627 InDeclarationOrder,
dev@189 3628 InLexicographicalOrder,
dev@189 3629 InRandomOrder
dev@189 3630 }; };
dev@189 3631 struct UseColour { enum YesOrNo {
dev@189 3632 Auto,
dev@189 3633 Yes,
dev@189 3634 No
dev@189 3635 }; };
dev@189 3636
dev@189 3637 class TestSpec;
dev@189 3638
dev@189 3639 struct IConfig : IShared {
dev@189 3640
dev@189 3641 virtual ~IConfig();
dev@189 3642
dev@189 3643 virtual bool allowThrows() const = 0;
dev@189 3644 virtual std::ostream& stream() const = 0;
dev@189 3645 virtual std::string name() const = 0;
dev@189 3646 virtual bool includeSuccessfulResults() const = 0;
dev@189 3647 virtual bool shouldDebugBreak() const = 0;
dev@189 3648 virtual bool warnAboutMissingAssertions() const = 0;
dev@189 3649 virtual int abortAfter() const = 0;
dev@189 3650 virtual bool showInvisibles() const = 0;
dev@189 3651 virtual ShowDurations::OrNot showDurations() const = 0;
dev@189 3652 virtual TestSpec const& testSpec() const = 0;
dev@189 3653 virtual RunTests::InWhatOrder runOrder() const = 0;
dev@189 3654 virtual unsigned int rngSeed() const = 0;
dev@189 3655 virtual UseColour::YesOrNo useColour() const = 0;
dev@189 3656 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
dev@189 3657
dev@189 3658 };
dev@189 3659 }
dev@189 3660
dev@189 3661 // #included from: catch_stream.h
dev@189 3662 #define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
dev@189 3663
dev@189 3664 // #included from: catch_streambuf.h
dev@189 3665 #define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
dev@189 3666
dev@189 3667 #include <streambuf>
dev@189 3668
dev@189 3669 namespace Catch {
dev@189 3670
dev@189 3671 class StreamBufBase : public std::streambuf {
dev@189 3672 public:
dev@189 3673 virtual ~StreamBufBase() CATCH_NOEXCEPT;
dev@189 3674 };
dev@189 3675 }
dev@189 3676
dev@189 3677 #include <streambuf>
dev@189 3678 #include <ostream>
dev@189 3679 #include <fstream>
dev@189 3680 #include <memory>
dev@189 3681
dev@189 3682 namespace Catch {
dev@189 3683
dev@189 3684 std::ostream& cout();
dev@189 3685 std::ostream& cerr();
dev@189 3686
dev@189 3687 struct IStream {
dev@189 3688 virtual ~IStream() CATCH_NOEXCEPT;
dev@189 3689 virtual std::ostream& stream() const = 0;
dev@189 3690 };
dev@189 3691
dev@189 3692 class FileStream : public IStream {
dev@189 3693 mutable std::ofstream m_ofs;
dev@189 3694 public:
dev@189 3695 FileStream( std::string const& filename );
dev@189 3696 virtual ~FileStream() CATCH_NOEXCEPT;
dev@189 3697 public: // IStream
dev@189 3698 virtual std::ostream& stream() const CATCH_OVERRIDE;
dev@189 3699 };
dev@189 3700
dev@189 3701 class CoutStream : public IStream {
dev@189 3702 mutable std::ostream m_os;
dev@189 3703 public:
dev@189 3704 CoutStream();
dev@189 3705 virtual ~CoutStream() CATCH_NOEXCEPT;
dev@189 3706
dev@189 3707 public: // IStream
dev@189 3708 virtual std::ostream& stream() const CATCH_OVERRIDE;
dev@189 3709 };
dev@189 3710
dev@189 3711 class DebugOutStream : public IStream {
dev@189 3712 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
dev@189 3713 mutable std::ostream m_os;
dev@189 3714 public:
dev@189 3715 DebugOutStream();
dev@189 3716 virtual ~DebugOutStream() CATCH_NOEXCEPT;
dev@189 3717
dev@189 3718 public: // IStream
dev@189 3719 virtual std::ostream& stream() const CATCH_OVERRIDE;
dev@189 3720 };
dev@189 3721 }
dev@189 3722
dev@189 3723 #include <memory>
dev@189 3724 #include <vector>
dev@189 3725 #include <string>
dev@189 3726 #include <iostream>
dev@189 3727 #include <ctime>
dev@189 3728
dev@189 3729 #ifndef CATCH_CONFIG_CONSOLE_WIDTH
dev@189 3730 #define CATCH_CONFIG_CONSOLE_WIDTH 80
dev@189 3731 #endif
dev@189 3732
dev@189 3733 namespace Catch {
dev@189 3734
dev@189 3735 struct ConfigData {
dev@189 3736
dev@189 3737 ConfigData()
dev@189 3738 : listTests( false ),
dev@189 3739 listTags( false ),
dev@189 3740 listReporters( false ),
dev@189 3741 listTestNamesOnly( false ),
dev@189 3742 showSuccessfulTests( false ),
dev@189 3743 shouldDebugBreak( false ),
dev@189 3744 noThrow( false ),
dev@189 3745 showHelp( false ),
dev@189 3746 showInvisibles( false ),
dev@189 3747 filenamesAsTags( false ),
dev@189 3748 abortAfter( -1 ),
dev@189 3749 rngSeed( 0 ),
dev@189 3750 verbosity( Verbosity::Normal ),
dev@189 3751 warnings( WarnAbout::Nothing ),
dev@189 3752 showDurations( ShowDurations::DefaultForReporter ),
dev@189 3753 runOrder( RunTests::InDeclarationOrder ),
dev@189 3754 useColour( UseColour::Auto )
dev@189 3755 {}
dev@189 3756
dev@189 3757 bool listTests;
dev@189 3758 bool listTags;
dev@189 3759 bool listReporters;
dev@189 3760 bool listTestNamesOnly;
dev@189 3761
dev@189 3762 bool showSuccessfulTests;
dev@189 3763 bool shouldDebugBreak;
dev@189 3764 bool noThrow;
dev@189 3765 bool showHelp;
dev@189 3766 bool showInvisibles;
dev@189 3767 bool filenamesAsTags;
dev@189 3768
dev@189 3769 int abortAfter;
dev@189 3770 unsigned int rngSeed;
dev@189 3771
dev@189 3772 Verbosity::Level verbosity;
dev@189 3773 WarnAbout::What warnings;
dev@189 3774 ShowDurations::OrNot showDurations;
dev@189 3775 RunTests::InWhatOrder runOrder;
dev@189 3776 UseColour::YesOrNo useColour;
dev@189 3777
dev@189 3778 std::string outputFilename;
dev@189 3779 std::string name;
dev@189 3780 std::string processName;
dev@189 3781
dev@189 3782 std::vector<std::string> reporterNames;
dev@189 3783 std::vector<std::string> testsOrTags;
dev@189 3784 std::vector<std::string> sectionsToRun;
dev@189 3785 };
dev@189 3786
dev@189 3787 class Config : public SharedImpl<IConfig> {
dev@189 3788 private:
dev@189 3789 Config( Config const& other );
dev@189 3790 Config& operator = ( Config const& other );
dev@189 3791 virtual void dummy();
dev@189 3792 public:
dev@189 3793
dev@189 3794 Config()
dev@189 3795 {}
dev@189 3796
dev@189 3797 Config( ConfigData const& data )
dev@189 3798 : m_data( data ),
dev@189 3799 m_stream( openStream() )
dev@189 3800 {
dev@189 3801 if( !data.testsOrTags.empty() ) {
dev@189 3802 TestSpecParser parser( ITagAliasRegistry::get() );
dev@189 3803 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
dev@189 3804 parser.parse( data.testsOrTags[i] );
dev@189 3805 m_testSpec = parser.testSpec();
dev@189 3806 }
dev@189 3807 }
dev@189 3808
dev@189 3809 virtual ~Config() {
dev@189 3810 }
dev@189 3811
dev@189 3812 std::string const& getFilename() const {
dev@189 3813 return m_data.outputFilename ;
dev@189 3814 }
dev@189 3815
dev@189 3816 bool listTests() const { return m_data.listTests; }
dev@189 3817 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
dev@189 3818 bool listTags() const { return m_data.listTags; }
dev@189 3819 bool listReporters() const { return m_data.listReporters; }
dev@189 3820
dev@189 3821 std::string getProcessName() const { return m_data.processName; }
dev@189 3822
dev@189 3823 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
dev@189 3824
dev@189 3825 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
dev@189 3826 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
dev@189 3827
dev@189 3828 int abortAfter() const { return m_data.abortAfter; }
dev@189 3829
dev@189 3830 TestSpec const& testSpec() const { return m_testSpec; }
dev@189 3831
dev@189 3832 bool showHelp() const { return m_data.showHelp; }
dev@189 3833 bool showInvisibles() const { return m_data.showInvisibles; }
dev@189 3834
dev@189 3835 // IConfig interface
dev@189 3836 virtual bool allowThrows() const { return !m_data.noThrow; }
dev@189 3837 virtual std::ostream& stream() const { return m_stream->stream(); }
dev@189 3838 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
dev@189 3839 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
dev@189 3840 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
dev@189 3841 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
dev@189 3842 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
dev@189 3843 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
dev@189 3844 virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
dev@189 3845
dev@189 3846 private:
dev@189 3847
dev@189 3848 IStream const* openStream() {
dev@189 3849 if( m_data.outputFilename.empty() )
dev@189 3850 return new CoutStream();
dev@189 3851 else if( m_data.outputFilename[0] == '%' ) {
dev@189 3852 if( m_data.outputFilename == "%debug" )
dev@189 3853 return new DebugOutStream();
dev@189 3854 else
dev@189 3855 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
dev@189 3856 }
dev@189 3857 else
dev@189 3858 return new FileStream( m_data.outputFilename );
dev@189 3859 }
dev@189 3860 ConfigData m_data;
dev@189 3861
dev@189 3862 CATCH_AUTO_PTR( IStream const ) m_stream;
dev@189 3863 TestSpec m_testSpec;
dev@189 3864 };
dev@189 3865
dev@189 3866 } // end namespace Catch
dev@189 3867
dev@189 3868 // #included from: catch_clara.h
dev@189 3869 #define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
dev@189 3870
dev@189 3871 // Use Catch's value for console width (store Clara's off to the side, if present)
dev@189 3872 #ifdef CLARA_CONFIG_CONSOLE_WIDTH
dev@189 3873 #define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
dev@189 3874 #undef CLARA_CONFIG_CONSOLE_WIDTH
dev@189 3875 #endif
dev@189 3876 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
dev@189 3877
dev@189 3878 // Declare Clara inside the Catch namespace
dev@189 3879 #define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
dev@189 3880 // #included from: ../external/clara.h
dev@189 3881
dev@189 3882 // Version 0.0.2.4
dev@189 3883
dev@189 3884 // Only use header guard if we are not using an outer namespace
dev@189 3885 #if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
dev@189 3886
dev@189 3887 #ifndef STITCH_CLARA_OPEN_NAMESPACE
dev@189 3888 #define TWOBLUECUBES_CLARA_H_INCLUDED
dev@189 3889 #define STITCH_CLARA_OPEN_NAMESPACE
dev@189 3890 #define STITCH_CLARA_CLOSE_NAMESPACE
dev@189 3891 #else
dev@189 3892 #define STITCH_CLARA_CLOSE_NAMESPACE }
dev@189 3893 #endif
dev@189 3894
dev@189 3895 #define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
dev@189 3896
dev@189 3897 // ----------- #included from tbc_text_format.h -----------
dev@189 3898
dev@189 3899 // Only use header guard if we are not using an outer namespace
dev@189 3900 #if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
dev@189 3901 #ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 3902 #define TBC_TEXT_FORMAT_H_INCLUDED
dev@189 3903 #endif
dev@189 3904
dev@189 3905 #include <string>
dev@189 3906 #include <vector>
dev@189 3907 #include <sstream>
dev@189 3908 #include <algorithm>
dev@189 3909
dev@189 3910 // Use optional outer namespace
dev@189 3911 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 3912 namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
dev@189 3913 #endif
dev@189 3914
dev@189 3915 namespace Tbc {
dev@189 3916
dev@189 3917 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
dev@189 3918 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
dev@189 3919 #else
dev@189 3920 const unsigned int consoleWidth = 80;
dev@189 3921 #endif
dev@189 3922
dev@189 3923 struct TextAttributes {
dev@189 3924 TextAttributes()
dev@189 3925 : initialIndent( std::string::npos ),
dev@189 3926 indent( 0 ),
dev@189 3927 width( consoleWidth-1 ),
dev@189 3928 tabChar( '\t' )
dev@189 3929 {}
dev@189 3930
dev@189 3931 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
dev@189 3932 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
dev@189 3933 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
dev@189 3934 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
dev@189 3935
dev@189 3936 std::size_t initialIndent; // indent of first line, or npos
dev@189 3937 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
dev@189 3938 std::size_t width; // maximum width of text, including indent. Longer text will wrap
dev@189 3939 char tabChar; // If this char is seen the indent is changed to current pos
dev@189 3940 };
dev@189 3941
dev@189 3942 class Text {
dev@189 3943 public:
dev@189 3944 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
dev@189 3945 : attr( _attr )
dev@189 3946 {
dev@189 3947 std::string wrappableChars = " [({.,/|\\-";
dev@189 3948 std::size_t indent = _attr.initialIndent != std::string::npos
dev@189 3949 ? _attr.initialIndent
dev@189 3950 : _attr.indent;
dev@189 3951 std::string remainder = _str;
dev@189 3952
dev@189 3953 while( !remainder.empty() ) {
dev@189 3954 if( lines.size() >= 1000 ) {
dev@189 3955 lines.push_back( "... message truncated due to excessive size" );
dev@189 3956 return;
dev@189 3957 }
dev@189 3958 std::size_t tabPos = std::string::npos;
dev@189 3959 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
dev@189 3960 std::size_t pos = remainder.find_first_of( '\n' );
dev@189 3961 if( pos <= width ) {
dev@189 3962 width = pos;
dev@189 3963 }
dev@189 3964 pos = remainder.find_last_of( _attr.tabChar, width );
dev@189 3965 if( pos != std::string::npos ) {
dev@189 3966 tabPos = pos;
dev@189 3967 if( remainder[width] == '\n' )
dev@189 3968 width--;
dev@189 3969 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
dev@189 3970 }
dev@189 3971
dev@189 3972 if( width == remainder.size() ) {
dev@189 3973 spliceLine( indent, remainder, width );
dev@189 3974 }
dev@189 3975 else if( remainder[width] == '\n' ) {
dev@189 3976 spliceLine( indent, remainder, width );
dev@189 3977 if( width <= 1 || remainder.size() != 1 )
dev@189 3978 remainder = remainder.substr( 1 );
dev@189 3979 indent = _attr.indent;
dev@189 3980 }
dev@189 3981 else {
dev@189 3982 pos = remainder.find_last_of( wrappableChars, width );
dev@189 3983 if( pos != std::string::npos && pos > 0 ) {
dev@189 3984 spliceLine( indent, remainder, pos );
dev@189 3985 if( remainder[0] == ' ' )
dev@189 3986 remainder = remainder.substr( 1 );
dev@189 3987 }
dev@189 3988 else {
dev@189 3989 spliceLine( indent, remainder, width-1 );
dev@189 3990 lines.back() += "-";
dev@189 3991 }
dev@189 3992 if( lines.size() == 1 )
dev@189 3993 indent = _attr.indent;
dev@189 3994 if( tabPos != std::string::npos )
dev@189 3995 indent += tabPos;
dev@189 3996 }
dev@189 3997 }
dev@189 3998 }
dev@189 3999
dev@189 4000 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
dev@189 4001 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
dev@189 4002 _remainder = _remainder.substr( _pos );
dev@189 4003 }
dev@189 4004
dev@189 4005 typedef std::vector<std::string>::const_iterator const_iterator;
dev@189 4006
dev@189 4007 const_iterator begin() const { return lines.begin(); }
dev@189 4008 const_iterator end() const { return lines.end(); }
dev@189 4009 std::string const& last() const { return lines.back(); }
dev@189 4010 std::size_t size() const { return lines.size(); }
dev@189 4011 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
dev@189 4012 std::string toString() const {
dev@189 4013 std::ostringstream oss;
dev@189 4014 oss << *this;
dev@189 4015 return oss.str();
dev@189 4016 }
dev@189 4017
dev@189 4018 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
dev@189 4019 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
dev@189 4020 it != itEnd; ++it ) {
dev@189 4021 if( it != _text.begin() )
dev@189 4022 _stream << "\n";
dev@189 4023 _stream << *it;
dev@189 4024 }
dev@189 4025 return _stream;
dev@189 4026 }
dev@189 4027
dev@189 4028 private:
dev@189 4029 std::string str;
dev@189 4030 TextAttributes attr;
dev@189 4031 std::vector<std::string> lines;
dev@189 4032 };
dev@189 4033
dev@189 4034 } // end namespace Tbc
dev@189 4035
dev@189 4036 #ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 4037 } // end outer namespace
dev@189 4038 #endif
dev@189 4039
dev@189 4040 #endif // TBC_TEXT_FORMAT_H_INCLUDED
dev@189 4041
dev@189 4042 // ----------- end of #include from tbc_text_format.h -----------
dev@189 4043 // ........... back in clara.h
dev@189 4044
dev@189 4045 #undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
dev@189 4046
dev@189 4047 // ----------- #included from clara_compilers.h -----------
dev@189 4048
dev@189 4049 #ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
dev@189 4050 #define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
dev@189 4051
dev@189 4052 // Detect a number of compiler features - mostly C++11/14 conformance - by compiler
dev@189 4053 // The following features are defined:
dev@189 4054 //
dev@189 4055 // CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
dev@189 4056 // CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
dev@189 4057 // CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
dev@189 4058 // CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
dev@189 4059 // CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
dev@189 4060
dev@189 4061 // CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
dev@189 4062
dev@189 4063 // CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
dev@189 4064
dev@189 4065 // In general each macro has a _NO_<feature name> form
dev@189 4066 // (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
dev@189 4067 // Many features, at point of detection, define an _INTERNAL_ macro, so they
dev@189 4068 // can be combined, en-mass, with the _NO_ forms later.
dev@189 4069
dev@189 4070 // All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
dev@189 4071
dev@189 4072 #ifdef __clang__
dev@189 4073
dev@189 4074 #if __has_feature(cxx_nullptr)
dev@189 4075 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 4076 #endif
dev@189 4077
dev@189 4078 #if __has_feature(cxx_noexcept)
dev@189 4079 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 4080 #endif
dev@189 4081
dev@189 4082 #endif // __clang__
dev@189 4083
dev@189 4084 ////////////////////////////////////////////////////////////////////////////////
dev@189 4085 // GCC
dev@189 4086 #ifdef __GNUC__
dev@189 4087
dev@189 4088 #if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
dev@189 4089 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 4090 #endif
dev@189 4091
dev@189 4092 // - otherwise more recent versions define __cplusplus >= 201103L
dev@189 4093 // and will get picked up below
dev@189 4094
dev@189 4095 #endif // __GNUC__
dev@189 4096
dev@189 4097 ////////////////////////////////////////////////////////////////////////////////
dev@189 4098 // Visual C++
dev@189 4099 #ifdef _MSC_VER
dev@189 4100
dev@189 4101 #if (_MSC_VER >= 1600)
dev@189 4102 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 4103 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
dev@189 4104 #endif
dev@189 4105
dev@189 4106 #if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
dev@189 4107 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 4108 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 4109 #endif
dev@189 4110
dev@189 4111 #endif // _MSC_VER
dev@189 4112
dev@189 4113 ////////////////////////////////////////////////////////////////////////////////
dev@189 4114 // C++ language feature support
dev@189 4115
dev@189 4116 // catch all support for C++11
dev@189 4117 #if defined(__cplusplus) && __cplusplus >= 201103L
dev@189 4118
dev@189 4119 #define CLARA_CPP11_OR_GREATER
dev@189 4120
dev@189 4121 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
dev@189 4122 #define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
dev@189 4123 #endif
dev@189 4124
dev@189 4125 #ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 4126 #define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
dev@189 4127 #endif
dev@189 4128
dev@189 4129 #ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 4130 #define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
dev@189 4131 #endif
dev@189 4132
dev@189 4133 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
dev@189 4134 #define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
dev@189 4135 #endif
dev@189 4136 #if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
dev@189 4137 #define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
dev@189 4138 #endif
dev@189 4139
dev@189 4140 #endif // __cplusplus >= 201103L
dev@189 4141
dev@189 4142 // Now set the actual defines based on the above + anything the user has configured
dev@189 4143 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
dev@189 4144 #define CLARA_CONFIG_CPP11_NULLPTR
dev@189 4145 #endif
dev@189 4146 #if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
dev@189 4147 #define CLARA_CONFIG_CPP11_NOEXCEPT
dev@189 4148 #endif
dev@189 4149 #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)
dev@189 4150 #define CLARA_CONFIG_CPP11_GENERATED_METHODS
dev@189 4151 #endif
dev@189 4152 #if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
dev@189 4153 #define CLARA_CONFIG_CPP11_OVERRIDE
dev@189 4154 #endif
dev@189 4155 #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)
dev@189 4156 #define CLARA_CONFIG_CPP11_UNIQUE_PTR
dev@189 4157 #endif
dev@189 4158
dev@189 4159 // noexcept support:
dev@189 4160 #if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
dev@189 4161 #define CLARA_NOEXCEPT noexcept
dev@189 4162 # define CLARA_NOEXCEPT_IS(x) noexcept(x)
dev@189 4163 #else
dev@189 4164 #define CLARA_NOEXCEPT throw()
dev@189 4165 # define CLARA_NOEXCEPT_IS(x)
dev@189 4166 #endif
dev@189 4167
dev@189 4168 // nullptr support
dev@189 4169 #ifdef CLARA_CONFIG_CPP11_NULLPTR
dev@189 4170 #define CLARA_NULL nullptr
dev@189 4171 #else
dev@189 4172 #define CLARA_NULL NULL
dev@189 4173 #endif
dev@189 4174
dev@189 4175 // override support
dev@189 4176 #ifdef CLARA_CONFIG_CPP11_OVERRIDE
dev@189 4177 #define CLARA_OVERRIDE override
dev@189 4178 #else
dev@189 4179 #define CLARA_OVERRIDE
dev@189 4180 #endif
dev@189 4181
dev@189 4182 // unique_ptr support
dev@189 4183 #ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
dev@189 4184 # define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
dev@189 4185 #else
dev@189 4186 # define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
dev@189 4187 #endif
dev@189 4188
dev@189 4189 #endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
dev@189 4190
dev@189 4191 // ----------- end of #include from clara_compilers.h -----------
dev@189 4192 // ........... back in clara.h
dev@189 4193
dev@189 4194 #include <map>
dev@189 4195 #include <stdexcept>
dev@189 4196 #include <memory>
dev@189 4197
dev@189 4198 #if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
dev@189 4199 #define CLARA_PLATFORM_WINDOWS
dev@189 4200 #endif
dev@189 4201
dev@189 4202 // Use optional outer namespace
dev@189 4203 #ifdef STITCH_CLARA_OPEN_NAMESPACE
dev@189 4204 STITCH_CLARA_OPEN_NAMESPACE
dev@189 4205 #endif
dev@189 4206
dev@189 4207 namespace Clara {
dev@189 4208
dev@189 4209 struct UnpositionalTag {};
dev@189 4210
dev@189 4211 extern UnpositionalTag _;
dev@189 4212
dev@189 4213 #ifdef CLARA_CONFIG_MAIN
dev@189 4214 UnpositionalTag _;
dev@189 4215 #endif
dev@189 4216
dev@189 4217 namespace Detail {
dev@189 4218
dev@189 4219 #ifdef CLARA_CONSOLE_WIDTH
dev@189 4220 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
dev@189 4221 #else
dev@189 4222 const unsigned int consoleWidth = 80;
dev@189 4223 #endif
dev@189 4224
dev@189 4225 using namespace Tbc;
dev@189 4226
dev@189 4227 inline bool startsWith( std::string const& str, std::string const& prefix ) {
dev@189 4228 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
dev@189 4229 }
dev@189 4230
dev@189 4231 template<typename T> struct RemoveConstRef{ typedef T type; };
dev@189 4232 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
dev@189 4233 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
dev@189 4234 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
dev@189 4235
dev@189 4236 template<typename T> struct IsBool { static const bool value = false; };
dev@189 4237 template<> struct IsBool<bool> { static const bool value = true; };
dev@189 4238
dev@189 4239 template<typename T>
dev@189 4240 void convertInto( std::string const& _source, T& _dest ) {
dev@189 4241 std::stringstream ss;
dev@189 4242 ss << _source;
dev@189 4243 ss >> _dest;
dev@189 4244 if( ss.fail() )
dev@189 4245 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
dev@189 4246 }
dev@189 4247 inline void convertInto( std::string const& _source, std::string& _dest ) {
dev@189 4248 _dest = _source;
dev@189 4249 }
dev@189 4250 char toLowerCh(char c) {
dev@189 4251 return static_cast<char>( ::tolower( c ) );
dev@189 4252 }
dev@189 4253 inline void convertInto( std::string const& _source, bool& _dest ) {
dev@189 4254 std::string sourceLC = _source;
dev@189 4255 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
dev@189 4256 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
dev@189 4257 _dest = true;
dev@189 4258 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
dev@189 4259 _dest = false;
dev@189 4260 else
dev@189 4261 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
dev@189 4262 }
dev@189 4263
dev@189 4264 template<typename ConfigT>
dev@189 4265 struct IArgFunction {
dev@189 4266 virtual ~IArgFunction() {}
dev@189 4267 #ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
dev@189 4268 IArgFunction() = default;
dev@189 4269 IArgFunction( IArgFunction const& ) = default;
dev@189 4270 #endif
dev@189 4271 virtual void set( ConfigT& config, std::string const& value ) const = 0;
dev@189 4272 virtual bool takesArg() const = 0;
dev@189 4273 virtual IArgFunction* clone() const = 0;
dev@189 4274 };
dev@189 4275
dev@189 4276 template<typename ConfigT>
dev@189 4277 class BoundArgFunction {
dev@189 4278 public:
dev@189 4279 BoundArgFunction() : functionObj( CLARA_NULL ) {}
dev@189 4280 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
dev@189 4281 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
dev@189 4282 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
dev@189 4283 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
dev@189 4284 delete functionObj;
dev@189 4285 functionObj = newFunctionObj;
dev@189 4286 return *this;
dev@189 4287 }
dev@189 4288 ~BoundArgFunction() { delete functionObj; }
dev@189 4289
dev@189 4290 void set( ConfigT& config, std::string const& value ) const {
dev@189 4291 functionObj->set( config, value );
dev@189 4292 }
dev@189 4293 bool takesArg() const { return functionObj->takesArg(); }
dev@189 4294
dev@189 4295 bool isSet() const {
dev@189 4296 return functionObj != CLARA_NULL;
dev@189 4297 }
dev@189 4298 private:
dev@189 4299 IArgFunction<ConfigT>* functionObj;
dev@189 4300 };
dev@189 4301
dev@189 4302 template<typename C>
dev@189 4303 struct NullBinder : IArgFunction<C>{
dev@189 4304 virtual void set( C&, std::string const& ) const {}
dev@189 4305 virtual bool takesArg() const { return true; }
dev@189 4306 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
dev@189 4307 };
dev@189 4308
dev@189 4309 template<typename C, typename M>
dev@189 4310 struct BoundDataMember : IArgFunction<C>{
dev@189 4311 BoundDataMember( M C::* _member ) : member( _member ) {}
dev@189 4312 virtual void set( C& p, std::string const& stringValue ) const {
dev@189 4313 convertInto( stringValue, p.*member );
dev@189 4314 }
dev@189 4315 virtual bool takesArg() const { return !IsBool<M>::value; }
dev@189 4316 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
dev@189 4317 M C::* member;
dev@189 4318 };
dev@189 4319 template<typename C, typename M>
dev@189 4320 struct BoundUnaryMethod : IArgFunction<C>{
dev@189 4321 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
dev@189 4322 virtual void set( C& p, std::string const& stringValue ) const {
dev@189 4323 typename RemoveConstRef<M>::type value;
dev@189 4324 convertInto( stringValue, value );
dev@189 4325 (p.*member)( value );
dev@189 4326 }
dev@189 4327 virtual bool takesArg() const { return !IsBool<M>::value; }
dev@189 4328 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
dev@189 4329 void (C::*member)( M );
dev@189 4330 };
dev@189 4331 template<typename C>
dev@189 4332 struct BoundNullaryMethod : IArgFunction<C>{
dev@189 4333 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
dev@189 4334 virtual void set( C& p, std::string const& stringValue ) const {
dev@189 4335 bool value;
dev@189 4336 convertInto( stringValue, value );
dev@189 4337 if( value )
dev@189 4338 (p.*member)();
dev@189 4339 }
dev@189 4340 virtual bool takesArg() const { return false; }
dev@189 4341 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
dev@189 4342 void (C::*member)();
dev@189 4343 };
dev@189 4344
dev@189 4345 template<typename C>
dev@189 4346 struct BoundUnaryFunction : IArgFunction<C>{
dev@189 4347 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
dev@189 4348 virtual void set( C& obj, std::string const& stringValue ) const {
dev@189 4349 bool value;
dev@189 4350 convertInto( stringValue, value );
dev@189 4351 if( value )
dev@189 4352 function( obj );
dev@189 4353 }
dev@189 4354 virtual bool takesArg() const { return false; }
dev@189 4355 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
dev@189 4356 void (*function)( C& );
dev@189 4357 };
dev@189 4358
dev@189 4359 template<typename C, typename T>
dev@189 4360 struct BoundBinaryFunction : IArgFunction<C>{
dev@189 4361 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
dev@189 4362 virtual void set( C& obj, std::string const& stringValue ) const {
dev@189 4363 typename RemoveConstRef<T>::type value;
dev@189 4364 convertInto( stringValue, value );
dev@189 4365 function( obj, value );
dev@189 4366 }
dev@189 4367 virtual bool takesArg() const { return !IsBool<T>::value; }
dev@189 4368 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
dev@189 4369 void (*function)( C&, T );
dev@189 4370 };
dev@189 4371
dev@189 4372 } // namespace Detail
dev@189 4373
dev@189 4374 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
dev@189 4375 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
dev@189 4376 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
dev@189 4377 args[i] = argv[i];
dev@189 4378
dev@189 4379 return args;
dev@189 4380 }
dev@189 4381
dev@189 4382 class Parser {
dev@189 4383 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
dev@189 4384 Mode mode;
dev@189 4385 std::size_t from;
dev@189 4386 bool inQuotes;
dev@189 4387 public:
dev@189 4388
dev@189 4389 struct Token {
dev@189 4390 enum Type { Positional, ShortOpt, LongOpt };
dev@189 4391 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
dev@189 4392 Type type;
dev@189 4393 std::string data;
dev@189 4394 };
dev@189 4395
dev@189 4396 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
dev@189 4397
dev@189 4398 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
dev@189 4399 const std::string doubleDash = "--";
dev@189 4400 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
dev@189 4401 parseIntoTokens( args[i], tokens);
dev@189 4402 }
dev@189 4403
dev@189 4404 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
dev@189 4405 for( std::size_t i = 0; i <= arg.size(); ++i ) {
dev@189 4406 char c = arg[i];
dev@189 4407 if( c == '"' )
dev@189 4408 inQuotes = !inQuotes;
dev@189 4409 mode = handleMode( i, c, arg, tokens );
dev@189 4410 }
dev@189 4411 }
dev@189 4412 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
dev@189 4413 switch( mode ) {
dev@189 4414 case None: return handleNone( i, c );
dev@189 4415 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
dev@189 4416 case ShortOpt:
dev@189 4417 case LongOpt:
dev@189 4418 case SlashOpt: return handleOpt( i, c, arg, tokens );
dev@189 4419 case Positional: return handlePositional( i, c, arg, tokens );
dev@189 4420 default: throw std::logic_error( "Unknown mode" );
dev@189 4421 }
dev@189 4422 }
dev@189 4423
dev@189 4424 Mode handleNone( std::size_t i, char c ) {
dev@189 4425 if( inQuotes ) {
dev@189 4426 from = i;
dev@189 4427 return Positional;
dev@189 4428 }
dev@189 4429 switch( c ) {
dev@189 4430 case '-': return MaybeShortOpt;
dev@189 4431 #ifdef CLARA_PLATFORM_WINDOWS
dev@189 4432 case '/': from = i+1; return SlashOpt;
dev@189 4433 #endif
dev@189 4434 default: from = i; return Positional;
dev@189 4435 }
dev@189 4436 }
dev@189 4437 Mode handleMaybeShortOpt( std::size_t i, char c ) {
dev@189 4438 switch( c ) {
dev@189 4439 case '-': from = i+1; return LongOpt;
dev@189 4440 default: from = i; return ShortOpt;
dev@189 4441 }
dev@189 4442 }
dev@189 4443 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
dev@189 4444 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
dev@189 4445 return mode;
dev@189 4446
dev@189 4447 std::string optName = arg.substr( from, i-from );
dev@189 4448 if( mode == ShortOpt )
dev@189 4449 for( std::size_t j = 0; j < optName.size(); ++j )
dev@189 4450 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
dev@189 4451 else if( mode == SlashOpt && optName.size() == 1 )
dev@189 4452 tokens.push_back( Token( Token::ShortOpt, optName ) );
dev@189 4453 else
dev@189 4454 tokens.push_back( Token( Token::LongOpt, optName ) );
dev@189 4455 return None;
dev@189 4456 }
dev@189 4457 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
dev@189 4458 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
dev@189 4459 return mode;
dev@189 4460
dev@189 4461 std::string data = arg.substr( from, i-from );
dev@189 4462 tokens.push_back( Token( Token::Positional, data ) );
dev@189 4463 return None;
dev@189 4464 }
dev@189 4465 };
dev@189 4466
dev@189 4467 template<typename ConfigT>
dev@189 4468 struct CommonArgProperties {
dev@189 4469 CommonArgProperties() {}
dev@189 4470 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
dev@189 4471
dev@189 4472 Detail::BoundArgFunction<ConfigT> boundField;
dev@189 4473 std::string description;
dev@189 4474 std::string detail;
dev@189 4475 std::string placeholder; // Only value if boundField takes an arg
dev@189 4476
dev@189 4477 bool takesArg() const {
dev@189 4478 return !placeholder.empty();
dev@189 4479 }
dev@189 4480 void validate() const {
dev@189 4481 if( !boundField.isSet() )
dev@189 4482 throw std::logic_error( "option not bound" );
dev@189 4483 }
dev@189 4484 };
dev@189 4485 struct OptionArgProperties {
dev@189 4486 std::vector<std::string> shortNames;
dev@189 4487 std::string longName;
dev@189 4488
dev@189 4489 bool hasShortName( std::string const& shortName ) const {
dev@189 4490 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
dev@189 4491 }
dev@189 4492 bool hasLongName( std::string const& _longName ) const {
dev@189 4493 return _longName == longName;
dev@189 4494 }
dev@189 4495 };
dev@189 4496 struct PositionalArgProperties {
dev@189 4497 PositionalArgProperties() : position( -1 ) {}
dev@189 4498 int position; // -1 means non-positional (floating)
dev@189 4499
dev@189 4500 bool isFixedPositional() const {
dev@189 4501 return position != -1;
dev@189 4502 }
dev@189 4503 };
dev@189 4504
dev@189 4505 template<typename ConfigT>
dev@189 4506 class CommandLine {
dev@189 4507
dev@189 4508 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
dev@189 4509 Arg() {}
dev@189 4510 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
dev@189 4511
dev@189 4512 using CommonArgProperties<ConfigT>::placeholder; // !TBD
dev@189 4513
dev@189 4514 std::string dbgName() const {
dev@189 4515 if( !longName.empty() )
dev@189 4516 return "--" + longName;
dev@189 4517 if( !shortNames.empty() )
dev@189 4518 return "-" + shortNames[0];
dev@189 4519 return "positional args";
dev@189 4520 }
dev@189 4521 std::string commands() const {
dev@189 4522 std::ostringstream oss;
dev@189 4523 bool first = true;
dev@189 4524 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
dev@189 4525 for(; it != itEnd; ++it ) {
dev@189 4526 if( first )
dev@189 4527 first = false;
dev@189 4528 else
dev@189 4529 oss << ", ";
dev@189 4530 oss << "-" << *it;
dev@189 4531 }
dev@189 4532 if( !longName.empty() ) {
dev@189 4533 if( !first )
dev@189 4534 oss << ", ";
dev@189 4535 oss << "--" << longName;
dev@189 4536 }
dev@189 4537 if( !placeholder.empty() )
dev@189 4538 oss << " <" << placeholder << ">";
dev@189 4539 return oss.str();
dev@189 4540 }
dev@189 4541 };
dev@189 4542
dev@189 4543 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
dev@189 4544
dev@189 4545 friend void addOptName( Arg& arg, std::string const& optName )
dev@189 4546 {
dev@189 4547 if( optName.empty() )
dev@189 4548 return;
dev@189 4549 if( Detail::startsWith( optName, "--" ) ) {
dev@189 4550 if( !arg.longName.empty() )
dev@189 4551 throw std::logic_error( "Only one long opt may be specified. '"
dev@189 4552 + arg.longName
dev@189 4553 + "' already specified, now attempting to add '"
dev@189 4554 + optName + "'" );
dev@189 4555 arg.longName = optName.substr( 2 );
dev@189 4556 }
dev@189 4557 else if( Detail::startsWith( optName, "-" ) )
dev@189 4558 arg.shortNames.push_back( optName.substr( 1 ) );
dev@189 4559 else
dev@189 4560 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
dev@189 4561 }
dev@189 4562 friend void setPositionalArg( Arg& arg, int position )
dev@189 4563 {
dev@189 4564 arg.position = position;
dev@189 4565 }
dev@189 4566
dev@189 4567 class ArgBuilder {
dev@189 4568 public:
dev@189 4569 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
dev@189 4570
dev@189 4571 // Bind a non-boolean data member (requires placeholder string)
dev@189 4572 template<typename C, typename M>
dev@189 4573 void bind( M C::* field, std::string const& placeholder ) {
dev@189 4574 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
dev@189 4575 m_arg->placeholder = placeholder;
dev@189 4576 }
dev@189 4577 // Bind a boolean data member (no placeholder required)
dev@189 4578 template<typename C>
dev@189 4579 void bind( bool C::* field ) {
dev@189 4580 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
dev@189 4581 }
dev@189 4582
dev@189 4583 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
dev@189 4584 template<typename C, typename M>
dev@189 4585 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
dev@189 4586 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
dev@189 4587 m_arg->placeholder = placeholder;
dev@189 4588 }
dev@189 4589
dev@189 4590 // Bind a method taking a single, boolean argument (no placeholder string required)
dev@189 4591 template<typename C>
dev@189 4592 void bind( void (C::* unaryMethod)( bool ) ) {
dev@189 4593 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
dev@189 4594 }
dev@189 4595
dev@189 4596 // Bind a method that takes no arguments (will be called if opt is present)
dev@189 4597 template<typename C>
dev@189 4598 void bind( void (C::* nullaryMethod)() ) {
dev@189 4599 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
dev@189 4600 }
dev@189 4601
dev@189 4602 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
dev@189 4603 template<typename C>
dev@189 4604 void bind( void (* unaryFunction)( C& ) ) {
dev@189 4605 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
dev@189 4606 }
dev@189 4607
dev@189 4608 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
dev@189 4609 template<typename C, typename T>
dev@189 4610 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
dev@189 4611 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
dev@189 4612 m_arg->placeholder = placeholder;
dev@189 4613 }
dev@189 4614
dev@189 4615 ArgBuilder& describe( std::string const& description ) {
dev@189 4616 m_arg->description = description;
dev@189 4617 return *this;
dev@189 4618 }
dev@189 4619 ArgBuilder& detail( std::string const& detail ) {
dev@189 4620 m_arg->detail = detail;
dev@189 4621 return *this;
dev@189 4622 }
dev@189 4623
dev@189 4624 protected:
dev@189 4625 Arg* m_arg;
dev@189 4626 };
dev@189 4627
dev@189 4628 class OptBuilder : public ArgBuilder {
dev@189 4629 public:
dev@189 4630 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
dev@189 4631 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
dev@189 4632
dev@189 4633 OptBuilder& operator[]( std::string const& optName ) {
dev@189 4634 addOptName( *ArgBuilder::m_arg, optName );
dev@189 4635 return *this;
dev@189 4636 }
dev@189 4637 };
dev@189 4638
dev@189 4639 public:
dev@189 4640
dev@189 4641 CommandLine()
dev@189 4642 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
dev@189 4643 m_highestSpecifiedArgPosition( 0 ),
dev@189 4644 m_throwOnUnrecognisedTokens( false )
dev@189 4645 {}
dev@189 4646 CommandLine( CommandLine const& other )
dev@189 4647 : m_boundProcessName( other.m_boundProcessName ),
dev@189 4648 m_options ( other.m_options ),
dev@189 4649 m_positionalArgs( other.m_positionalArgs ),
dev@189 4650 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
dev@189 4651 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
dev@189 4652 {
dev@189 4653 if( other.m_floatingArg.get() )
dev@189 4654 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
dev@189 4655 }
dev@189 4656
dev@189 4657 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
dev@189 4658 m_throwOnUnrecognisedTokens = shouldThrow;
dev@189 4659 return *this;
dev@189 4660 }
dev@189 4661
dev@189 4662 OptBuilder operator[]( std::string const& optName ) {
dev@189 4663 m_options.push_back( Arg() );
dev@189 4664 addOptName( m_options.back(), optName );
dev@189 4665 OptBuilder builder( &m_options.back() );
dev@189 4666 return builder;
dev@189 4667 }
dev@189 4668
dev@189 4669 ArgBuilder operator[]( int position ) {
dev@189 4670 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
dev@189 4671 if( position > m_highestSpecifiedArgPosition )
dev@189 4672 m_highestSpecifiedArgPosition = position;
dev@189 4673 setPositionalArg( m_positionalArgs[position], position );
dev@189 4674 ArgBuilder builder( &m_positionalArgs[position] );
dev@189 4675 return builder;
dev@189 4676 }
dev@189 4677
dev@189 4678 // Invoke this with the _ instance
dev@189 4679 ArgBuilder operator[]( UnpositionalTag ) {
dev@189 4680 if( m_floatingArg.get() )
dev@189 4681 throw std::logic_error( "Only one unpositional argument can be added" );
dev@189 4682 m_floatingArg.reset( new Arg() );
dev@189 4683 ArgBuilder builder( m_floatingArg.get() );
dev@189 4684 return builder;
dev@189 4685 }
dev@189 4686
dev@189 4687 template<typename C, typename M>
dev@189 4688 void bindProcessName( M C::* field ) {
dev@189 4689 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
dev@189 4690 }
dev@189 4691 template<typename C, typename M>
dev@189 4692 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
dev@189 4693 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
dev@189 4694 }
dev@189 4695
dev@189 4696 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
dev@189 4697 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
dev@189 4698 std::size_t maxWidth = 0;
dev@189 4699 for( it = itBegin; it != itEnd; ++it )
dev@189 4700 maxWidth = (std::max)( maxWidth, it->commands().size() );
dev@189 4701
dev@189 4702 for( it = itBegin; it != itEnd; ++it ) {
dev@189 4703 Detail::Text usage( it->commands(), Detail::TextAttributes()
dev@189 4704 .setWidth( maxWidth+indent )
dev@189 4705 .setIndent( indent ) );
dev@189 4706 Detail::Text desc( it->description, Detail::TextAttributes()
dev@189 4707 .setWidth( width - maxWidth - 3 ) );
dev@189 4708
dev@189 4709 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
dev@189 4710 std::string usageCol = i < usage.size() ? usage[i] : "";
dev@189 4711 os << usageCol;
dev@189 4712
dev@189 4713 if( i < desc.size() && !desc[i].empty() )
dev@189 4714 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
dev@189 4715 << desc[i];
dev@189 4716 os << "\n";
dev@189 4717 }
dev@189 4718 }
dev@189 4719 }
dev@189 4720 std::string optUsage() const {
dev@189 4721 std::ostringstream oss;
dev@189 4722 optUsage( oss );
dev@189 4723 return oss.str();
dev@189 4724 }
dev@189 4725
dev@189 4726 void argSynopsis( std::ostream& os ) const {
dev@189 4727 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
dev@189 4728 if( i > 1 )
dev@189 4729 os << " ";
dev@189 4730 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
dev@189 4731 if( it != m_positionalArgs.end() )
dev@189 4732 os << "<" << it->second.placeholder << ">";
dev@189 4733 else if( m_floatingArg.get() )
dev@189 4734 os << "<" << m_floatingArg->placeholder << ">";
dev@189 4735 else
dev@189 4736 throw std::logic_error( "non consecutive positional arguments with no floating args" );
dev@189 4737 }
dev@189 4738 // !TBD No indication of mandatory args
dev@189 4739 if( m_floatingArg.get() ) {
dev@189 4740 if( m_highestSpecifiedArgPosition > 1 )
dev@189 4741 os << " ";
dev@189 4742 os << "[<" << m_floatingArg->placeholder << "> ...]";
dev@189 4743 }
dev@189 4744 }
dev@189 4745 std::string argSynopsis() const {
dev@189 4746 std::ostringstream oss;
dev@189 4747 argSynopsis( oss );
dev@189 4748 return oss.str();
dev@189 4749 }
dev@189 4750
dev@189 4751 void usage( std::ostream& os, std::string const& procName ) const {
dev@189 4752 validate();
dev@189 4753 os << "usage:\n " << procName << " ";
dev@189 4754 argSynopsis( os );
dev@189 4755 if( !m_options.empty() ) {
dev@189 4756 os << " [options]\n\nwhere options are: \n";
dev@189 4757 optUsage( os, 2 );
dev@189 4758 }
dev@189 4759 os << "\n";
dev@189 4760 }
dev@189 4761 std::string usage( std::string const& procName ) const {
dev@189 4762 std::ostringstream oss;
dev@189 4763 usage( oss, procName );
dev@189 4764 return oss.str();
dev@189 4765 }
dev@189 4766
dev@189 4767 ConfigT parse( std::vector<std::string> const& args ) const {
dev@189 4768 ConfigT config;
dev@189 4769 parseInto( args, config );
dev@189 4770 return config;
dev@189 4771 }
dev@189 4772
dev@189 4773 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
dev@189 4774 std::string processName = args[0];
dev@189 4775 std::size_t lastSlash = processName.find_last_of( "/\\" );
dev@189 4776 if( lastSlash != std::string::npos )
dev@189 4777 processName = processName.substr( lastSlash+1 );
dev@189 4778 m_boundProcessName.set( config, processName );
dev@189 4779 std::vector<Parser::Token> tokens;
dev@189 4780 Parser parser;
dev@189 4781 parser.parseIntoTokens( args, tokens );
dev@189 4782 return populate( tokens, config );
dev@189 4783 }
dev@189 4784
dev@189 4785 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
dev@189 4786 validate();
dev@189 4787 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
dev@189 4788 unusedTokens = populateFixedArgs( unusedTokens, config );
dev@189 4789 unusedTokens = populateFloatingArgs( unusedTokens, config );
dev@189 4790 return unusedTokens;
dev@189 4791 }
dev@189 4792
dev@189 4793 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
dev@189 4794 std::vector<Parser::Token> unusedTokens;
dev@189 4795 std::vector<std::string> errors;
dev@189 4796 for( std::size_t i = 0; i < tokens.size(); ++i ) {
dev@189 4797 Parser::Token const& token = tokens[i];
dev@189 4798 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
dev@189 4799 for(; it != itEnd; ++it ) {
dev@189 4800 Arg const& arg = *it;
dev@189 4801
dev@189 4802 try {
dev@189 4803 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
dev@189 4804 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
dev@189 4805 if( arg.takesArg() ) {
dev@189 4806 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
dev@189 4807 errors.push_back( "Expected argument to option: " + token.data );
dev@189 4808 else
dev@189 4809 arg.boundField.set( config, tokens[++i].data );
dev@189 4810 }
dev@189 4811 else {
dev@189 4812 arg.boundField.set( config, "true" );
dev@189 4813 }
dev@189 4814 break;
dev@189 4815 }
dev@189 4816 }
dev@189 4817 catch( std::exception& ex ) {
dev@189 4818 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
dev@189 4819 }
dev@189 4820 }
dev@189 4821 if( it == itEnd ) {
dev@189 4822 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
dev@189 4823 unusedTokens.push_back( token );
dev@189 4824 else if( errors.empty() && m_throwOnUnrecognisedTokens )
dev@189 4825 errors.push_back( "unrecognised option: " + token.data );
dev@189 4826 }
dev@189 4827 }
dev@189 4828 if( !errors.empty() ) {
dev@189 4829 std::ostringstream oss;
dev@189 4830 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
dev@189 4831 it != itEnd;
dev@189 4832 ++it ) {
dev@189 4833 if( it != errors.begin() )
dev@189 4834 oss << "\n";
dev@189 4835 oss << *it;
dev@189 4836 }
dev@189 4837 throw std::runtime_error( oss.str() );
dev@189 4838 }
dev@189 4839 return unusedTokens;
dev@189 4840 }
dev@189 4841 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
dev@189 4842 std::vector<Parser::Token> unusedTokens;
dev@189 4843 int position = 1;
dev@189 4844 for( std::size_t i = 0; i < tokens.size(); ++i ) {
dev@189 4845 Parser::Token const& token = tokens[i];
dev@189 4846 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
dev@189 4847 if( it != m_positionalArgs.end() )
dev@189 4848 it->second.boundField.set( config, token.data );
dev@189 4849 else
dev@189 4850 unusedTokens.push_back( token );
dev@189 4851 if( token.type == Parser::Token::Positional )
dev@189 4852 position++;
dev@189 4853 }
dev@189 4854 return unusedTokens;
dev@189 4855 }
dev@189 4856 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
dev@189 4857 if( !m_floatingArg.get() )
dev@189 4858 return tokens;
dev@189 4859 std::vector<Parser::Token> unusedTokens;
dev@189 4860 for( std::size_t i = 0; i < tokens.size(); ++i ) {
dev@189 4861 Parser::Token const& token = tokens[i];
dev@189 4862 if( token.type == Parser::Token::Positional )
dev@189 4863 m_floatingArg->boundField.set( config, token.data );
dev@189 4864 else
dev@189 4865 unusedTokens.push_back( token );
dev@189 4866 }
dev@189 4867 return unusedTokens;
dev@189 4868 }
dev@189 4869
dev@189 4870 void validate() const
dev@189 4871 {
dev@189 4872 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
dev@189 4873 throw std::logic_error( "No options or arguments specified" );
dev@189 4874
dev@189 4875 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
dev@189 4876 itEnd = m_options.end();
dev@189 4877 it != itEnd; ++it )
dev@189 4878 it->validate();
dev@189 4879 }
dev@189 4880
dev@189 4881 private:
dev@189 4882 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
dev@189 4883 std::vector<Arg> m_options;
dev@189 4884 std::map<int, Arg> m_positionalArgs;
dev@189 4885 ArgAutoPtr m_floatingArg;
dev@189 4886 int m_highestSpecifiedArgPosition;
dev@189 4887 bool m_throwOnUnrecognisedTokens;
dev@189 4888 };
dev@189 4889
dev@189 4890 } // end namespace Clara
dev@189 4891
dev@189 4892 STITCH_CLARA_CLOSE_NAMESPACE
dev@189 4893 #undef STITCH_CLARA_OPEN_NAMESPACE
dev@189 4894 #undef STITCH_CLARA_CLOSE_NAMESPACE
dev@189 4895
dev@189 4896 #endif // TWOBLUECUBES_CLARA_H_INCLUDED
dev@189 4897 #undef STITCH_CLARA_OPEN_NAMESPACE
dev@189 4898
dev@189 4899 // Restore Clara's value for console width, if present
dev@189 4900 #ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
dev@189 4901 #define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
dev@189 4902 #undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
dev@189 4903 #endif
dev@189 4904
dev@189 4905 #include <fstream>
dev@189 4906
dev@189 4907 namespace Catch {
dev@189 4908
dev@189 4909 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
dev@189 4910 inline void abortAfterX( ConfigData& config, int x ) {
dev@189 4911 if( x < 1 )
dev@189 4912 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
dev@189 4913 config.abortAfter = x;
dev@189 4914 }
dev@189 4915 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
dev@189 4916 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
dev@189 4917 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
dev@189 4918
dev@189 4919 inline void addWarning( ConfigData& config, std::string const& _warning ) {
dev@189 4920 if( _warning == "NoAssertions" )
dev@189 4921 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
dev@189 4922 else
dev@189 4923 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
dev@189 4924 }
dev@189 4925 inline void setOrder( ConfigData& config, std::string const& order ) {
dev@189 4926 if( startsWith( "declared", order ) )
dev@189 4927 config.runOrder = RunTests::InDeclarationOrder;
dev@189 4928 else if( startsWith( "lexical", order ) )
dev@189 4929 config.runOrder = RunTests::InLexicographicalOrder;
dev@189 4930 else if( startsWith( "random", order ) )
dev@189 4931 config.runOrder = RunTests::InRandomOrder;
dev@189 4932 else
dev@189 4933 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
dev@189 4934 }
dev@189 4935 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
dev@189 4936 if( seed == "time" ) {
dev@189 4937 config.rngSeed = static_cast<unsigned int>( std::time(0) );
dev@189 4938 }
dev@189 4939 else {
dev@189 4940 std::stringstream ss;
dev@189 4941 ss << seed;
dev@189 4942 ss >> config.rngSeed;
dev@189 4943 if( ss.fail() )
dev@189 4944 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
dev@189 4945 }
dev@189 4946 }
dev@189 4947 inline void setVerbosity( ConfigData& config, int level ) {
dev@189 4948 // !TBD: accept strings?
dev@189 4949 config.verbosity = static_cast<Verbosity::Level>( level );
dev@189 4950 }
dev@189 4951 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
dev@189 4952 config.showDurations = _showDurations
dev@189 4953 ? ShowDurations::Always
dev@189 4954 : ShowDurations::Never;
dev@189 4955 }
dev@189 4956 inline void setUseColour( ConfigData& config, std::string const& value ) {
dev@189 4957 std::string mode = toLower( value );
dev@189 4958
dev@189 4959 if( mode == "yes" )
dev@189 4960 config.useColour = UseColour::Yes;
dev@189 4961 else if( mode == "no" )
dev@189 4962 config.useColour = UseColour::No;
dev@189 4963 else if( mode == "auto" )
dev@189 4964 config.useColour = UseColour::Auto;
dev@189 4965 else
dev@189 4966 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
dev@189 4967 }
dev@189 4968 inline void forceColour( ConfigData& config ) {
dev@189 4969 config.useColour = UseColour::Yes;
dev@189 4970 }
dev@189 4971 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
dev@189 4972 std::ifstream f( _filename.c_str() );
dev@189 4973 if( !f.is_open() )
dev@189 4974 throw std::domain_error( "Unable to load input file: " + _filename );
dev@189 4975
dev@189 4976 std::string line;
dev@189 4977 while( std::getline( f, line ) ) {
dev@189 4978 line = trim(line);
dev@189 4979 if( !line.empty() && !startsWith( line, '#' ) ) {
dev@189 4980 if( !startsWith( line, '"' ) )
dev@189 4981 line = '"' + line + '"';
dev@189 4982 addTestOrTags( config, line + ',' );
dev@189 4983 }
dev@189 4984 }
dev@189 4985 }
dev@189 4986
dev@189 4987 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
dev@189 4988
dev@189 4989 using namespace Clara;
dev@189 4990 CommandLine<ConfigData> cli;
dev@189 4991
dev@189 4992 cli.bindProcessName( &ConfigData::processName );
dev@189 4993
dev@189 4994 cli["-?"]["-h"]["--help"]
dev@189 4995 .describe( "display usage information" )
dev@189 4996 .bind( &ConfigData::showHelp );
dev@189 4997
dev@189 4998 cli["-l"]["--list-tests"]
dev@189 4999 .describe( "list all/matching test cases" )
dev@189 5000 .bind( &ConfigData::listTests );
dev@189 5001
dev@189 5002 cli["-t"]["--list-tags"]
dev@189 5003 .describe( "list all/matching tags" )
dev@189 5004 .bind( &ConfigData::listTags );
dev@189 5005
dev@189 5006 cli["-s"]["--success"]
dev@189 5007 .describe( "include successful tests in output" )
dev@189 5008 .bind( &ConfigData::showSuccessfulTests );
dev@189 5009
dev@189 5010 cli["-b"]["--break"]
dev@189 5011 .describe( "break into debugger on failure" )
dev@189 5012 .bind( &ConfigData::shouldDebugBreak );
dev@189 5013
dev@189 5014 cli["-e"]["--nothrow"]
dev@189 5015 .describe( "skip exception tests" )
dev@189 5016 .bind( &ConfigData::noThrow );
dev@189 5017
dev@189 5018 cli["-i"]["--invisibles"]
dev@189 5019 .describe( "show invisibles (tabs, newlines)" )
dev@189 5020 .bind( &ConfigData::showInvisibles );
dev@189 5021
dev@189 5022 cli["-o"]["--out"]
dev@189 5023 .describe( "output filename" )
dev@189 5024 .bind( &ConfigData::outputFilename, "filename" );
dev@189 5025
dev@189 5026 cli["-r"]["--reporter"]
dev@189 5027 // .placeholder( "name[:filename]" )
dev@189 5028 .describe( "reporter to use (defaults to console)" )
dev@189 5029 .bind( &addReporterName, "name" );
dev@189 5030
dev@189 5031 cli["-n"]["--name"]
dev@189 5032 .describe( "suite name" )
dev@189 5033 .bind( &ConfigData::name, "name" );
dev@189 5034
dev@189 5035 cli["-a"]["--abort"]
dev@189 5036 .describe( "abort at first failure" )
dev@189 5037 .bind( &abortAfterFirst );
dev@189 5038
dev@189 5039 cli["-x"]["--abortx"]
dev@189 5040 .describe( "abort after x failures" )
dev@189 5041 .bind( &abortAfterX, "no. failures" );
dev@189 5042
dev@189 5043 cli["-w"]["--warn"]
dev@189 5044 .describe( "enable warnings" )
dev@189 5045 .bind( &addWarning, "warning name" );
dev@189 5046
dev@189 5047 // - needs updating if reinstated
dev@189 5048 // cli.into( &setVerbosity )
dev@189 5049 // .describe( "level of verbosity (0=no output)" )
dev@189 5050 // .shortOpt( "v")
dev@189 5051 // .longOpt( "verbosity" )
dev@189 5052 // .placeholder( "level" );
dev@189 5053
dev@189 5054 cli[_]
dev@189 5055 .describe( "which test or tests to use" )
dev@189 5056 .bind( &addTestOrTags, "test name, pattern or tags" );
dev@189 5057
dev@189 5058 cli["-d"]["--durations"]
dev@189 5059 .describe( "show test durations" )
dev@189 5060 .bind( &setShowDurations, "yes|no" );
dev@189 5061
dev@189 5062 cli["-f"]["--input-file"]
dev@189 5063 .describe( "load test names to run from a file" )
dev@189 5064 .bind( &loadTestNamesFromFile, "filename" );
dev@189 5065
dev@189 5066 cli["-#"]["--filenames-as-tags"]
dev@189 5067 .describe( "adds a tag for the filename" )
dev@189 5068 .bind( &ConfigData::filenamesAsTags );
dev@189 5069
dev@189 5070 cli["-c"]["--section"]
dev@189 5071 .describe( "specify section to run" )
dev@189 5072 .bind( &addSectionToRun, "section name" );
dev@189 5073
dev@189 5074 // Less common commands which don't have a short form
dev@189 5075 cli["--list-test-names-only"]
dev@189 5076 .describe( "list all/matching test cases names only" )
dev@189 5077 .bind( &ConfigData::listTestNamesOnly );
dev@189 5078
dev@189 5079 cli["--list-reporters"]
dev@189 5080 .describe( "list all reporters" )
dev@189 5081 .bind( &ConfigData::listReporters );
dev@189 5082
dev@189 5083 cli["--order"]
dev@189 5084 .describe( "test case order (defaults to decl)" )
dev@189 5085 .bind( &setOrder, "decl|lex|rand" );
dev@189 5086
dev@189 5087 cli["--rng-seed"]
dev@189 5088 .describe( "set a specific seed for random numbers" )
dev@189 5089 .bind( &setRngSeed, "'time'|number" );
dev@189 5090
dev@189 5091 cli["--force-colour"]
dev@189 5092 .describe( "force colourised output (deprecated)" )
dev@189 5093 .bind( &forceColour );
dev@189 5094
dev@189 5095 cli["--use-colour"]
dev@189 5096 .describe( "should output be colourised" )
dev@189 5097 .bind( &setUseColour, "yes|no" );
dev@189 5098
dev@189 5099 return cli;
dev@189 5100 }
dev@189 5101
dev@189 5102 } // end namespace Catch
dev@189 5103
dev@189 5104 // #included from: internal/catch_list.hpp
dev@189 5105 #define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
dev@189 5106
dev@189 5107 // #included from: catch_text.h
dev@189 5108 #define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
dev@189 5109
dev@189 5110 #define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
dev@189 5111
dev@189 5112 #define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
dev@189 5113 // #included from: ../external/tbc_text_format.h
dev@189 5114 // Only use header guard if we are not using an outer namespace
dev@189 5115 #ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 5116 # ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
dev@189 5117 # ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
dev@189 5118 # define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
dev@189 5119 # endif
dev@189 5120 # else
dev@189 5121 # define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
dev@189 5122 # endif
dev@189 5123 #endif
dev@189 5124 #ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
dev@189 5125 #include <string>
dev@189 5126 #include <vector>
dev@189 5127 #include <sstream>
dev@189 5128
dev@189 5129 // Use optional outer namespace
dev@189 5130 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 5131 namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
dev@189 5132 #endif
dev@189 5133
dev@189 5134 namespace Tbc {
dev@189 5135
dev@189 5136 #ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
dev@189 5137 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
dev@189 5138 #else
dev@189 5139 const unsigned int consoleWidth = 80;
dev@189 5140 #endif
dev@189 5141
dev@189 5142 struct TextAttributes {
dev@189 5143 TextAttributes()
dev@189 5144 : initialIndent( std::string::npos ),
dev@189 5145 indent( 0 ),
dev@189 5146 width( consoleWidth-1 )
dev@189 5147 {}
dev@189 5148
dev@189 5149 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
dev@189 5150 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
dev@189 5151 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
dev@189 5152
dev@189 5153 std::size_t initialIndent; // indent of first line, or npos
dev@189 5154 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
dev@189 5155 std::size_t width; // maximum width of text, including indent. Longer text will wrap
dev@189 5156 };
dev@189 5157
dev@189 5158 class Text {
dev@189 5159 public:
dev@189 5160 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
dev@189 5161 : attr( _attr )
dev@189 5162 {
dev@189 5163 const std::string wrappableBeforeChars = "[({<\t";
dev@189 5164 const std::string wrappableAfterChars = "])}>-,./|\\";
dev@189 5165 const std::string wrappableInsteadOfChars = " \n\r";
dev@189 5166 std::string indent = _attr.initialIndent != std::string::npos
dev@189 5167 ? std::string( _attr.initialIndent, ' ' )
dev@189 5168 : std::string( _attr.indent, ' ' );
dev@189 5169
dev@189 5170 typedef std::string::const_iterator iterator;
dev@189 5171 iterator it = _str.begin();
dev@189 5172 const iterator strEnd = _str.end();
dev@189 5173
dev@189 5174 while( it != strEnd ) {
dev@189 5175
dev@189 5176 if( lines.size() >= 1000 ) {
dev@189 5177 lines.push_back( "... message truncated due to excessive size" );
dev@189 5178 return;
dev@189 5179 }
dev@189 5180
dev@189 5181 std::string suffix;
dev@189 5182 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
dev@189 5183 iterator itEnd = it+width;
dev@189 5184 iterator itNext = _str.end();
dev@189 5185
dev@189 5186 iterator itNewLine = std::find( it, itEnd, '\n' );
dev@189 5187 if( itNewLine != itEnd )
dev@189 5188 itEnd = itNewLine;
dev@189 5189
dev@189 5190 if( itEnd != strEnd ) {
dev@189 5191 bool foundWrapPoint = false;
dev@189 5192 iterator findIt = itEnd;
dev@189 5193 do {
dev@189 5194 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
dev@189 5195 itEnd = findIt+1;
dev@189 5196 itNext = findIt+1;
dev@189 5197 foundWrapPoint = true;
dev@189 5198 }
dev@189 5199 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
dev@189 5200 itEnd = findIt;
dev@189 5201 itNext = findIt;
dev@189 5202 foundWrapPoint = true;
dev@189 5203 }
dev@189 5204 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
dev@189 5205 itNext = findIt+1;
dev@189 5206 itEnd = findIt;
dev@189 5207 foundWrapPoint = true;
dev@189 5208 }
dev@189 5209 if( findIt == it )
dev@189 5210 break;
dev@189 5211 else
dev@189 5212 --findIt;
dev@189 5213 }
dev@189 5214 while( !foundWrapPoint );
dev@189 5215
dev@189 5216 if( !foundWrapPoint ) {
dev@189 5217 // No good wrap char, so we'll break mid word and add a hyphen
dev@189 5218 --itEnd;
dev@189 5219 itNext = itEnd;
dev@189 5220 suffix = "-";
dev@189 5221 }
dev@189 5222 else {
dev@189 5223 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
dev@189 5224 --itEnd;
dev@189 5225 }
dev@189 5226 }
dev@189 5227 lines.push_back( indent + std::string( it, itEnd ) + suffix );
dev@189 5228
dev@189 5229 if( indent.size() != _attr.indent )
dev@189 5230 indent = std::string( _attr.indent, ' ' );
dev@189 5231 it = itNext;
dev@189 5232 }
dev@189 5233 }
dev@189 5234
dev@189 5235 typedef std::vector<std::string>::const_iterator const_iterator;
dev@189 5236
dev@189 5237 const_iterator begin() const { return lines.begin(); }
dev@189 5238 const_iterator end() const { return lines.end(); }
dev@189 5239 std::string const& last() const { return lines.back(); }
dev@189 5240 std::size_t size() const { return lines.size(); }
dev@189 5241 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
dev@189 5242 std::string toString() const {
dev@189 5243 std::ostringstream oss;
dev@189 5244 oss << *this;
dev@189 5245 return oss.str();
dev@189 5246 }
dev@189 5247
dev@189 5248 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
dev@189 5249 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
dev@189 5250 it != itEnd; ++it ) {
dev@189 5251 if( it != _text.begin() )
dev@189 5252 _stream << "\n";
dev@189 5253 _stream << *it;
dev@189 5254 }
dev@189 5255 return _stream;
dev@189 5256 }
dev@189 5257
dev@189 5258 private:
dev@189 5259 std::string str;
dev@189 5260 TextAttributes attr;
dev@189 5261 std::vector<std::string> lines;
dev@189 5262 };
dev@189 5263
dev@189 5264 } // end namespace Tbc
dev@189 5265
dev@189 5266 #ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 5267 } // end outer namespace
dev@189 5268 #endif
dev@189 5269
dev@189 5270 #endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
dev@189 5271 #undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
dev@189 5272
dev@189 5273 namespace Catch {
dev@189 5274 using Tbc::Text;
dev@189 5275 using Tbc::TextAttributes;
dev@189 5276 }
dev@189 5277
dev@189 5278 // #included from: catch_console_colour.hpp
dev@189 5279 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
dev@189 5280
dev@189 5281 namespace Catch {
dev@189 5282
dev@189 5283 struct Colour {
dev@189 5284 enum Code {
dev@189 5285 None = 0,
dev@189 5286
dev@189 5287 White,
dev@189 5288 Red,
dev@189 5289 Green,
dev@189 5290 Blue,
dev@189 5291 Cyan,
dev@189 5292 Yellow,
dev@189 5293 Grey,
dev@189 5294
dev@189 5295 Bright = 0x10,
dev@189 5296
dev@189 5297 BrightRed = Bright | Red,
dev@189 5298 BrightGreen = Bright | Green,
dev@189 5299 LightGrey = Bright | Grey,
dev@189 5300 BrightWhite = Bright | White,
dev@189 5301
dev@189 5302 // By intention
dev@189 5303 FileName = LightGrey,
dev@189 5304 Warning = Yellow,
dev@189 5305 ResultError = BrightRed,
dev@189 5306 ResultSuccess = BrightGreen,
dev@189 5307 ResultExpectedFailure = Warning,
dev@189 5308
dev@189 5309 Error = BrightRed,
dev@189 5310 Success = Green,
dev@189 5311
dev@189 5312 OriginalExpression = Cyan,
dev@189 5313 ReconstructedExpression = Yellow,
dev@189 5314
dev@189 5315 SecondaryText = LightGrey,
dev@189 5316 Headers = White
dev@189 5317 };
dev@189 5318
dev@189 5319 // Use constructed object for RAII guard
dev@189 5320 Colour( Code _colourCode );
dev@189 5321 Colour( Colour const& other );
dev@189 5322 ~Colour();
dev@189 5323
dev@189 5324 // Use static method for one-shot changes
dev@189 5325 static void use( Code _colourCode );
dev@189 5326
dev@189 5327 private:
dev@189 5328 bool m_moved;
dev@189 5329 };
dev@189 5330
dev@189 5331 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
dev@189 5332
dev@189 5333 } // end namespace Catch
dev@189 5334
dev@189 5335 // #included from: catch_interfaces_reporter.h
dev@189 5336 #define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
dev@189 5337
dev@189 5338 #include <string>
dev@189 5339 #include <ostream>
dev@189 5340 #include <map>
dev@189 5341 #include <assert.h>
dev@189 5342
dev@189 5343 namespace Catch
dev@189 5344 {
dev@189 5345 struct ReporterConfig {
dev@189 5346 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
dev@189 5347 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
dev@189 5348
dev@189 5349 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
dev@189 5350 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
dev@189 5351
dev@189 5352 std::ostream& stream() const { return *m_stream; }
dev@189 5353 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
dev@189 5354
dev@189 5355 private:
dev@189 5356 std::ostream* m_stream;
dev@189 5357 Ptr<IConfig const> m_fullConfig;
dev@189 5358 };
dev@189 5359
dev@189 5360 struct ReporterPreferences {
dev@189 5361 ReporterPreferences()
dev@189 5362 : shouldRedirectStdOut( false )
dev@189 5363 {}
dev@189 5364
dev@189 5365 bool shouldRedirectStdOut;
dev@189 5366 };
dev@189 5367
dev@189 5368 template<typename T>
dev@189 5369 struct LazyStat : Option<T> {
dev@189 5370 LazyStat() : used( false ) {}
dev@189 5371 LazyStat& operator=( T const& _value ) {
dev@189 5372 Option<T>::operator=( _value );
dev@189 5373 used = false;
dev@189 5374 return *this;
dev@189 5375 }
dev@189 5376 void reset() {
dev@189 5377 Option<T>::reset();
dev@189 5378 used = false;
dev@189 5379 }
dev@189 5380 bool used;
dev@189 5381 };
dev@189 5382
dev@189 5383 struct TestRunInfo {
dev@189 5384 TestRunInfo( std::string const& _name ) : name( _name ) {}
dev@189 5385 std::string name;
dev@189 5386 };
dev@189 5387 struct GroupInfo {
dev@189 5388 GroupInfo( std::string const& _name,
dev@189 5389 std::size_t _groupIndex,
dev@189 5390 std::size_t _groupsCount )
dev@189 5391 : name( _name ),
dev@189 5392 groupIndex( _groupIndex ),
dev@189 5393 groupsCounts( _groupsCount )
dev@189 5394 {}
dev@189 5395
dev@189 5396 std::string name;
dev@189 5397 std::size_t groupIndex;
dev@189 5398 std::size_t groupsCounts;
dev@189 5399 };
dev@189 5400
dev@189 5401 struct AssertionStats {
dev@189 5402 AssertionStats( AssertionResult const& _assertionResult,
dev@189 5403 std::vector<MessageInfo> const& _infoMessages,
dev@189 5404 Totals const& _totals )
dev@189 5405 : assertionResult( _assertionResult ),
dev@189 5406 infoMessages( _infoMessages ),
dev@189 5407 totals( _totals )
dev@189 5408 {
dev@189 5409 if( assertionResult.hasMessage() ) {
dev@189 5410 // Copy message into messages list.
dev@189 5411 // !TBD This should have been done earlier, somewhere
dev@189 5412 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
dev@189 5413 builder << assertionResult.getMessage();
dev@189 5414 builder.m_info.message = builder.m_stream.str();
dev@189 5415
dev@189 5416 infoMessages.push_back( builder.m_info );
dev@189 5417 }
dev@189 5418 }
dev@189 5419 virtual ~AssertionStats();
dev@189 5420
dev@189 5421 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 5422 AssertionStats( AssertionStats const& ) = default;
dev@189 5423 AssertionStats( AssertionStats && ) = default;
dev@189 5424 AssertionStats& operator = ( AssertionStats const& ) = default;
dev@189 5425 AssertionStats& operator = ( AssertionStats && ) = default;
dev@189 5426 # endif
dev@189 5427
dev@189 5428 AssertionResult assertionResult;
dev@189 5429 std::vector<MessageInfo> infoMessages;
dev@189 5430 Totals totals;
dev@189 5431 };
dev@189 5432
dev@189 5433 struct SectionStats {
dev@189 5434 SectionStats( SectionInfo const& _sectionInfo,
dev@189 5435 Counts const& _assertions,
dev@189 5436 double _durationInSeconds,
dev@189 5437 bool _missingAssertions )
dev@189 5438 : sectionInfo( _sectionInfo ),
dev@189 5439 assertions( _assertions ),
dev@189 5440 durationInSeconds( _durationInSeconds ),
dev@189 5441 missingAssertions( _missingAssertions )
dev@189 5442 {}
dev@189 5443 virtual ~SectionStats();
dev@189 5444 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 5445 SectionStats( SectionStats const& ) = default;
dev@189 5446 SectionStats( SectionStats && ) = default;
dev@189 5447 SectionStats& operator = ( SectionStats const& ) = default;
dev@189 5448 SectionStats& operator = ( SectionStats && ) = default;
dev@189 5449 # endif
dev@189 5450
dev@189 5451 SectionInfo sectionInfo;
dev@189 5452 Counts assertions;
dev@189 5453 double durationInSeconds;
dev@189 5454 bool missingAssertions;
dev@189 5455 };
dev@189 5456
dev@189 5457 struct TestCaseStats {
dev@189 5458 TestCaseStats( TestCaseInfo const& _testInfo,
dev@189 5459 Totals const& _totals,
dev@189 5460 std::string const& _stdOut,
dev@189 5461 std::string const& _stdErr,
dev@189 5462 bool _aborting )
dev@189 5463 : testInfo( _testInfo ),
dev@189 5464 totals( _totals ),
dev@189 5465 stdOut( _stdOut ),
dev@189 5466 stdErr( _stdErr ),
dev@189 5467 aborting( _aborting )
dev@189 5468 {}
dev@189 5469 virtual ~TestCaseStats();
dev@189 5470
dev@189 5471 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 5472 TestCaseStats( TestCaseStats const& ) = default;
dev@189 5473 TestCaseStats( TestCaseStats && ) = default;
dev@189 5474 TestCaseStats& operator = ( TestCaseStats const& ) = default;
dev@189 5475 TestCaseStats& operator = ( TestCaseStats && ) = default;
dev@189 5476 # endif
dev@189 5477
dev@189 5478 TestCaseInfo testInfo;
dev@189 5479 Totals totals;
dev@189 5480 std::string stdOut;
dev@189 5481 std::string stdErr;
dev@189 5482 bool aborting;
dev@189 5483 };
dev@189 5484
dev@189 5485 struct TestGroupStats {
dev@189 5486 TestGroupStats( GroupInfo const& _groupInfo,
dev@189 5487 Totals const& _totals,
dev@189 5488 bool _aborting )
dev@189 5489 : groupInfo( _groupInfo ),
dev@189 5490 totals( _totals ),
dev@189 5491 aborting( _aborting )
dev@189 5492 {}
dev@189 5493 TestGroupStats( GroupInfo const& _groupInfo )
dev@189 5494 : groupInfo( _groupInfo ),
dev@189 5495 aborting( false )
dev@189 5496 {}
dev@189 5497 virtual ~TestGroupStats();
dev@189 5498
dev@189 5499 # ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 5500 TestGroupStats( TestGroupStats const& ) = default;
dev@189 5501 TestGroupStats( TestGroupStats && ) = default;
dev@189 5502 TestGroupStats& operator = ( TestGroupStats const& ) = default;
dev@189 5503 TestGroupStats& operator = ( TestGroupStats && ) = default;
dev@189 5504 # endif
dev@189 5505
dev@189 5506 GroupInfo groupInfo;
dev@189 5507 Totals totals;
dev@189 5508 bool aborting;
dev@189 5509 };
dev@189 5510
dev@189 5511 struct TestRunStats {
dev@189 5512 TestRunStats( TestRunInfo const& _runInfo,
dev@189 5513 Totals const& _totals,
dev@189 5514 bool _aborting )
dev@189 5515 : runInfo( _runInfo ),
dev@189 5516 totals( _totals ),
dev@189 5517 aborting( _aborting )
dev@189 5518 {}
dev@189 5519 virtual ~TestRunStats();
dev@189 5520
dev@189 5521 # ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
dev@189 5522 TestRunStats( TestRunStats const& _other )
dev@189 5523 : runInfo( _other.runInfo ),
dev@189 5524 totals( _other.totals ),
dev@189 5525 aborting( _other.aborting )
dev@189 5526 {}
dev@189 5527 # else
dev@189 5528 TestRunStats( TestRunStats const& ) = default;
dev@189 5529 TestRunStats( TestRunStats && ) = default;
dev@189 5530 TestRunStats& operator = ( TestRunStats const& ) = default;
dev@189 5531 TestRunStats& operator = ( TestRunStats && ) = default;
dev@189 5532 # endif
dev@189 5533
dev@189 5534 TestRunInfo runInfo;
dev@189 5535 Totals totals;
dev@189 5536 bool aborting;
dev@189 5537 };
dev@189 5538
dev@189 5539 class MultipleReporters;
dev@189 5540
dev@189 5541 struct IStreamingReporter : IShared {
dev@189 5542 virtual ~IStreamingReporter();
dev@189 5543
dev@189 5544 // Implementing class must also provide the following static method:
dev@189 5545 // static std::string getDescription();
dev@189 5546
dev@189 5547 virtual ReporterPreferences getPreferences() const = 0;
dev@189 5548
dev@189 5549 virtual void noMatchingTestCases( std::string const& spec ) = 0;
dev@189 5550
dev@189 5551 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
dev@189 5552 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
dev@189 5553
dev@189 5554 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
dev@189 5555 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
dev@189 5556
dev@189 5557 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
dev@189 5558
dev@189 5559 // The return value indicates if the messages buffer should be cleared:
dev@189 5560 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
dev@189 5561
dev@189 5562 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
dev@189 5563 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
dev@189 5564 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
dev@189 5565 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
dev@189 5566
dev@189 5567 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
dev@189 5568
dev@189 5569 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
dev@189 5570 };
dev@189 5571
dev@189 5572 struct IReporterFactory : IShared {
dev@189 5573 virtual ~IReporterFactory();
dev@189 5574 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
dev@189 5575 virtual std::string getDescription() const = 0;
dev@189 5576 };
dev@189 5577
dev@189 5578 struct IReporterRegistry {
dev@189 5579 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
dev@189 5580 typedef std::vector<Ptr<IReporterFactory> > Listeners;
dev@189 5581
dev@189 5582 virtual ~IReporterRegistry();
dev@189 5583 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
dev@189 5584 virtual FactoryMap const& getFactories() const = 0;
dev@189 5585 virtual Listeners const& getListeners() const = 0;
dev@189 5586 };
dev@189 5587
dev@189 5588 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
dev@189 5589
dev@189 5590 }
dev@189 5591
dev@189 5592 #include <limits>
dev@189 5593 #include <algorithm>
dev@189 5594
dev@189 5595 namespace Catch {
dev@189 5596
dev@189 5597 inline std::size_t listTests( Config const& config ) {
dev@189 5598
dev@189 5599 TestSpec testSpec = config.testSpec();
dev@189 5600 if( config.testSpec().hasFilters() )
dev@189 5601 Catch::cout() << "Matching test cases:\n";
dev@189 5602 else {
dev@189 5603 Catch::cout() << "All available test cases:\n";
dev@189 5604 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
dev@189 5605 }
dev@189 5606
dev@189 5607 std::size_t matchedTests = 0;
dev@189 5608 TextAttributes nameAttr, tagsAttr;
dev@189 5609 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
dev@189 5610 tagsAttr.setIndent( 6 );
dev@189 5611
dev@189 5612 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
dev@189 5613 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
dev@189 5614 it != itEnd;
dev@189 5615 ++it ) {
dev@189 5616 matchedTests++;
dev@189 5617 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
dev@189 5618 Colour::Code colour = testCaseInfo.isHidden()
dev@189 5619 ? Colour::SecondaryText
dev@189 5620 : Colour::None;
dev@189 5621 Colour colourGuard( colour );
dev@189 5622
dev@189 5623 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
dev@189 5624 if( !testCaseInfo.tags.empty() )
dev@189 5625 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
dev@189 5626 }
dev@189 5627
dev@189 5628 if( !config.testSpec().hasFilters() )
dev@189 5629 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
dev@189 5630 else
dev@189 5631 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
dev@189 5632 return matchedTests;
dev@189 5633 }
dev@189 5634
dev@189 5635 inline std::size_t listTestsNamesOnly( Config const& config ) {
dev@189 5636 TestSpec testSpec = config.testSpec();
dev@189 5637 if( !config.testSpec().hasFilters() )
dev@189 5638 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
dev@189 5639 std::size_t matchedTests = 0;
dev@189 5640 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
dev@189 5641 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
dev@189 5642 it != itEnd;
dev@189 5643 ++it ) {
dev@189 5644 matchedTests++;
dev@189 5645 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
dev@189 5646 if( startsWith( testCaseInfo.name, '#' ) )
dev@189 5647 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
dev@189 5648 else
dev@189 5649 Catch::cout() << testCaseInfo.name << std::endl;
dev@189 5650 }
dev@189 5651 return matchedTests;
dev@189 5652 }
dev@189 5653
dev@189 5654 struct TagInfo {
dev@189 5655 TagInfo() : count ( 0 ) {}
dev@189 5656 void add( std::string const& spelling ) {
dev@189 5657 ++count;
dev@189 5658 spellings.insert( spelling );
dev@189 5659 }
dev@189 5660 std::string all() const {
dev@189 5661 std::string out;
dev@189 5662 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
dev@189 5663 it != itEnd;
dev@189 5664 ++it )
dev@189 5665 out += "[" + *it + "]";
dev@189 5666 return out;
dev@189 5667 }
dev@189 5668 std::set<std::string> spellings;
dev@189 5669 std::size_t count;
dev@189 5670 };
dev@189 5671
dev@189 5672 inline std::size_t listTags( Config const& config ) {
dev@189 5673 TestSpec testSpec = config.testSpec();
dev@189 5674 if( config.testSpec().hasFilters() )
dev@189 5675 Catch::cout() << "Tags for matching test cases:\n";
dev@189 5676 else {
dev@189 5677 Catch::cout() << "All available tags:\n";
dev@189 5678 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
dev@189 5679 }
dev@189 5680
dev@189 5681 std::map<std::string, TagInfo> tagCounts;
dev@189 5682
dev@189 5683 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
dev@189 5684 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
dev@189 5685 it != itEnd;
dev@189 5686 ++it ) {
dev@189 5687 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
dev@189 5688 tagItEnd = it->getTestCaseInfo().tags.end();
dev@189 5689 tagIt != tagItEnd;
dev@189 5690 ++tagIt ) {
dev@189 5691 std::string tagName = *tagIt;
dev@189 5692 std::string lcaseTagName = toLower( tagName );
dev@189 5693 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
dev@189 5694 if( countIt == tagCounts.end() )
dev@189 5695 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
dev@189 5696 countIt->second.add( tagName );
dev@189 5697 }
dev@189 5698 }
dev@189 5699
dev@189 5700 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
dev@189 5701 countItEnd = tagCounts.end();
dev@189 5702 countIt != countItEnd;
dev@189 5703 ++countIt ) {
dev@189 5704 std::ostringstream oss;
dev@189 5705 oss << " " << std::setw(2) << countIt->second.count << " ";
dev@189 5706 Text wrapper( countIt->second.all(), TextAttributes()
dev@189 5707 .setInitialIndent( 0 )
dev@189 5708 .setIndent( oss.str().size() )
dev@189 5709 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
dev@189 5710 Catch::cout() << oss.str() << wrapper << '\n';
dev@189 5711 }
dev@189 5712 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
dev@189 5713 return tagCounts.size();
dev@189 5714 }
dev@189 5715
dev@189 5716 inline std::size_t listReporters( Config const& /*config*/ ) {
dev@189 5717 Catch::cout() << "Available reporters:\n";
dev@189 5718 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
dev@189 5719 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
dev@189 5720 std::size_t maxNameLen = 0;
dev@189 5721 for(it = itBegin; it != itEnd; ++it )
dev@189 5722 maxNameLen = (std::max)( maxNameLen, it->first.size() );
dev@189 5723
dev@189 5724 for(it = itBegin; it != itEnd; ++it ) {
dev@189 5725 Text wrapper( it->second->getDescription(), TextAttributes()
dev@189 5726 .setInitialIndent( 0 )
dev@189 5727 .setIndent( 7+maxNameLen )
dev@189 5728 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
dev@189 5729 Catch::cout() << " "
dev@189 5730 << it->first
dev@189 5731 << ':'
dev@189 5732 << std::string( maxNameLen - it->first.size() + 2, ' ' )
dev@189 5733 << wrapper << '\n';
dev@189 5734 }
dev@189 5735 Catch::cout() << std::endl;
dev@189 5736 return factories.size();
dev@189 5737 }
dev@189 5738
dev@189 5739 inline Option<std::size_t> list( Config const& config ) {
dev@189 5740 Option<std::size_t> listedCount;
dev@189 5741 if( config.listTests() )
dev@189 5742 listedCount = listedCount.valueOr(0) + listTests( config );
dev@189 5743 if( config.listTestNamesOnly() )
dev@189 5744 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
dev@189 5745 if( config.listTags() )
dev@189 5746 listedCount = listedCount.valueOr(0) + listTags( config );
dev@189 5747 if( config.listReporters() )
dev@189 5748 listedCount = listedCount.valueOr(0) + listReporters( config );
dev@189 5749 return listedCount;
dev@189 5750 }
dev@189 5751
dev@189 5752 } // end namespace Catch
dev@189 5753
dev@189 5754 // #included from: internal/catch_run_context.hpp
dev@189 5755 #define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
dev@189 5756
dev@189 5757 // #included from: catch_test_case_tracker.hpp
dev@189 5758 #define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
dev@189 5759
dev@189 5760 #include <map>
dev@189 5761 #include <string>
dev@189 5762 #include <assert.h>
dev@189 5763 #include <vector>
dev@189 5764 #include <iterator>
dev@189 5765
dev@189 5766 namespace Catch {
dev@189 5767 namespace TestCaseTracking {
dev@189 5768
dev@189 5769 struct NameAndLocation {
dev@189 5770 std::string name;
dev@189 5771 SourceLineInfo location;
dev@189 5772
dev@189 5773 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
dev@189 5774 : name( _name ),
dev@189 5775 location( _location )
dev@189 5776 {}
dev@189 5777 };
dev@189 5778
dev@189 5779 struct ITracker : SharedImpl<> {
dev@189 5780 virtual ~ITracker();
dev@189 5781
dev@189 5782 // static queries
dev@189 5783 virtual NameAndLocation const& nameAndLocation() const = 0;
dev@189 5784
dev@189 5785 // dynamic queries
dev@189 5786 virtual bool isComplete() const = 0; // Successfully completed or failed
dev@189 5787 virtual bool isSuccessfullyCompleted() const = 0;
dev@189 5788 virtual bool isOpen() const = 0; // Started but not complete
dev@189 5789 virtual bool hasChildren() const = 0;
dev@189 5790
dev@189 5791 virtual ITracker& parent() = 0;
dev@189 5792
dev@189 5793 // actions
dev@189 5794 virtual void close() = 0; // Successfully complete
dev@189 5795 virtual void fail() = 0;
dev@189 5796 virtual void markAsNeedingAnotherRun() = 0;
dev@189 5797
dev@189 5798 virtual void addChild( Ptr<ITracker> const& child ) = 0;
dev@189 5799 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
dev@189 5800 virtual void openChild() = 0;
dev@189 5801
dev@189 5802 // Debug/ checking
dev@189 5803 virtual bool isSectionTracker() const = 0;
dev@189 5804 virtual bool isIndexTracker() const = 0;
dev@189 5805 };
dev@189 5806
dev@189 5807 class TrackerContext {
dev@189 5808
dev@189 5809 enum RunState {
dev@189 5810 NotStarted,
dev@189 5811 Executing,
dev@189 5812 CompletedCycle
dev@189 5813 };
dev@189 5814
dev@189 5815 Ptr<ITracker> m_rootTracker;
dev@189 5816 ITracker* m_currentTracker;
dev@189 5817 RunState m_runState;
dev@189 5818
dev@189 5819 public:
dev@189 5820
dev@189 5821 static TrackerContext& instance() {
dev@189 5822 static TrackerContext s_instance;
dev@189 5823 return s_instance;
dev@189 5824 }
dev@189 5825
dev@189 5826 TrackerContext()
dev@189 5827 : m_currentTracker( CATCH_NULL ),
dev@189 5828 m_runState( NotStarted )
dev@189 5829 {}
dev@189 5830
dev@189 5831 ITracker& startRun();
dev@189 5832
dev@189 5833 void endRun() {
dev@189 5834 m_rootTracker.reset();
dev@189 5835 m_currentTracker = CATCH_NULL;
dev@189 5836 m_runState = NotStarted;
dev@189 5837 }
dev@189 5838
dev@189 5839 void startCycle() {
dev@189 5840 m_currentTracker = m_rootTracker.get();
dev@189 5841 m_runState = Executing;
dev@189 5842 }
dev@189 5843 void completeCycle() {
dev@189 5844 m_runState = CompletedCycle;
dev@189 5845 }
dev@189 5846
dev@189 5847 bool completedCycle() const {
dev@189 5848 return m_runState == CompletedCycle;
dev@189 5849 }
dev@189 5850 ITracker& currentTracker() {
dev@189 5851 return *m_currentTracker;
dev@189 5852 }
dev@189 5853 void setCurrentTracker( ITracker* tracker ) {
dev@189 5854 m_currentTracker = tracker;
dev@189 5855 }
dev@189 5856 };
dev@189 5857
dev@189 5858 class TrackerBase : public ITracker {
dev@189 5859 protected:
dev@189 5860 enum CycleState {
dev@189 5861 NotStarted,
dev@189 5862 Executing,
dev@189 5863 ExecutingChildren,
dev@189 5864 NeedsAnotherRun,
dev@189 5865 CompletedSuccessfully,
dev@189 5866 Failed
dev@189 5867 };
dev@189 5868 class TrackerHasName {
dev@189 5869 NameAndLocation m_nameAndLocation;
dev@189 5870 public:
dev@189 5871 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
dev@189 5872 bool operator ()( Ptr<ITracker> const& tracker ) {
dev@189 5873 return
dev@189 5874 tracker->nameAndLocation().name == m_nameAndLocation.name &&
dev@189 5875 tracker->nameAndLocation().location == m_nameAndLocation.location;
dev@189 5876 }
dev@189 5877 };
dev@189 5878 typedef std::vector<Ptr<ITracker> > Children;
dev@189 5879 NameAndLocation m_nameAndLocation;
dev@189 5880 TrackerContext& m_ctx;
dev@189 5881 ITracker* m_parent;
dev@189 5882 Children m_children;
dev@189 5883 CycleState m_runState;
dev@189 5884 public:
dev@189 5885 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
dev@189 5886 : m_nameAndLocation( nameAndLocation ),
dev@189 5887 m_ctx( ctx ),
dev@189 5888 m_parent( parent ),
dev@189 5889 m_runState( NotStarted )
dev@189 5890 {}
dev@189 5891 virtual ~TrackerBase();
dev@189 5892
dev@189 5893 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
dev@189 5894 return m_nameAndLocation;
dev@189 5895 }
dev@189 5896 virtual bool isComplete() const CATCH_OVERRIDE {
dev@189 5897 return m_runState == CompletedSuccessfully || m_runState == Failed;
dev@189 5898 }
dev@189 5899 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
dev@189 5900 return m_runState == CompletedSuccessfully;
dev@189 5901 }
dev@189 5902 virtual bool isOpen() const CATCH_OVERRIDE {
dev@189 5903 return m_runState != NotStarted && !isComplete();
dev@189 5904 }
dev@189 5905 virtual bool hasChildren() const CATCH_OVERRIDE {
dev@189 5906 return !m_children.empty();
dev@189 5907 }
dev@189 5908
dev@189 5909 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
dev@189 5910 m_children.push_back( child );
dev@189 5911 }
dev@189 5912
dev@189 5913 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
dev@189 5914 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
dev@189 5915 return( it != m_children.end() )
dev@189 5916 ? it->get()
dev@189 5917 : CATCH_NULL;
dev@189 5918 }
dev@189 5919 virtual ITracker& parent() CATCH_OVERRIDE {
dev@189 5920 assert( m_parent ); // Should always be non-null except for root
dev@189 5921 return *m_parent;
dev@189 5922 }
dev@189 5923
dev@189 5924 virtual void openChild() CATCH_OVERRIDE {
dev@189 5925 if( m_runState != ExecutingChildren ) {
dev@189 5926 m_runState = ExecutingChildren;
dev@189 5927 if( m_parent )
dev@189 5928 m_parent->openChild();
dev@189 5929 }
dev@189 5930 }
dev@189 5931
dev@189 5932 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
dev@189 5933 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
dev@189 5934
dev@189 5935 void open() {
dev@189 5936 m_runState = Executing;
dev@189 5937 moveToThis();
dev@189 5938 if( m_parent )
dev@189 5939 m_parent->openChild();
dev@189 5940 }
dev@189 5941
dev@189 5942 virtual void close() CATCH_OVERRIDE {
dev@189 5943
dev@189 5944 // Close any still open children (e.g. generators)
dev@189 5945 while( &m_ctx.currentTracker() != this )
dev@189 5946 m_ctx.currentTracker().close();
dev@189 5947
dev@189 5948 switch( m_runState ) {
dev@189 5949 case NotStarted:
dev@189 5950 case CompletedSuccessfully:
dev@189 5951 case Failed:
dev@189 5952 throw std::logic_error( "Illogical state" );
dev@189 5953
dev@189 5954 case NeedsAnotherRun:
dev@189 5955 break;;
dev@189 5956
dev@189 5957 case Executing:
dev@189 5958 m_runState = CompletedSuccessfully;
dev@189 5959 break;
dev@189 5960 case ExecutingChildren:
dev@189 5961 if( m_children.empty() || m_children.back()->isComplete() )
dev@189 5962 m_runState = CompletedSuccessfully;
dev@189 5963 break;
dev@189 5964
dev@189 5965 default:
dev@189 5966 throw std::logic_error( "Unexpected state" );
dev@189 5967 }
dev@189 5968 moveToParent();
dev@189 5969 m_ctx.completeCycle();
dev@189 5970 }
dev@189 5971 virtual void fail() CATCH_OVERRIDE {
dev@189 5972 m_runState = Failed;
dev@189 5973 if( m_parent )
dev@189 5974 m_parent->markAsNeedingAnotherRun();
dev@189 5975 moveToParent();
dev@189 5976 m_ctx.completeCycle();
dev@189 5977 }
dev@189 5978 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
dev@189 5979 m_runState = NeedsAnotherRun;
dev@189 5980 }
dev@189 5981 private:
dev@189 5982 void moveToParent() {
dev@189 5983 assert( m_parent );
dev@189 5984 m_ctx.setCurrentTracker( m_parent );
dev@189 5985 }
dev@189 5986 void moveToThis() {
dev@189 5987 m_ctx.setCurrentTracker( this );
dev@189 5988 }
dev@189 5989 };
dev@189 5990
dev@189 5991 class SectionTracker : public TrackerBase {
dev@189 5992 std::vector<std::string> m_filters;
dev@189 5993 public:
dev@189 5994 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
dev@189 5995 : TrackerBase( nameAndLocation, ctx, parent )
dev@189 5996 {
dev@189 5997 if( parent ) {
dev@189 5998 while( !parent->isSectionTracker() )
dev@189 5999 parent = &parent->parent();
dev@189 6000
dev@189 6001 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
dev@189 6002 addNextFilters( parentSection.m_filters );
dev@189 6003 }
dev@189 6004 }
dev@189 6005 virtual ~SectionTracker();
dev@189 6006
dev@189 6007 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
dev@189 6008
dev@189 6009 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
dev@189 6010 SectionTracker* section = CATCH_NULL;
dev@189 6011
dev@189 6012 ITracker& currentTracker = ctx.currentTracker();
dev@189 6013 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
dev@189 6014 assert( childTracker );
dev@189 6015 assert( childTracker->isSectionTracker() );
dev@189 6016 section = static_cast<SectionTracker*>( childTracker );
dev@189 6017 }
dev@189 6018 else {
dev@189 6019 section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
dev@189 6020 currentTracker.addChild( section );
dev@189 6021 }
dev@189 6022 if( !ctx.completedCycle() )
dev@189 6023 section->tryOpen();
dev@189 6024 return *section;
dev@189 6025 }
dev@189 6026
dev@189 6027 void tryOpen() {
dev@189 6028 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
dev@189 6029 open();
dev@189 6030 }
dev@189 6031
dev@189 6032 void addInitialFilters( std::vector<std::string> const& filters ) {
dev@189 6033 if( !filters.empty() ) {
dev@189 6034 m_filters.push_back(""); // Root - should never be consulted
dev@189 6035 m_filters.push_back(""); // Test Case - not a section filter
dev@189 6036 std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) );
dev@189 6037 }
dev@189 6038 }
dev@189 6039 void addNextFilters( std::vector<std::string> const& filters ) {
dev@189 6040 if( filters.size() > 1 )
dev@189 6041 std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) );
dev@189 6042 }
dev@189 6043 };
dev@189 6044
dev@189 6045 class IndexTracker : public TrackerBase {
dev@189 6046 int m_size;
dev@189 6047 int m_index;
dev@189 6048 public:
dev@189 6049 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
dev@189 6050 : TrackerBase( nameAndLocation, ctx, parent ),
dev@189 6051 m_size( size ),
dev@189 6052 m_index( -1 )
dev@189 6053 {}
dev@189 6054 virtual ~IndexTracker();
dev@189 6055
dev@189 6056 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
dev@189 6057
dev@189 6058 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
dev@189 6059 IndexTracker* tracker = CATCH_NULL;
dev@189 6060
dev@189 6061 ITracker& currentTracker = ctx.currentTracker();
dev@189 6062 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
dev@189 6063 assert( childTracker );
dev@189 6064 assert( childTracker->isIndexTracker() );
dev@189 6065 tracker = static_cast<IndexTracker*>( childTracker );
dev@189 6066 }
dev@189 6067 else {
dev@189 6068 tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
dev@189 6069 currentTracker.addChild( tracker );
dev@189 6070 }
dev@189 6071
dev@189 6072 if( !ctx.completedCycle() && !tracker->isComplete() ) {
dev@189 6073 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
dev@189 6074 tracker->moveNext();
dev@189 6075 tracker->open();
dev@189 6076 }
dev@189 6077
dev@189 6078 return *tracker;
dev@189 6079 }
dev@189 6080
dev@189 6081 int index() const { return m_index; }
dev@189 6082
dev@189 6083 void moveNext() {
dev@189 6084 m_index++;
dev@189 6085 m_children.clear();
dev@189 6086 }
dev@189 6087
dev@189 6088 virtual void close() CATCH_OVERRIDE {
dev@189 6089 TrackerBase::close();
dev@189 6090 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
dev@189 6091 m_runState = Executing;
dev@189 6092 }
dev@189 6093 };
dev@189 6094
dev@189 6095 inline ITracker& TrackerContext::startRun() {
dev@189 6096 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
dev@189 6097 m_currentTracker = CATCH_NULL;
dev@189 6098 m_runState = Executing;
dev@189 6099 return *m_rootTracker;
dev@189 6100 }
dev@189 6101
dev@189 6102 } // namespace TestCaseTracking
dev@189 6103
dev@189 6104 using TestCaseTracking::ITracker;
dev@189 6105 using TestCaseTracking::TrackerContext;
dev@189 6106 using TestCaseTracking::SectionTracker;
dev@189 6107 using TestCaseTracking::IndexTracker;
dev@189 6108
dev@189 6109 } // namespace Catch
dev@189 6110
dev@189 6111 // #included from: catch_fatal_condition.hpp
dev@189 6112 #define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
dev@189 6113
dev@189 6114 namespace Catch {
dev@189 6115
dev@189 6116 // Report the error condition
dev@189 6117 inline void reportFatal( std::string const& message ) {
dev@189 6118 IContext& context = Catch::getCurrentContext();
dev@189 6119 IResultCapture* resultCapture = context.getResultCapture();
dev@189 6120 resultCapture->handleFatalErrorCondition( message );
dev@189 6121 }
dev@189 6122
dev@189 6123 } // namespace Catch
dev@189 6124
dev@189 6125 #if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
dev@189 6126 // #included from: catch_windows_h_proxy.h
dev@189 6127
dev@189 6128 #define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
dev@189 6129
dev@189 6130 #ifdef CATCH_DEFINES_NOMINMAX
dev@189 6131 # define NOMINMAX
dev@189 6132 #endif
dev@189 6133 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
dev@189 6134 # define WIN32_LEAN_AND_MEAN
dev@189 6135 #endif
dev@189 6136
dev@189 6137 #ifdef __AFXDLL
dev@189 6138 #include <AfxWin.h>
dev@189 6139 #else
dev@189 6140 #include <windows.h>
dev@189 6141 #endif
dev@189 6142
dev@189 6143 #ifdef CATCH_DEFINES_NOMINMAX
dev@189 6144 # undef NOMINMAX
dev@189 6145 #endif
dev@189 6146 #ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
dev@189 6147 # undef WIN32_LEAN_AND_MEAN
dev@189 6148 #endif
dev@189 6149
dev@189 6150
dev@189 6151 # if !defined ( CATCH_CONFIG_WINDOWS_SEH )
dev@189 6152
dev@189 6153 namespace Catch {
dev@189 6154 struct FatalConditionHandler {
dev@189 6155 void reset() {}
dev@189 6156 };
dev@189 6157 }
dev@189 6158
dev@189 6159 # else // CATCH_CONFIG_WINDOWS_SEH is defined
dev@189 6160
dev@189 6161 namespace Catch {
dev@189 6162
dev@189 6163 struct SignalDefs { DWORD id; const char* name; };
dev@189 6164 extern SignalDefs signalDefs[];
dev@189 6165 // There is no 1-1 mapping between signals and windows exceptions.
dev@189 6166 // Windows can easily distinguish between SO and SigSegV,
dev@189 6167 // but SigInt, SigTerm, etc are handled differently.
dev@189 6168 SignalDefs signalDefs[] = {
dev@189 6169 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
dev@189 6170 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
dev@189 6171 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
dev@189 6172 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
dev@189 6173 };
dev@189 6174
dev@189 6175 struct FatalConditionHandler {
dev@189 6176
dev@189 6177 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
dev@189 6178 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
dev@189 6179 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
dev@189 6180 reset();
dev@189 6181 reportFatal(signalDefs[i].name);
dev@189 6182 }
dev@189 6183 }
dev@189 6184 // If its not an exception we care about, pass it along.
dev@189 6185 // This stops us from eating debugger breaks etc.
dev@189 6186 return EXCEPTION_CONTINUE_SEARCH;
dev@189 6187 }
dev@189 6188
dev@189 6189 FatalConditionHandler() {
dev@189 6190 isSet = true;
dev@189 6191 // 32k seems enough for Catch to handle stack overflow,
dev@189 6192 // but the value was found experimentally, so there is no strong guarantee
dev@189 6193 guaranteeSize = 32 * 1024;
dev@189 6194 exceptionHandlerHandle = CATCH_NULL;
dev@189 6195 // Register as first handler in current chain
dev@189 6196 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
dev@189 6197 // Pass in guarantee size to be filled
dev@189 6198 SetThreadStackGuarantee(&guaranteeSize);
dev@189 6199 }
dev@189 6200
dev@189 6201 static void reset() {
dev@189 6202 if (isSet) {
dev@189 6203 // Unregister handler and restore the old guarantee
dev@189 6204 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
dev@189 6205 SetThreadStackGuarantee(&guaranteeSize);
dev@189 6206 exceptionHandlerHandle = CATCH_NULL;
dev@189 6207 isSet = false;
dev@189 6208 }
dev@189 6209 }
dev@189 6210
dev@189 6211 ~FatalConditionHandler() {
dev@189 6212 reset();
dev@189 6213 }
dev@189 6214 private:
dev@189 6215 static bool isSet;
dev@189 6216 static ULONG guaranteeSize;
dev@189 6217 static PVOID exceptionHandlerHandle;
dev@189 6218 };
dev@189 6219
dev@189 6220 bool FatalConditionHandler::isSet = false;
dev@189 6221 ULONG FatalConditionHandler::guaranteeSize = 0;
dev@189 6222 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
dev@189 6223
dev@189 6224 } // namespace Catch
dev@189 6225
dev@189 6226 # endif // CATCH_CONFIG_WINDOWS_SEH
dev@189 6227
dev@189 6228 #else // Not Windows - assumed to be POSIX compatible //////////////////////////
dev@189 6229
dev@189 6230 #include <signal.h>
dev@189 6231
dev@189 6232 namespace Catch {
dev@189 6233
dev@189 6234 struct SignalDefs {
dev@189 6235 int id;
dev@189 6236 const char* name;
dev@189 6237 };
dev@189 6238 extern SignalDefs signalDefs[];
dev@189 6239 SignalDefs signalDefs[] = {
dev@189 6240 { SIGINT, "SIGINT - Terminal interrupt signal" },
dev@189 6241 { SIGILL, "SIGILL - Illegal instruction signal" },
dev@189 6242 { SIGFPE, "SIGFPE - Floating point error signal" },
dev@189 6243 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
dev@189 6244 { SIGTERM, "SIGTERM - Termination request signal" },
dev@189 6245 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
dev@189 6246 };
dev@189 6247
dev@189 6248 struct FatalConditionHandler {
dev@189 6249
dev@189 6250 static bool isSet;
dev@189 6251 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
dev@189 6252 static stack_t oldSigStack;
dev@189 6253 static char altStackMem[SIGSTKSZ];
dev@189 6254
dev@189 6255 static void handleSignal( int sig ) {
dev@189 6256 std::string name = "<unknown signal>";
dev@189 6257 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
dev@189 6258 SignalDefs &def = signalDefs[i];
dev@189 6259 if (sig == def.id) {
dev@189 6260 name = def.name;
dev@189 6261 break;
dev@189 6262 }
dev@189 6263 }
dev@189 6264 reset();
dev@189 6265 reportFatal(name);
dev@189 6266 raise( sig );
dev@189 6267 }
dev@189 6268
dev@189 6269 FatalConditionHandler() {
dev@189 6270 isSet = true;
dev@189 6271 stack_t sigStack;
dev@189 6272 sigStack.ss_sp = altStackMem;
dev@189 6273 sigStack.ss_size = SIGSTKSZ;
dev@189 6274 sigStack.ss_flags = 0;
dev@189 6275 sigaltstack(&sigStack, &oldSigStack);
dev@189 6276 struct sigaction sa = { 0 };
dev@189 6277
dev@189 6278 sa.sa_handler = handleSignal;
dev@189 6279 sa.sa_flags = SA_ONSTACK;
dev@189 6280 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
dev@189 6281 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
dev@189 6282 }
dev@189 6283 }
dev@189 6284
dev@189 6285 ~FatalConditionHandler() {
dev@189 6286 reset();
dev@189 6287 }
dev@189 6288 static void reset() {
dev@189 6289 if( isSet ) {
dev@189 6290 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
dev@189 6291 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
dev@189 6292 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
dev@189 6293 }
dev@189 6294 // Return the old stack
dev@189 6295 sigaltstack(&oldSigStack, CATCH_NULL);
dev@189 6296 isSet = false;
dev@189 6297 }
dev@189 6298 }
dev@189 6299 };
dev@189 6300
dev@189 6301 bool FatalConditionHandler::isSet = false;
dev@189 6302 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
dev@189 6303 stack_t FatalConditionHandler::oldSigStack = {};
dev@189 6304 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
dev@189 6305
dev@189 6306 } // namespace Catch
dev@189 6307
dev@189 6308 #endif // not Windows
dev@189 6309
dev@189 6310 #include <set>
dev@189 6311 #include <string>
dev@189 6312
dev@189 6313 namespace Catch {
dev@189 6314
dev@189 6315 class StreamRedirect {
dev@189 6316
dev@189 6317 public:
dev@189 6318 StreamRedirect( std::ostream& stream, std::string& targetString )
dev@189 6319 : m_stream( stream ),
dev@189 6320 m_prevBuf( stream.rdbuf() ),
dev@189 6321 m_targetString( targetString )
dev@189 6322 {
dev@189 6323 stream.rdbuf( m_oss.rdbuf() );
dev@189 6324 }
dev@189 6325
dev@189 6326 ~StreamRedirect() {
dev@189 6327 m_targetString += m_oss.str();
dev@189 6328 m_stream.rdbuf( m_prevBuf );
dev@189 6329 }
dev@189 6330
dev@189 6331 private:
dev@189 6332 std::ostream& m_stream;
dev@189 6333 std::streambuf* m_prevBuf;
dev@189 6334 std::ostringstream m_oss;
dev@189 6335 std::string& m_targetString;
dev@189 6336 };
dev@189 6337
dev@189 6338 ///////////////////////////////////////////////////////////////////////////
dev@189 6339
dev@189 6340 class RunContext : public IResultCapture, public IRunner {
dev@189 6341
dev@189 6342 RunContext( RunContext const& );
dev@189 6343 void operator =( RunContext const& );
dev@189 6344
dev@189 6345 public:
dev@189 6346
dev@189 6347 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
dev@189 6348 : m_runInfo( _config->name() ),
dev@189 6349 m_context( getCurrentMutableContext() ),
dev@189 6350 m_activeTestCase( CATCH_NULL ),
dev@189 6351 m_config( _config ),
dev@189 6352 m_reporter( reporter )
dev@189 6353 {
dev@189 6354 m_context.setRunner( this );
dev@189 6355 m_context.setConfig( m_config );
dev@189 6356 m_context.setResultCapture( this );
dev@189 6357 m_reporter->testRunStarting( m_runInfo );
dev@189 6358 }
dev@189 6359
dev@189 6360 virtual ~RunContext() {
dev@189 6361 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
dev@189 6362 }
dev@189 6363
dev@189 6364 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
dev@189 6365 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
dev@189 6366 }
dev@189 6367 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
dev@189 6368 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
dev@189 6369 }
dev@189 6370
dev@189 6371 Totals runTest( TestCase const& testCase ) {
dev@189 6372 Totals prevTotals = m_totals;
dev@189 6373
dev@189 6374 std::string redirectedCout;
dev@189 6375 std::string redirectedCerr;
dev@189 6376
dev@189 6377 TestCaseInfo testInfo = testCase.getTestCaseInfo();
dev@189 6378
dev@189 6379 m_reporter->testCaseStarting( testInfo );
dev@189 6380
dev@189 6381 m_activeTestCase = &testCase;
dev@189 6382
dev@189 6383 do {
dev@189 6384 ITracker& rootTracker = m_trackerContext.startRun();
dev@189 6385 dynamic_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
dev@189 6386 do {
dev@189 6387 m_trackerContext.startCycle();
dev@189 6388 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
dev@189 6389 runCurrentTest( redirectedCout, redirectedCerr );
dev@189 6390 }
dev@189 6391 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
dev@189 6392 }
dev@189 6393 // !TBD: deprecated - this will be replaced by indexed trackers
dev@189 6394 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
dev@189 6395
dev@189 6396 Totals deltaTotals = m_totals.delta( prevTotals );
dev@189 6397 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
dev@189 6398 deltaTotals.assertions.failed++;
dev@189 6399 deltaTotals.testCases.passed--;
dev@189 6400 deltaTotals.testCases.failed++;
dev@189 6401 }
dev@189 6402 m_totals.testCases += deltaTotals.testCases;
dev@189 6403 m_reporter->testCaseEnded( TestCaseStats( testInfo,
dev@189 6404 deltaTotals,
dev@189 6405 redirectedCout,
dev@189 6406 redirectedCerr,
dev@189 6407 aborting() ) );
dev@189 6408
dev@189 6409 m_activeTestCase = CATCH_NULL;
dev@189 6410 m_testCaseTracker = CATCH_NULL;
dev@189 6411
dev@189 6412 return deltaTotals;
dev@189 6413 }
dev@189 6414
dev@189 6415 Ptr<IConfig const> config() const {
dev@189 6416 return m_config;
dev@189 6417 }
dev@189 6418
dev@189 6419 private: // IResultCapture
dev@189 6420
dev@189 6421 virtual void assertionEnded( AssertionResult const& result ) {
dev@189 6422 if( result.getResultType() == ResultWas::Ok ) {
dev@189 6423 m_totals.assertions.passed++;
dev@189 6424 }
dev@189 6425 else if( !result.isOk() ) {
dev@189 6426 m_totals.assertions.failed++;
dev@189 6427 }
dev@189 6428
dev@189 6429 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
dev@189 6430 m_messages.clear();
dev@189 6431
dev@189 6432 // Reset working state
dev@189 6433 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
dev@189 6434 m_lastResult = result;
dev@189 6435 }
dev@189 6436
dev@189 6437 virtual bool sectionStarted (
dev@189 6438 SectionInfo const& sectionInfo,
dev@189 6439 Counts& assertions
dev@189 6440 )
dev@189 6441 {
dev@189 6442 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
dev@189 6443 if( !sectionTracker.isOpen() )
dev@189 6444 return false;
dev@189 6445 m_activeSections.push_back( &sectionTracker );
dev@189 6446
dev@189 6447 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
dev@189 6448
dev@189 6449 m_reporter->sectionStarting( sectionInfo );
dev@189 6450
dev@189 6451 assertions = m_totals.assertions;
dev@189 6452
dev@189 6453 return true;
dev@189 6454 }
dev@189 6455 bool testForMissingAssertions( Counts& assertions ) {
dev@189 6456 if( assertions.total() != 0 )
dev@189 6457 return false;
dev@189 6458 if( !m_config->warnAboutMissingAssertions() )
dev@189 6459 return false;
dev@189 6460 if( m_trackerContext.currentTracker().hasChildren() )
dev@189 6461 return false;
dev@189 6462 m_totals.assertions.failed++;
dev@189 6463 assertions.failed++;
dev@189 6464 return true;
dev@189 6465 }
dev@189 6466
dev@189 6467 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
dev@189 6468 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
dev@189 6469 bool missingAssertions = testForMissingAssertions( assertions );
dev@189 6470
dev@189 6471 if( !m_activeSections.empty() ) {
dev@189 6472 m_activeSections.back()->close();
dev@189 6473 m_activeSections.pop_back();
dev@189 6474 }
dev@189 6475
dev@189 6476 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
dev@189 6477 m_messages.clear();
dev@189 6478 }
dev@189 6479
dev@189 6480 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
dev@189 6481 if( m_unfinishedSections.empty() )
dev@189 6482 m_activeSections.back()->fail();
dev@189 6483 else
dev@189 6484 m_activeSections.back()->close();
dev@189 6485 m_activeSections.pop_back();
dev@189 6486
dev@189 6487 m_unfinishedSections.push_back( endInfo );
dev@189 6488 }
dev@189 6489
dev@189 6490 virtual void pushScopedMessage( MessageInfo const& message ) {
dev@189 6491 m_messages.push_back( message );
dev@189 6492 }
dev@189 6493
dev@189 6494 virtual void popScopedMessage( MessageInfo const& message ) {
dev@189 6495 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
dev@189 6496 }
dev@189 6497
dev@189 6498 virtual std::string getCurrentTestName() const {
dev@189 6499 return m_activeTestCase
dev@189 6500 ? m_activeTestCase->getTestCaseInfo().name
dev@189 6501 : std::string();
dev@189 6502 }
dev@189 6503
dev@189 6504 virtual const AssertionResult* getLastResult() const {
dev@189 6505 return &m_lastResult;
dev@189 6506 }
dev@189 6507
dev@189 6508 virtual void handleFatalErrorCondition( std::string const& message ) {
dev@189 6509 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
dev@189 6510 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
dev@189 6511 resultBuilder << message;
dev@189 6512 resultBuilder.captureExpression();
dev@189 6513
dev@189 6514 handleUnfinishedSections();
dev@189 6515
dev@189 6516 // Recreate section for test case (as we will lose the one that was in scope)
dev@189 6517 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
dev@189 6518 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
dev@189 6519
dev@189 6520 Counts assertions;
dev@189 6521 assertions.failed = 1;
dev@189 6522 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
dev@189 6523 m_reporter->sectionEnded( testCaseSectionStats );
dev@189 6524
dev@189 6525 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
dev@189 6526
dev@189 6527 Totals deltaTotals;
dev@189 6528 deltaTotals.testCases.failed = 1;
dev@189 6529 m_reporter->testCaseEnded( TestCaseStats( testInfo,
dev@189 6530 deltaTotals,
dev@189 6531 std::string(),
dev@189 6532 std::string(),
dev@189 6533 false ) );
dev@189 6534 m_totals.testCases.failed++;
dev@189 6535 testGroupEnded( std::string(), m_totals, 1, 1 );
dev@189 6536 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
dev@189 6537 }
dev@189 6538
dev@189 6539 public:
dev@189 6540 // !TBD We need to do this another way!
dev@189 6541 bool aborting() const {
dev@189 6542 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
dev@189 6543 }
dev@189 6544
dev@189 6545 private:
dev@189 6546
dev@189 6547 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
dev@189 6548 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
dev@189 6549 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
dev@189 6550 m_reporter->sectionStarting( testCaseSection );
dev@189 6551 Counts prevAssertions = m_totals.assertions;
dev@189 6552 double duration = 0;
dev@189 6553 try {
dev@189 6554 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
dev@189 6555
dev@189 6556 seedRng( *m_config );
dev@189 6557
dev@189 6558 Timer timer;
dev@189 6559 timer.start();
dev@189 6560 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
dev@189 6561 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
dev@189 6562 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
dev@189 6563 invokeActiveTestCase();
dev@189 6564 }
dev@189 6565 else {
dev@189 6566 invokeActiveTestCase();
dev@189 6567 }
dev@189 6568 duration = timer.getElapsedSeconds();
dev@189 6569 }
dev@189 6570 catch( TestFailureException& ) {
dev@189 6571 // This just means the test was aborted due to failure
dev@189 6572 }
dev@189 6573 catch(...) {
dev@189 6574 makeUnexpectedResultBuilder().useActiveException();
dev@189 6575 }
dev@189 6576 m_testCaseTracker->close();
dev@189 6577 handleUnfinishedSections();
dev@189 6578 m_messages.clear();
dev@189 6579
dev@189 6580 Counts assertions = m_totals.assertions - prevAssertions;
dev@189 6581 bool missingAssertions = testForMissingAssertions( assertions );
dev@189 6582
dev@189 6583 if( testCaseInfo.okToFail() ) {
dev@189 6584 std::swap( assertions.failedButOk, assertions.failed );
dev@189 6585 m_totals.assertions.failed -= assertions.failedButOk;
dev@189 6586 m_totals.assertions.failedButOk += assertions.failedButOk;
dev@189 6587 }
dev@189 6588
dev@189 6589 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
dev@189 6590 m_reporter->sectionEnded( testCaseSectionStats );
dev@189 6591 }
dev@189 6592
dev@189 6593 void invokeActiveTestCase() {
dev@189 6594 FatalConditionHandler fatalConditionHandler; // Handle signals
dev@189 6595 m_activeTestCase->invoke();
dev@189 6596 fatalConditionHandler.reset();
dev@189 6597 }
dev@189 6598
dev@189 6599 private:
dev@189 6600
dev@189 6601 ResultBuilder makeUnexpectedResultBuilder() const {
dev@189 6602 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
dev@189 6603 m_lastAssertionInfo.lineInfo,
dev@189 6604 m_lastAssertionInfo.capturedExpression.c_str(),
dev@189 6605 m_lastAssertionInfo.resultDisposition );
dev@189 6606 }
dev@189 6607
dev@189 6608 void handleUnfinishedSections() {
dev@189 6609 // If sections ended prematurely due to an exception we stored their
dev@189 6610 // infos here so we can tear them down outside the unwind process.
dev@189 6611 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
dev@189 6612 itEnd = m_unfinishedSections.rend();
dev@189 6613 it != itEnd;
dev@189 6614 ++it )
dev@189 6615 sectionEnded( *it );
dev@189 6616 m_unfinishedSections.clear();
dev@189 6617 }
dev@189 6618
dev@189 6619 TestRunInfo m_runInfo;
dev@189 6620 IMutableContext& m_context;
dev@189 6621 TestCase const* m_activeTestCase;
dev@189 6622 ITracker* m_testCaseTracker;
dev@189 6623 ITracker* m_currentSectionTracker;
dev@189 6624 AssertionResult m_lastResult;
dev@189 6625
dev@189 6626 Ptr<IConfig const> m_config;
dev@189 6627 Totals m_totals;
dev@189 6628 Ptr<IStreamingReporter> m_reporter;
dev@189 6629 std::vector<MessageInfo> m_messages;
dev@189 6630 AssertionInfo m_lastAssertionInfo;
dev@189 6631 std::vector<SectionEndInfo> m_unfinishedSections;
dev@189 6632 std::vector<ITracker*> m_activeSections;
dev@189 6633 TrackerContext m_trackerContext;
dev@189 6634 };
dev@189 6635
dev@189 6636 IResultCapture& getResultCapture() {
dev@189 6637 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
dev@189 6638 return *capture;
dev@189 6639 else
dev@189 6640 throw std::logic_error( "No result capture instance" );
dev@189 6641 }
dev@189 6642
dev@189 6643 } // end namespace Catch
dev@189 6644
dev@189 6645 // #included from: internal/catch_version.h
dev@189 6646 #define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
dev@189 6647
dev@189 6648 namespace Catch {
dev@189 6649
dev@189 6650 // Versioning information
dev@189 6651 struct Version {
dev@189 6652 Version( unsigned int _majorVersion,
dev@189 6653 unsigned int _minorVersion,
dev@189 6654 unsigned int _patchNumber,
dev@189 6655 std::string const& _branchName,
dev@189 6656 unsigned int _buildNumber );
dev@189 6657
dev@189 6658 unsigned int const majorVersion;
dev@189 6659 unsigned int const minorVersion;
dev@189 6660 unsigned int const patchNumber;
dev@189 6661
dev@189 6662 // buildNumber is only used if branchName is not null
dev@189 6663 std::string const branchName;
dev@189 6664 unsigned int const buildNumber;
dev@189 6665
dev@189 6666 friend std::ostream& operator << ( std::ostream& os, Version const& version );
dev@189 6667
dev@189 6668 private:
dev@189 6669 void operator=( Version const& );
dev@189 6670 };
dev@189 6671
dev@189 6672 extern Version libraryVersion;
dev@189 6673 }
dev@189 6674
dev@189 6675 #include <fstream>
dev@189 6676 #include <stdlib.h>
dev@189 6677 #include <limits>
dev@189 6678
dev@189 6679 namespace Catch {
dev@189 6680
dev@189 6681 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
dev@189 6682 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
dev@189 6683 if( !reporter ) {
dev@189 6684 std::ostringstream oss;
dev@189 6685 oss << "No reporter registered with name: '" << reporterName << "'";
dev@189 6686 throw std::domain_error( oss.str() );
dev@189 6687 }
dev@189 6688 return reporter;
dev@189 6689 }
dev@189 6690
dev@189 6691 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
dev@189 6692 std::vector<std::string> reporters = config->getReporterNames();
dev@189 6693 if( reporters.empty() )
dev@189 6694 reporters.push_back( "console" );
dev@189 6695
dev@189 6696 Ptr<IStreamingReporter> reporter;
dev@189 6697 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
dev@189 6698 it != itEnd;
dev@189 6699 ++it )
dev@189 6700 reporter = addReporter( reporter, createReporter( *it, config ) );
dev@189 6701 return reporter;
dev@189 6702 }
dev@189 6703 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
dev@189 6704 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
dev@189 6705 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
dev@189 6706 it != itEnd;
dev@189 6707 ++it )
dev@189 6708 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
dev@189 6709 return reporters;
dev@189 6710 }
dev@189 6711
dev@189 6712 Totals runTests( Ptr<Config> const& config ) {
dev@189 6713
dev@189 6714 Ptr<IConfig const> iconfig = config.get();
dev@189 6715
dev@189 6716 Ptr<IStreamingReporter> reporter = makeReporter( config );
dev@189 6717 reporter = addListeners( iconfig, reporter );
dev@189 6718
dev@189 6719 RunContext context( iconfig, reporter );
dev@189 6720
dev@189 6721 Totals totals;
dev@189 6722
dev@189 6723 context.testGroupStarting( config->name(), 1, 1 );
dev@189 6724
dev@189 6725 TestSpec testSpec = config->testSpec();
dev@189 6726 if( !testSpec.hasFilters() )
dev@189 6727 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
dev@189 6728
dev@189 6729 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
dev@189 6730 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
dev@189 6731 it != itEnd;
dev@189 6732 ++it ) {
dev@189 6733 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
dev@189 6734 totals += context.runTest( *it );
dev@189 6735 else
dev@189 6736 reporter->skipTest( *it );
dev@189 6737 }
dev@189 6738
dev@189 6739 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
dev@189 6740 return totals;
dev@189 6741 }
dev@189 6742
dev@189 6743 void applyFilenamesAsTags( IConfig const& config ) {
dev@189 6744 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
dev@189 6745 for(std::size_t i = 0; i < tests.size(); ++i ) {
dev@189 6746 TestCase& test = const_cast<TestCase&>( tests[i] );
dev@189 6747 std::set<std::string> tags = test.tags;
dev@189 6748
dev@189 6749 std::string filename = test.lineInfo.file;
dev@189 6750 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
dev@189 6751 if( lastSlash != std::string::npos )
dev@189 6752 filename = filename.substr( lastSlash+1 );
dev@189 6753
dev@189 6754 std::string::size_type lastDot = filename.find_last_of( "." );
dev@189 6755 if( lastDot != std::string::npos )
dev@189 6756 filename = filename.substr( 0, lastDot );
dev@189 6757
dev@189 6758 tags.insert( "#" + filename );
dev@189 6759 setTags( test, tags );
dev@189 6760 }
dev@189 6761 }
dev@189 6762
dev@189 6763 class Session : NonCopyable {
dev@189 6764 static bool alreadyInstantiated;
dev@189 6765
dev@189 6766 public:
dev@189 6767
dev@189 6768 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
dev@189 6769
dev@189 6770 Session()
dev@189 6771 : m_cli( makeCommandLineParser() ) {
dev@189 6772 if( alreadyInstantiated ) {
dev@189 6773 std::string msg = "Only one instance of Catch::Session can ever be used";
dev@189 6774 Catch::cerr() << msg << std::endl;
dev@189 6775 throw std::logic_error( msg );
dev@189 6776 }
dev@189 6777 alreadyInstantiated = true;
dev@189 6778 }
dev@189 6779 ~Session() {
dev@189 6780 Catch::cleanUp();
dev@189 6781 }
dev@189 6782
dev@189 6783 void showHelp( std::string const& processName ) {
dev@189 6784 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
dev@189 6785
dev@189 6786 m_cli.usage( Catch::cout(), processName );
dev@189 6787 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
dev@189 6788 }
dev@189 6789
dev@189 6790 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
dev@189 6791 try {
dev@189 6792 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
dev@189 6793 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
dev@189 6794 if( m_configData.showHelp )
dev@189 6795 showHelp( m_configData.processName );
dev@189 6796 m_config.reset();
dev@189 6797 }
dev@189 6798 catch( std::exception& ex ) {
dev@189 6799 {
dev@189 6800 Colour colourGuard( Colour::Red );
dev@189 6801 Catch::cerr()
dev@189 6802 << "\nError(s) in input:\n"
dev@189 6803 << Text( ex.what(), TextAttributes().setIndent(2) )
dev@189 6804 << "\n\n";
dev@189 6805 }
dev@189 6806 m_cli.usage( Catch::cout(), m_configData.processName );
dev@189 6807 return (std::numeric_limits<int>::max)();
dev@189 6808 }
dev@189 6809 return 0;
dev@189 6810 }
dev@189 6811
dev@189 6812 void useConfigData( ConfigData const& _configData ) {
dev@189 6813 m_configData = _configData;
dev@189 6814 m_config.reset();
dev@189 6815 }
dev@189 6816
dev@189 6817 int run( int argc, char const* const* const argv ) {
dev@189 6818
dev@189 6819 int returnCode = applyCommandLine( argc, argv );
dev@189 6820 if( returnCode == 0 )
dev@189 6821 returnCode = run();
dev@189 6822 return returnCode;
dev@189 6823 }
dev@189 6824
dev@189 6825 int run() {
dev@189 6826 if( m_configData.showHelp )
dev@189 6827 return 0;
dev@189 6828
dev@189 6829 try
dev@189 6830 {
dev@189 6831 config(); // Force config to be constructed
dev@189 6832
dev@189 6833 seedRng( *m_config );
dev@189 6834
dev@189 6835 if( m_configData.filenamesAsTags )
dev@189 6836 applyFilenamesAsTags( *m_config );
dev@189 6837
dev@189 6838 // Handle list request
dev@189 6839 if( Option<std::size_t> listed = list( config() ) )
dev@189 6840 return static_cast<int>( *listed );
dev@189 6841
dev@189 6842 return static_cast<int>( runTests( m_config ).assertions.failed );
dev@189 6843 }
dev@189 6844 catch( std::exception& ex ) {
dev@189 6845 Catch::cerr() << ex.what() << std::endl;
dev@189 6846 return (std::numeric_limits<int>::max)();
dev@189 6847 }
dev@189 6848 }
dev@189 6849
dev@189 6850 Clara::CommandLine<ConfigData> const& cli() const {
dev@189 6851 return m_cli;
dev@189 6852 }
dev@189 6853 std::vector<Clara::Parser::Token> const& unusedTokens() const {
dev@189 6854 return m_unusedTokens;
dev@189 6855 }
dev@189 6856 ConfigData& configData() {
dev@189 6857 return m_configData;
dev@189 6858 }
dev@189 6859 Config& config() {
dev@189 6860 if( !m_config )
dev@189 6861 m_config = new Config( m_configData );
dev@189 6862 return *m_config;
dev@189 6863 }
dev@189 6864 private:
dev@189 6865 Clara::CommandLine<ConfigData> m_cli;
dev@189 6866 std::vector<Clara::Parser::Token> m_unusedTokens;
dev@189 6867 ConfigData m_configData;
dev@189 6868 Ptr<Config> m_config;
dev@189 6869 };
dev@189 6870
dev@189 6871 bool Session::alreadyInstantiated = false;
dev@189 6872
dev@189 6873 } // end namespace Catch
dev@189 6874
dev@189 6875 // #included from: catch_registry_hub.hpp
dev@189 6876 #define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
dev@189 6877
dev@189 6878 // #included from: catch_test_case_registry_impl.hpp
dev@189 6879 #define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
dev@189 6880
dev@189 6881 #include <vector>
dev@189 6882 #include <set>
dev@189 6883 #include <sstream>
dev@189 6884 #include <iostream>
dev@189 6885 #include <algorithm>
dev@189 6886
dev@189 6887 namespace Catch {
dev@189 6888
dev@189 6889 struct RandomNumberGenerator {
dev@189 6890 typedef std::ptrdiff_t result_type;
dev@189 6891
dev@189 6892 result_type operator()( result_type n ) const { return std::rand() % n; }
dev@189 6893
dev@189 6894 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
dev@189 6895 static constexpr result_type min() { return 0; }
dev@189 6896 static constexpr result_type max() { return 1000000; }
dev@189 6897 result_type operator()() const { return std::rand() % max(); }
dev@189 6898 #endif
dev@189 6899 template<typename V>
dev@189 6900 static void shuffle( V& vector ) {
dev@189 6901 RandomNumberGenerator rng;
dev@189 6902 #ifdef CATCH_CONFIG_CPP11_SHUFFLE
dev@189 6903 std::shuffle( vector.begin(), vector.end(), rng );
dev@189 6904 #else
dev@189 6905 std::random_shuffle( vector.begin(), vector.end(), rng );
dev@189 6906 #endif
dev@189 6907 }
dev@189 6908 };
dev@189 6909
dev@189 6910 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
dev@189 6911
dev@189 6912 std::vector<TestCase> sorted = unsortedTestCases;
dev@189 6913
dev@189 6914 switch( config.runOrder() ) {
dev@189 6915 case RunTests::InLexicographicalOrder:
dev@189 6916 std::sort( sorted.begin(), sorted.end() );
dev@189 6917 break;
dev@189 6918 case RunTests::InRandomOrder:
dev@189 6919 {
dev@189 6920 seedRng( config );
dev@189 6921 RandomNumberGenerator::shuffle( sorted );
dev@189 6922 }
dev@189 6923 break;
dev@189 6924 case RunTests::InDeclarationOrder:
dev@189 6925 // already in declaration order
dev@189 6926 break;
dev@189 6927 }
dev@189 6928 return sorted;
dev@189 6929 }
dev@189 6930 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
dev@189 6931 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
dev@189 6932 }
dev@189 6933
dev@189 6934 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
dev@189 6935 std::set<TestCase> seenFunctions;
dev@189 6936 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
dev@189 6937 it != itEnd;
dev@189 6938 ++it ) {
dev@189 6939 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
dev@189 6940 if( !prev.second ) {
dev@189 6941 std::ostringstream ss;
dev@189 6942
dev@189 6943 ss << Colour( Colour::Red )
dev@189 6944 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
dev@189 6945 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
dev@189 6946 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
dev@189 6947
dev@189 6948 throw std::runtime_error(ss.str());
dev@189 6949 }
dev@189 6950 }
dev@189 6951 }
dev@189 6952
dev@189 6953 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
dev@189 6954 std::vector<TestCase> filtered;
dev@189 6955 filtered.reserve( testCases.size() );
dev@189 6956 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
dev@189 6957 it != itEnd;
dev@189 6958 ++it )
dev@189 6959 if( matchTest( *it, testSpec, config ) )
dev@189 6960 filtered.push_back( *it );
dev@189 6961 return filtered;
dev@189 6962 }
dev@189 6963 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
dev@189 6964 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
dev@189 6965 }
dev@189 6966
dev@189 6967 class TestRegistry : public ITestCaseRegistry {
dev@189 6968 public:
dev@189 6969 TestRegistry()
dev@189 6970 : m_currentSortOrder( RunTests::InDeclarationOrder ),
dev@189 6971 m_unnamedCount( 0 )
dev@189 6972 {}
dev@189 6973 virtual ~TestRegistry();
dev@189 6974
dev@189 6975 virtual void registerTest( TestCase const& testCase ) {
dev@189 6976 std::string name = testCase.getTestCaseInfo().name;
dev@189 6977 if( name.empty() ) {
dev@189 6978 std::ostringstream oss;
dev@189 6979 oss << "Anonymous test case " << ++m_unnamedCount;
dev@189 6980 return registerTest( testCase.withName( oss.str() ) );
dev@189 6981 }
dev@189 6982 m_functions.push_back( testCase );
dev@189 6983 }
dev@189 6984
dev@189 6985 virtual std::vector<TestCase> const& getAllTests() const {
dev@189 6986 return m_functions;
dev@189 6987 }
dev@189 6988 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
dev@189 6989 if( m_sortedFunctions.empty() )
dev@189 6990 enforceNoDuplicateTestCases( m_functions );
dev@189 6991
dev@189 6992 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
dev@189 6993 m_sortedFunctions = sortTests( config, m_functions );
dev@189 6994 m_currentSortOrder = config.runOrder();
dev@189 6995 }
dev@189 6996 return m_sortedFunctions;
dev@189 6997 }
dev@189 6998
dev@189 6999 private:
dev@189 7000 std::vector<TestCase> m_functions;
dev@189 7001 mutable RunTests::InWhatOrder m_currentSortOrder;
dev@189 7002 mutable std::vector<TestCase> m_sortedFunctions;
dev@189 7003 size_t m_unnamedCount;
dev@189 7004 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
dev@189 7005 };
dev@189 7006
dev@189 7007 ///////////////////////////////////////////////////////////////////////////
dev@189 7008
dev@189 7009 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
dev@189 7010 public:
dev@189 7011
dev@189 7012 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
dev@189 7013
dev@189 7014 virtual void invoke() const {
dev@189 7015 m_fun();
dev@189 7016 }
dev@189 7017
dev@189 7018 private:
dev@189 7019 virtual ~FreeFunctionTestCase();
dev@189 7020
dev@189 7021 TestFunction m_fun;
dev@189 7022 };
dev@189 7023
dev@189 7024 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
dev@189 7025 std::string className = classOrQualifiedMethodName;
dev@189 7026 if( startsWith( className, '&' ) )
dev@189 7027 {
dev@189 7028 std::size_t lastColons = className.rfind( "::" );
dev@189 7029 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
dev@189 7030 if( penultimateColons == std::string::npos )
dev@189 7031 penultimateColons = 1;
dev@189 7032 className = className.substr( penultimateColons, lastColons-penultimateColons );
dev@189 7033 }
dev@189 7034 return className;
dev@189 7035 }
dev@189 7036
dev@189 7037 void registerTestCase
dev@189 7038 ( ITestCase* testCase,
dev@189 7039 char const* classOrQualifiedMethodName,
dev@189 7040 NameAndDesc const& nameAndDesc,
dev@189 7041 SourceLineInfo const& lineInfo ) {
dev@189 7042
dev@189 7043 getMutableRegistryHub().registerTest
dev@189 7044 ( makeTestCase
dev@189 7045 ( testCase,
dev@189 7046 extractClassName( classOrQualifiedMethodName ),
dev@189 7047 nameAndDesc.name,
dev@189 7048 nameAndDesc.description,
dev@189 7049 lineInfo ) );
dev@189 7050 }
dev@189 7051 void registerTestCaseFunction
dev@189 7052 ( TestFunction function,
dev@189 7053 SourceLineInfo const& lineInfo,
dev@189 7054 NameAndDesc const& nameAndDesc ) {
dev@189 7055 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
dev@189 7056 }
dev@189 7057
dev@189 7058 ///////////////////////////////////////////////////////////////////////////
dev@189 7059
dev@189 7060 AutoReg::AutoReg
dev@189 7061 ( TestFunction function,
dev@189 7062 SourceLineInfo const& lineInfo,
dev@189 7063 NameAndDesc const& nameAndDesc ) {
dev@189 7064 registerTestCaseFunction( function, lineInfo, nameAndDesc );
dev@189 7065 }
dev@189 7066
dev@189 7067 AutoReg::~AutoReg() {}
dev@189 7068
dev@189 7069 } // end namespace Catch
dev@189 7070
dev@189 7071 // #included from: catch_reporter_registry.hpp
dev@189 7072 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
dev@189 7073
dev@189 7074 #include <map>
dev@189 7075
dev@189 7076 namespace Catch {
dev@189 7077
dev@189 7078 class ReporterRegistry : public IReporterRegistry {
dev@189 7079
dev@189 7080 public:
dev@189 7081
dev@189 7082 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
dev@189 7083
dev@189 7084 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
dev@189 7085 FactoryMap::const_iterator it = m_factories.find( name );
dev@189 7086 if( it == m_factories.end() )
dev@189 7087 return CATCH_NULL;
dev@189 7088 return it->second->create( ReporterConfig( config ) );
dev@189 7089 }
dev@189 7090
dev@189 7091 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
dev@189 7092 m_factories.insert( std::make_pair( name, factory ) );
dev@189 7093 }
dev@189 7094 void registerListener( Ptr<IReporterFactory> const& factory ) {
dev@189 7095 m_listeners.push_back( factory );
dev@189 7096 }
dev@189 7097
dev@189 7098 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
dev@189 7099 return m_factories;
dev@189 7100 }
dev@189 7101 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
dev@189 7102 return m_listeners;
dev@189 7103 }
dev@189 7104
dev@189 7105 private:
dev@189 7106 FactoryMap m_factories;
dev@189 7107 Listeners m_listeners;
dev@189 7108 };
dev@189 7109 }
dev@189 7110
dev@189 7111 // #included from: catch_exception_translator_registry.hpp
dev@189 7112 #define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
dev@189 7113
dev@189 7114 #ifdef __OBJC__
dev@189 7115 #import "Foundation/Foundation.h"
dev@189 7116 #endif
dev@189 7117
dev@189 7118 namespace Catch {
dev@189 7119
dev@189 7120 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
dev@189 7121 public:
dev@189 7122 ~ExceptionTranslatorRegistry() {
dev@189 7123 deleteAll( m_translators );
dev@189 7124 }
dev@189 7125
dev@189 7126 virtual void registerTranslator( const IExceptionTranslator* translator ) {
dev@189 7127 m_translators.push_back( translator );
dev@189 7128 }
dev@189 7129
dev@189 7130 virtual std::string translateActiveException() const {
dev@189 7131 try {
dev@189 7132 #ifdef __OBJC__
dev@189 7133 // In Objective-C try objective-c exceptions first
dev@189 7134 @try {
dev@189 7135 return tryTranslators();
dev@189 7136 }
dev@189 7137 @catch (NSException *exception) {
dev@189 7138 return Catch::toString( [exception description] );
dev@189 7139 }
dev@189 7140 #else
dev@189 7141 return tryTranslators();
dev@189 7142 #endif
dev@189 7143 }
dev@189 7144 catch( TestFailureException& ) {
dev@189 7145 throw;
dev@189 7146 }
dev@189 7147 catch( std::exception& ex ) {
dev@189 7148 return ex.what();
dev@189 7149 }
dev@189 7150 catch( std::string& msg ) {
dev@189 7151 return msg;
dev@189 7152 }
dev@189 7153 catch( const char* msg ) {
dev@189 7154 return msg;
dev@189 7155 }
dev@189 7156 catch(...) {
dev@189 7157 return "Unknown exception";
dev@189 7158 }
dev@189 7159 }
dev@189 7160
dev@189 7161 std::string tryTranslators() const {
dev@189 7162 if( m_translators.empty() )
dev@189 7163 throw;
dev@189 7164 else
dev@189 7165 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
dev@189 7166 }
dev@189 7167
dev@189 7168 private:
dev@189 7169 std::vector<const IExceptionTranslator*> m_translators;
dev@189 7170 };
dev@189 7171 }
dev@189 7172
dev@189 7173 namespace Catch {
dev@189 7174
dev@189 7175 namespace {
dev@189 7176
dev@189 7177 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
dev@189 7178
dev@189 7179 RegistryHub( RegistryHub const& );
dev@189 7180 void operator=( RegistryHub const& );
dev@189 7181
dev@189 7182 public: // IRegistryHub
dev@189 7183 RegistryHub() {
dev@189 7184 }
dev@189 7185 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
dev@189 7186 return m_reporterRegistry;
dev@189 7187 }
dev@189 7188 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
dev@189 7189 return m_testCaseRegistry;
dev@189 7190 }
dev@189 7191 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
dev@189 7192 return m_exceptionTranslatorRegistry;
dev@189 7193 }
dev@189 7194
dev@189 7195 public: // IMutableRegistryHub
dev@189 7196 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
dev@189 7197 m_reporterRegistry.registerReporter( name, factory );
dev@189 7198 }
dev@189 7199 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
dev@189 7200 m_reporterRegistry.registerListener( factory );
dev@189 7201 }
dev@189 7202 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
dev@189 7203 m_testCaseRegistry.registerTest( testInfo );
dev@189 7204 }
dev@189 7205 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
dev@189 7206 m_exceptionTranslatorRegistry.registerTranslator( translator );
dev@189 7207 }
dev@189 7208
dev@189 7209 private:
dev@189 7210 TestRegistry m_testCaseRegistry;
dev@189 7211 ReporterRegistry m_reporterRegistry;
dev@189 7212 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
dev@189 7213 };
dev@189 7214
dev@189 7215 // Single, global, instance
dev@189 7216 inline RegistryHub*& getTheRegistryHub() {
dev@189 7217 static RegistryHub* theRegistryHub = CATCH_NULL;
dev@189 7218 if( !theRegistryHub )
dev@189 7219 theRegistryHub = new RegistryHub();
dev@189 7220 return theRegistryHub;
dev@189 7221 }
dev@189 7222 }
dev@189 7223
dev@189 7224 IRegistryHub& getRegistryHub() {
dev@189 7225 return *getTheRegistryHub();
dev@189 7226 }
dev@189 7227 IMutableRegistryHub& getMutableRegistryHub() {
dev@189 7228 return *getTheRegistryHub();
dev@189 7229 }
dev@189 7230 void cleanUp() {
dev@189 7231 delete getTheRegistryHub();
dev@189 7232 getTheRegistryHub() = CATCH_NULL;
dev@189 7233 cleanUpContext();
dev@189 7234 }
dev@189 7235 std::string translateActiveException() {
dev@189 7236 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
dev@189 7237 }
dev@189 7238
dev@189 7239 } // end namespace Catch
dev@189 7240
dev@189 7241 // #included from: catch_notimplemented_exception.hpp
dev@189 7242 #define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
dev@189 7243
dev@189 7244 #include <ostream>
dev@189 7245
dev@189 7246 namespace Catch {
dev@189 7247
dev@189 7248 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
dev@189 7249 : m_lineInfo( lineInfo ) {
dev@189 7250 std::ostringstream oss;
dev@189 7251 oss << lineInfo << ": function ";
dev@189 7252 oss << "not implemented";
dev@189 7253 m_what = oss.str();
dev@189 7254 }
dev@189 7255
dev@189 7256 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
dev@189 7257 return m_what.c_str();
dev@189 7258 }
dev@189 7259
dev@189 7260 } // end namespace Catch
dev@189 7261
dev@189 7262 // #included from: catch_context_impl.hpp
dev@189 7263 #define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
dev@189 7264
dev@189 7265 // #included from: catch_stream.hpp
dev@189 7266 #define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
dev@189 7267
dev@189 7268 #include <stdexcept>
dev@189 7269 #include <cstdio>
dev@189 7270 #include <iostream>
dev@189 7271
dev@189 7272 namespace Catch {
dev@189 7273
dev@189 7274 template<typename WriterF, size_t bufferSize=256>
dev@189 7275 class StreamBufImpl : public StreamBufBase {
dev@189 7276 char data[bufferSize];
dev@189 7277 WriterF m_writer;
dev@189 7278
dev@189 7279 public:
dev@189 7280 StreamBufImpl() {
dev@189 7281 setp( data, data + sizeof(data) );
dev@189 7282 }
dev@189 7283
dev@189 7284 ~StreamBufImpl() CATCH_NOEXCEPT {
dev@189 7285 sync();
dev@189 7286 }
dev@189 7287
dev@189 7288 private:
dev@189 7289 int overflow( int c ) {
dev@189 7290 sync();
dev@189 7291
dev@189 7292 if( c != EOF ) {
dev@189 7293 if( pbase() == epptr() )
dev@189 7294 m_writer( std::string( 1, static_cast<char>( c ) ) );
dev@189 7295 else
dev@189 7296 sputc( static_cast<char>( c ) );
dev@189 7297 }
dev@189 7298 return 0;
dev@189 7299 }
dev@189 7300
dev@189 7301 int sync() {
dev@189 7302 if( pbase() != pptr() ) {
dev@189 7303 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
dev@189 7304 setp( pbase(), epptr() );
dev@189 7305 }
dev@189 7306 return 0;
dev@189 7307 }
dev@189 7308 };
dev@189 7309
dev@189 7310 ///////////////////////////////////////////////////////////////////////////
dev@189 7311
dev@189 7312 FileStream::FileStream( std::string const& filename ) {
dev@189 7313 m_ofs.open( filename.c_str() );
dev@189 7314 if( m_ofs.fail() ) {
dev@189 7315 std::ostringstream oss;
dev@189 7316 oss << "Unable to open file: '" << filename << '\'';
dev@189 7317 throw std::domain_error( oss.str() );
dev@189 7318 }
dev@189 7319 }
dev@189 7320
dev@189 7321 std::ostream& FileStream::stream() const {
dev@189 7322 return m_ofs;
dev@189 7323 }
dev@189 7324
dev@189 7325 struct OutputDebugWriter {
dev@189 7326
dev@189 7327 void operator()( std::string const&str ) {
dev@189 7328 writeToDebugConsole( str );
dev@189 7329 }
dev@189 7330 };
dev@189 7331
dev@189 7332 DebugOutStream::DebugOutStream()
dev@189 7333 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
dev@189 7334 m_os( m_streamBuf.get() )
dev@189 7335 {}
dev@189 7336
dev@189 7337 std::ostream& DebugOutStream::stream() const {
dev@189 7338 return m_os;
dev@189 7339 }
dev@189 7340
dev@189 7341 // Store the streambuf from cout up-front because
dev@189 7342 // cout may get redirected when running tests
dev@189 7343 CoutStream::CoutStream()
dev@189 7344 : m_os( Catch::cout().rdbuf() )
dev@189 7345 {}
dev@189 7346
dev@189 7347 std::ostream& CoutStream::stream() const {
dev@189 7348 return m_os;
dev@189 7349 }
dev@189 7350
dev@189 7351 #ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
dev@189 7352 std::ostream& cout() {
dev@189 7353 return std::cout;
dev@189 7354 }
dev@189 7355 std::ostream& cerr() {
dev@189 7356 return std::cerr;
dev@189 7357 }
dev@189 7358 #endif
dev@189 7359 }
dev@189 7360
dev@189 7361 namespace Catch {
dev@189 7362
dev@189 7363 class Context : public IMutableContext {
dev@189 7364
dev@189 7365 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
dev@189 7366 Context( Context const& );
dev@189 7367 void operator=( Context const& );
dev@189 7368
dev@189 7369 public:
dev@189 7370 virtual ~Context() {
dev@189 7371 deleteAllValues( m_generatorsByTestName );
dev@189 7372 }
dev@189 7373
dev@189 7374 public: // IContext
dev@189 7375 virtual IResultCapture* getResultCapture() {
dev@189 7376 return m_resultCapture;
dev@189 7377 }
dev@189 7378 virtual IRunner* getRunner() {
dev@189 7379 return m_runner;
dev@189 7380 }
dev@189 7381 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
dev@189 7382 return getGeneratorsForCurrentTest()
dev@189 7383 .getGeneratorInfo( fileInfo, totalSize )
dev@189 7384 .getCurrentIndex();
dev@189 7385 }
dev@189 7386 virtual bool advanceGeneratorsForCurrentTest() {
dev@189 7387 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
dev@189 7388 return generators && generators->moveNext();
dev@189 7389 }
dev@189 7390
dev@189 7391 virtual Ptr<IConfig const> getConfig() const {
dev@189 7392 return m_config;
dev@189 7393 }
dev@189 7394
dev@189 7395 public: // IMutableContext
dev@189 7396 virtual void setResultCapture( IResultCapture* resultCapture ) {
dev@189 7397 m_resultCapture = resultCapture;
dev@189 7398 }
dev@189 7399 virtual void setRunner( IRunner* runner ) {
dev@189 7400 m_runner = runner;
dev@189 7401 }
dev@189 7402 virtual void setConfig( Ptr<IConfig const> const& config ) {
dev@189 7403 m_config = config;
dev@189 7404 }
dev@189 7405
dev@189 7406 friend IMutableContext& getCurrentMutableContext();
dev@189 7407
dev@189 7408 private:
dev@189 7409 IGeneratorsForTest* findGeneratorsForCurrentTest() {
dev@189 7410 std::string testName = getResultCapture()->getCurrentTestName();
dev@189 7411
dev@189 7412 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
dev@189 7413 m_generatorsByTestName.find( testName );
dev@189 7414 return it != m_generatorsByTestName.end()
dev@189 7415 ? it->second
dev@189 7416 : CATCH_NULL;
dev@189 7417 }
dev@189 7418
dev@189 7419 IGeneratorsForTest& getGeneratorsForCurrentTest() {
dev@189 7420 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
dev@189 7421 if( !generators ) {
dev@189 7422 std::string testName = getResultCapture()->getCurrentTestName();
dev@189 7423 generators = createGeneratorsForTest();
dev@189 7424 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
dev@189 7425 }
dev@189 7426 return *generators;
dev@189 7427 }
dev@189 7428
dev@189 7429 private:
dev@189 7430 Ptr<IConfig const> m_config;
dev@189 7431 IRunner* m_runner;
dev@189 7432 IResultCapture* m_resultCapture;
dev@189 7433 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
dev@189 7434 };
dev@189 7435
dev@189 7436 namespace {
dev@189 7437 Context* currentContext = CATCH_NULL;
dev@189 7438 }
dev@189 7439 IMutableContext& getCurrentMutableContext() {
dev@189 7440 if( !currentContext )
dev@189 7441 currentContext = new Context();
dev@189 7442 return *currentContext;
dev@189 7443 }
dev@189 7444 IContext& getCurrentContext() {
dev@189 7445 return getCurrentMutableContext();
dev@189 7446 }
dev@189 7447
dev@189 7448 void cleanUpContext() {
dev@189 7449 delete currentContext;
dev@189 7450 currentContext = CATCH_NULL;
dev@189 7451 }
dev@189 7452 }
dev@189 7453
dev@189 7454 // #included from: catch_console_colour_impl.hpp
dev@189 7455 #define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
dev@189 7456
dev@189 7457 namespace Catch {
dev@189 7458 namespace {
dev@189 7459
dev@189 7460 struct IColourImpl {
dev@189 7461 virtual ~IColourImpl() {}
dev@189 7462 virtual void use( Colour::Code _colourCode ) = 0;
dev@189 7463 };
dev@189 7464
dev@189 7465 struct NoColourImpl : IColourImpl {
dev@189 7466 void use( Colour::Code ) {}
dev@189 7467
dev@189 7468 static IColourImpl* instance() {
dev@189 7469 static NoColourImpl s_instance;
dev@189 7470 return &s_instance;
dev@189 7471 }
dev@189 7472 };
dev@189 7473
dev@189 7474 } // anon namespace
dev@189 7475 } // namespace Catch
dev@189 7476
dev@189 7477 #if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
dev@189 7478 # ifdef CATCH_PLATFORM_WINDOWS
dev@189 7479 # define CATCH_CONFIG_COLOUR_WINDOWS
dev@189 7480 # else
dev@189 7481 # define CATCH_CONFIG_COLOUR_ANSI
dev@189 7482 # endif
dev@189 7483 #endif
dev@189 7484
dev@189 7485 #if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
dev@189 7486
dev@189 7487 namespace Catch {
dev@189 7488 namespace {
dev@189 7489
dev@189 7490 class Win32ColourImpl : public IColourImpl {
dev@189 7491 public:
dev@189 7492 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
dev@189 7493 {
dev@189 7494 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
dev@189 7495 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
dev@189 7496 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
dev@189 7497 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
dev@189 7498 }
dev@189 7499
dev@189 7500 virtual void use( Colour::Code _colourCode ) {
dev@189 7501 switch( _colourCode ) {
dev@189 7502 case Colour::None: return setTextAttribute( originalForegroundAttributes );
dev@189 7503 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
dev@189 7504 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
dev@189 7505 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
dev@189 7506 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
dev@189 7507 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
dev@189 7508 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
dev@189 7509 case Colour::Grey: return setTextAttribute( 0 );
dev@189 7510
dev@189 7511 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
dev@189 7512 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
dev@189 7513 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
dev@189 7514 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
dev@189 7515
dev@189 7516 case Colour::Bright: throw std::logic_error( "not a colour" );
dev@189 7517 }
dev@189 7518 }
dev@189 7519
dev@189 7520 private:
dev@189 7521 void setTextAttribute( WORD _textAttribute ) {
dev@189 7522 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
dev@189 7523 }
dev@189 7524 HANDLE stdoutHandle;
dev@189 7525 WORD originalForegroundAttributes;
dev@189 7526 WORD originalBackgroundAttributes;
dev@189 7527 };
dev@189 7528
dev@189 7529 IColourImpl* platformColourInstance() {
dev@189 7530 static Win32ColourImpl s_instance;
dev@189 7531
dev@189 7532 Ptr<IConfig const> config = getCurrentContext().getConfig();
dev@189 7533 UseColour::YesOrNo colourMode = config
dev@189 7534 ? config->useColour()
dev@189 7535 : UseColour::Auto;
dev@189 7536 if( colourMode == UseColour::Auto )
dev@189 7537 colourMode = !isDebuggerActive()
dev@189 7538 ? UseColour::Yes
dev@189 7539 : UseColour::No;
dev@189 7540 return colourMode == UseColour::Yes
dev@189 7541 ? &s_instance
dev@189 7542 : NoColourImpl::instance();
dev@189 7543 }
dev@189 7544
dev@189 7545 } // end anon namespace
dev@189 7546 } // end namespace Catch
dev@189 7547
dev@189 7548 #elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
dev@189 7549
dev@189 7550 #include <unistd.h>
dev@189 7551
dev@189 7552 namespace Catch {
dev@189 7553 namespace {
dev@189 7554
dev@189 7555 // use POSIX/ ANSI console terminal codes
dev@189 7556 // Thanks to Adam Strzelecki for original contribution
dev@189 7557 // (http://github.com/nanoant)
dev@189 7558 // https://github.com/philsquared/Catch/pull/131
dev@189 7559 class PosixColourImpl : public IColourImpl {
dev@189 7560 public:
dev@189 7561 virtual void use( Colour::Code _colourCode ) {
dev@189 7562 switch( _colourCode ) {
dev@189 7563 case Colour::None:
dev@189 7564 case Colour::White: return setColour( "[0m" );
dev@189 7565 case Colour::Red: return setColour( "[0;31m" );
dev@189 7566 case Colour::Green: return setColour( "[0;32m" );
dev@189 7567 case Colour::Blue: return setColour( "[0;34m" );
dev@189 7568 case Colour::Cyan: return setColour( "[0;36m" );
dev@189 7569 case Colour::Yellow: return setColour( "[0;33m" );
dev@189 7570 case Colour::Grey: return setColour( "[1;30m" );
dev@189 7571
dev@189 7572 case Colour::LightGrey: return setColour( "[0;37m" );
dev@189 7573 case Colour::BrightRed: return setColour( "[1;31m" );
dev@189 7574 case Colour::BrightGreen: return setColour( "[1;32m" );
dev@189 7575 case Colour::BrightWhite: return setColour( "[1;37m" );
dev@189 7576
dev@189 7577 case Colour::Bright: throw std::logic_error( "not a colour" );
dev@189 7578 }
dev@189 7579 }
dev@189 7580 static IColourImpl* instance() {
dev@189 7581 static PosixColourImpl s_instance;
dev@189 7582 return &s_instance;
dev@189 7583 }
dev@189 7584
dev@189 7585 private:
dev@189 7586 void setColour( const char* _escapeCode ) {
dev@189 7587 Catch::cout() << '\033' << _escapeCode;
dev@189 7588 }
dev@189 7589 };
dev@189 7590
dev@189 7591 IColourImpl* platformColourInstance() {
dev@189 7592 Ptr<IConfig const> config = getCurrentContext().getConfig();
dev@189 7593 UseColour::YesOrNo colourMode = config
dev@189 7594 ? config->useColour()
dev@189 7595 : UseColour::Auto;
dev@189 7596 if( colourMode == UseColour::Auto )
dev@189 7597 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
dev@189 7598 ? UseColour::Yes
dev@189 7599 : UseColour::No;
dev@189 7600 return colourMode == UseColour::Yes
dev@189 7601 ? PosixColourImpl::instance()
dev@189 7602 : NoColourImpl::instance();
dev@189 7603 }
dev@189 7604
dev@189 7605 } // end anon namespace
dev@189 7606 } // end namespace Catch
dev@189 7607
dev@189 7608 #else // not Windows or ANSI ///////////////////////////////////////////////
dev@189 7609
dev@189 7610 namespace Catch {
dev@189 7611
dev@189 7612 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
dev@189 7613
dev@189 7614 } // end namespace Catch
dev@189 7615
dev@189 7616 #endif // Windows/ ANSI/ None
dev@189 7617
dev@189 7618 namespace Catch {
dev@189 7619
dev@189 7620 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
dev@189 7621 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
dev@189 7622 Colour::~Colour(){ if( !m_moved ) use( None ); }
dev@189 7623
dev@189 7624 void Colour::use( Code _colourCode ) {
dev@189 7625 static IColourImpl* impl = platformColourInstance();
dev@189 7626 impl->use( _colourCode );
dev@189 7627 }
dev@189 7628
dev@189 7629 } // end namespace Catch
dev@189 7630
dev@189 7631 // #included from: catch_generators_impl.hpp
dev@189 7632 #define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
dev@189 7633
dev@189 7634 #include <vector>
dev@189 7635 #include <string>
dev@189 7636 #include <map>
dev@189 7637
dev@189 7638 namespace Catch {
dev@189 7639
dev@189 7640 struct GeneratorInfo : IGeneratorInfo {
dev@189 7641
dev@189 7642 GeneratorInfo( std::size_t size )
dev@189 7643 : m_size( size ),
dev@189 7644 m_currentIndex( 0 )
dev@189 7645 {}
dev@189 7646
dev@189 7647 bool moveNext() {
dev@189 7648 if( ++m_currentIndex == m_size ) {
dev@189 7649 m_currentIndex = 0;
dev@189 7650 return false;
dev@189 7651 }
dev@189 7652 return true;
dev@189 7653 }
dev@189 7654
dev@189 7655 std::size_t getCurrentIndex() const {
dev@189 7656 return m_currentIndex;
dev@189 7657 }
dev@189 7658
dev@189 7659 std::size_t m_size;
dev@189 7660 std::size_t m_currentIndex;
dev@189 7661 };
dev@189 7662
dev@189 7663 ///////////////////////////////////////////////////////////////////////////
dev@189 7664
dev@189 7665 class GeneratorsForTest : public IGeneratorsForTest {
dev@189 7666
dev@189 7667 public:
dev@189 7668 ~GeneratorsForTest() {
dev@189 7669 deleteAll( m_generatorsInOrder );
dev@189 7670 }
dev@189 7671
dev@189 7672 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
dev@189 7673 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
dev@189 7674 if( it == m_generatorsByName.end() ) {
dev@189 7675 IGeneratorInfo* info = new GeneratorInfo( size );
dev@189 7676 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
dev@189 7677 m_generatorsInOrder.push_back( info );
dev@189 7678 return *info;
dev@189 7679 }
dev@189 7680 return *it->second;
dev@189 7681 }
dev@189 7682
dev@189 7683 bool moveNext() {
dev@189 7684 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
dev@189 7685 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
dev@189 7686 for(; it != itEnd; ++it ) {
dev@189 7687 if( (*it)->moveNext() )
dev@189 7688 return true;
dev@189 7689 }
dev@189 7690 return false;
dev@189 7691 }
dev@189 7692
dev@189 7693 private:
dev@189 7694 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
dev@189 7695 std::vector<IGeneratorInfo*> m_generatorsInOrder;
dev@189 7696 };
dev@189 7697
dev@189 7698 IGeneratorsForTest* createGeneratorsForTest()
dev@189 7699 {
dev@189 7700 return new GeneratorsForTest();
dev@189 7701 }
dev@189 7702
dev@189 7703 } // end namespace Catch
dev@189 7704
dev@189 7705 // #included from: catch_assertionresult.hpp
dev@189 7706 #define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
dev@189 7707
dev@189 7708 namespace Catch {
dev@189 7709
dev@189 7710 AssertionInfo::AssertionInfo( std::string const& _macroName,
dev@189 7711 SourceLineInfo const& _lineInfo,
dev@189 7712 std::string const& _capturedExpression,
dev@189 7713 ResultDisposition::Flags _resultDisposition )
dev@189 7714 : macroName( _macroName ),
dev@189 7715 lineInfo( _lineInfo ),
dev@189 7716 capturedExpression( _capturedExpression ),
dev@189 7717 resultDisposition( _resultDisposition )
dev@189 7718 {}
dev@189 7719
dev@189 7720 AssertionResult::AssertionResult() {}
dev@189 7721
dev@189 7722 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
dev@189 7723 : m_info( info ),
dev@189 7724 m_resultData( data )
dev@189 7725 {}
dev@189 7726
dev@189 7727 AssertionResult::~AssertionResult() {}
dev@189 7728
dev@189 7729 // Result was a success
dev@189 7730 bool AssertionResult::succeeded() const {
dev@189 7731 return Catch::isOk( m_resultData.resultType );
dev@189 7732 }
dev@189 7733
dev@189 7734 // Result was a success, or failure is suppressed
dev@189 7735 bool AssertionResult::isOk() const {
dev@189 7736 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
dev@189 7737 }
dev@189 7738
dev@189 7739 ResultWas::OfType AssertionResult::getResultType() const {
dev@189 7740 return m_resultData.resultType;
dev@189 7741 }
dev@189 7742
dev@189 7743 bool AssertionResult::hasExpression() const {
dev@189 7744 return !m_info.capturedExpression.empty();
dev@189 7745 }
dev@189 7746
dev@189 7747 bool AssertionResult::hasMessage() const {
dev@189 7748 return !m_resultData.message.empty();
dev@189 7749 }
dev@189 7750
dev@189 7751 std::string AssertionResult::getExpression() const {
dev@189 7752 if( isFalseTest( m_info.resultDisposition ) )
dev@189 7753 return '!' + m_info.capturedExpression;
dev@189 7754 else
dev@189 7755 return m_info.capturedExpression;
dev@189 7756 }
dev@189 7757 std::string AssertionResult::getExpressionInMacro() const {
dev@189 7758 if( m_info.macroName.empty() )
dev@189 7759 return m_info.capturedExpression;
dev@189 7760 else
dev@189 7761 return m_info.macroName + "( " + m_info.capturedExpression + " )";
dev@189 7762 }
dev@189 7763
dev@189 7764 bool AssertionResult::hasExpandedExpression() const {
dev@189 7765 return hasExpression() && getExpandedExpression() != getExpression();
dev@189 7766 }
dev@189 7767
dev@189 7768 std::string AssertionResult::getExpandedExpression() const {
dev@189 7769 return m_resultData.reconstructExpression();
dev@189 7770 }
dev@189 7771
dev@189 7772 std::string AssertionResult::getMessage() const {
dev@189 7773 return m_resultData.message;
dev@189 7774 }
dev@189 7775 SourceLineInfo AssertionResult::getSourceInfo() const {
dev@189 7776 return m_info.lineInfo;
dev@189 7777 }
dev@189 7778
dev@189 7779 std::string AssertionResult::getTestMacroName() const {
dev@189 7780 return m_info.macroName;
dev@189 7781 }
dev@189 7782
dev@189 7783 void AssertionResult::discardDecomposedExpression() const {
dev@189 7784 m_resultData.decomposedExpression = CATCH_NULL;
dev@189 7785 }
dev@189 7786
dev@189 7787 void AssertionResult::expandDecomposedExpression() const {
dev@189 7788 m_resultData.reconstructExpression();
dev@189 7789 }
dev@189 7790
dev@189 7791 } // end namespace Catch
dev@189 7792
dev@189 7793 // #included from: catch_test_case_info.hpp
dev@189 7794 #define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
dev@189 7795
dev@189 7796 namespace Catch {
dev@189 7797
dev@189 7798 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
dev@189 7799 if( startsWith( tag, '.' ) ||
dev@189 7800 tag == "hide" ||
dev@189 7801 tag == "!hide" )
dev@189 7802 return TestCaseInfo::IsHidden;
dev@189 7803 else if( tag == "!throws" )
dev@189 7804 return TestCaseInfo::Throws;
dev@189 7805 else if( tag == "!shouldfail" )
dev@189 7806 return TestCaseInfo::ShouldFail;
dev@189 7807 else if( tag == "!mayfail" )
dev@189 7808 return TestCaseInfo::MayFail;
dev@189 7809 else if( tag == "!nonportable" )
dev@189 7810 return TestCaseInfo::NonPortable;
dev@189 7811 else
dev@189 7812 return TestCaseInfo::None;
dev@189 7813 }
dev@189 7814 inline bool isReservedTag( std::string const& tag ) {
dev@189 7815 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
dev@189 7816 }
dev@189 7817 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
dev@189 7818 if( isReservedTag( tag ) ) {
dev@189 7819 {
dev@189 7820 Colour colourGuard( Colour::Red );
dev@189 7821 Catch::cerr()
dev@189 7822 << "Tag name [" << tag << "] not allowed.\n"
dev@189 7823 << "Tag names starting with non alpha-numeric characters are reserved\n";
dev@189 7824 }
dev@189 7825 {
dev@189 7826 Colour colourGuard( Colour::FileName );
dev@189 7827 Catch::cerr() << _lineInfo << std::endl;
dev@189 7828 }
dev@189 7829 exit(1);
dev@189 7830 }
dev@189 7831 }
dev@189 7832
dev@189 7833 TestCase makeTestCase( ITestCase* _testCase,
dev@189 7834 std::string const& _className,
dev@189 7835 std::string const& _name,
dev@189 7836 std::string const& _descOrTags,
dev@189 7837 SourceLineInfo const& _lineInfo )
dev@189 7838 {
dev@189 7839 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
dev@189 7840
dev@189 7841 // Parse out tags
dev@189 7842 std::set<std::string> tags;
dev@189 7843 std::string desc, tag;
dev@189 7844 bool inTag = false;
dev@189 7845 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
dev@189 7846 char c = _descOrTags[i];
dev@189 7847 if( !inTag ) {
dev@189 7848 if( c == '[' )
dev@189 7849 inTag = true;
dev@189 7850 else
dev@189 7851 desc += c;
dev@189 7852 }
dev@189 7853 else {
dev@189 7854 if( c == ']' ) {
dev@189 7855 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
dev@189 7856 if( prop == TestCaseInfo::IsHidden )
dev@189 7857 isHidden = true;
dev@189 7858 else if( prop == TestCaseInfo::None )
dev@189 7859 enforceNotReservedTag( tag, _lineInfo );
dev@189 7860
dev@189 7861 tags.insert( tag );
dev@189 7862 tag.clear();
dev@189 7863 inTag = false;
dev@189 7864 }
dev@189 7865 else
dev@189 7866 tag += c;
dev@189 7867 }
dev@189 7868 }
dev@189 7869 if( isHidden ) {
dev@189 7870 tags.insert( "hide" );
dev@189 7871 tags.insert( "." );
dev@189 7872 }
dev@189 7873
dev@189 7874 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
dev@189 7875 return TestCase( _testCase, info );
dev@189 7876 }
dev@189 7877
dev@189 7878 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
dev@189 7879 {
dev@189 7880 testCaseInfo.tags = tags;
dev@189 7881 testCaseInfo.lcaseTags.clear();
dev@189 7882
dev@189 7883 std::ostringstream oss;
dev@189 7884 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
dev@189 7885 oss << '[' << *it << ']';
dev@189 7886 std::string lcaseTag = toLower( *it );
dev@189 7887 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
dev@189 7888 testCaseInfo.lcaseTags.insert( lcaseTag );
dev@189 7889 }
dev@189 7890 testCaseInfo.tagsAsString = oss.str();
dev@189 7891 }
dev@189 7892
dev@189 7893 TestCaseInfo::TestCaseInfo( std::string const& _name,
dev@189 7894 std::string const& _className,
dev@189 7895 std::string const& _description,
dev@189 7896 std::set<std::string> const& _tags,
dev@189 7897 SourceLineInfo const& _lineInfo )
dev@189 7898 : name( _name ),
dev@189 7899 className( _className ),
dev@189 7900 description( _description ),
dev@189 7901 lineInfo( _lineInfo ),
dev@189 7902 properties( None )
dev@189 7903 {
dev@189 7904 setTags( *this, _tags );
dev@189 7905 }
dev@189 7906
dev@189 7907 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
dev@189 7908 : name( other.name ),
dev@189 7909 className( other.className ),
dev@189 7910 description( other.description ),
dev@189 7911 tags( other.tags ),
dev@189 7912 lcaseTags( other.lcaseTags ),
dev@189 7913 tagsAsString( other.tagsAsString ),
dev@189 7914 lineInfo( other.lineInfo ),
dev@189 7915 properties( other.properties )
dev@189 7916 {}
dev@189 7917
dev@189 7918 bool TestCaseInfo::isHidden() const {
dev@189 7919 return ( properties & IsHidden ) != 0;
dev@189 7920 }
dev@189 7921 bool TestCaseInfo::throws() const {
dev@189 7922 return ( properties & Throws ) != 0;
dev@189 7923 }
dev@189 7924 bool TestCaseInfo::okToFail() const {
dev@189 7925 return ( properties & (ShouldFail | MayFail ) ) != 0;
dev@189 7926 }
dev@189 7927 bool TestCaseInfo::expectedToFail() const {
dev@189 7928 return ( properties & (ShouldFail ) ) != 0;
dev@189 7929 }
dev@189 7930
dev@189 7931 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
dev@189 7932
dev@189 7933 TestCase::TestCase( TestCase const& other )
dev@189 7934 : TestCaseInfo( other ),
dev@189 7935 test( other.test )
dev@189 7936 {}
dev@189 7937
dev@189 7938 TestCase TestCase::withName( std::string const& _newName ) const {
dev@189 7939 TestCase other( *this );
dev@189 7940 other.name = _newName;
dev@189 7941 return other;
dev@189 7942 }
dev@189 7943
dev@189 7944 void TestCase::swap( TestCase& other ) {
dev@189 7945 test.swap( other.test );
dev@189 7946 name.swap( other.name );
dev@189 7947 className.swap( other.className );
dev@189 7948 description.swap( other.description );
dev@189 7949 tags.swap( other.tags );
dev@189 7950 lcaseTags.swap( other.lcaseTags );
dev@189 7951 tagsAsString.swap( other.tagsAsString );
dev@189 7952 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
dev@189 7953 std::swap( lineInfo, other.lineInfo );
dev@189 7954 }
dev@189 7955
dev@189 7956 void TestCase::invoke() const {
dev@189 7957 test->invoke();
dev@189 7958 }
dev@189 7959
dev@189 7960 bool TestCase::operator == ( TestCase const& other ) const {
dev@189 7961 return test.get() == other.test.get() &&
dev@189 7962 name == other.name &&
dev@189 7963 className == other.className;
dev@189 7964 }
dev@189 7965
dev@189 7966 bool TestCase::operator < ( TestCase const& other ) const {
dev@189 7967 return name < other.name;
dev@189 7968 }
dev@189 7969 TestCase& TestCase::operator = ( TestCase const& other ) {
dev@189 7970 TestCase temp( other );
dev@189 7971 swap( temp );
dev@189 7972 return *this;
dev@189 7973 }
dev@189 7974
dev@189 7975 TestCaseInfo const& TestCase::getTestCaseInfo() const
dev@189 7976 {
dev@189 7977 return *this;
dev@189 7978 }
dev@189 7979
dev@189 7980 } // end namespace Catch
dev@189 7981
dev@189 7982 // #included from: catch_version.hpp
dev@189 7983 #define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
dev@189 7984
dev@189 7985 namespace Catch {
dev@189 7986
dev@189 7987 Version::Version
dev@189 7988 ( unsigned int _majorVersion,
dev@189 7989 unsigned int _minorVersion,
dev@189 7990 unsigned int _patchNumber,
dev@189 7991 std::string const& _branchName,
dev@189 7992 unsigned int _buildNumber )
dev@189 7993 : majorVersion( _majorVersion ),
dev@189 7994 minorVersion( _minorVersion ),
dev@189 7995 patchNumber( _patchNumber ),
dev@189 7996 branchName( _branchName ),
dev@189 7997 buildNumber( _buildNumber )
dev@189 7998 {}
dev@189 7999
dev@189 8000 std::ostream& operator << ( std::ostream& os, Version const& version ) {
dev@189 8001 os << version.majorVersion << '.'
dev@189 8002 << version.minorVersion << '.'
dev@189 8003 << version.patchNumber;
dev@189 8004
dev@189 8005 if( !version.branchName.empty() ) {
dev@189 8006 os << '-' << version.branchName
dev@189 8007 << '.' << version.buildNumber;
dev@189 8008 }
dev@189 8009 return os;
dev@189 8010 }
dev@189 8011
dev@189 8012 Version libraryVersion( 1, 7, 1, "", 0 );
dev@189 8013
dev@189 8014 }
dev@189 8015
dev@189 8016 // #included from: catch_message.hpp
dev@189 8017 #define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
dev@189 8018
dev@189 8019 namespace Catch {
dev@189 8020
dev@189 8021 MessageInfo::MessageInfo( std::string const& _macroName,
dev@189 8022 SourceLineInfo const& _lineInfo,
dev@189 8023 ResultWas::OfType _type )
dev@189 8024 : macroName( _macroName ),
dev@189 8025 lineInfo( _lineInfo ),
dev@189 8026 type( _type ),
dev@189 8027 sequence( ++globalCount )
dev@189 8028 {}
dev@189 8029
dev@189 8030 // This may need protecting if threading support is added
dev@189 8031 unsigned int MessageInfo::globalCount = 0;
dev@189 8032
dev@189 8033 ////////////////////////////////////////////////////////////////////////////
dev@189 8034
dev@189 8035 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
dev@189 8036 : m_info( builder.m_info )
dev@189 8037 {
dev@189 8038 m_info.message = builder.m_stream.str();
dev@189 8039 getResultCapture().pushScopedMessage( m_info );
dev@189 8040 }
dev@189 8041 ScopedMessage::ScopedMessage( ScopedMessage const& other )
dev@189 8042 : m_info( other.m_info )
dev@189 8043 {}
dev@189 8044
dev@189 8045 ScopedMessage::~ScopedMessage() {
dev@189 8046 getResultCapture().popScopedMessage( m_info );
dev@189 8047 }
dev@189 8048
dev@189 8049 } // end namespace Catch
dev@189 8050
dev@189 8051 // #included from: catch_legacy_reporter_adapter.hpp
dev@189 8052 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
dev@189 8053
dev@189 8054 // #included from: catch_legacy_reporter_adapter.h
dev@189 8055 #define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
dev@189 8056
dev@189 8057 namespace Catch
dev@189 8058 {
dev@189 8059 // Deprecated
dev@189 8060 struct IReporter : IShared {
dev@189 8061 virtual ~IReporter();
dev@189 8062
dev@189 8063 virtual bool shouldRedirectStdout() const = 0;
dev@189 8064
dev@189 8065 virtual void StartTesting() = 0;
dev@189 8066 virtual void EndTesting( Totals const& totals ) = 0;
dev@189 8067 virtual void StartGroup( std::string const& groupName ) = 0;
dev@189 8068 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
dev@189 8069 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
dev@189 8070 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
dev@189 8071 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
dev@189 8072 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
dev@189 8073 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
dev@189 8074 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
dev@189 8075 virtual void Aborted() = 0;
dev@189 8076 virtual void Result( AssertionResult const& result ) = 0;
dev@189 8077 };
dev@189 8078
dev@189 8079 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
dev@189 8080 {
dev@189 8081 public:
dev@189 8082 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
dev@189 8083 virtual ~LegacyReporterAdapter();
dev@189 8084
dev@189 8085 virtual ReporterPreferences getPreferences() const;
dev@189 8086 virtual void noMatchingTestCases( std::string const& );
dev@189 8087 virtual void testRunStarting( TestRunInfo const& );
dev@189 8088 virtual void testGroupStarting( GroupInfo const& groupInfo );
dev@189 8089 virtual void testCaseStarting( TestCaseInfo const& testInfo );
dev@189 8090 virtual void sectionStarting( SectionInfo const& sectionInfo );
dev@189 8091 virtual void assertionStarting( AssertionInfo const& );
dev@189 8092 virtual bool assertionEnded( AssertionStats const& assertionStats );
dev@189 8093 virtual void sectionEnded( SectionStats const& sectionStats );
dev@189 8094 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
dev@189 8095 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
dev@189 8096 virtual void testRunEnded( TestRunStats const& testRunStats );
dev@189 8097 virtual void skipTest( TestCaseInfo const& );
dev@189 8098
dev@189 8099 private:
dev@189 8100 Ptr<IReporter> m_legacyReporter;
dev@189 8101 };
dev@189 8102 }
dev@189 8103
dev@189 8104 namespace Catch
dev@189 8105 {
dev@189 8106 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
dev@189 8107 : m_legacyReporter( legacyReporter )
dev@189 8108 {}
dev@189 8109 LegacyReporterAdapter::~LegacyReporterAdapter() {}
dev@189 8110
dev@189 8111 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
dev@189 8112 ReporterPreferences prefs;
dev@189 8113 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
dev@189 8114 return prefs;
dev@189 8115 }
dev@189 8116
dev@189 8117 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
dev@189 8118 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
dev@189 8119 m_legacyReporter->StartTesting();
dev@189 8120 }
dev@189 8121 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
dev@189 8122 m_legacyReporter->StartGroup( groupInfo.name );
dev@189 8123 }
dev@189 8124 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
dev@189 8125 m_legacyReporter->StartTestCase( testInfo );
dev@189 8126 }
dev@189 8127 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
dev@189 8128 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
dev@189 8129 }
dev@189 8130 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
dev@189 8131 // Not on legacy interface
dev@189 8132 }
dev@189 8133
dev@189 8134 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
dev@189 8135 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
dev@189 8136 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
dev@189 8137 it != itEnd;
dev@189 8138 ++it ) {
dev@189 8139 if( it->type == ResultWas::Info ) {
dev@189 8140 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
dev@189 8141 rb << it->message;
dev@189 8142 rb.setResultType( ResultWas::Info );
dev@189 8143 AssertionResult result = rb.build();
dev@189 8144 m_legacyReporter->Result( result );
dev@189 8145 }
dev@189 8146 }
dev@189 8147 }
dev@189 8148 m_legacyReporter->Result( assertionStats.assertionResult );
dev@189 8149 return true;
dev@189 8150 }
dev@189 8151 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
dev@189 8152 if( sectionStats.missingAssertions )
dev@189 8153 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
dev@189 8154 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
dev@189 8155 }
dev@189 8156 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
dev@189 8157 m_legacyReporter->EndTestCase
dev@189 8158 ( testCaseStats.testInfo,
dev@189 8159 testCaseStats.totals,
dev@189 8160 testCaseStats.stdOut,
dev@189 8161 testCaseStats.stdErr );
dev@189 8162 }
dev@189 8163 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
dev@189 8164 if( testGroupStats.aborting )
dev@189 8165 m_legacyReporter->Aborted();
dev@189 8166 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
dev@189 8167 }
dev@189 8168 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
dev@189 8169 m_legacyReporter->EndTesting( testRunStats.totals );
dev@189 8170 }
dev@189 8171 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
dev@189 8172 }
dev@189 8173 }
dev@189 8174
dev@189 8175 // #included from: catch_timer.hpp
dev@189 8176
dev@189 8177 #ifdef __clang__
dev@189 8178 #pragma clang diagnostic push
dev@189 8179 #pragma clang diagnostic ignored "-Wc++11-long-long"
dev@189 8180 #endif
dev@189 8181
dev@189 8182 #ifdef CATCH_PLATFORM_WINDOWS
dev@189 8183 #else
dev@189 8184 #include <sys/time.h>
dev@189 8185 #endif
dev@189 8186
dev@189 8187 namespace Catch {
dev@189 8188
dev@189 8189 namespace {
dev@189 8190 #ifdef CATCH_PLATFORM_WINDOWS
dev@189 8191 uint64_t getCurrentTicks() {
dev@189 8192 static uint64_t hz=0, hzo=0;
dev@189 8193 if (!hz) {
dev@189 8194 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
dev@189 8195 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
dev@189 8196 }
dev@189 8197 uint64_t t;
dev@189 8198 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
dev@189 8199 return ((t-hzo)*1000000)/hz;
dev@189 8200 }
dev@189 8201 #else
dev@189 8202 uint64_t getCurrentTicks() {
dev@189 8203 timeval t;
dev@189 8204 gettimeofday(&t,CATCH_NULL);
dev@189 8205 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
dev@189 8206 }
dev@189 8207 #endif
dev@189 8208 }
dev@189 8209
dev@189 8210 void Timer::start() {
dev@189 8211 m_ticks = getCurrentTicks();
dev@189 8212 }
dev@189 8213 unsigned int Timer::getElapsedMicroseconds() const {
dev@189 8214 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
dev@189 8215 }
dev@189 8216 unsigned int Timer::getElapsedMilliseconds() const {
dev@189 8217 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
dev@189 8218 }
dev@189 8219 double Timer::getElapsedSeconds() const {
dev@189 8220 return getElapsedMicroseconds()/1000000.0;
dev@189 8221 }
dev@189 8222
dev@189 8223 } // namespace Catch
dev@189 8224
dev@189 8225 #ifdef __clang__
dev@189 8226 #pragma clang diagnostic pop
dev@189 8227 #endif
dev@189 8228 // #included from: catch_common.hpp
dev@189 8229 #define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
dev@189 8230
dev@189 8231 #include <cstring>
dev@189 8232
dev@189 8233 namespace Catch {
dev@189 8234
dev@189 8235 bool startsWith( std::string const& s, std::string const& prefix ) {
dev@189 8236 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
dev@189 8237 }
dev@189 8238 bool startsWith( std::string const& s, char prefix ) {
dev@189 8239 return !s.empty() && s[0] == prefix;
dev@189 8240 }
dev@189 8241 bool endsWith( std::string const& s, std::string const& suffix ) {
dev@189 8242 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
dev@189 8243 }
dev@189 8244 bool endsWith( std::string const& s, char suffix ) {
dev@189 8245 return !s.empty() && s[s.size()-1] == suffix;
dev@189 8246 }
dev@189 8247 bool contains( std::string const& s, std::string const& infix ) {
dev@189 8248 return s.find( infix ) != std::string::npos;
dev@189 8249 }
dev@189 8250 bool contains( std::string const& s, char infix ) {
dev@189 8251 return s.find(infix) != std::string::npos;
dev@189 8252 }
dev@189 8253 char toLowerCh(char c) {
dev@189 8254 return static_cast<char>( ::tolower( c ) );
dev@189 8255 }
dev@189 8256 void toLowerInPlace( std::string& s ) {
dev@189 8257 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
dev@189 8258 }
dev@189 8259 std::string toLower( std::string const& s ) {
dev@189 8260 std::string lc = s;
dev@189 8261 toLowerInPlace( lc );
dev@189 8262 return lc;
dev@189 8263 }
dev@189 8264 std::string trim( std::string const& str ) {
dev@189 8265 static char const* whitespaceChars = "\n\r\t ";
dev@189 8266 std::string::size_type start = str.find_first_not_of( whitespaceChars );
dev@189 8267 std::string::size_type end = str.find_last_not_of( whitespaceChars );
dev@189 8268
dev@189 8269 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
dev@189 8270 }
dev@189 8271
dev@189 8272 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
dev@189 8273 bool replaced = false;
dev@189 8274 std::size_t i = str.find( replaceThis );
dev@189 8275 while( i != std::string::npos ) {
dev@189 8276 replaced = true;
dev@189 8277 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
dev@189 8278 if( i < str.size()-withThis.size() )
dev@189 8279 i = str.find( replaceThis, i+withThis.size() );
dev@189 8280 else
dev@189 8281 i = std::string::npos;
dev@189 8282 }
dev@189 8283 return replaced;
dev@189 8284 }
dev@189 8285
dev@189 8286 pluralise::pluralise( std::size_t count, std::string const& label )
dev@189 8287 : m_count( count ),
dev@189 8288 m_label( label )
dev@189 8289 {}
dev@189 8290
dev@189 8291 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
dev@189 8292 os << pluraliser.m_count << ' ' << pluraliser.m_label;
dev@189 8293 if( pluraliser.m_count != 1 )
dev@189 8294 os << 's';
dev@189 8295 return os;
dev@189 8296 }
dev@189 8297
dev@189 8298 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
dev@189 8299 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
dev@189 8300 : file( _file ),
dev@189 8301 line( _line )
dev@189 8302 {}
dev@189 8303 bool SourceLineInfo::empty() const {
dev@189 8304 return file[0] == '\0';
dev@189 8305 }
dev@189 8306 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
dev@189 8307 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
dev@189 8308 }
dev@189 8309 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
dev@189 8310 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
dev@189 8311 }
dev@189 8312
dev@189 8313 void seedRng( IConfig const& config ) {
dev@189 8314 if( config.rngSeed() != 0 )
dev@189 8315 std::srand( config.rngSeed() );
dev@189 8316 }
dev@189 8317 unsigned int rngSeed() {
dev@189 8318 return getCurrentContext().getConfig()->rngSeed();
dev@189 8319 }
dev@189 8320
dev@189 8321 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
dev@189 8322 #ifndef __GNUG__
dev@189 8323 os << info.file << '(' << info.line << ')';
dev@189 8324 #else
dev@189 8325 os << info.file << ':' << info.line;
dev@189 8326 #endif
dev@189 8327 return os;
dev@189 8328 }
dev@189 8329
dev@189 8330 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
dev@189 8331 std::ostringstream oss;
dev@189 8332 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
dev@189 8333 if( alwaysTrue() )
dev@189 8334 throw std::logic_error( oss.str() );
dev@189 8335 }
dev@189 8336 }
dev@189 8337
dev@189 8338 // #included from: catch_section.hpp
dev@189 8339 #define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
dev@189 8340
dev@189 8341 namespace Catch {
dev@189 8342
dev@189 8343 SectionInfo::SectionInfo
dev@189 8344 ( SourceLineInfo const& _lineInfo,
dev@189 8345 std::string const& _name,
dev@189 8346 std::string const& _description )
dev@189 8347 : name( _name ),
dev@189 8348 description( _description ),
dev@189 8349 lineInfo( _lineInfo )
dev@189 8350 {}
dev@189 8351
dev@189 8352 Section::Section( SectionInfo const& info )
dev@189 8353 : m_info( info ),
dev@189 8354 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
dev@189 8355 {
dev@189 8356 m_timer.start();
dev@189 8357 }
dev@189 8358
dev@189 8359 Section::~Section() {
dev@189 8360 if( m_sectionIncluded ) {
dev@189 8361 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
dev@189 8362 if( std::uncaught_exception() )
dev@189 8363 getResultCapture().sectionEndedEarly( endInfo );
dev@189 8364 else
dev@189 8365 getResultCapture().sectionEnded( endInfo );
dev@189 8366 }
dev@189 8367 }
dev@189 8368
dev@189 8369 // This indicates whether the section should be executed or not
dev@189 8370 Section::operator bool() const {
dev@189 8371 return m_sectionIncluded;
dev@189 8372 }
dev@189 8373
dev@189 8374 } // end namespace Catch
dev@189 8375
dev@189 8376 // #included from: catch_debugger.hpp
dev@189 8377 #define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
dev@189 8378
dev@189 8379 #include <iostream>
dev@189 8380
dev@189 8381 #ifdef CATCH_PLATFORM_MAC
dev@189 8382
dev@189 8383 #include <assert.h>
dev@189 8384 #include <stdbool.h>
dev@189 8385 #include <sys/types.h>
dev@189 8386 #include <unistd.h>
dev@189 8387 #include <sys/sysctl.h>
dev@189 8388
dev@189 8389 namespace Catch{
dev@189 8390
dev@189 8391 // The following function is taken directly from the following technical note:
dev@189 8392 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
dev@189 8393
dev@189 8394 // Returns true if the current process is being debugged (either
dev@189 8395 // running under the debugger or has a debugger attached post facto).
dev@189 8396 bool isDebuggerActive(){
dev@189 8397
dev@189 8398 int mib[4];
dev@189 8399 struct kinfo_proc info;
dev@189 8400 size_t size;
dev@189 8401
dev@189 8402 // Initialize the flags so that, if sysctl fails for some bizarre
dev@189 8403 // reason, we get a predictable result.
dev@189 8404
dev@189 8405 info.kp_proc.p_flag = 0;
dev@189 8406
dev@189 8407 // Initialize mib, which tells sysctl the info we want, in this case
dev@189 8408 // we're looking for information about a specific process ID.
dev@189 8409
dev@189 8410 mib[0] = CTL_KERN;
dev@189 8411 mib[1] = KERN_PROC;
dev@189 8412 mib[2] = KERN_PROC_PID;
dev@189 8413 mib[3] = getpid();
dev@189 8414
dev@189 8415 // Call sysctl.
dev@189 8416
dev@189 8417 size = sizeof(info);
dev@189 8418 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
dev@189 8419 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
dev@189 8420 return false;
dev@189 8421 }
dev@189 8422
dev@189 8423 // We're being debugged if the P_TRACED flag is set.
dev@189 8424
dev@189 8425 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
dev@189 8426 }
dev@189 8427 } // namespace Catch
dev@189 8428
dev@189 8429 #elif defined(CATCH_PLATFORM_LINUX)
dev@189 8430 #include <fstream>
dev@189 8431 #include <string>
dev@189 8432
dev@189 8433 namespace Catch{
dev@189 8434 // The standard POSIX way of detecting a debugger is to attempt to
dev@189 8435 // ptrace() the process, but this needs to be done from a child and not
dev@189 8436 // this process itself to still allow attaching to this process later
dev@189 8437 // if wanted, so is rather heavy. Under Linux we have the PID of the
dev@189 8438 // "debugger" (which doesn't need to be gdb, of course, it could also
dev@189 8439 // be strace, for example) in /proc/$PID/status, so just get it from
dev@189 8440 // there instead.
dev@189 8441 bool isDebuggerActive(){
dev@189 8442 std::ifstream in("/proc/self/status");
dev@189 8443 for( std::string line; std::getline(in, line); ) {
dev@189 8444 static const int PREFIX_LEN = 11;
dev@189 8445 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
dev@189 8446 // We're traced if the PID is not 0 and no other PID starts
dev@189 8447 // with 0 digit, so it's enough to check for just a single
dev@189 8448 // character.
dev@189 8449 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
dev@189 8450 }
dev@189 8451 }
dev@189 8452
dev@189 8453 return false;
dev@189 8454 }
dev@189 8455 } // namespace Catch
dev@189 8456 #elif defined(_MSC_VER)
dev@189 8457 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
dev@189 8458 namespace Catch {
dev@189 8459 bool isDebuggerActive() {
dev@189 8460 return IsDebuggerPresent() != 0;
dev@189 8461 }
dev@189 8462 }
dev@189 8463 #elif defined(__MINGW32__)
dev@189 8464 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
dev@189 8465 namespace Catch {
dev@189 8466 bool isDebuggerActive() {
dev@189 8467 return IsDebuggerPresent() != 0;
dev@189 8468 }
dev@189 8469 }
dev@189 8470 #else
dev@189 8471 namespace Catch {
dev@189 8472 inline bool isDebuggerActive() { return false; }
dev@189 8473 }
dev@189 8474 #endif // Platform
dev@189 8475
dev@189 8476 #ifdef CATCH_PLATFORM_WINDOWS
dev@189 8477 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
dev@189 8478 namespace Catch {
dev@189 8479 void writeToDebugConsole( std::string const& text ) {
dev@189 8480 ::OutputDebugStringA( text.c_str() );
dev@189 8481 }
dev@189 8482 }
dev@189 8483 #else
dev@189 8484 namespace Catch {
dev@189 8485 void writeToDebugConsole( std::string const& text ) {
dev@189 8486 // !TBD: Need a version for Mac/ XCode and other IDEs
dev@189 8487 Catch::cout() << text;
dev@189 8488 }
dev@189 8489 }
dev@189 8490 #endif // Platform
dev@189 8491
dev@189 8492 // #included from: catch_tostring.hpp
dev@189 8493 #define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
dev@189 8494
dev@189 8495 namespace Catch {
dev@189 8496
dev@189 8497 namespace Detail {
dev@189 8498
dev@189 8499 const std::string unprintableString = "{?}";
dev@189 8500
dev@189 8501 namespace {
dev@189 8502 const int hexThreshold = 255;
dev@189 8503
dev@189 8504 struct Endianness {
dev@189 8505 enum Arch { Big, Little };
dev@189 8506
dev@189 8507 static Arch which() {
dev@189 8508 union _{
dev@189 8509 int asInt;
dev@189 8510 char asChar[sizeof (int)];
dev@189 8511 } u;
dev@189 8512
dev@189 8513 u.asInt = 1;
dev@189 8514 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
dev@189 8515 }
dev@189 8516 };
dev@189 8517 }
dev@189 8518
dev@189 8519 std::string rawMemoryToString( const void *object, std::size_t size )
dev@189 8520 {
dev@189 8521 // Reverse order for little endian architectures
dev@189 8522 int i = 0, end = static_cast<int>( size ), inc = 1;
dev@189 8523 if( Endianness::which() == Endianness::Little ) {
dev@189 8524 i = end-1;
dev@189 8525 end = inc = -1;
dev@189 8526 }
dev@189 8527
dev@189 8528 unsigned char const *bytes = static_cast<unsigned char const *>(object);
dev@189 8529 std::ostringstream os;
dev@189 8530 os << "0x" << std::setfill('0') << std::hex;
dev@189 8531 for( ; i != end; i += inc )
dev@189 8532 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
dev@189 8533 return os.str();
dev@189 8534 }
dev@189 8535 }
dev@189 8536
dev@189 8537 std::string toString( std::string const& value ) {
dev@189 8538 std::string s = value;
dev@189 8539 if( getCurrentContext().getConfig()->showInvisibles() ) {
dev@189 8540 for(size_t i = 0; i < s.size(); ++i ) {
dev@189 8541 std::string subs;
dev@189 8542 switch( s[i] ) {
dev@189 8543 case '\n': subs = "\\n"; break;
dev@189 8544 case '\t': subs = "\\t"; break;
dev@189 8545 default: break;
dev@189 8546 }
dev@189 8547 if( !subs.empty() ) {
dev@189 8548 s = s.substr( 0, i ) + subs + s.substr( i+1 );
dev@189 8549 ++i;
dev@189 8550 }
dev@189 8551 }
dev@189 8552 }
dev@189 8553 return '"' + s + '"';
dev@189 8554 }
dev@189 8555 std::string toString( std::wstring const& value ) {
dev@189 8556
dev@189 8557 std::string s;
dev@189 8558 s.reserve( value.size() );
dev@189 8559 for(size_t i = 0; i < value.size(); ++i )
dev@189 8560 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
dev@189 8561 return Catch::toString( s );
dev@189 8562 }
dev@189 8563
dev@189 8564 std::string toString( const char* const value ) {
dev@189 8565 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
dev@189 8566 }
dev@189 8567
dev@189 8568 std::string toString( char* const value ) {
dev@189 8569 return Catch::toString( static_cast<const char*>( value ) );
dev@189 8570 }
dev@189 8571
dev@189 8572 std::string toString( const wchar_t* const value )
dev@189 8573 {
dev@189 8574 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
dev@189 8575 }
dev@189 8576
dev@189 8577 std::string toString( wchar_t* const value )
dev@189 8578 {
dev@189 8579 return Catch::toString( static_cast<const wchar_t*>( value ) );
dev@189 8580 }
dev@189 8581
dev@189 8582 std::string toString( int value ) {
dev@189 8583 std::ostringstream oss;
dev@189 8584 oss << value;
dev@189 8585 if( value > Detail::hexThreshold )
dev@189 8586 oss << " (0x" << std::hex << value << ')';
dev@189 8587 return oss.str();
dev@189 8588 }
dev@189 8589
dev@189 8590 std::string toString( unsigned long value ) {
dev@189 8591 std::ostringstream oss;
dev@189 8592 oss << value;
dev@189 8593 if( value > Detail::hexThreshold )
dev@189 8594 oss << " (0x" << std::hex << value << ')';
dev@189 8595 return oss.str();
dev@189 8596 }
dev@189 8597
dev@189 8598 std::string toString( unsigned int value ) {
dev@189 8599 return Catch::toString( static_cast<unsigned long>( value ) );
dev@189 8600 }
dev@189 8601
dev@189 8602 template<typename T>
dev@189 8603 std::string fpToString( T value, int precision ) {
dev@189 8604 std::ostringstream oss;
dev@189 8605 oss << std::setprecision( precision )
dev@189 8606 << std::fixed
dev@189 8607 << value;
dev@189 8608 std::string d = oss.str();
dev@189 8609 std::size_t i = d.find_last_not_of( '0' );
dev@189 8610 if( i != std::string::npos && i != d.size()-1 ) {
dev@189 8611 if( d[i] == '.' )
dev@189 8612 i++;
dev@189 8613 d = d.substr( 0, i+1 );
dev@189 8614 }
dev@189 8615 return d;
dev@189 8616 }
dev@189 8617
dev@189 8618 std::string toString( const double value ) {
dev@189 8619 return fpToString( value, 10 );
dev@189 8620 }
dev@189 8621 std::string toString( const float value ) {
dev@189 8622 return fpToString( value, 5 ) + 'f';
dev@189 8623 }
dev@189 8624
dev@189 8625 std::string toString( bool value ) {
dev@189 8626 return value ? "true" : "false";
dev@189 8627 }
dev@189 8628
dev@189 8629 std::string toString( char value ) {
dev@189 8630 if ( value == '\r' )
dev@189 8631 return "'\\r'";
dev@189 8632 if ( value == '\f' )
dev@189 8633 return "'\\f'";
dev@189 8634 if ( value == '\n' )
dev@189 8635 return "'\\n'";
dev@189 8636 if ( value == '\t' )
dev@189 8637 return "'\\t'";
dev@189 8638 if ( '\0' <= value && value < ' ' )
dev@189 8639 return toString( static_cast<unsigned int>( value ) );
dev@189 8640 char chstr[] = "' '";
dev@189 8641 chstr[1] = value;
dev@189 8642 return chstr;
dev@189 8643 }
dev@189 8644
dev@189 8645 std::string toString( signed char value ) {
dev@189 8646 return toString( static_cast<char>( value ) );
dev@189 8647 }
dev@189 8648
dev@189 8649 std::string toString( unsigned char value ) {
dev@189 8650 return toString( static_cast<char>( value ) );
dev@189 8651 }
dev@189 8652
dev@189 8653 #ifdef CATCH_CONFIG_CPP11_LONG_LONG
dev@189 8654 std::string toString( long long value ) {
dev@189 8655 std::ostringstream oss;
dev@189 8656 oss << value;
dev@189 8657 if( value > Detail::hexThreshold )
dev@189 8658 oss << " (0x" << std::hex << value << ')';
dev@189 8659 return oss.str();
dev@189 8660 }
dev@189 8661 std::string toString( unsigned long long value ) {
dev@189 8662 std::ostringstream oss;
dev@189 8663 oss << value;
dev@189 8664 if( value > Detail::hexThreshold )
dev@189 8665 oss << " (0x" << std::hex << value << ')';
dev@189 8666 return oss.str();
dev@189 8667 }
dev@189 8668 #endif
dev@189 8669
dev@189 8670 #ifdef CATCH_CONFIG_CPP11_NULLPTR
dev@189 8671 std::string toString( std::nullptr_t ) {
dev@189 8672 return "nullptr";
dev@189 8673 }
dev@189 8674 #endif
dev@189 8675
dev@189 8676 #ifdef __OBJC__
dev@189 8677 std::string toString( NSString const * const& nsstring ) {
dev@189 8678 if( !nsstring )
dev@189 8679 return "nil";
dev@189 8680 return "@" + toString([nsstring UTF8String]);
dev@189 8681 }
dev@189 8682 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
dev@189 8683 if( !nsstring )
dev@189 8684 return "nil";
dev@189 8685 return "@" + toString([nsstring UTF8String]);
dev@189 8686 }
dev@189 8687 std::string toString( NSObject* const& nsObject ) {
dev@189 8688 return toString( [nsObject description] );
dev@189 8689 }
dev@189 8690 #endif
dev@189 8691
dev@189 8692 } // end namespace Catch
dev@189 8693
dev@189 8694 // #included from: catch_result_builder.hpp
dev@189 8695 #define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
dev@189 8696
dev@189 8697 namespace Catch {
dev@189 8698
dev@189 8699 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
dev@189 8700 return secondArg.empty() || secondArg == "\"\""
dev@189 8701 ? capturedExpression
dev@189 8702 : capturedExpression + ", " + secondArg;
dev@189 8703 }
dev@189 8704 ResultBuilder::ResultBuilder( char const* macroName,
dev@189 8705 SourceLineInfo const& lineInfo,
dev@189 8706 char const* capturedExpression,
dev@189 8707 ResultDisposition::Flags resultDisposition,
dev@189 8708 char const* secondArg )
dev@189 8709 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
dev@189 8710 m_shouldDebugBreak( false ),
dev@189 8711 m_shouldThrow( false )
dev@189 8712 {}
dev@189 8713
dev@189 8714 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
dev@189 8715 m_data.resultType = result;
dev@189 8716 return *this;
dev@189 8717 }
dev@189 8718 ResultBuilder& ResultBuilder::setResultType( bool result ) {
dev@189 8719 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
dev@189 8720 return *this;
dev@189 8721 }
dev@189 8722
dev@189 8723 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
dev@189 8724 AssertionResult result = build( expr );
dev@189 8725 handleResult( result );
dev@189 8726 }
dev@189 8727
dev@189 8728 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
dev@189 8729 m_assertionInfo.resultDisposition = resultDisposition;
dev@189 8730 m_stream.oss << Catch::translateActiveException();
dev@189 8731 captureResult( ResultWas::ThrewException );
dev@189 8732 }
dev@189 8733
dev@189 8734 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
dev@189 8735 setResultType( resultType );
dev@189 8736 captureExpression();
dev@189 8737 }
dev@189 8738
dev@189 8739 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
dev@189 8740 if( expectedMessage.empty() )
dev@189 8741 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
dev@189 8742 else
dev@189 8743 captureExpectedException( Matchers::Equals( expectedMessage ) );
dev@189 8744 }
dev@189 8745
dev@189 8746 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
dev@189 8747
dev@189 8748 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
dev@189 8749 AssertionResultData data = m_data;
dev@189 8750 data.resultType = ResultWas::Ok;
dev@189 8751 data.reconstructedExpression = m_assertionInfo.capturedExpression;
dev@189 8752
dev@189 8753 std::string actualMessage = Catch::translateActiveException();
dev@189 8754 if( !matcher.match( actualMessage ) ) {
dev@189 8755 data.resultType = ResultWas::ExpressionFailed;
dev@189 8756 data.reconstructedExpression = actualMessage;
dev@189 8757 }
dev@189 8758 AssertionResult result( m_assertionInfo, data );
dev@189 8759 handleResult( result );
dev@189 8760 }
dev@189 8761
dev@189 8762 void ResultBuilder::captureExpression() {
dev@189 8763 AssertionResult result = build();
dev@189 8764 handleResult( result );
dev@189 8765 }
dev@189 8766
dev@189 8767 void ResultBuilder::handleResult( AssertionResult const& result )
dev@189 8768 {
dev@189 8769 getResultCapture().assertionEnded( result );
dev@189 8770
dev@189 8771 if( !result.isOk() ) {
dev@189 8772 if( getCurrentContext().getConfig()->shouldDebugBreak() )
dev@189 8773 m_shouldDebugBreak = true;
dev@189 8774 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
dev@189 8775 m_shouldThrow = true;
dev@189 8776 }
dev@189 8777 }
dev@189 8778
dev@189 8779 void ResultBuilder::react() {
dev@189 8780 if( m_shouldThrow )
dev@189 8781 throw Catch::TestFailureException();
dev@189 8782 }
dev@189 8783
dev@189 8784 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
dev@189 8785 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
dev@189 8786
dev@189 8787 AssertionResult ResultBuilder::build() const
dev@189 8788 {
dev@189 8789 return build( *this );
dev@189 8790 }
dev@189 8791
dev@189 8792 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
dev@189 8793 // a temporary DecomposedExpression, which in turn holds references to
dev@189 8794 // operands, possibly temporary as well.
dev@189 8795 // It should immediately be passed to handleResult; if the expression
dev@189 8796 // needs to be reported, its string expansion must be composed before
dev@189 8797 // the temporaries are destroyed.
dev@189 8798 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
dev@189 8799 {
dev@189 8800 assert( m_data.resultType != ResultWas::Unknown );
dev@189 8801 AssertionResultData data = m_data;
dev@189 8802
dev@189 8803 // Flip bool results if FalseTest flag is set
dev@189 8804 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
dev@189 8805 data.negate( expr.isBinaryExpression() );
dev@189 8806 }
dev@189 8807
dev@189 8808 data.message = m_stream.oss.str();
dev@189 8809 data.decomposedExpression = &expr; // for lazy reconstruction
dev@189 8810 return AssertionResult( m_assertionInfo, data );
dev@189 8811 }
dev@189 8812
dev@189 8813 void ResultBuilder::reconstructExpression( std::string& dest ) const {
dev@189 8814 dest = m_assertionInfo.capturedExpression;
dev@189 8815 }
dev@189 8816
dev@189 8817 } // end namespace Catch
dev@189 8818
dev@189 8819 // #included from: catch_tag_alias_registry.hpp
dev@189 8820 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
dev@189 8821
dev@189 8822 // #included from: catch_tag_alias_registry.h
dev@189 8823 #define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
dev@189 8824
dev@189 8825 #include <map>
dev@189 8826
dev@189 8827 namespace Catch {
dev@189 8828
dev@189 8829 class TagAliasRegistry : public ITagAliasRegistry {
dev@189 8830 public:
dev@189 8831 virtual ~TagAliasRegistry();
dev@189 8832 virtual Option<TagAlias> find( std::string const& alias ) const;
dev@189 8833 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
dev@189 8834 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
dev@189 8835 static TagAliasRegistry& get();
dev@189 8836
dev@189 8837 private:
dev@189 8838 std::map<std::string, TagAlias> m_registry;
dev@189 8839 };
dev@189 8840
dev@189 8841 } // end namespace Catch
dev@189 8842
dev@189 8843 #include <map>
dev@189 8844 #include <iostream>
dev@189 8845
dev@189 8846 namespace Catch {
dev@189 8847
dev@189 8848 TagAliasRegistry::~TagAliasRegistry() {}
dev@189 8849
dev@189 8850 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
dev@189 8851 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
dev@189 8852 if( it != m_registry.end() )
dev@189 8853 return it->second;
dev@189 8854 else
dev@189 8855 return Option<TagAlias>();
dev@189 8856 }
dev@189 8857
dev@189 8858 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
dev@189 8859 std::string expandedTestSpec = unexpandedTestSpec;
dev@189 8860 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
dev@189 8861 it != itEnd;
dev@189 8862 ++it ) {
dev@189 8863 std::size_t pos = expandedTestSpec.find( it->first );
dev@189 8864 if( pos != std::string::npos ) {
dev@189 8865 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
dev@189 8866 it->second.tag +
dev@189 8867 expandedTestSpec.substr( pos + it->first.size() );
dev@189 8868 }
dev@189 8869 }
dev@189 8870 return expandedTestSpec;
dev@189 8871 }
dev@189 8872
dev@189 8873 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
dev@189 8874
dev@189 8875 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
dev@189 8876 std::ostringstream oss;
dev@189 8877 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
dev@189 8878 throw std::domain_error( oss.str().c_str() );
dev@189 8879 }
dev@189 8880 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
dev@189 8881 std::ostringstream oss;
dev@189 8882 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
dev@189 8883 << "\tFirst seen at " << find(alias)->lineInfo << '\n'
dev@189 8884 << "\tRedefined at " << lineInfo;
dev@189 8885 throw std::domain_error( oss.str().c_str() );
dev@189 8886 }
dev@189 8887 }
dev@189 8888
dev@189 8889 TagAliasRegistry& TagAliasRegistry::get() {
dev@189 8890 static TagAliasRegistry instance;
dev@189 8891 return instance;
dev@189 8892
dev@189 8893 }
dev@189 8894
dev@189 8895 ITagAliasRegistry::~ITagAliasRegistry() {}
dev@189 8896 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
dev@189 8897
dev@189 8898 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
dev@189 8899 try {
dev@189 8900 TagAliasRegistry::get().add( alias, tag, lineInfo );
dev@189 8901 }
dev@189 8902 catch( std::exception& ex ) {
dev@189 8903 Colour colourGuard( Colour::Red );
dev@189 8904 Catch::cerr() << ex.what() << std::endl;
dev@189 8905 exit(1);
dev@189 8906 }
dev@189 8907 }
dev@189 8908
dev@189 8909 } // end namespace Catch
dev@189 8910
dev@189 8911 // #included from: ../reporters/catch_reporter_multi.hpp
dev@189 8912 #define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
dev@189 8913
dev@189 8914 namespace Catch {
dev@189 8915
dev@189 8916 class MultipleReporters : public SharedImpl<IStreamingReporter> {
dev@189 8917 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
dev@189 8918 Reporters m_reporters;
dev@189 8919
dev@189 8920 public:
dev@189 8921 void add( Ptr<IStreamingReporter> const& reporter ) {
dev@189 8922 m_reporters.push_back( reporter );
dev@189 8923 }
dev@189 8924
dev@189 8925 public: // IStreamingReporter
dev@189 8926
dev@189 8927 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
dev@189 8928 return m_reporters[0]->getPreferences();
dev@189 8929 }
dev@189 8930
dev@189 8931 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
dev@189 8932 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8933 it != itEnd;
dev@189 8934 ++it )
dev@189 8935 (*it)->noMatchingTestCases( spec );
dev@189 8936 }
dev@189 8937
dev@189 8938 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
dev@189 8939 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8940 it != itEnd;
dev@189 8941 ++it )
dev@189 8942 (*it)->testRunStarting( testRunInfo );
dev@189 8943 }
dev@189 8944
dev@189 8945 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
dev@189 8946 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8947 it != itEnd;
dev@189 8948 ++it )
dev@189 8949 (*it)->testGroupStarting( groupInfo );
dev@189 8950 }
dev@189 8951
dev@189 8952 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
dev@189 8953 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8954 it != itEnd;
dev@189 8955 ++it )
dev@189 8956 (*it)->testCaseStarting( testInfo );
dev@189 8957 }
dev@189 8958
dev@189 8959 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
dev@189 8960 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8961 it != itEnd;
dev@189 8962 ++it )
dev@189 8963 (*it)->sectionStarting( sectionInfo );
dev@189 8964 }
dev@189 8965
dev@189 8966 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
dev@189 8967 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8968 it != itEnd;
dev@189 8969 ++it )
dev@189 8970 (*it)->assertionStarting( assertionInfo );
dev@189 8971 }
dev@189 8972
dev@189 8973 // The return value indicates if the messages buffer should be cleared:
dev@189 8974 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
dev@189 8975 bool clearBuffer = false;
dev@189 8976 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8977 it != itEnd;
dev@189 8978 ++it )
dev@189 8979 clearBuffer |= (*it)->assertionEnded( assertionStats );
dev@189 8980 return clearBuffer;
dev@189 8981 }
dev@189 8982
dev@189 8983 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
dev@189 8984 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8985 it != itEnd;
dev@189 8986 ++it )
dev@189 8987 (*it)->sectionEnded( sectionStats );
dev@189 8988 }
dev@189 8989
dev@189 8990 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
dev@189 8991 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8992 it != itEnd;
dev@189 8993 ++it )
dev@189 8994 (*it)->testCaseEnded( testCaseStats );
dev@189 8995 }
dev@189 8996
dev@189 8997 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
dev@189 8998 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 8999 it != itEnd;
dev@189 9000 ++it )
dev@189 9001 (*it)->testGroupEnded( testGroupStats );
dev@189 9002 }
dev@189 9003
dev@189 9004 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
dev@189 9005 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 9006 it != itEnd;
dev@189 9007 ++it )
dev@189 9008 (*it)->testRunEnded( testRunStats );
dev@189 9009 }
dev@189 9010
dev@189 9011 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
dev@189 9012 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
dev@189 9013 it != itEnd;
dev@189 9014 ++it )
dev@189 9015 (*it)->skipTest( testInfo );
dev@189 9016 }
dev@189 9017
dev@189 9018 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
dev@189 9019 return this;
dev@189 9020 }
dev@189 9021
dev@189 9022 };
dev@189 9023
dev@189 9024 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
dev@189 9025 Ptr<IStreamingReporter> resultingReporter;
dev@189 9026
dev@189 9027 if( existingReporter ) {
dev@189 9028 MultipleReporters* multi = existingReporter->tryAsMulti();
dev@189 9029 if( !multi ) {
dev@189 9030 multi = new MultipleReporters;
dev@189 9031 resultingReporter = Ptr<IStreamingReporter>( multi );
dev@189 9032 if( existingReporter )
dev@189 9033 multi->add( existingReporter );
dev@189 9034 }
dev@189 9035 else
dev@189 9036 resultingReporter = existingReporter;
dev@189 9037 multi->add( additionalReporter );
dev@189 9038 }
dev@189 9039 else
dev@189 9040 resultingReporter = additionalReporter;
dev@189 9041
dev@189 9042 return resultingReporter;
dev@189 9043 }
dev@189 9044
dev@189 9045 } // end namespace Catch
dev@189 9046
dev@189 9047 // #included from: ../reporters/catch_reporter_xml.hpp
dev@189 9048 #define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
dev@189 9049
dev@189 9050 // #included from: catch_reporter_bases.hpp
dev@189 9051 #define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
dev@189 9052
dev@189 9053 #include <cstring>
dev@189 9054
dev@189 9055 namespace Catch {
dev@189 9056
dev@189 9057 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
dev@189 9058
dev@189 9059 StreamingReporterBase( ReporterConfig const& _config )
dev@189 9060 : m_config( _config.fullConfig() ),
dev@189 9061 stream( _config.stream() )
dev@189 9062 {
dev@189 9063 m_reporterPrefs.shouldRedirectStdOut = false;
dev@189 9064 }
dev@189 9065
dev@189 9066 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
dev@189 9067 return m_reporterPrefs;
dev@189 9068 }
dev@189 9069
dev@189 9070 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
dev@189 9071
dev@189 9072 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
dev@189 9073
dev@189 9074 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
dev@189 9075 currentTestRunInfo = _testRunInfo;
dev@189 9076 }
dev@189 9077 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
dev@189 9078 currentGroupInfo = _groupInfo;
dev@189 9079 }
dev@189 9080
dev@189 9081 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
dev@189 9082 currentTestCaseInfo = _testInfo;
dev@189 9083 }
dev@189 9084 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
dev@189 9085 m_sectionStack.push_back( _sectionInfo );
dev@189 9086 }
dev@189 9087
dev@189 9088 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
dev@189 9089 m_sectionStack.pop_back();
dev@189 9090 }
dev@189 9091 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
dev@189 9092 currentTestCaseInfo.reset();
dev@189 9093 }
dev@189 9094 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
dev@189 9095 currentGroupInfo.reset();
dev@189 9096 }
dev@189 9097 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
dev@189 9098 currentTestCaseInfo.reset();
dev@189 9099 currentGroupInfo.reset();
dev@189 9100 currentTestRunInfo.reset();
dev@189 9101 }
dev@189 9102
dev@189 9103 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
dev@189 9104 // Don't do anything with this by default.
dev@189 9105 // It can optionally be overridden in the derived class.
dev@189 9106 }
dev@189 9107
dev@189 9108 Ptr<IConfig const> m_config;
dev@189 9109 std::ostream& stream;
dev@189 9110
dev@189 9111 LazyStat<TestRunInfo> currentTestRunInfo;
dev@189 9112 LazyStat<GroupInfo> currentGroupInfo;
dev@189 9113 LazyStat<TestCaseInfo> currentTestCaseInfo;
dev@189 9114
dev@189 9115 std::vector<SectionInfo> m_sectionStack;
dev@189 9116 ReporterPreferences m_reporterPrefs;
dev@189 9117 };
dev@189 9118
dev@189 9119 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
dev@189 9120 template<typename T, typename ChildNodeT>
dev@189 9121 struct Node : SharedImpl<> {
dev@189 9122 explicit Node( T const& _value ) : value( _value ) {}
dev@189 9123 virtual ~Node() {}
dev@189 9124
dev@189 9125 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
dev@189 9126 T value;
dev@189 9127 ChildNodes children;
dev@189 9128 };
dev@189 9129 struct SectionNode : SharedImpl<> {
dev@189 9130 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
dev@189 9131 virtual ~SectionNode();
dev@189 9132
dev@189 9133 bool operator == ( SectionNode const& other ) const {
dev@189 9134 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
dev@189 9135 }
dev@189 9136 bool operator == ( Ptr<SectionNode> const& other ) const {
dev@189 9137 return operator==( *other );
dev@189 9138 }
dev@189 9139
dev@189 9140 SectionStats stats;
dev@189 9141 typedef std::vector<Ptr<SectionNode> > ChildSections;
dev@189 9142 typedef std::vector<AssertionStats> Assertions;
dev@189 9143 ChildSections childSections;
dev@189 9144 Assertions assertions;
dev@189 9145 std::string stdOut;
dev@189 9146 std::string stdErr;
dev@189 9147 };
dev@189 9148
dev@189 9149 struct BySectionInfo {
dev@189 9150 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
dev@189 9151 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
dev@189 9152 bool operator() ( Ptr<SectionNode> const& node ) const {
dev@189 9153 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
dev@189 9154 }
dev@189 9155 private:
dev@189 9156 void operator=( BySectionInfo const& );
dev@189 9157 SectionInfo const& m_other;
dev@189 9158 };
dev@189 9159
dev@189 9160 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
dev@189 9161 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
dev@189 9162 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
dev@189 9163
dev@189 9164 CumulativeReporterBase( ReporterConfig const& _config )
dev@189 9165 : m_config( _config.fullConfig() ),
dev@189 9166 stream( _config.stream() )
dev@189 9167 {
dev@189 9168 m_reporterPrefs.shouldRedirectStdOut = false;
dev@189 9169 }
dev@189 9170 ~CumulativeReporterBase();
dev@189 9171
dev@189 9172 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
dev@189 9173 return m_reporterPrefs;
dev@189 9174 }
dev@189 9175
dev@189 9176 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
dev@189 9177 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
dev@189 9178
dev@189 9179 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
dev@189 9180
dev@189 9181 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
dev@189 9182 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
dev@189 9183 Ptr<SectionNode> node;
dev@189 9184 if( m_sectionStack.empty() ) {
dev@189 9185 if( !m_rootSection )
dev@189 9186 m_rootSection = new SectionNode( incompleteStats );
dev@189 9187 node = m_rootSection;
dev@189 9188 }
dev@189 9189 else {
dev@189 9190 SectionNode& parentNode = *m_sectionStack.back();
dev@189 9191 SectionNode::ChildSections::const_iterator it =
dev@189 9192 std::find_if( parentNode.childSections.begin(),
dev@189 9193 parentNode.childSections.end(),
dev@189 9194 BySectionInfo( sectionInfo ) );
dev@189 9195 if( it == parentNode.childSections.end() ) {
dev@189 9196 node = new SectionNode( incompleteStats );
dev@189 9197 parentNode.childSections.push_back( node );
dev@189 9198 }
dev@189 9199 else
dev@189 9200 node = *it;
dev@189 9201 }
dev@189 9202 m_sectionStack.push_back( node );
dev@189 9203 m_deepestSection = node;
dev@189 9204 }
dev@189 9205
dev@189 9206 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
dev@189 9207
dev@189 9208 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
dev@189 9209 assert( !m_sectionStack.empty() );
dev@189 9210 SectionNode& sectionNode = *m_sectionStack.back();
dev@189 9211 sectionNode.assertions.push_back( assertionStats );
dev@189 9212 // AssertionResult holds a pointer to a temporary DecomposedExpression,
dev@189 9213 // which getExpandedExpression() calls to build the expression string.
dev@189 9214 // Our section stack copy of the assertionResult will likely outlive the
dev@189 9215 // temporary, so it must be expanded or discarded now to avoid calling
dev@189 9216 // a destroyed object later.
dev@189 9217 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
dev@189 9218 return true;
dev@189 9219 }
dev@189 9220 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
dev@189 9221 assert( !m_sectionStack.empty() );
dev@189 9222 SectionNode& node = *m_sectionStack.back();
dev@189 9223 node.stats = sectionStats;
dev@189 9224 m_sectionStack.pop_back();
dev@189 9225 }
dev@189 9226 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
dev@189 9227 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
dev@189 9228 assert( m_sectionStack.size() == 0 );
dev@189 9229 node->children.push_back( m_rootSection );
dev@189 9230 m_testCases.push_back( node );
dev@189 9231 m_rootSection.reset();
dev@189 9232
dev@189 9233 assert( m_deepestSection );
dev@189 9234 m_deepestSection->stdOut = testCaseStats.stdOut;
dev@189 9235 m_deepestSection->stdErr = testCaseStats.stdErr;
dev@189 9236 }
dev@189 9237 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
dev@189 9238 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
dev@189 9239 node->children.swap( m_testCases );
dev@189 9240 m_testGroups.push_back( node );
dev@189 9241 }
dev@189 9242 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
dev@189 9243 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
dev@189 9244 node->children.swap( m_testGroups );
dev@189 9245 m_testRuns.push_back( node );
dev@189 9246 testRunEndedCumulative();
dev@189 9247 }
dev@189 9248 virtual void testRunEndedCumulative() = 0;
dev@189 9249
dev@189 9250 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
dev@189 9251
dev@189 9252 virtual void prepareExpandedExpression( AssertionResult& result ) const {
dev@189 9253 if( result.isOk() )
dev@189 9254 result.discardDecomposedExpression();
dev@189 9255 else
dev@189 9256 result.expandDecomposedExpression();
dev@189 9257 }
dev@189 9258
dev@189 9259 Ptr<IConfig const> m_config;
dev@189 9260 std::ostream& stream;
dev@189 9261 std::vector<AssertionStats> m_assertions;
dev@189 9262 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
dev@189 9263 std::vector<Ptr<TestCaseNode> > m_testCases;
dev@189 9264 std::vector<Ptr<TestGroupNode> > m_testGroups;
dev@189 9265
dev@189 9266 std::vector<Ptr<TestRunNode> > m_testRuns;
dev@189 9267
dev@189 9268 Ptr<SectionNode> m_rootSection;
dev@189 9269 Ptr<SectionNode> m_deepestSection;
dev@189 9270 std::vector<Ptr<SectionNode> > m_sectionStack;
dev@189 9271 ReporterPreferences m_reporterPrefs;
dev@189 9272
dev@189 9273 };
dev@189 9274
dev@189 9275 template<char C>
dev@189 9276 char const* getLineOfChars() {
dev@189 9277 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
dev@189 9278 if( !*line ) {
dev@189 9279 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
dev@189 9280 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
dev@189 9281 }
dev@189 9282 return line;
dev@189 9283 }
dev@189 9284
dev@189 9285 struct TestEventListenerBase : StreamingReporterBase {
dev@189 9286 TestEventListenerBase( ReporterConfig const& _config )
dev@189 9287 : StreamingReporterBase( _config )
dev@189 9288 {}
dev@189 9289
dev@189 9290 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
dev@189 9291 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
dev@189 9292 return false;
dev@189 9293 }
dev@189 9294 };
dev@189 9295
dev@189 9296 } // end namespace Catch
dev@189 9297
dev@189 9298 // #included from: ../internal/catch_reporter_registrars.hpp
dev@189 9299 #define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
dev@189 9300
dev@189 9301 namespace Catch {
dev@189 9302
dev@189 9303 template<typename T>
dev@189 9304 class LegacyReporterRegistrar {
dev@189 9305
dev@189 9306 class ReporterFactory : public IReporterFactory {
dev@189 9307 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
dev@189 9308 return new LegacyReporterAdapter( new T( config ) );
dev@189 9309 }
dev@189 9310
dev@189 9311 virtual std::string getDescription() const {
dev@189 9312 return T::getDescription();
dev@189 9313 }
dev@189 9314 };
dev@189 9315
dev@189 9316 public:
dev@189 9317
dev@189 9318 LegacyReporterRegistrar( std::string const& name ) {
dev@189 9319 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
dev@189 9320 }
dev@189 9321 };
dev@189 9322
dev@189 9323 template<typename T>
dev@189 9324 class ReporterRegistrar {
dev@189 9325
dev@189 9326 class ReporterFactory : public SharedImpl<IReporterFactory> {
dev@189 9327
dev@189 9328 // *** Please Note ***:
dev@189 9329 // - If you end up here looking at a compiler error because it's trying to register
dev@189 9330 // your custom reporter class be aware that the native reporter interface has changed
dev@189 9331 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
dev@189 9332 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
dev@189 9333 // However please consider updating to the new interface as the old one is now
dev@189 9334 // deprecated and will probably be removed quite soon!
dev@189 9335 // Please contact me via github if you have any questions at all about this.
dev@189 9336 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
dev@189 9337 // no idea who is actually using custom reporters at all (possibly no-one!).
dev@189 9338 // The new interface is designed to minimise exposure to interface changes in the future.
dev@189 9339 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
dev@189 9340 return new T( config );
dev@189 9341 }
dev@189 9342
dev@189 9343 virtual std::string getDescription() const {
dev@189 9344 return T::getDescription();
dev@189 9345 }
dev@189 9346 };
dev@189 9347
dev@189 9348 public:
dev@189 9349
dev@189 9350 ReporterRegistrar( std::string const& name ) {
dev@189 9351 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
dev@189 9352 }
dev@189 9353 };
dev@189 9354
dev@189 9355 template<typename T>
dev@189 9356 class ListenerRegistrar {
dev@189 9357
dev@189 9358 class ListenerFactory : public SharedImpl<IReporterFactory> {
dev@189 9359
dev@189 9360 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
dev@189 9361 return new T( config );
dev@189 9362 }
dev@189 9363 virtual std::string getDescription() const {
dev@189 9364 return std::string();
dev@189 9365 }
dev@189 9366 };
dev@189 9367
dev@189 9368 public:
dev@189 9369
dev@189 9370 ListenerRegistrar() {
dev@189 9371 getMutableRegistryHub().registerListener( new ListenerFactory() );
dev@189 9372 }
dev@189 9373 };
dev@189 9374 }
dev@189 9375
dev@189 9376 #define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
dev@189 9377 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
dev@189 9378
dev@189 9379 #define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
dev@189 9380 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
dev@189 9381
dev@189 9382 #define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
dev@189 9383 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
dev@189 9384
dev@189 9385 // #included from: ../internal/catch_xmlwriter.hpp
dev@189 9386 #define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
dev@189 9387
dev@189 9388 #include <sstream>
dev@189 9389 #include <string>
dev@189 9390 #include <vector>
dev@189 9391 #include <iomanip>
dev@189 9392
dev@189 9393 namespace Catch {
dev@189 9394
dev@189 9395 class XmlEncode {
dev@189 9396 public:
dev@189 9397 enum ForWhat { ForTextNodes, ForAttributes };
dev@189 9398
dev@189 9399 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
dev@189 9400 : m_str( str ),
dev@189 9401 m_forWhat( forWhat )
dev@189 9402 {}
dev@189 9403
dev@189 9404 void encodeTo( std::ostream& os ) const {
dev@189 9405
dev@189 9406 // Apostrophe escaping not necessary if we always use " to write attributes
dev@189 9407 // (see: http://www.w3.org/TR/xml/#syntax)
dev@189 9408
dev@189 9409 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
dev@189 9410 char c = m_str[i];
dev@189 9411 switch( c ) {
dev@189 9412 case '<': os << "&lt;"; break;
dev@189 9413 case '&': os << "&amp;"; break;
dev@189 9414
dev@189 9415 case '>':
dev@189 9416 // See: http://www.w3.org/TR/xml/#syntax
dev@189 9417 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
dev@189 9418 os << "&gt;";
dev@189 9419 else
dev@189 9420 os << c;
dev@189 9421 break;
dev@189 9422
dev@189 9423 case '\"':
dev@189 9424 if( m_forWhat == ForAttributes )
dev@189 9425 os << "&quot;";
dev@189 9426 else
dev@189 9427 os << c;
dev@189 9428 break;
dev@189 9429
dev@189 9430 default:
dev@189 9431 // Escape control chars - based on contribution by @espenalb in PR #465 and
dev@189 9432 // by @mrpi PR #588
dev@189 9433 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
dev@189 9434 os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
dev@189 9435 else
dev@189 9436 os << c;
dev@189 9437 }
dev@189 9438 }
dev@189 9439 }
dev@189 9440
dev@189 9441 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
dev@189 9442 xmlEncode.encodeTo( os );
dev@189 9443 return os;
dev@189 9444 }
dev@189 9445
dev@189 9446 private:
dev@189 9447 std::string m_str;
dev@189 9448 ForWhat m_forWhat;
dev@189 9449 };
dev@189 9450
dev@189 9451 class XmlWriter {
dev@189 9452 public:
dev@189 9453
dev@189 9454 class ScopedElement {
dev@189 9455 public:
dev@189 9456 ScopedElement( XmlWriter* writer )
dev@189 9457 : m_writer( writer )
dev@189 9458 {}
dev@189 9459
dev@189 9460 ScopedElement( ScopedElement const& other )
dev@189 9461 : m_writer( other.m_writer ){
dev@189 9462 other.m_writer = CATCH_NULL;
dev@189 9463 }
dev@189 9464
dev@189 9465 ~ScopedElement() {
dev@189 9466 if( m_writer )
dev@189 9467 m_writer->endElement();
dev@189 9468 }
dev@189 9469
dev@189 9470 ScopedElement& writeText( std::string const& text, bool indent = true ) {
dev@189 9471 m_writer->writeText( text, indent );
dev@189 9472 return *this;
dev@189 9473 }
dev@189 9474
dev@189 9475 template<typename T>
dev@189 9476 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
dev@189 9477 m_writer->writeAttribute( name, attribute );
dev@189 9478 return *this;
dev@189 9479 }
dev@189 9480
dev@189 9481 private:
dev@189 9482 mutable XmlWriter* m_writer;
dev@189 9483 };
dev@189 9484
dev@189 9485 XmlWriter()
dev@189 9486 : m_tagIsOpen( false ),
dev@189 9487 m_needsNewline( false ),
dev@189 9488 m_os( &Catch::cout() )
dev@189 9489 {
dev@189 9490 // We encode control characters, which requires
dev@189 9491 // XML 1.1
dev@189 9492 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
dev@189 9493 *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
dev@189 9494 }
dev@189 9495
dev@189 9496 XmlWriter( std::ostream& os )
dev@189 9497 : m_tagIsOpen( false ),
dev@189 9498 m_needsNewline( false ),
dev@189 9499 m_os( &os )
dev@189 9500 {
dev@189 9501 *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
dev@189 9502 }
dev@189 9503
dev@189 9504 ~XmlWriter() {
dev@189 9505 while( !m_tags.empty() )
dev@189 9506 endElement();
dev@189 9507 }
dev@189 9508
dev@189 9509 XmlWriter& startElement( std::string const& name ) {
dev@189 9510 ensureTagClosed();
dev@189 9511 newlineIfNecessary();
dev@189 9512 stream() << m_indent << '<' << name;
dev@189 9513 m_tags.push_back( name );
dev@189 9514 m_indent += " ";
dev@189 9515 m_tagIsOpen = true;
dev@189 9516 return *this;
dev@189 9517 }
dev@189 9518
dev@189 9519 ScopedElement scopedElement( std::string const& name ) {
dev@189 9520 ScopedElement scoped( this );
dev@189 9521 startElement( name );
dev@189 9522 return scoped;
dev@189 9523 }
dev@189 9524
dev@189 9525 XmlWriter& endElement() {
dev@189 9526 newlineIfNecessary();
dev@189 9527 m_indent = m_indent.substr( 0, m_indent.size()-2 );
dev@189 9528 if( m_tagIsOpen ) {
dev@189 9529 stream() << "/>";
dev@189 9530 m_tagIsOpen = false;
dev@189 9531 }
dev@189 9532 else {
dev@189 9533 stream() << m_indent << "</" << m_tags.back() << ">";
dev@189 9534 }
dev@189 9535 stream() << std::endl;
dev@189 9536 m_tags.pop_back();
dev@189 9537 return *this;
dev@189 9538 }
dev@189 9539
dev@189 9540 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
dev@189 9541 if( !name.empty() && !attribute.empty() )
dev@189 9542 stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
dev@189 9543 return *this;
dev@189 9544 }
dev@189 9545
dev@189 9546 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
dev@189 9547 stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
dev@189 9548 return *this;
dev@189 9549 }
dev@189 9550
dev@189 9551 template<typename T>
dev@189 9552 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
dev@189 9553 std::ostringstream oss;
dev@189 9554 oss << attribute;
dev@189 9555 return writeAttribute( name, oss.str() );
dev@189 9556 }
dev@189 9557
dev@189 9558 XmlWriter& writeText( std::string const& text, bool indent = true ) {
dev@189 9559 if( !text.empty() ){
dev@189 9560 bool tagWasOpen = m_tagIsOpen;
dev@189 9561 ensureTagClosed();
dev@189 9562 if( tagWasOpen && indent )
dev@189 9563 stream() << m_indent;
dev@189 9564 stream() << XmlEncode( text );
dev@189 9565 m_needsNewline = true;
dev@189 9566 }
dev@189 9567 return *this;
dev@189 9568 }
dev@189 9569
dev@189 9570 XmlWriter& writeComment( std::string const& text ) {
dev@189 9571 ensureTagClosed();
dev@189 9572 stream() << m_indent << "<!--" << text << "-->";
dev@189 9573 m_needsNewline = true;
dev@189 9574 return *this;
dev@189 9575 }
dev@189 9576
dev@189 9577 XmlWriter& writeBlankLine() {
dev@189 9578 ensureTagClosed();
dev@189 9579 stream() << '\n';
dev@189 9580 return *this;
dev@189 9581 }
dev@189 9582
dev@189 9583 void setStream( std::ostream& os ) {
dev@189 9584 m_os = &os;
dev@189 9585 }
dev@189 9586
dev@189 9587 private:
dev@189 9588 XmlWriter( XmlWriter const& );
dev@189 9589 void operator=( XmlWriter const& );
dev@189 9590
dev@189 9591 std::ostream& stream() {
dev@189 9592 return *m_os;
dev@189 9593 }
dev@189 9594
dev@189 9595 void ensureTagClosed() {
dev@189 9596 if( m_tagIsOpen ) {
dev@189 9597 stream() << ">\n";
dev@189 9598 m_tagIsOpen = false;
dev@189 9599 }
dev@189 9600 }
dev@189 9601
dev@189 9602 void newlineIfNecessary() {
dev@189 9603 if( m_needsNewline ) {
dev@189 9604 stream() << '\n';
dev@189 9605 m_needsNewline = false;
dev@189 9606 }
dev@189 9607 }
dev@189 9608
dev@189 9609 bool m_tagIsOpen;
dev@189 9610 bool m_needsNewline;
dev@189 9611 std::vector<std::string> m_tags;
dev@189 9612 std::string m_indent;
dev@189 9613 std::ostream* m_os;
dev@189 9614 };
dev@189 9615
dev@189 9616 }
dev@189 9617 // #included from: catch_reenable_warnings.h
dev@189 9618
dev@189 9619 #define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
dev@189 9620
dev@189 9621 #ifdef __clang__
dev@189 9622 # ifdef __ICC // icpc defines the __clang__ macro
dev@189 9623 # pragma warning(pop)
dev@189 9624 # else
dev@189 9625 # pragma clang diagnostic pop
dev@189 9626 # endif
dev@189 9627 #elif defined __GNUC__
dev@189 9628 # pragma GCC diagnostic pop
dev@189 9629 #endif
dev@189 9630
dev@189 9631
dev@189 9632 namespace Catch {
dev@189 9633 class XmlReporter : public StreamingReporterBase {
dev@189 9634 public:
dev@189 9635 XmlReporter( ReporterConfig const& _config )
dev@189 9636 : StreamingReporterBase( _config ),
dev@189 9637 m_xml(_config.stream()),
dev@189 9638 m_sectionDepth( 0 )
dev@189 9639 {
dev@189 9640 m_reporterPrefs.shouldRedirectStdOut = true;
dev@189 9641 }
dev@189 9642
dev@189 9643 virtual ~XmlReporter() CATCH_OVERRIDE;
dev@189 9644
dev@189 9645 static std::string getDescription() {
dev@189 9646 return "Reports test results as an XML document";
dev@189 9647 }
dev@189 9648
dev@189 9649 public: // StreamingReporterBase
dev@189 9650
dev@189 9651 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
dev@189 9652 StreamingReporterBase::noMatchingTestCases( s );
dev@189 9653 }
dev@189 9654
dev@189 9655 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
dev@189 9656 StreamingReporterBase::testRunStarting( testInfo );
dev@189 9657 m_xml.startElement( "Catch" );
dev@189 9658 if( !m_config->name().empty() )
dev@189 9659 m_xml.writeAttribute( "name", m_config->name() );
dev@189 9660 }
dev@189 9661
dev@189 9662 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
dev@189 9663 StreamingReporterBase::testGroupStarting( groupInfo );
dev@189 9664 m_xml.startElement( "Group" )
dev@189 9665 .writeAttribute( "name", groupInfo.name );
dev@189 9666 }
dev@189 9667
dev@189 9668 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
dev@189 9669 StreamingReporterBase::testCaseStarting(testInfo);
dev@189 9670 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
dev@189 9671
dev@189 9672 if ( m_config->showDurations() == ShowDurations::Always )
dev@189 9673 m_testCaseTimer.start();
dev@189 9674 }
dev@189 9675
dev@189 9676 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
dev@189 9677 StreamingReporterBase::sectionStarting( sectionInfo );
dev@189 9678 if( m_sectionDepth++ > 0 ) {
dev@189 9679 m_xml.startElement( "Section" )
dev@189 9680 .writeAttribute( "name", trim( sectionInfo.name ) )
dev@189 9681 .writeAttribute( "description", sectionInfo.description );
dev@189 9682 }
dev@189 9683 }
dev@189 9684
dev@189 9685 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
dev@189 9686
dev@189 9687 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
dev@189 9688 const AssertionResult& assertionResult = assertionStats.assertionResult;
dev@189 9689
dev@189 9690 // Print any info messages in <Info> tags.
dev@189 9691 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
dev@189 9692 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
dev@189 9693 it != itEnd;
dev@189 9694 ++it ) {
dev@189 9695 if( it->type == ResultWas::Info ) {
dev@189 9696 m_xml.scopedElement( "Info" )
dev@189 9697 .writeText( it->message );
dev@189 9698 } else if ( it->type == ResultWas::Warning ) {
dev@189 9699 m_xml.scopedElement( "Warning" )
dev@189 9700 .writeText( it->message );
dev@189 9701 }
dev@189 9702 }
dev@189 9703 }
dev@189 9704
dev@189 9705 // Drop out if result was successful but we're not printing them.
dev@189 9706 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
dev@189 9707 return true;
dev@189 9708
dev@189 9709 // Print the expression if there is one.
dev@189 9710 if( assertionResult.hasExpression() ) {
dev@189 9711 m_xml.startElement( "Expression" )
dev@189 9712 .writeAttribute( "success", assertionResult.succeeded() )
dev@189 9713 .writeAttribute( "type", assertionResult.getTestMacroName() )
dev@189 9714 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
dev@189 9715 .writeAttribute( "line", assertionResult.getSourceInfo().line );
dev@189 9716
dev@189 9717 m_xml.scopedElement( "Original" )
dev@189 9718 .writeText( assertionResult.getExpression() );
dev@189 9719 m_xml.scopedElement( "Expanded" )
dev@189 9720 .writeText( assertionResult.getExpandedExpression() );
dev@189 9721 }
dev@189 9722
dev@189 9723 // And... Print a result applicable to each result type.
dev@189 9724 switch( assertionResult.getResultType() ) {
dev@189 9725 case ResultWas::ThrewException:
dev@189 9726 m_xml.scopedElement( "Exception" )
dev@189 9727 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
dev@189 9728 .writeAttribute( "line", assertionResult.getSourceInfo().line )
dev@189 9729 .writeText( assertionResult.getMessage() );
dev@189 9730 break;
dev@189 9731 case ResultWas::FatalErrorCondition:
dev@189 9732 m_xml.scopedElement( "FatalErrorCondition" )
dev@189 9733 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
dev@189 9734 .writeAttribute( "line", assertionResult.getSourceInfo().line )
dev@189 9735 .writeText( assertionResult.getMessage() );
dev@189 9736 break;
dev@189 9737 case ResultWas::Info:
dev@189 9738 m_xml.scopedElement( "Info" )
dev@189 9739 .writeText( assertionResult.getMessage() );
dev@189 9740 break;
dev@189 9741 case ResultWas::Warning:
dev@189 9742 // Warning will already have been written
dev@189 9743 break;
dev@189 9744 case ResultWas::ExplicitFailure:
dev@189 9745 m_xml.scopedElement( "Failure" )
dev@189 9746 .writeText( assertionResult.getMessage() );
dev@189 9747 break;
dev@189 9748 default:
dev@189 9749 break;
dev@189 9750 }
dev@189 9751
dev@189 9752 if( assertionResult.hasExpression() )
dev@189 9753 m_xml.endElement();
dev@189 9754
dev@189 9755 return true;
dev@189 9756 }
dev@189 9757
dev@189 9758 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
dev@189 9759 StreamingReporterBase::sectionEnded( sectionStats );
dev@189 9760 if( --m_sectionDepth > 0 ) {
dev@189 9761 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
dev@189 9762 e.writeAttribute( "successes", sectionStats.assertions.passed );
dev@189 9763 e.writeAttribute( "failures", sectionStats.assertions.failed );
dev@189 9764 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
dev@189 9765
dev@189 9766 if ( m_config->showDurations() == ShowDurations::Always )
dev@189 9767 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
dev@189 9768
dev@189 9769 m_xml.endElement();
dev@189 9770 }
dev@189 9771 }
dev@189 9772
dev@189 9773 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
dev@189 9774 StreamingReporterBase::testCaseEnded( testCaseStats );
dev@189 9775 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
dev@189 9776 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
dev@189 9777
dev@189 9778 if ( m_config->showDurations() == ShowDurations::Always )
dev@189 9779 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
dev@189 9780
dev@189 9781 if( !testCaseStats.stdOut.empty() )
dev@189 9782 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
dev@189 9783 if( !testCaseStats.stdErr.empty() )
dev@189 9784 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
dev@189 9785
dev@189 9786 m_xml.endElement();
dev@189 9787 }
dev@189 9788
dev@189 9789 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
dev@189 9790 StreamingReporterBase::testGroupEnded( testGroupStats );
dev@189 9791 // TODO: Check testGroupStats.aborting and act accordingly.
dev@189 9792 m_xml.scopedElement( "OverallResults" )
dev@189 9793 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
dev@189 9794 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
dev@189 9795 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
dev@189 9796 m_xml.endElement();
dev@189 9797 }
dev@189 9798
dev@189 9799 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
dev@189 9800 StreamingReporterBase::testRunEnded( testRunStats );
dev@189 9801 m_xml.scopedElement( "OverallResults" )
dev@189 9802 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
dev@189 9803 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
dev@189 9804 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
dev@189 9805 m_xml.endElement();
dev@189 9806 }
dev@189 9807
dev@189 9808 private:
dev@189 9809 Timer m_testCaseTimer;
dev@189 9810 XmlWriter m_xml;
dev@189 9811 int m_sectionDepth;
dev@189 9812 };
dev@189 9813
dev@189 9814 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
dev@189 9815
dev@189 9816 } // end namespace Catch
dev@189 9817
dev@189 9818 // #included from: ../reporters/catch_reporter_junit.hpp
dev@189 9819 #define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
dev@189 9820
dev@189 9821 #include <assert.h>
dev@189 9822
dev@189 9823 namespace Catch {
dev@189 9824
dev@189 9825 namespace {
dev@189 9826 std::string getCurrentTimestamp() {
dev@189 9827 // Beware, this is not reentrant because of backward compatibility issues
dev@189 9828 // Also, UTC only, again because of backward compatibility (%z is C++11)
dev@189 9829 time_t rawtime;
dev@189 9830 std::time(&rawtime);
dev@189 9831 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
dev@189 9832
dev@189 9833 #ifdef _MSC_VER
dev@189 9834 std::tm timeInfo = {};
dev@189 9835 gmtime_s(&timeInfo, &rawtime);
dev@189 9836 #else
dev@189 9837 std::tm* timeInfo;
dev@189 9838 timeInfo = std::gmtime(&rawtime);
dev@189 9839 #endif
dev@189 9840
dev@189 9841 char timeStamp[timeStampSize];
dev@189 9842 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
dev@189 9843
dev@189 9844 #ifdef _MSC_VER
dev@189 9845 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
dev@189 9846 #else
dev@189 9847 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
dev@189 9848 #endif
dev@189 9849 return std::string(timeStamp);
dev@189 9850 }
dev@189 9851
dev@189 9852 }
dev@189 9853
dev@189 9854 class JunitReporter : public CumulativeReporterBase {
dev@189 9855 public:
dev@189 9856 JunitReporter( ReporterConfig const& _config )
dev@189 9857 : CumulativeReporterBase( _config ),
dev@189 9858 xml( _config.stream() )
dev@189 9859 {
dev@189 9860 m_reporterPrefs.shouldRedirectStdOut = true;
dev@189 9861 }
dev@189 9862
dev@189 9863 virtual ~JunitReporter() CATCH_OVERRIDE;
dev@189 9864
dev@189 9865 static std::string getDescription() {
dev@189 9866 return "Reports test results in an XML format that looks like Ant's junitreport target";
dev@189 9867 }
dev@189 9868
dev@189 9869 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
dev@189 9870
dev@189 9871 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
dev@189 9872 CumulativeReporterBase::testRunStarting( runInfo );
dev@189 9873 xml.startElement( "testsuites" );
dev@189 9874 }
dev@189 9875
dev@189 9876 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
dev@189 9877 suiteTimer.start();
dev@189 9878 stdOutForSuite.str("");
dev@189 9879 stdErrForSuite.str("");
dev@189 9880 unexpectedExceptions = 0;
dev@189 9881 CumulativeReporterBase::testGroupStarting( groupInfo );
dev@189 9882 }
dev@189 9883
dev@189 9884 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
dev@189 9885 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
dev@189 9886 unexpectedExceptions++;
dev@189 9887 return CumulativeReporterBase::assertionEnded( assertionStats );
dev@189 9888 }
dev@189 9889
dev@189 9890 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
dev@189 9891 stdOutForSuite << testCaseStats.stdOut;
dev@189 9892 stdErrForSuite << testCaseStats.stdErr;
dev@189 9893 CumulativeReporterBase::testCaseEnded( testCaseStats );
dev@189 9894 }
dev@189 9895
dev@189 9896 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
dev@189 9897 double suiteTime = suiteTimer.getElapsedSeconds();
dev@189 9898 CumulativeReporterBase::testGroupEnded( testGroupStats );
dev@189 9899 writeGroup( *m_testGroups.back(), suiteTime );
dev@189 9900 }
dev@189 9901
dev@189 9902 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
dev@189 9903 xml.endElement();
dev@189 9904 }
dev@189 9905
dev@189 9906 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
dev@189 9907 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
dev@189 9908 TestGroupStats const& stats = groupNode.value;
dev@189 9909 xml.writeAttribute( "name", stats.groupInfo.name );
dev@189 9910 xml.writeAttribute( "errors", unexpectedExceptions );
dev@189 9911 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
dev@189 9912 xml.writeAttribute( "tests", stats.totals.assertions.total() );
dev@189 9913 xml.writeAttribute( "hostname", "tbd" ); // !TBD
dev@189 9914 if( m_config->showDurations() == ShowDurations::Never )
dev@189 9915 xml.writeAttribute( "time", "" );
dev@189 9916 else
dev@189 9917 xml.writeAttribute( "time", suiteTime );
dev@189 9918 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
dev@189 9919
dev@189 9920 // Write test cases
dev@189 9921 for( TestGroupNode::ChildNodes::const_iterator
dev@189 9922 it = groupNode.children.begin(), itEnd = groupNode.children.end();
dev@189 9923 it != itEnd;
dev@189 9924 ++it )
dev@189 9925 writeTestCase( **it );
dev@189 9926
dev@189 9927 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
dev@189 9928 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
dev@189 9929 }
dev@189 9930
dev@189 9931 void writeTestCase( TestCaseNode const& testCaseNode ) {
dev@189 9932 TestCaseStats const& stats = testCaseNode.value;
dev@189 9933
dev@189 9934 // All test cases have exactly one section - which represents the
dev@189 9935 // test case itself. That section may have 0-n nested sections
dev@189 9936 assert( testCaseNode.children.size() == 1 );
dev@189 9937 SectionNode const& rootSection = *testCaseNode.children.front();
dev@189 9938
dev@189 9939 std::string className = stats.testInfo.className;
dev@189 9940
dev@189 9941 if( className.empty() ) {
dev@189 9942 if( rootSection.childSections.empty() )
dev@189 9943 className = "global";
dev@189 9944 }
dev@189 9945 writeSection( className, "", rootSection );
dev@189 9946 }
dev@189 9947
dev@189 9948 void writeSection( std::string const& className,
dev@189 9949 std::string const& rootName,
dev@189 9950 SectionNode const& sectionNode ) {
dev@189 9951 std::string name = trim( sectionNode.stats.sectionInfo.name );
dev@189 9952 if( !rootName.empty() )
dev@189 9953 name = rootName + '/' + name;
dev@189 9954
dev@189 9955 if( !sectionNode.assertions.empty() ||
dev@189 9956 !sectionNode.stdOut.empty() ||
dev@189 9957 !sectionNode.stdErr.empty() ) {
dev@189 9958 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
dev@189 9959 if( className.empty() ) {
dev@189 9960 xml.writeAttribute( "classname", name );
dev@189 9961 xml.writeAttribute( "name", "root" );
dev@189 9962 }
dev@189 9963 else {
dev@189 9964 xml.writeAttribute( "classname", className );
dev@189 9965 xml.writeAttribute( "name", name );
dev@189 9966 }
dev@189 9967 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
dev@189 9968
dev@189 9969 writeAssertions( sectionNode );
dev@189 9970
dev@189 9971 if( !sectionNode.stdOut.empty() )
dev@189 9972 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
dev@189 9973 if( !sectionNode.stdErr.empty() )
dev@189 9974 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
dev@189 9975 }
dev@189 9976 for( SectionNode::ChildSections::const_iterator
dev@189 9977 it = sectionNode.childSections.begin(),
dev@189 9978 itEnd = sectionNode.childSections.end();
dev@189 9979 it != itEnd;
dev@189 9980 ++it )
dev@189 9981 if( className.empty() )
dev@189 9982 writeSection( name, "", **it );
dev@189 9983 else
dev@189 9984 writeSection( className, name, **it );
dev@189 9985 }
dev@189 9986
dev@189 9987 void writeAssertions( SectionNode const& sectionNode ) {
dev@189 9988 for( SectionNode::Assertions::const_iterator
dev@189 9989 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
dev@189 9990 it != itEnd;
dev@189 9991 ++it )
dev@189 9992 writeAssertion( *it );
dev@189 9993 }
dev@189 9994 void writeAssertion( AssertionStats const& stats ) {
dev@189 9995 AssertionResult const& result = stats.assertionResult;
dev@189 9996 if( !result.isOk() ) {
dev@189 9997 std::string elementName;
dev@189 9998 switch( result.getResultType() ) {
dev@189 9999 case ResultWas::ThrewException:
dev@189 10000 case ResultWas::FatalErrorCondition:
dev@189 10001 elementName = "error";
dev@189 10002 break;
dev@189 10003 case ResultWas::ExplicitFailure:
dev@189 10004 elementName = "failure";
dev@189 10005 break;
dev@189 10006 case ResultWas::ExpressionFailed:
dev@189 10007 elementName = "failure";
dev@189 10008 break;
dev@189 10009 case ResultWas::DidntThrowException:
dev@189 10010 elementName = "failure";
dev@189 10011 break;
dev@189 10012
dev@189 10013 // We should never see these here:
dev@189 10014 case ResultWas::Info:
dev@189 10015 case ResultWas::Warning:
dev@189 10016 case ResultWas::Ok:
dev@189 10017 case ResultWas::Unknown:
dev@189 10018 case ResultWas::FailureBit:
dev@189 10019 case ResultWas::Exception:
dev@189 10020 elementName = "internalError";
dev@189 10021 break;
dev@189 10022 }
dev@189 10023
dev@189 10024 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
dev@189 10025
dev@189 10026 xml.writeAttribute( "message", result.getExpandedExpression() );
dev@189 10027 xml.writeAttribute( "type", result.getTestMacroName() );
dev@189 10028
dev@189 10029 std::ostringstream oss;
dev@189 10030 if( !result.getMessage().empty() )
dev@189 10031 oss << result.getMessage() << '\n';
dev@189 10032 for( std::vector<MessageInfo>::const_iterator
dev@189 10033 it = stats.infoMessages.begin(),
dev@189 10034 itEnd = stats.infoMessages.end();
dev@189 10035 it != itEnd;
dev@189 10036 ++it )
dev@189 10037 if( it->type == ResultWas::Info )
dev@189 10038 oss << it->message << '\n';
dev@189 10039
dev@189 10040 oss << "at " << result.getSourceInfo();
dev@189 10041 xml.writeText( oss.str(), false );
dev@189 10042 }
dev@189 10043 }
dev@189 10044
dev@189 10045 XmlWriter xml;
dev@189 10046 Timer suiteTimer;
dev@189 10047 std::ostringstream stdOutForSuite;
dev@189 10048 std::ostringstream stdErrForSuite;
dev@189 10049 unsigned int unexpectedExceptions;
dev@189 10050 };
dev@189 10051
dev@189 10052 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
dev@189 10053
dev@189 10054 } // end namespace Catch
dev@189 10055
dev@189 10056 // #included from: ../reporters/catch_reporter_console.hpp
dev@189 10057 #define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
dev@189 10058
dev@189 10059 namespace Catch {
dev@189 10060
dev@189 10061 struct ConsoleReporter : StreamingReporterBase {
dev@189 10062 ConsoleReporter( ReporterConfig const& _config )
dev@189 10063 : StreamingReporterBase( _config ),
dev@189 10064 m_headerPrinted( false )
dev@189 10065 {}
dev@189 10066
dev@189 10067 virtual ~ConsoleReporter() CATCH_OVERRIDE;
dev@189 10068 static std::string getDescription() {
dev@189 10069 return "Reports test results as plain lines of text";
dev@189 10070 }
dev@189 10071
dev@189 10072 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
dev@189 10073 stream << "No test cases matched '" << spec << '\'' << std::endl;
dev@189 10074 }
dev@189 10075
dev@189 10076 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
dev@189 10077 }
dev@189 10078
dev@189 10079 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
dev@189 10080 AssertionResult const& result = _assertionStats.assertionResult;
dev@189 10081
dev@189 10082 bool printInfoMessages = true;
dev@189 10083
dev@189 10084 // Drop out if result was successful and we're not printing those
dev@189 10085 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
dev@189 10086 if( result.getResultType() != ResultWas::Warning )
dev@189 10087 return false;
dev@189 10088 printInfoMessages = false;
dev@189 10089 }
dev@189 10090
dev@189 10091 lazyPrint();
dev@189 10092
dev@189 10093 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
dev@189 10094 printer.print();
dev@189 10095 stream << std::endl;
dev@189 10096 return true;
dev@189 10097 }
dev@189 10098
dev@189 10099 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
dev@189 10100 m_headerPrinted = false;
dev@189 10101 StreamingReporterBase::sectionStarting( _sectionInfo );
dev@189 10102 }
dev@189 10103 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
dev@189 10104 if( _sectionStats.missingAssertions ) {
dev@189 10105 lazyPrint();
dev@189 10106 Colour colour( Colour::ResultError );
dev@189 10107 if( m_sectionStack.size() > 1 )
dev@189 10108 stream << "\nNo assertions in section";
dev@189 10109 else
dev@189 10110 stream << "\nNo assertions in test case";
dev@189 10111 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
dev@189 10112 }
dev@189 10113 if( m_headerPrinted ) {
dev@189 10114 if( m_config->showDurations() == ShowDurations::Always )
dev@189 10115 stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
dev@189 10116 m_headerPrinted = false;
dev@189 10117 }
dev@189 10118 else {
dev@189 10119 if( m_config->showDurations() == ShowDurations::Always )
dev@189 10120 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
dev@189 10121 }
dev@189 10122 StreamingReporterBase::sectionEnded( _sectionStats );
dev@189 10123 }
dev@189 10124
dev@189 10125 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
dev@189 10126 StreamingReporterBase::testCaseEnded( _testCaseStats );
dev@189 10127 m_headerPrinted = false;
dev@189 10128 }
dev@189 10129 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
dev@189 10130 if( currentGroupInfo.used ) {
dev@189 10131 printSummaryDivider();
dev@189 10132 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
dev@189 10133 printTotals( _testGroupStats.totals );
dev@189 10134 stream << '\n' << std::endl;
dev@189 10135 }
dev@189 10136 StreamingReporterBase::testGroupEnded( _testGroupStats );
dev@189 10137 }
dev@189 10138 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
dev@189 10139 printTotalsDivider( _testRunStats.totals );
dev@189 10140 printTotals( _testRunStats.totals );
dev@189 10141 stream << std::endl;
dev@189 10142 StreamingReporterBase::testRunEnded( _testRunStats );
dev@189 10143 }
dev@189 10144
dev@189 10145 private:
dev@189 10146
dev@189 10147 class AssertionPrinter {
dev@189 10148 void operator= ( AssertionPrinter const& );
dev@189 10149 public:
dev@189 10150 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
dev@189 10151 : stream( _stream ),
dev@189 10152 stats( _stats ),
dev@189 10153 result( _stats.assertionResult ),
dev@189 10154 colour( Colour::None ),
dev@189 10155 message( result.getMessage() ),
dev@189 10156 messages( _stats.infoMessages ),
dev@189 10157 printInfoMessages( _printInfoMessages )
dev@189 10158 {
dev@189 10159 switch( result.getResultType() ) {
dev@189 10160 case ResultWas::Ok:
dev@189 10161 colour = Colour::Success;
dev@189 10162 passOrFail = "PASSED";
dev@189 10163 //if( result.hasMessage() )
dev@189 10164 if( _stats.infoMessages.size() == 1 )
dev@189 10165 messageLabel = "with message";
dev@189 10166 if( _stats.infoMessages.size() > 1 )
dev@189 10167 messageLabel = "with messages";
dev@189 10168 break;
dev@189 10169 case ResultWas::ExpressionFailed:
dev@189 10170 if( result.isOk() ) {
dev@189 10171 colour = Colour::Success;
dev@189 10172 passOrFail = "FAILED - but was ok";
dev@189 10173 }
dev@189 10174 else {
dev@189 10175 colour = Colour::Error;
dev@189 10176 passOrFail = "FAILED";
dev@189 10177 }
dev@189 10178 if( _stats.infoMessages.size() == 1 )
dev@189 10179 messageLabel = "with message";
dev@189 10180 if( _stats.infoMessages.size() > 1 )
dev@189 10181 messageLabel = "with messages";
dev@189 10182 break;
dev@189 10183 case ResultWas::ThrewException:
dev@189 10184 colour = Colour::Error;
dev@189 10185 passOrFail = "FAILED";
dev@189 10186 messageLabel = "due to unexpected exception with message";
dev@189 10187 break;
dev@189 10188 case ResultWas::FatalErrorCondition:
dev@189 10189 colour = Colour::Error;
dev@189 10190 passOrFail = "FAILED";
dev@189 10191 messageLabel = "due to a fatal error condition";
dev@189 10192 break;
dev@189 10193 case ResultWas::DidntThrowException:
dev@189 10194 colour = Colour::Error;
dev@189 10195 passOrFail = "FAILED";
dev@189 10196 messageLabel = "because no exception was thrown where one was expected";
dev@189 10197 break;
dev@189 10198 case ResultWas::Info:
dev@189 10199 messageLabel = "info";
dev@189 10200 break;
dev@189 10201 case ResultWas::Warning:
dev@189 10202 messageLabel = "warning";
dev@189 10203 break;
dev@189 10204 case ResultWas::ExplicitFailure:
dev@189 10205 passOrFail = "FAILED";
dev@189 10206 colour = Colour::Error;
dev@189 10207 if( _stats.infoMessages.size() == 1 )
dev@189 10208 messageLabel = "explicitly with message";
dev@189 10209 if( _stats.infoMessages.size() > 1 )
dev@189 10210 messageLabel = "explicitly with messages";
dev@189 10211 break;
dev@189 10212 // These cases are here to prevent compiler warnings
dev@189 10213 case ResultWas::Unknown:
dev@189 10214 case ResultWas::FailureBit:
dev@189 10215 case ResultWas::Exception:
dev@189 10216 passOrFail = "** internal error **";
dev@189 10217 colour = Colour::Error;
dev@189 10218 break;
dev@189 10219 }
dev@189 10220 }
dev@189 10221
dev@189 10222 void print() const {
dev@189 10223 printSourceInfo();
dev@189 10224 if( stats.totals.assertions.total() > 0 ) {
dev@189 10225 if( result.isOk() )
dev@189 10226 stream << '\n';
dev@189 10227 printResultType();
dev@189 10228 printOriginalExpression();
dev@189 10229 printReconstructedExpression();
dev@189 10230 }
dev@189 10231 else {
dev@189 10232 stream << '\n';
dev@189 10233 }
dev@189 10234 printMessage();
dev@189 10235 }
dev@189 10236
dev@189 10237 private:
dev@189 10238 void printResultType() const {
dev@189 10239 if( !passOrFail.empty() ) {
dev@189 10240 Colour colourGuard( colour );
dev@189 10241 stream << passOrFail << ":\n";
dev@189 10242 }
dev@189 10243 }
dev@189 10244 void printOriginalExpression() const {
dev@189 10245 if( result.hasExpression() ) {
dev@189 10246 Colour colourGuard( Colour::OriginalExpression );
dev@189 10247 stream << " ";
dev@189 10248 stream << result.getExpressionInMacro();
dev@189 10249 stream << '\n';
dev@189 10250 }
dev@189 10251 }
dev@189 10252 void printReconstructedExpression() const {
dev@189 10253 if( result.hasExpandedExpression() ) {
dev@189 10254 stream << "with expansion:\n";
dev@189 10255 Colour colourGuard( Colour::ReconstructedExpression );
dev@189 10256 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
dev@189 10257 }
dev@189 10258 }
dev@189 10259 void printMessage() const {
dev@189 10260 if( !messageLabel.empty() )
dev@189 10261 stream << messageLabel << ':' << '\n';
dev@189 10262 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
dev@189 10263 it != itEnd;
dev@189 10264 ++it ) {
dev@189 10265 // If this assertion is a warning ignore any INFO messages
dev@189 10266 if( printInfoMessages || it->type != ResultWas::Info )
dev@189 10267 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
dev@189 10268 }
dev@189 10269 }
dev@189 10270 void printSourceInfo() const {
dev@189 10271 Colour colourGuard( Colour::FileName );
dev@189 10272 stream << result.getSourceInfo() << ": ";
dev@189 10273 }
dev@189 10274
dev@189 10275 std::ostream& stream;
dev@189 10276 AssertionStats const& stats;
dev@189 10277 AssertionResult const& result;
dev@189 10278 Colour::Code colour;
dev@189 10279 std::string passOrFail;
dev@189 10280 std::string messageLabel;
dev@189 10281 std::string message;
dev@189 10282 std::vector<MessageInfo> messages;
dev@189 10283 bool printInfoMessages;
dev@189 10284 };
dev@189 10285
dev@189 10286 void lazyPrint() {
dev@189 10287
dev@189 10288 if( !currentTestRunInfo.used )
dev@189 10289 lazyPrintRunInfo();
dev@189 10290 if( !currentGroupInfo.used )
dev@189 10291 lazyPrintGroupInfo();
dev@189 10292
dev@189 10293 if( !m_headerPrinted ) {
dev@189 10294 printTestCaseAndSectionHeader();
dev@189 10295 m_headerPrinted = true;
dev@189 10296 }
dev@189 10297 }
dev@189 10298 void lazyPrintRunInfo() {
dev@189 10299 stream << '\n' << getLineOfChars<'~'>() << '\n';
dev@189 10300 Colour colour( Colour::SecondaryText );
dev@189 10301 stream << currentTestRunInfo->name
dev@189 10302 << " is a Catch v" << libraryVersion << " host application.\n"
dev@189 10303 << "Run with -? for options\n\n";
dev@189 10304
dev@189 10305 if( m_config->rngSeed() != 0 )
dev@189 10306 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
dev@189 10307
dev@189 10308 currentTestRunInfo.used = true;
dev@189 10309 }
dev@189 10310 void lazyPrintGroupInfo() {
dev@189 10311 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
dev@189 10312 printClosedHeader( "Group: " + currentGroupInfo->name );
dev@189 10313 currentGroupInfo.used = true;
dev@189 10314 }
dev@189 10315 }
dev@189 10316 void printTestCaseAndSectionHeader() {
dev@189 10317 assert( !m_sectionStack.empty() );
dev@189 10318 printOpenHeader( currentTestCaseInfo->name );
dev@189 10319
dev@189 10320 if( m_sectionStack.size() > 1 ) {
dev@189 10321 Colour colourGuard( Colour::Headers );
dev@189 10322
dev@189 10323 std::vector<SectionInfo>::const_iterator
dev@189 10324 it = m_sectionStack.begin()+1, // Skip first section (test case)
dev@189 10325 itEnd = m_sectionStack.end();
dev@189 10326 for( ; it != itEnd; ++it )
dev@189 10327 printHeaderString( it->name, 2 );
dev@189 10328 }
dev@189 10329
dev@189 10330 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
dev@189 10331
dev@189 10332 if( !lineInfo.empty() ){
dev@189 10333 stream << getLineOfChars<'-'>() << '\n';
dev@189 10334 Colour colourGuard( Colour::FileName );
dev@189 10335 stream << lineInfo << '\n';
dev@189 10336 }
dev@189 10337 stream << getLineOfChars<'.'>() << '\n' << std::endl;
dev@189 10338 }
dev@189 10339
dev@189 10340 void printClosedHeader( std::string const& _name ) {
dev@189 10341 printOpenHeader( _name );
dev@189 10342 stream << getLineOfChars<'.'>() << '\n';
dev@189 10343 }
dev@189 10344 void printOpenHeader( std::string const& _name ) {
dev@189 10345 stream << getLineOfChars<'-'>() << '\n';
dev@189 10346 {
dev@189 10347 Colour colourGuard( Colour::Headers );
dev@189 10348 printHeaderString( _name );
dev@189 10349 }
dev@189 10350 }
dev@189 10351
dev@189 10352 // if string has a : in first line will set indent to follow it on
dev@189 10353 // subsequent lines
dev@189 10354 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
dev@189 10355 std::size_t i = _string.find( ": " );
dev@189 10356 if( i != std::string::npos )
dev@189 10357 i+=2;
dev@189 10358 else
dev@189 10359 i = 0;
dev@189 10360 stream << Text( _string, TextAttributes()
dev@189 10361 .setIndent( indent+i)
dev@189 10362 .setInitialIndent( indent ) ) << '\n';
dev@189 10363 }
dev@189 10364
dev@189 10365 struct SummaryColumn {
dev@189 10366
dev@189 10367 SummaryColumn( std::string const& _label, Colour::Code _colour )
dev@189 10368 : label( _label ),
dev@189 10369 colour( _colour )
dev@189 10370 {}
dev@189 10371 SummaryColumn addRow( std::size_t count ) {
dev@189 10372 std::ostringstream oss;
dev@189 10373 oss << count;
dev@189 10374 std::string row = oss.str();
dev@189 10375 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
dev@189 10376 while( it->size() < row.size() )
dev@189 10377 *it = ' ' + *it;
dev@189 10378 while( it->size() > row.size() )
dev@189 10379 row = ' ' + row;
dev@189 10380 }
dev@189 10381 rows.push_back( row );
dev@189 10382 return *this;
dev@189 10383 }
dev@189 10384
dev@189 10385 std::string label;
dev@189 10386 Colour::Code colour;
dev@189 10387 std::vector<std::string> rows;
dev@189 10388
dev@189 10389 };
dev@189 10390
dev@189 10391 void printTotals( Totals const& totals ) {
dev@189 10392 if( totals.testCases.total() == 0 ) {
dev@189 10393 stream << Colour( Colour::Warning ) << "No tests ran\n";
dev@189 10394 }
dev@189 10395 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
dev@189 10396 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
dev@189 10397 stream << " ("
dev@189 10398 << pluralise( totals.assertions.passed, "assertion" ) << " in "
dev@189 10399 << pluralise( totals.testCases.passed, "test case" ) << ')'
dev@189 10400 << '\n';
dev@189 10401 }
dev@189 10402 else {
dev@189 10403
dev@189 10404 std::vector<SummaryColumn> columns;
dev@189 10405 columns.push_back( SummaryColumn( "", Colour::None )
dev@189 10406 .addRow( totals.testCases.total() )
dev@189 10407 .addRow( totals.assertions.total() ) );
dev@189 10408 columns.push_back( SummaryColumn( "passed", Colour::Success )
dev@189 10409 .addRow( totals.testCases.passed )
dev@189 10410 .addRow( totals.assertions.passed ) );
dev@189 10411 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
dev@189 10412 .addRow( totals.testCases.failed )
dev@189 10413 .addRow( totals.assertions.failed ) );
dev@189 10414 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
dev@189 10415 .addRow( totals.testCases.failedButOk )
dev@189 10416 .addRow( totals.assertions.failedButOk ) );
dev@189 10417
dev@189 10418 printSummaryRow( "test cases", columns, 0 );
dev@189 10419 printSummaryRow( "assertions", columns, 1 );
dev@189 10420 }
dev@189 10421 }
dev@189 10422 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
dev@189 10423 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
dev@189 10424 std::string value = it->rows[row];
dev@189 10425 if( it->label.empty() ) {
dev@189 10426 stream << label << ": ";
dev@189 10427 if( value != "0" )
dev@189 10428 stream << value;
dev@189 10429 else
dev@189 10430 stream << Colour( Colour::Warning ) << "- none -";
dev@189 10431 }
dev@189 10432 else if( value != "0" ) {
dev@189 10433 stream << Colour( Colour::LightGrey ) << " | ";
dev@189 10434 stream << Colour( it->colour )
dev@189 10435 << value << ' ' << it->label;
dev@189 10436 }
dev@189 10437 }
dev@189 10438 stream << '\n';
dev@189 10439 }
dev@189 10440
dev@189 10441 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
dev@189 10442 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
dev@189 10443 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
dev@189 10444 }
dev@189 10445 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
dev@189 10446 if( i > j && i > k )
dev@189 10447 return i;
dev@189 10448 else if( j > k )
dev@189 10449 return j;
dev@189 10450 else
dev@189 10451 return k;
dev@189 10452 }
dev@189 10453
dev@189 10454 void printTotalsDivider( Totals const& totals ) {
dev@189 10455 if( totals.testCases.total() > 0 ) {
dev@189 10456 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
dev@189 10457 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
dev@189 10458 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
dev@189 10459 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
dev@189 10460 findMax( failedRatio, failedButOkRatio, passedRatio )++;
dev@189 10461 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
dev@189 10462 findMax( failedRatio, failedButOkRatio, passedRatio )--;
dev@189 10463
dev@189 10464 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
dev@189 10465 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
dev@189 10466 if( totals.testCases.allPassed() )
dev@189 10467 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
dev@189 10468 else
dev@189 10469 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
dev@189 10470 }
dev@189 10471 else {
dev@189 10472 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
dev@189 10473 }
dev@189 10474 stream << '\n';
dev@189 10475 }
dev@189 10476 void printSummaryDivider() {
dev@189 10477 stream << getLineOfChars<'-'>() << '\n';
dev@189 10478 }
dev@189 10479
dev@189 10480 private:
dev@189 10481 bool m_headerPrinted;
dev@189 10482 };
dev@189 10483
dev@189 10484 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
dev@189 10485
dev@189 10486 } // end namespace Catch
dev@189 10487
dev@189 10488 // #included from: ../reporters/catch_reporter_compact.hpp
dev@189 10489 #define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
dev@189 10490
dev@189 10491 namespace Catch {
dev@189 10492
dev@189 10493 struct CompactReporter : StreamingReporterBase {
dev@189 10494
dev@189 10495 CompactReporter( ReporterConfig const& _config )
dev@189 10496 : StreamingReporterBase( _config )
dev@189 10497 {}
dev@189 10498
dev@189 10499 virtual ~CompactReporter();
dev@189 10500
dev@189 10501 static std::string getDescription() {
dev@189 10502 return "Reports test results on a single line, suitable for IDEs";
dev@189 10503 }
dev@189 10504
dev@189 10505 virtual ReporterPreferences getPreferences() const {
dev@189 10506 ReporterPreferences prefs;
dev@189 10507 prefs.shouldRedirectStdOut = false;
dev@189 10508 return prefs;
dev@189 10509 }
dev@189 10510
dev@189 10511 virtual void noMatchingTestCases( std::string const& spec ) {
dev@189 10512 stream << "No test cases matched '" << spec << '\'' << std::endl;
dev@189 10513 }
dev@189 10514
dev@189 10515 virtual void assertionStarting( AssertionInfo const& ) {
dev@189 10516 }
dev@189 10517
dev@189 10518 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
dev@189 10519 AssertionResult const& result = _assertionStats.assertionResult;
dev@189 10520
dev@189 10521 bool printInfoMessages = true;
dev@189 10522
dev@189 10523 // Drop out if result was successful and we're not printing those
dev@189 10524 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
dev@189 10525 if( result.getResultType() != ResultWas::Warning )
dev@189 10526 return false;
dev@189 10527 printInfoMessages = false;
dev@189 10528 }
dev@189 10529
dev@189 10530 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
dev@189 10531 printer.print();
dev@189 10532
dev@189 10533 stream << std::endl;
dev@189 10534 return true;
dev@189 10535 }
dev@189 10536
dev@189 10537 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
dev@189 10538 printTotals( _testRunStats.totals );
dev@189 10539 stream << '\n' << std::endl;
dev@189 10540 StreamingReporterBase::testRunEnded( _testRunStats );
dev@189 10541 }
dev@189 10542
dev@189 10543 private:
dev@189 10544 class AssertionPrinter {
dev@189 10545 void operator= ( AssertionPrinter const& );
dev@189 10546 public:
dev@189 10547 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
dev@189 10548 : stream( _stream )
dev@189 10549 , stats( _stats )
dev@189 10550 , result( _stats.assertionResult )
dev@189 10551 , messages( _stats.infoMessages )
dev@189 10552 , itMessage( _stats.infoMessages.begin() )
dev@189 10553 , printInfoMessages( _printInfoMessages )
dev@189 10554 {}
dev@189 10555
dev@189 10556 void print() {
dev@189 10557 printSourceInfo();
dev@189 10558
dev@189 10559 itMessage = messages.begin();
dev@189 10560
dev@189 10561 switch( result.getResultType() ) {
dev@189 10562 case ResultWas::Ok:
dev@189 10563 printResultType( Colour::ResultSuccess, passedString() );
dev@189 10564 printOriginalExpression();
dev@189 10565 printReconstructedExpression();
dev@189 10566 if ( ! result.hasExpression() )
dev@189 10567 printRemainingMessages( Colour::None );
dev@189 10568 else
dev@189 10569 printRemainingMessages();
dev@189 10570 break;
dev@189 10571 case ResultWas::ExpressionFailed:
dev@189 10572 if( result.isOk() )
dev@189 10573 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
dev@189 10574 else
dev@189 10575 printResultType( Colour::Error, failedString() );
dev@189 10576 printOriginalExpression();
dev@189 10577 printReconstructedExpression();
dev@189 10578 printRemainingMessages();
dev@189 10579 break;
dev@189 10580 case ResultWas::ThrewException:
dev@189 10581 printResultType( Colour::Error, failedString() );
dev@189 10582 printIssue( "unexpected exception with message:" );
dev@189 10583 printMessage();
dev@189 10584 printExpressionWas();
dev@189 10585 printRemainingMessages();
dev@189 10586 break;
dev@189 10587 case ResultWas::FatalErrorCondition:
dev@189 10588 printResultType( Colour::Error, failedString() );
dev@189 10589 printIssue( "fatal error condition with message:" );
dev@189 10590 printMessage();
dev@189 10591 printExpressionWas();
dev@189 10592 printRemainingMessages();
dev@189 10593 break;
dev@189 10594 case ResultWas::DidntThrowException:
dev@189 10595 printResultType( Colour::Error, failedString() );
dev@189 10596 printIssue( "expected exception, got none" );
dev@189 10597 printExpressionWas();
dev@189 10598 printRemainingMessages();
dev@189 10599 break;
dev@189 10600 case ResultWas::Info:
dev@189 10601 printResultType( Colour::None, "info" );
dev@189 10602 printMessage();
dev@189 10603 printRemainingMessages();
dev@189 10604 break;
dev@189 10605 case ResultWas::Warning:
dev@189 10606 printResultType( Colour::None, "warning" );
dev@189 10607 printMessage();
dev@189 10608 printRemainingMessages();
dev@189 10609 break;
dev@189 10610 case ResultWas::ExplicitFailure:
dev@189 10611 printResultType( Colour::Error, failedString() );
dev@189 10612 printIssue( "explicitly" );
dev@189 10613 printRemainingMessages( Colour::None );
dev@189 10614 break;
dev@189 10615 // These cases are here to prevent compiler warnings
dev@189 10616 case ResultWas::Unknown:
dev@189 10617 case ResultWas::FailureBit:
dev@189 10618 case ResultWas::Exception:
dev@189 10619 printResultType( Colour::Error, "** internal error **" );
dev@189 10620 break;
dev@189 10621 }
dev@189 10622 }
dev@189 10623
dev@189 10624 private:
dev@189 10625 // Colour::LightGrey
dev@189 10626
dev@189 10627 static Colour::Code dimColour() { return Colour::FileName; }
dev@189 10628
dev@189 10629 #ifdef CATCH_PLATFORM_MAC
dev@189 10630 static const char* failedString() { return "FAILED"; }
dev@189 10631 static const char* passedString() { return "PASSED"; }
dev@189 10632 #else
dev@189 10633 static const char* failedString() { return "failed"; }
dev@189 10634 static const char* passedString() { return "passed"; }
dev@189 10635 #endif
dev@189 10636
dev@189 10637 void printSourceInfo() const {
dev@189 10638 Colour colourGuard( Colour::FileName );
dev@189 10639 stream << result.getSourceInfo() << ':';
dev@189 10640 }
dev@189 10641
dev@189 10642 void printResultType( Colour::Code colour, std::string passOrFail ) const {
dev@189 10643 if( !passOrFail.empty() ) {
dev@189 10644 {
dev@189 10645 Colour colourGuard( colour );
dev@189 10646 stream << ' ' << passOrFail;
dev@189 10647 }
dev@189 10648 stream << ':';
dev@189 10649 }
dev@189 10650 }
dev@189 10651
dev@189 10652 void printIssue( std::string issue ) const {
dev@189 10653 stream << ' ' << issue;
dev@189 10654 }
dev@189 10655
dev@189 10656 void printExpressionWas() {
dev@189 10657 if( result.hasExpression() ) {
dev@189 10658 stream << ';';
dev@189 10659 {
dev@189 10660 Colour colour( dimColour() );
dev@189 10661 stream << " expression was:";
dev@189 10662 }
dev@189 10663 printOriginalExpression();
dev@189 10664 }
dev@189 10665 }
dev@189 10666
dev@189 10667 void printOriginalExpression() const {
dev@189 10668 if( result.hasExpression() ) {
dev@189 10669 stream << ' ' << result.getExpression();
dev@189 10670 }
dev@189 10671 }
dev@189 10672
dev@189 10673 void printReconstructedExpression() const {
dev@189 10674 if( result.hasExpandedExpression() ) {
dev@189 10675 {
dev@189 10676 Colour colour( dimColour() );
dev@189 10677 stream << " for: ";
dev@189 10678 }
dev@189 10679 stream << result.getExpandedExpression();
dev@189 10680 }
dev@189 10681 }
dev@189 10682
dev@189 10683 void printMessage() {
dev@189 10684 if ( itMessage != messages.end() ) {
dev@189 10685 stream << " '" << itMessage->message << '\'';
dev@189 10686 ++itMessage;
dev@189 10687 }
dev@189 10688 }
dev@189 10689
dev@189 10690 void printRemainingMessages( Colour::Code colour = dimColour() ) {
dev@189 10691 if ( itMessage == messages.end() )
dev@189 10692 return;
dev@189 10693
dev@189 10694 // using messages.end() directly yields compilation error:
dev@189 10695 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
dev@189 10696 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
dev@189 10697
dev@189 10698 {
dev@189 10699 Colour colourGuard( colour );
dev@189 10700 stream << " with " << pluralise( N, "message" ) << ':';
dev@189 10701 }
dev@189 10702
dev@189 10703 for(; itMessage != itEnd; ) {
dev@189 10704 // If this assertion is a warning ignore any INFO messages
dev@189 10705 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
dev@189 10706 stream << " '" << itMessage->message << '\'';
dev@189 10707 if ( ++itMessage != itEnd ) {
dev@189 10708 Colour colourGuard( dimColour() );
dev@189 10709 stream << " and";
dev@189 10710 }
dev@189 10711 }
dev@189 10712 }
dev@189 10713 }
dev@189 10714
dev@189 10715 private:
dev@189 10716 std::ostream& stream;
dev@189 10717 AssertionStats const& stats;
dev@189 10718 AssertionResult const& result;
dev@189 10719 std::vector<MessageInfo> messages;
dev@189 10720 std::vector<MessageInfo>::const_iterator itMessage;
dev@189 10721 bool printInfoMessages;
dev@189 10722 };
dev@189 10723
dev@189 10724 // Colour, message variants:
dev@189 10725 // - white: No tests ran.
dev@189 10726 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
dev@189 10727 // - white: Passed [both/all] N test cases (no assertions).
dev@189 10728 // - red: Failed N tests cases, failed M assertions.
dev@189 10729 // - green: Passed [both/all] N tests cases with M assertions.
dev@189 10730
dev@189 10731 std::string bothOrAll( std::size_t count ) const {
dev@189 10732 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
dev@189 10733 }
dev@189 10734
dev@189 10735 void printTotals( const Totals& totals ) const {
dev@189 10736 if( totals.testCases.total() == 0 ) {
dev@189 10737 stream << "No tests ran.";
dev@189 10738 }
dev@189 10739 else if( totals.testCases.failed == totals.testCases.total() ) {
dev@189 10740 Colour colour( Colour::ResultError );
dev@189 10741 const std::string qualify_assertions_failed =
dev@189 10742 totals.assertions.failed == totals.assertions.total() ?
dev@189 10743 bothOrAll( totals.assertions.failed ) : std::string();
dev@189 10744 stream <<
dev@189 10745 "Failed " << bothOrAll( totals.testCases.failed )
dev@189 10746 << pluralise( totals.testCases.failed, "test case" ) << ", "
dev@189 10747 "failed " << qualify_assertions_failed <<
dev@189 10748 pluralise( totals.assertions.failed, "assertion" ) << '.';
dev@189 10749 }
dev@189 10750 else if( totals.assertions.total() == 0 ) {
dev@189 10751 stream <<
dev@189 10752 "Passed " << bothOrAll( totals.testCases.total() )
dev@189 10753 << pluralise( totals.testCases.total(), "test case" )
dev@189 10754 << " (no assertions).";
dev@189 10755 }
dev@189 10756 else if( totals.assertions.failed ) {
dev@189 10757 Colour colour( Colour::ResultError );
dev@189 10758 stream <<
dev@189 10759 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
dev@189 10760 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
dev@189 10761 }
dev@189 10762 else {
dev@189 10763 Colour colour( Colour::ResultSuccess );
dev@189 10764 stream <<
dev@189 10765 "Passed " << bothOrAll( totals.testCases.passed )
dev@189 10766 << pluralise( totals.testCases.passed, "test case" ) <<
dev@189 10767 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
dev@189 10768 }
dev@189 10769 }
dev@189 10770 };
dev@189 10771
dev@189 10772 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
dev@189 10773
dev@189 10774 } // end namespace Catch
dev@189 10775
dev@189 10776 namespace Catch {
dev@189 10777 // These are all here to avoid warnings about not having any out of line
dev@189 10778 // virtual methods
dev@189 10779 NonCopyable::~NonCopyable() {}
dev@189 10780 IShared::~IShared() {}
dev@189 10781 IStream::~IStream() CATCH_NOEXCEPT {}
dev@189 10782 FileStream::~FileStream() CATCH_NOEXCEPT {}
dev@189 10783 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
dev@189 10784 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
dev@189 10785 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
dev@189 10786 IContext::~IContext() {}
dev@189 10787 IResultCapture::~IResultCapture() {}
dev@189 10788 ITestCase::~ITestCase() {}
dev@189 10789 ITestCaseRegistry::~ITestCaseRegistry() {}
dev@189 10790 IRegistryHub::~IRegistryHub() {}
dev@189 10791 IMutableRegistryHub::~IMutableRegistryHub() {}
dev@189 10792 IExceptionTranslator::~IExceptionTranslator() {}
dev@189 10793 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
dev@189 10794 IReporter::~IReporter() {}
dev@189 10795 IReporterFactory::~IReporterFactory() {}
dev@189 10796 IReporterRegistry::~IReporterRegistry() {}
dev@189 10797 IStreamingReporter::~IStreamingReporter() {}
dev@189 10798 AssertionStats::~AssertionStats() {}
dev@189 10799 SectionStats::~SectionStats() {}
dev@189 10800 TestCaseStats::~TestCaseStats() {}
dev@189 10801 TestGroupStats::~TestGroupStats() {}
dev@189 10802 TestRunStats::~TestRunStats() {}
dev@189 10803 CumulativeReporterBase::SectionNode::~SectionNode() {}
dev@189 10804 CumulativeReporterBase::~CumulativeReporterBase() {}
dev@189 10805
dev@189 10806 StreamingReporterBase::~StreamingReporterBase() {}
dev@189 10807 ConsoleReporter::~ConsoleReporter() {}
dev@189 10808 CompactReporter::~CompactReporter() {}
dev@189 10809 IRunner::~IRunner() {}
dev@189 10810 IMutableContext::~IMutableContext() {}
dev@189 10811 IConfig::~IConfig() {}
dev@189 10812 XmlReporter::~XmlReporter() {}
dev@189 10813 JunitReporter::~JunitReporter() {}
dev@189 10814 TestRegistry::~TestRegistry() {}
dev@189 10815 FreeFunctionTestCase::~FreeFunctionTestCase() {}
dev@189 10816 IGeneratorInfo::~IGeneratorInfo() {}
dev@189 10817 IGeneratorsForTest::~IGeneratorsForTest() {}
dev@189 10818 WildcardPattern::~WildcardPattern() {}
dev@189 10819 TestSpec::Pattern::~Pattern() {}
dev@189 10820 TestSpec::NamePattern::~NamePattern() {}
dev@189 10821 TestSpec::TagPattern::~TagPattern() {}
dev@189 10822 TestSpec::ExcludedPattern::~ExcludedPattern() {}
dev@189 10823
dev@189 10824 Matchers::Impl::StdString::Equals::~Equals() {}
dev@189 10825 Matchers::Impl::StdString::Contains::~Contains() {}
dev@189 10826 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
dev@189 10827 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
dev@189 10828
dev@189 10829 void Config::dummy() {}
dev@189 10830
dev@189 10831 namespace TestCaseTracking {
dev@189 10832 ITracker::~ITracker() {}
dev@189 10833 TrackerBase::~TrackerBase() {}
dev@189 10834 SectionTracker::~SectionTracker() {}
dev@189 10835 IndexTracker::~IndexTracker() {}
dev@189 10836 }
dev@189 10837 }
dev@189 10838
dev@189 10839 #ifdef __clang__
dev@189 10840 #pragma clang diagnostic pop
dev@189 10841 #endif
dev@189 10842
dev@189 10843 #endif
dev@189 10844
dev@189 10845 #ifdef CATCH_CONFIG_MAIN
dev@189 10846 // #included from: internal/catch_default_main.hpp
dev@189 10847 #define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
dev@189 10848
dev@189 10849 #ifndef __OBJC__
dev@189 10850
dev@189 10851 // Standard C/C++ main entry point
dev@189 10852 int main (int argc, char * argv[]) {
dev@189 10853 int result = Catch::Session().run( argc, argv );
dev@189 10854 return ( result < 0xff ? result : 0xff );
dev@189 10855 }
dev@189 10856
dev@189 10857 #else // __OBJC__
dev@189 10858
dev@189 10859 // Objective-C entry point
dev@189 10860 int main (int argc, char * const argv[]) {
dev@189 10861 #if !CATCH_ARC_ENABLED
dev@189 10862 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
dev@189 10863 #endif
dev@189 10864
dev@189 10865 Catch::registerTestMethods();
dev@189 10866 int result = Catch::Session().run( argc, (char* const*)argv );
dev@189 10867
dev@189 10868 #if !CATCH_ARC_ENABLED
dev@189 10869 [pool drain];
dev@189 10870 #endif
dev@189 10871
dev@189 10872 return ( result < 0xff ? result : 0xff );
dev@189 10873 }
dev@189 10874
dev@189 10875 #endif // __OBJC__
dev@189 10876
dev@189 10877 #endif
dev@189 10878
dev@189 10879 #ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
dev@189 10880 # undef CLARA_CONFIG_MAIN
dev@189 10881 #endif
dev@189 10882
dev@189 10883 //////
dev@189 10884
dev@189 10885 // If this config identifier is defined then all CATCH macros are prefixed with CATCH_
dev@189 10886 #ifdef CATCH_CONFIG_PREFIX_ALL
dev@189 10887
dev@189 10888 #define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
dev@189 10889 #define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
dev@189 10890
dev@189 10891 #define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
dev@189 10892 #define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
dev@189 10893 #define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
dev@189 10894 #define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
dev@189 10895
dev@189 10896 #define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
dev@189 10897 #define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
dev@189 10898 #define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
dev@189 10899 #define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
dev@189 10900 #define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
dev@189 10901
dev@189 10902 #define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
dev@189 10903 #define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
dev@189 10904 #define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
dev@189 10905 #define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
dev@189 10906
dev@189 10907 #define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
dev@189 10908 #define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
dev@189 10909
dev@189 10910 #define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
dev@189 10911 #define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
dev@189 10912 #define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
dev@189 10913 #define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
dev@189 10914 #define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
dev@189 10915
dev@189 10916 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 10917 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
dev@189 10918 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
dev@189 10919 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
dev@189 10920 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
dev@189 10921 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
dev@189 10922 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
dev@189 10923 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
dev@189 10924 #else
dev@189 10925 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
dev@189 10926 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
dev@189 10927 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
dev@189 10928 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
dev@189 10929 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
dev@189 10930 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
dev@189 10931 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
dev@189 10932 #endif
dev@189 10933 #define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
dev@189 10934
dev@189 10935 #define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
dev@189 10936 #define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
dev@189 10937
dev@189 10938 #define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
dev@189 10939
dev@189 10940 // "BDD-style" convenience wrappers
dev@189 10941 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 10942 #define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
dev@189 10943 #define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
dev@189 10944 #else
dev@189 10945 #define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
dev@189 10946 #define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
dev@189 10947 #endif
dev@189 10948 #define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
dev@189 10949 #define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
dev@189 10950 #define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
dev@189 10951 #define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
dev@189 10952 #define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
dev@189 10953
dev@189 10954 // If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
dev@189 10955 #else
dev@189 10956
dev@189 10957 #define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
dev@189 10958 #define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
dev@189 10959
dev@189 10960 #define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
dev@189 10961 #define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
dev@189 10962 #define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
dev@189 10963 #define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
dev@189 10964
dev@189 10965 #define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
dev@189 10966 #define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
dev@189 10967 #define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
dev@189 10968 #define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
dev@189 10969 #define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
dev@189 10970
dev@189 10971 #define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
dev@189 10972 #define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
dev@189 10973 #define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
dev@189 10974 #define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
dev@189 10975
dev@189 10976 #define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
dev@189 10977 #define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
dev@189 10978
dev@189 10979 #define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
dev@189 10980 #define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
dev@189 10981 #define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
dev@189 10982 #define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
dev@189 10983 #define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
dev@189 10984
dev@189 10985 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 10986 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
dev@189 10987 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
dev@189 10988 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
dev@189 10989 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
dev@189 10990 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
dev@189 10991 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
dev@189 10992 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
dev@189 10993 #else
dev@189 10994 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
dev@189 10995 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
dev@189 10996 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
dev@189 10997 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
dev@189 10998 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
dev@189 10999 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
dev@189 11000 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
dev@189 11001 #endif
dev@189 11002 #define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
dev@189 11003
dev@189 11004 #define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
dev@189 11005 #define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
dev@189 11006
dev@189 11007 #define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
dev@189 11008
dev@189 11009 #endif
dev@189 11010
dev@189 11011 #define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
dev@189 11012
dev@189 11013 // "BDD-style" convenience wrappers
dev@189 11014 #ifdef CATCH_CONFIG_VARIADIC_MACROS
dev@189 11015 #define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
dev@189 11016 #define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
dev@189 11017 #else
dev@189 11018 #define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
dev@189 11019 #define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
dev@189 11020 #endif
dev@189 11021 #define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
dev@189 11022 #define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
dev@189 11023 #define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
dev@189 11024 #define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
dev@189 11025 #define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
dev@189 11026
dev@189 11027 using Catch::Detail::Approx;
dev@189 11028
dev@189 11029 #endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
dev@189 11030