annotate ext/catch/catch.hpp @ 218:ea8994465322

Rebuild these for capnp v0.6. But it would probably be better at this point not to commit them, as the main reason they are in the repo is because the compiler wasn't available for Visual Studio builds, and that's no longer the case.
author Chris Cannam <cannam@all-day-breakfast.com>
date Tue, 09 May 2017 11:46:23 +0100
parents 6859f35cb4f8
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