blob: f52eebd594d31b2ab8928a744f98c77ce04bceb8 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Phil Nash02af70e2016-03-11 18:31:52 +00002 * Catch v1.3.6
3 * Generated: 2016-03-11 18:30:42.852700
Phil Nash4df051b2012-05-22 22:22:22 +01004 * ----------------------------------------------------------
Phil Nashaec1e5e2012-05-09 19:37:51 +01005 * This file has been merged from multiple headers. Please don't edit it directly
6 * Copyright (c) 2012 Two Blue Cubes Ltd. All rights reserved.
Phil Nash89d1e6c2011-05-24 08:23:02 +01007 *
8 * Distributed under the Boost Software License, Version 1.0. (See accompanying
9 * file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Phil Nash89d1e6c2011-05-24 08:23:02 +010010 */
Phil Nashaec1e5e2012-05-09 19:37:51 +010011#ifndef TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
12#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010013
Phil Nash3b80af72012-08-09 07:47:30 +010014#define TWOBLUECUBES_CATCH_HPP_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +010015
Phil Nashc51e8682015-05-21 06:16:15 +010016#ifdef __clang__
17# pragma clang system_header
18#elif defined __GNUC__
19# pragma GCC system_header
20#endif
21
Phil Nash9241e432014-05-20 18:50:59 +010022// #included from: internal/catch_suppress_warnings.h
23
Phil Nash5bc030d2012-08-16 18:48:50 +010024#ifdef __clang__
Phil Nasha806c3e2015-03-04 08:23:40 +000025# ifdef __ICC // icpc defines the __clang__ macro
26# pragma warning(push)
27# pragma warning(disable: 161 1682)
28# else // __ICC
29# pragma clang diagnostic ignored "-Wglobal-constructors"
30# pragma clang diagnostic ignored "-Wvariadic-macros"
31# pragma clang diagnostic ignored "-Wc99-extensions"
32# pragma clang diagnostic ignored "-Wunused-variable"
33# pragma clang diagnostic push
34# pragma clang diagnostic ignored "-Wpadded"
35# pragma clang diagnostic ignored "-Wc++98-compat"
36# pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
Phil Nashc51e8682015-05-21 06:16:15 +010037# pragma clang diagnostic ignored "-Wswitch-enum"
Phil Nash7e346192015-11-03 08:00:43 +000038# pragma clang diagnostic ignored "-Wcovered-switch-default"
Phil Nasha806c3e2015-03-04 08:23:40 +000039# endif
Fabien Caylusae769452014-07-27 15:16:10 +020040#elif defined __GNUC__
Phil Nasha806c3e2015-03-04 08:23:40 +000041# pragma GCC diagnostic ignored "-Wvariadic-macros"
42# pragma GCC diagnostic ignored "-Wunused-variable"
43# pragma GCC diagnostic push
44# pragma GCC diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010045#endif
Phil Nash576aff62014-12-21 00:21:23 +000046#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
47# define CATCH_IMPL
Phil Nashf9df35b2014-03-10 18:02:18 +000048#endif
49
Phil Nash576aff62014-12-21 00:21:23 +000050#ifdef CATCH_IMPL
Phil Nash9abb2762014-03-06 21:53:34 +000051# ifndef CLARA_CONFIG_MAIN
52# define CLARA_CONFIG_MAIN_NOT_DEFINED
53# define CLARA_CONFIG_MAIN
54# endif
55#endif
56
Phil Nash3b80af72012-08-09 07:47:30 +010057// #included from: internal/catch_notimplemented_exception.h
58#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010059
Phil Nash89d1e6c2011-05-24 08:23:02 +010060// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010061#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010062
Phil Nash89d1e6c2011-05-24 08:23:02 +010063#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
64#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
65#define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
66
67#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
68#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
69
Phil Nash89d1e6c2011-05-24 08:23:02 +010070#include <sstream>
71#include <stdexcept>
72#include <algorithm>
73
Phil Nash8defc712013-04-24 19:10:02 +010074// #included from: catch_compiler_capabilities.h
75#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
76
Phil Nash318c9362015-05-19 18:40:00 +010077// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
78// The following features are defined:
79//
80// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
81// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
82// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
83// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
84// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
Phil Nash2f6371f2015-07-23 23:06:26 +010085// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
Phil Nashe73583d2015-08-07 17:30:34 +010086// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
Phil Nashd234ed12015-08-24 06:28:25 +010087// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
Phil Nash318c9362015-05-19 18:40:00 +010088
89// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
90
Phil Nash318c9362015-05-19 18:40:00 +010091// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
92
Phil Nashd234ed12015-08-24 06:28:25 +010093// ****************
94// Note to maintainers: if new toggles are added please document them
95// in configuration.md, too
96// ****************
97
Phil Nash3b18d9e2015-06-30 18:26:09 +010098// In general each macro has a _NO_<feature name> form
99// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
100// Many features, at point of detection, define an _INTERNAL_ macro, so they
101// can be combined, en-mass, with the _NO_ forms later.
102
103// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
Phil Nash8defc712013-04-24 19:10:02 +0100104
Phil Nashae5ee2c2016-02-29 08:17:18 +0000105#if defined(__cplusplus) && __cplusplus >= 201103L
106# define CATCH_CPP11_OR_GREATER
107#endif
108
Phil Nash859760a2013-12-14 14:34:05 +0000109#ifdef __clang__
Phil Nash859760a2013-12-14 14:34:05 +0000110
Phil Nash17404952014-04-23 18:19:49 +0100111# if __has_feature(cxx_nullptr)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100112# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash17404952014-04-23 18:19:49 +0100113# endif
Phil Nash859760a2013-12-14 14:34:05 +0000114
Phil Nash17404952014-04-23 18:19:49 +0100115# if __has_feature(cxx_noexcept)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100116# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash17404952014-04-23 18:19:49 +0100117# endif
Phil Nash859760a2013-12-14 14:34:05 +0000118
Phil Nashae5ee2c2016-02-29 08:17:18 +0000119# if defined(CATCH_CPP11_OR_GREATER)
120# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
121# endif
122
Phil Nash859760a2013-12-14 14:34:05 +0000123#endif // __clang__
124
Phil Nash8defc712013-04-24 19:10:02 +0100125////////////////////////////////////////////////////////////////////////////////
126// Borland
127#ifdef __BORLANDC__
128
Phil Nash8defc712013-04-24 19:10:02 +0100129#endif // __BORLANDC__
130
131////////////////////////////////////////////////////////////////////////////////
132// EDG
133#ifdef __EDG_VERSION__
134
Phil Nash8defc712013-04-24 19:10:02 +0100135#endif // __EDG_VERSION__
136
137////////////////////////////////////////////////////////////////////////////////
138// Digital Mars
139#ifdef __DMC__
140
Phil Nash8defc712013-04-24 19:10:02 +0100141#endif // __DMC__
142
143////////////////////////////////////////////////////////////////////////////////
144// GCC
145#ifdef __GNUC__
146
Phil Nashae5ee2c2016-02-29 08:17:18 +0000147# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
148# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
149# endif
150
151# if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS) && defined(CATCH_CPP11_OR_GREATER)
Phil Nash02af70e2016-03-11 18:31:52 +0000152# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS _Pragma( "GCC diagnostic ignored \"-Wparentheses\"" )
Phil Nashae5ee2c2016-02-29 08:17:18 +0000153# endif
Phil Nash859760a2013-12-14 14:34:05 +0000154
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100155// - otherwise more recent versions define __cplusplus >= 201103L
156// and will get picked up below
157
Phil Nash8defc712013-04-24 19:10:02 +0100158#endif // __GNUC__
159
160////////////////////////////////////////////////////////////////////////////////
161// Visual C++
162#ifdef _MSC_VER
163
Phil Nash43470b22015-05-19 22:37:23 +0100164#if (_MSC_VER >= 1600)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100165# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nashd234ed12015-08-24 06:28:25 +0100166# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
Phil Nash43470b22015-05-19 22:37:23 +0100167#endif
168
Phil Nash318c9362015-05-19 18:40:00 +0100169#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
Phil Nash3b18d9e2015-06-30 18:26:09 +0100170#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
171#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash318c9362015-05-19 18:40:00 +0100172#endif
173
Phil Nash8defc712013-04-24 19:10:02 +0100174#endif // _MSC_VER
175
Phil Nashd234ed12015-08-24 06:28:25 +0100176////////////////////////////////////////////////////////////////////////////////
177
Phil Nash8defc712013-04-24 19:10:02 +0100178// Use variadic macros if the compiler supports them
179#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
180 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
181 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
182 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100183
Phil Nash3b18d9e2015-06-30 18:26:09 +0100184#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash786959d2013-06-07 19:07:50 +0100185
Phil Nash8defc712013-04-24 19:10:02 +0100186#endif
187
Phil Nashd7e17902014-04-18 08:49:35 +0100188////////////////////////////////////////////////////////////////////////////////
189// C++ language feature support
190
Phil Nash318c9362015-05-19 18:40:00 +0100191// catch all support for C++11
Phil Nashae5ee2c2016-02-29 08:17:18 +0000192#if defined(CATCH_CPP11_OR_GREATER)
Phil Nash318c9362015-05-19 18:40:00 +0100193
Phil Nash3b18d9e2015-06-30 18:26:09 +0100194# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
195# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash318c9362015-05-19 18:40:00 +0100196# endif
197
Phil Nash3b18d9e2015-06-30 18:26:09 +0100198# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
199# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash318c9362015-05-19 18:40:00 +0100200# endif
201
Phil Nash3b18d9e2015-06-30 18:26:09 +0100202# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
203# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash318c9362015-05-19 18:40:00 +0100204# endif
205
Phil Nash3b18d9e2015-06-30 18:26:09 +0100206# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
207# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
Phil Nash318c9362015-05-19 18:40:00 +0100208# endif
209
Phil Nash3b18d9e2015-06-30 18:26:09 +0100210# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
211# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
Phil Nash318c9362015-05-19 18:40:00 +0100212# endif
213
Phil Nash3b18d9e2015-06-30 18:26:09 +0100214# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
215# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash318c9362015-05-19 18:40:00 +0100216# endif
217
Phil Nash2f6371f2015-07-23 23:06:26 +0100218# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
219# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
220# endif
221
Phil Nashe73583d2015-08-07 17:30:34 +0100222# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
223# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
224# endif
Phil Nashd234ed12015-08-24 06:28:25 +0100225# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
226# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
227# endif
Phil Nashe73583d2015-08-07 17:30:34 +0100228
Phil Nash318c9362015-05-19 18:40:00 +0100229#endif // __cplusplus >= 201103L
Phil Nashd7e17902014-04-18 08:49:35 +0100230
Phil Nash3b18d9e2015-06-30 18:26:09 +0100231// Now set the actual defines based on the above + anything the user has configured
232#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
233# define CATCH_CONFIG_CPP11_NULLPTR
234#endif
235#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
236# define CATCH_CONFIG_CPP11_NOEXCEPT
237#endif
238#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)
239# define CATCH_CONFIG_CPP11_GENERATED_METHODS
240#endif
241#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)
242# define CATCH_CONFIG_CPP11_IS_ENUM
243#endif
244#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
245# define CATCH_CONFIG_CPP11_TUPLE
246#endif
247#if defined(CATCH_INTERNAL_CONFIG_VARIADIC_MACROS) && !defined(CATCH_CONFIG_NO_VARIADIC_MACROS) && !defined(CATCH_CONFIG_VARIADIC_MACROS)
Phil Nash2f6371f2015-07-23 23:06:26 +0100248# define CATCH_CONFIG_VARIADIC_MACROS
249#endif
Phil Nashd234ed12015-08-24 06:28:25 +0100250#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
Phil Nash2f6371f2015-07-23 23:06:26 +0100251# define CATCH_CONFIG_CPP11_LONG_LONG
Phil Nash3b18d9e2015-06-30 18:26:09 +0100252#endif
Phil Nashd234ed12015-08-24 06:28:25 +0100253#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
Phil Nashe73583d2015-08-07 17:30:34 +0100254# define CATCH_CONFIG_CPP11_OVERRIDE
255#endif
Phil Nashd234ed12015-08-24 06:28:25 +0100256#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
257# define CATCH_CONFIG_CPP11_UNIQUE_PTR
Phil Nash3b18d9e2015-06-30 18:26:09 +0100258#endif
259
Phil Nashae5ee2c2016-02-29 08:17:18 +0000260#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
261# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
262#endif
263
Phil Nashd7e17902014-04-18 08:49:35 +0100264// noexcept support:
Phil Nash17404952014-04-23 18:19:49 +0100265#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
266# define CATCH_NOEXCEPT noexcept
267# define CATCH_NOEXCEPT_IS(x) noexcept(x)
268#else
Phil Nashd7e17902014-04-18 08:49:35 +0100269# define CATCH_NOEXCEPT throw()
270# define CATCH_NOEXCEPT_IS(x)
271#endif
272
Phil Nashb971fe72015-07-02 08:21:38 +0100273// nullptr support
274#ifdef CATCH_CONFIG_CPP11_NULLPTR
275# define CATCH_NULL nullptr
276#else
277# define CATCH_NULL NULL
278#endif
279
Phil Nashe73583d2015-08-07 17:30:34 +0100280// override support
281#ifdef CATCH_CONFIG_CPP11_OVERRIDE
282# define CATCH_OVERRIDE override
283#else
284# define CATCH_OVERRIDE
285#endif
286
Phil Nashd234ed12015-08-24 06:28:25 +0100287// unique_ptr support
288#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
289# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
290#else
291# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
292#endif
293
Phil Nash89d2a3f2012-05-16 15:09:17 +0100294namespace Catch {
295
Phil Nash8f66e342015-07-02 23:03:13 +0100296 struct IConfig;
297
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100298 struct CaseSensitive { enum Choice {
299 Yes,
300 No
301 }; };
302
Phil Nasha04981b2013-03-08 09:30:25 +0000303 class NonCopyable {
Phil Nash318c9362015-05-19 18:40:00 +0100304#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashe54ac702014-10-21 07:25:26 +0100305 NonCopyable( NonCopyable const& ) = delete;
306 NonCopyable( NonCopyable && ) = delete;
307 NonCopyable& operator = ( NonCopyable const& ) = delete;
308 NonCopyable& operator = ( NonCopyable && ) = delete;
309#else
310 NonCopyable( NonCopyable const& info );
311 NonCopyable& operator = ( NonCopyable const& );
312#endif
313
Phil Nasha04981b2013-03-08 09:30:25 +0000314 protected:
315 NonCopyable() {}
316 virtual ~NonCopyable();
317 };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100318
Phil Nash163088a2012-05-31 19:40:26 +0100319 class SafeBool {
320 public:
321 typedef void (SafeBool::*type)() const;
322
323 static type makeSafe( bool value ) {
324 return value ? &SafeBool::trueValue : 0;
325 }
326 private:
327 void trueValue() const {}
328 };
329
Phil Nash89d1e6c2011-05-24 08:23:02 +0100330 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100331 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100332 typename ContainerT::const_iterator it = container.begin();
333 typename ContainerT::const_iterator itEnd = container.end();
334 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100335 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100336 }
337 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100338 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100339 typename AssociativeContainerT::const_iterator it = container.begin();
340 typename AssociativeContainerT::const_iterator itEnd = container.end();
341 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100342 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100343 }
344
Phil Nash3649fdf2013-12-03 18:53:55 +0000345 bool startsWith( std::string const& s, std::string const& prefix );
346 bool endsWith( std::string const& s, std::string const& suffix );
347 bool contains( std::string const& s, std::string const& infix );
348 void toLowerInPlace( std::string& s );
349 std::string toLower( std::string const& s );
350 std::string trim( std::string const& str );
Phil Nash576aff62014-12-21 00:21:23 +0000351 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
Phil Nash4c97fc52012-08-24 08:23:50 +0100352
353 struct pluralise {
Phil Nash3649fdf2013-12-03 18:53:55 +0000354 pluralise( std::size_t count, std::string const& label );
Phil Nash4c97fc52012-08-24 08:23:50 +0100355
Phil Nash3649fdf2013-12-03 18:53:55 +0000356 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
Phil Nash4c97fc52012-08-24 08:23:50 +0100357
358 std::size_t m_count;
359 std::string m_label;
360 };
Phil Nash56d5c422012-08-23 20:08:50 +0100361
Phil Nash89d2a3f2012-05-16 15:09:17 +0100362 struct SourceLineInfo {
363
Phil Nash3649fdf2013-12-03 18:53:55 +0000364 SourceLineInfo();
Phil Nashde49ec42013-12-04 20:25:14 +0000365 SourceLineInfo( char const* _file, std::size_t _line );
Phil Nash3649fdf2013-12-03 18:53:55 +0000366 SourceLineInfo( SourceLineInfo const& other );
Phil Nash318c9362015-05-19 18:40:00 +0100367# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +0100368 SourceLineInfo( SourceLineInfo && ) = default;
369 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
370 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
371# endif
Phil Nash3649fdf2013-12-03 18:53:55 +0000372 bool empty() const;
373 bool operator == ( SourceLineInfo const& other ) const;
Phil Nasha806c3e2015-03-04 08:23:40 +0000374 bool operator < ( SourceLineInfo const& other ) const;
Phil Nash3649fdf2013-12-03 18:53:55 +0000375
Phil Nash6e0f58d2012-02-15 18:37:21 +0000376 std::string file;
377 std::size_t line;
378 };
379
Phil Nash3649fdf2013-12-03 18:53:55 +0000380 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
Phil Nash6e0f58d2012-02-15 18:37:21 +0000381
Phil Nash8defc712013-04-24 19:10:02 +0100382 // This is just here to avoid compiler warnings with macro constants and boolean literals
383 inline bool isTrue( bool value ){ return value; }
Phil Nashab036682014-06-02 07:48:03 +0100384 inline bool alwaysTrue() { return true; }
385 inline bool alwaysFalse() { return false; }
Phil Nash8defc712013-04-24 19:10:02 +0100386
Phil Nash3649fdf2013-12-03 18:53:55 +0000387 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
Phil Nash859760a2013-12-14 14:34:05 +0000388
Phil Nash8f66e342015-07-02 23:03:13 +0100389 void seedRng( IConfig const& config );
390 unsigned int rngSeed();
391
Phil Nash859760a2013-12-14 14:34:05 +0000392 // Use this in variadic streaming macros to allow
393 // >> +StreamEndStop
394 // as well as
395 // >> stuff +StreamEndStop
396 struct StreamEndStop {
397 std::string operator+() {
398 return std::string();
399 }
400 };
401 template<typename T>
402 T const& operator + ( T const& value, StreamEndStop ) {
403 return value;
404 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100405}
406
Phil Nasha695eb92012-08-13 07:46:10 +0100407#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
408#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100409
Phil Nash3b80af72012-08-09 07:47:30 +0100410#include <ostream>
411
412namespace Catch {
413
414 class NotImplementedException : public std::exception
415 {
416 public:
Phil Nash8defc712013-04-24 19:10:02 +0100417 NotImplementedException( SourceLineInfo const& lineInfo );
Phil Nash9241e432014-05-20 18:50:59 +0100418 NotImplementedException( NotImplementedException const& ) {}
Phil Nash3b80af72012-08-09 07:47:30 +0100419
Phil Nashd7e17902014-04-18 08:49:35 +0100420 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
Phil Nash3b80af72012-08-09 07:47:30 +0100421
Phil Nashd7e17902014-04-18 08:49:35 +0100422 virtual const char* what() const CATCH_NOEXCEPT;
Phil Nash3b80af72012-08-09 07:47:30 +0100423
424 private:
425 std::string m_what;
426 SourceLineInfo m_lineInfo;
427 };
428
429} // end namespace Catch
430
431///////////////////////////////////////////////////////////////////////////////
432#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
433
434// #included from: internal/catch_context.h
435#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
436
Phil Nasha70fbe32012-08-31 08:10:36 +0100437// #included from: catch_interfaces_generators.h
438#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100439
Phil Nasha70fbe32012-08-31 08:10:36 +0100440#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000441
Phil Nash89d2a3f2012-05-16 15:09:17 +0100442namespace Catch {
443
Phil Nasha70fbe32012-08-31 08:10:36 +0100444 struct IGeneratorInfo {
445 virtual ~IGeneratorInfo();
446 virtual bool moveNext() = 0;
447 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000448 };
449
Phil Nasha70fbe32012-08-31 08:10:36 +0100450 struct IGeneratorsForTest {
451 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100452
Phil Nash8defc712013-04-24 19:10:02 +0100453 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +0100454 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000455 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100456
457 IGeneratorsForTest* createGeneratorsForTest();
458
459} // end namespace Catch
460
Phil Nash49e6d532012-05-05 19:35:35 +0100461// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100462#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100463
Phil Nash37186a12013-03-13 12:19:30 +0000464#ifdef __clang__
465#pragma clang diagnostic push
466#pragma clang diagnostic ignored "-Wpadded"
467#endif
468
Phil Nash89d2a3f2012-05-16 15:09:17 +0100469namespace Catch {
470
Phil Nash49e6d532012-05-05 19:35:35 +0100471 // An intrusive reference counting smart pointer.
472 // T must implement addRef() and release() methods
473 // typically implementing the IShared interface
474 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100475 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100476 public:
Phil Nashb971fe72015-07-02 08:21:38 +0100477 Ptr() : m_p( CATCH_NULL ){}
Phil Nash49e6d532012-05-05 19:35:35 +0100478 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100479 if( m_p )
480 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100481 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000482 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100483 if( m_p )
484 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100485 }
486 ~Ptr(){
487 if( m_p )
488 m_p->release();
489 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000490 void reset() {
491 if( m_p )
492 m_p->release();
Phil Nashb971fe72015-07-02 08:21:38 +0100493 m_p = CATCH_NULL;
Phil Nashff03cdf2012-12-06 08:44:51 +0000494 }
Phil Nash49e6d532012-05-05 19:35:35 +0100495 Ptr& operator = ( T* p ){
496 Ptr temp( p );
497 swap( temp );
498 return *this;
499 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000500 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100501 Ptr temp( other );
502 swap( temp );
503 return *this;
504 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000505 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100506 T* get() const{ return m_p; }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000507 T& operator*() const { return *m_p; }
508 T* operator->() const { return m_p; }
Phil Nashb971fe72015-07-02 08:21:38 +0100509 bool operator !() const { return m_p == CATCH_NULL; }
510 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100511
512 private:
513 T* m_p;
514 };
515
516 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100517 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000518 virtual void addRef() const = 0;
519 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100520 };
521
Phil Nasha1fbfea2012-12-01 23:57:18 +0000522 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100523 struct SharedImpl : T {
524
525 SharedImpl() : m_rc( 0 ){}
526
Phil Nasha1fbfea2012-12-01 23:57:18 +0000527 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100528 ++m_rc;
529 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000530 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100531 if( --m_rc == 0 )
532 delete this;
533 }
534
Phil Nasha1fbfea2012-12-01 23:57:18 +0000535 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100536 };
537
538} // end namespace Catch
539
Phil Nash37186a12013-03-13 12:19:30 +0000540#ifdef __clang__
541#pragma clang diagnostic pop
542#endif
543
Phil Nash786959d2013-06-07 19:07:50 +0100544#include <memory>
545#include <vector>
546#include <stdlib.h>
547
548namespace Catch {
549
550 class TestCase;
551 class Stream;
552 struct IResultCapture;
553 struct IRunner;
554 struct IGeneratorsForTest;
555 struct IConfig;
556
557 struct IContext
558 {
559 virtual ~IContext();
560
Phil Nash9241e432014-05-20 18:50:59 +0100561 virtual IResultCapture* getResultCapture() = 0;
562 virtual IRunner* getRunner() = 0;
Phil Nash786959d2013-06-07 19:07:50 +0100563 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
564 virtual bool advanceGeneratorsForCurrentTest() = 0;
565 virtual Ptr<IConfig const> getConfig() const = 0;
566 };
567
568 struct IMutableContext : IContext
569 {
570 virtual ~IMutableContext();
571 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
572 virtual void setRunner( IRunner* runner ) = 0;
573 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
574 };
575
576 IContext& getCurrentContext();
577 IMutableContext& getCurrentMutableContext();
578 void cleanUpContext();
579 Stream createStream( std::string const& streamName );
580
581}
582
583// #included from: internal/catch_test_registry.hpp
584#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
585
586// #included from: catch_interfaces_testcase.h
587#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
588
Phil Nash0f9c5512012-06-02 23:12:42 +0100589#include <vector>
590
591namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100592
Phil Nash65cc14c2014-05-16 18:54:48 +0100593 class TestSpec;
Phil Nash56d5c422012-08-23 20:08:50 +0100594
Phil Nash5bc030d2012-08-16 18:48:50 +0100595 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100596 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100597 protected:
598 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100599 };
600
Phil Nasha1fbfea2012-12-01 23:57:18 +0000601 class TestCase;
Phil Nash20cad7c2014-04-15 18:44:37 +0100602 struct IConfig;
Phil Nash0f9c5512012-06-02 23:12:42 +0100603
604 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100605 virtual ~ITestCaseRegistry();
Phil Nash8defc712013-04-24 19:10:02 +0100606 virtual std::vector<TestCase> const& getAllTests() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +0100607 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100608 };
Phil Nashe73583d2015-08-07 17:30:34 +0100609
610 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
611 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
612 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
613
Phil Nash0f9c5512012-06-02 23:12:42 +0100614}
615
Phil Nash89d2a3f2012-05-16 15:09:17 +0100616namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100617
618template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100619class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100620
Phil Nash176eb812012-05-11 08:17:16 +0100621public:
622 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100623
Phil Nash176eb812012-05-11 08:17:16 +0100624 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100625 C obj;
626 (obj.*m_method)();
627 }
628
Phil Nash89d1e6c2011-05-24 08:23:02 +0100629private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100630 virtual ~MethodTestCase() {}
631
Phil Nash89d1e6c2011-05-24 08:23:02 +0100632 void (C::*m_method)();
633};
634
635typedef void(*TestFunction)();
636
Phil Nash93906752013-03-16 20:21:51 +0000637struct NameAndDesc {
638 NameAndDesc( const char* _name = "", const char* _description= "" )
639 : name( _name ), description( _description )
640 {}
641
642 const char* name;
643 const char* description;
644};
645
Phil Nash7e15d9b2015-11-20 16:59:14 +0000646void registerTestCase
647 ( ITestCase* testCase,
648 char const* className,
649 NameAndDesc const& nameAndDesc,
650 SourceLineInfo const& lineInfo );
651
Phil Nash89d2a3f2012-05-16 15:09:17 +0100652struct AutoReg {
653
Phil Nash7e15d9b2015-11-20 16:59:14 +0000654 AutoReg
655 ( TestFunction function,
656 SourceLineInfo const& lineInfo,
657 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100658
Phil Nash89d1e6c2011-05-24 08:23:02 +0100659 template<typename C>
Phil Nash7e15d9b2015-11-20 16:59:14 +0000660 AutoReg
661 ( void (C::*method)(),
662 char const* className,
663 NameAndDesc const& nameAndDesc,
664 SourceLineInfo const& lineInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100665
Phil Nash7e15d9b2015-11-20 16:59:14 +0000666 registerTestCase
667 ( new MethodTestCase<C>( method ),
668 className,
669 nameAndDesc,
670 lineInfo );
671 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100672
Phil Nash176eb812012-05-11 08:17:16 +0100673 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100674
675private:
Phil Nash8defc712013-04-24 19:10:02 +0100676 AutoReg( AutoReg const& );
677 void operator= ( AutoReg const& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100678};
679
Phil Nash7e15d9b2015-11-20 16:59:14 +0000680void registerTestCaseFunction
681 ( TestFunction function,
682 SourceLineInfo const& lineInfo,
683 NameAndDesc const& nameAndDesc );
684
Phil Nash89d1e6c2011-05-24 08:23:02 +0100685} // end namespace Catch
686
Phil Nash93906752013-03-16 20:21:51 +0000687#ifdef CATCH_CONFIG_VARIADIC_MACROS
688 ///////////////////////////////////////////////////////////////////////////////
689 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nash786959d2013-06-07 19:07:50 +0100690 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
691 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
692 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100693
Phil Nash93906752013-03-16 20:21:51 +0000694 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000695 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
696 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100697
Phil Nash93906752013-03-16 20:21:51 +0000698 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100699 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... )\
Phil Nash93906752013-03-16 20:21:51 +0000700 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100701 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000702 void test(); \
703 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100704 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000705 } \
Phil Nash786959d2013-06-07 19:07:50 +0100706 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash89d1e6c2011-05-24 08:23:02 +0100707
Phil Nash7e15d9b2015-11-20 16:59:14 +0000708 ///////////////////////////////////////////////////////////////////////////////
709 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
710 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
711
Phil Nash93906752013-03-16 20:21:51 +0000712#else
713 ///////////////////////////////////////////////////////////////////////////////
714 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nash786959d2013-06-07 19:07:50 +0100715 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )(); \
716 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
717 static void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )()
Phil Nash93906752013-03-16 20:21:51 +0000718
719 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000720 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
721 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
722
723 ///////////////////////////////////////////////////////////////////////////////
Phil Nash786959d2013-06-07 19:07:50 +0100724 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
Phil Nash93906752013-03-16 20:21:51 +0000725 namespace{ \
Phil Nash786959d2013-06-07 19:07:50 +0100726 struct INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000727 void test(); \
728 }; \
Phil Nash786959d2013-06-07 19:07:50 +0100729 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000730 } \
Phil Nash786959d2013-06-07 19:07:50 +0100731 void INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ )::test()
Phil Nash93906752013-03-16 20:21:51 +0000732
Phil Nash7e15d9b2015-11-20 16:59:14 +0000733 ///////////////////////////////////////////////////////////////////////////////
734 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
735 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
Phil Nash93906752013-03-16 20:21:51 +0000736#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100737
738// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100739#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100740
Phil Nashab036682014-06-02 07:48:03 +0100741// #included from: catch_result_builder.h
742#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100743
Phil Nash89d1e6c2011-05-24 08:23:02 +0100744// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100745#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100746
Phil Nash89d2a3f2012-05-16 15:09:17 +0100747namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100748
Phil Nash90a35942012-11-13 22:04:29 +0000749 // ResultWas::OfType enum
750 struct ResultWas { enum OfType {
751 Unknown = -1,
752 Ok = 0,
753 Info = 1,
754 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100755
Phil Nash90a35942012-11-13 22:04:29 +0000756 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100757
Phil Nash90a35942012-11-13 22:04:29 +0000758 ExpressionFailed = FailureBit | 1,
759 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100760
Phil Nash90a35942012-11-13 22:04:29 +0000761 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100762
Phil Nash90a35942012-11-13 22:04:29 +0000763 ThrewException = Exception | 1,
Phil Nash93b61e12014-08-22 19:35:41 +0100764 DidntThrowException = Exception | 2,
765
766 FatalErrorCondition = 0x200 | FailureBit
Phil Nash89d1e6c2011-05-24 08:23:02 +0100767
Phil Nash90a35942012-11-13 22:04:29 +0000768 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100769
Phil Nash90a35942012-11-13 22:04:29 +0000770 inline bool isOk( ResultWas::OfType resultType ) {
771 return ( resultType & ResultWas::FailureBit ) == 0;
772 }
Phil Nasha2773812013-02-02 20:37:58 +0000773 inline bool isJustInfo( int flags ) {
774 return flags == ResultWas::Info;
775 }
Phil Nash67305122012-10-09 11:48:55 +0100776
Phil Nash90a35942012-11-13 22:04:29 +0000777 // ResultDisposition::Flags enum
778 struct ResultDisposition { enum Flags {
Phil Nash318c9362015-05-19 18:40:00 +0100779 Normal = 0x01,
Phil Nash90a35942012-11-13 22:04:29 +0000780
Phil Nash318c9362015-05-19 18:40:00 +0100781 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
782 FalseTest = 0x04, // Prefix expression with !
783 SuppressFail = 0x08 // Failures are reported but do not fail the test
Phil Nash90a35942012-11-13 22:04:29 +0000784 }; };
785
786 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
787 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
788 }
789
Phil Nash3e2e3182012-11-17 10:49:24 +0000790 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
Phil Nashab036682014-06-02 07:48:03 +0100791 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
Phil Nash3e2e3182012-11-17 10:49:24 +0000792 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000793
794} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100795
Phil Nashab036682014-06-02 07:48:03 +0100796// #included from: catch_assertionresult.h
797#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
798
799#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +0100800
Phil Nash89d2a3f2012-05-16 15:09:17 +0100801namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100802
Phil Nashce612bf2012-11-01 08:27:09 +0000803 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100804 {
Phil Nashce612bf2012-11-01 08:27:09 +0000805 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100806 AssertionInfo( std::string const& _macroName,
807 SourceLineInfo const& _lineInfo,
808 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000809 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100810
811 std::string macroName;
812 SourceLineInfo lineInfo;
813 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000814 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000815 };
816
817 struct AssertionResultData
818 {
819 AssertionResultData() : resultType( ResultWas::Unknown ) {}
820
Phil Nash67305122012-10-09 11:48:55 +0100821 std::string reconstructedExpression;
822 std::string message;
823 ResultWas::OfType resultType;
824 };
825
Phil Nashce612bf2012-11-01 08:27:09 +0000826 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100827 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000828 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100829 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000830 ~AssertionResult();
Phil Nash318c9362015-05-19 18:40:00 +0100831# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +0100832 AssertionResult( AssertionResult const& ) = default;
833 AssertionResult( AssertionResult && ) = default;
834 AssertionResult& operator = ( AssertionResult const& ) = default;
835 AssertionResult& operator = ( AssertionResult && ) = default;
836# endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100837
Phil Nash90a35942012-11-13 22:04:29 +0000838 bool isOk() const;
839 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100840 ResultWas::OfType getResultType() const;
841 bool hasExpression() const;
842 bool hasMessage() const;
843 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +0100844 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100845 bool hasExpandedExpression() const;
846 std::string getExpandedExpression() const;
847 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +0000848 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100849 std::string getTestMacroName() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100850
851 protected:
Phil Nashce612bf2012-11-01 08:27:09 +0000852 AssertionInfo m_info;
853 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100854 };
855
856} // end namespace Catch
857
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100858// #included from: catch_matchers.hpp
859#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
860
861namespace Catch {
862namespace Matchers {
863 namespace Impl {
864
Phil Nash08844e72015-11-05 18:52:18 +0000865 namespace Generic {
866 template<typename ExpressionT> class AllOf;
867 template<typename ExpressionT> class AnyOf;
868 template<typename ExpressionT> class Not;
869 }
870
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100871 template<typename ExpressionT>
872 struct Matcher : SharedImpl<IShared>
873 {
874 typedef ExpressionT ExpressionType;
875
876 virtual ~Matcher() {}
877 virtual Ptr<Matcher> clone() const = 0;
878 virtual bool match( ExpressionT const& expr ) const = 0;
879 virtual std::string toString() const = 0;
Phil Nash08844e72015-11-05 18:52:18 +0000880
881 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
882 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
883 Generic::Not<ExpressionT> operator ! () const;
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100884 };
885
886 template<typename DerivedT, typename ExpressionT>
887 struct MatcherImpl : Matcher<ExpressionT> {
888
889 virtual Ptr<Matcher<ExpressionT> > clone() const {
890 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
891 }
892 };
893
894 namespace Generic {
Phil Nashd234ed12015-08-24 06:28:25 +0100895 template<typename ExpressionT>
Phil Nash92356762015-11-06 18:06:56 +0000896 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
897 public:
Phil Nash08844e72015-11-05 18:52:18 +0000898 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
Phil Nashd234ed12015-08-24 06:28:25 +0100899 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
900
901 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
902 return !m_matcher->match( expr );
903 }
904
905 virtual std::string toString() const CATCH_OVERRIDE {
906 return "not " + m_matcher->toString();
907 }
Phil Nash92356762015-11-06 18:06:56 +0000908 private:
Phil Nashd234ed12015-08-24 06:28:25 +0100909 Ptr< Matcher<ExpressionT> > m_matcher;
910 };
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100911
912 template<typename ExpressionT>
913 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
914 public:
915
916 AllOf() {}
917 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
918
919 AllOf& add( Matcher<ExpressionT> const& matcher ) {
920 m_matchers.push_back( matcher.clone() );
921 return *this;
922 }
923 virtual bool match( ExpressionT const& expr ) const
924 {
925 for( std::size_t i = 0; i < m_matchers.size(); ++i )
926 if( !m_matchers[i]->match( expr ) )
927 return false;
928 return true;
929 }
930 virtual std::string toString() const {
931 std::ostringstream oss;
932 oss << "( ";
933 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
934 if( i != 0 )
935 oss << " and ";
936 oss << m_matchers[i]->toString();
937 }
938 oss << " )";
939 return oss.str();
940 }
941
Phil Nash08844e72015-11-05 18:52:18 +0000942 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
943 AllOf allOfExpr( *this );
944 allOfExpr.add( other );
945 return allOfExpr;
946 }
947
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100948 private:
949 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
950 };
951
952 template<typename ExpressionT>
953 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
954 public:
955
956 AnyOf() {}
957 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
958
959 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
960 m_matchers.push_back( matcher.clone() );
961 return *this;
962 }
963 virtual bool match( ExpressionT const& expr ) const
964 {
965 for( std::size_t i = 0; i < m_matchers.size(); ++i )
966 if( m_matchers[i]->match( expr ) )
967 return true;
968 return false;
969 }
970 virtual std::string toString() const {
971 std::ostringstream oss;
972 oss << "( ";
973 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
974 if( i != 0 )
975 oss << " or ";
976 oss << m_matchers[i]->toString();
977 }
978 oss << " )";
979 return oss.str();
980 }
981
Phil Nash08844e72015-11-05 18:52:18 +0000982 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
983 AnyOf anyOfExpr( *this );
984 anyOfExpr.add( other );
985 return anyOfExpr;
986 }
987
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100988 private:
989 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
990 };
Phil Nash08844e72015-11-05 18:52:18 +0000991
992 } // namespace Generic
993
994 template<typename ExpressionT>
995 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
996 Generic::AllOf<ExpressionT> allOfExpr;
997 allOfExpr.add( *this );
998 allOfExpr.add( other );
999 return allOfExpr;
1000 }
1001
1002 template<typename ExpressionT>
1003 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
1004 Generic::AnyOf<ExpressionT> anyOfExpr;
1005 anyOfExpr.add( *this );
1006 anyOfExpr.add( other );
1007 return anyOfExpr;
1008 }
1009
1010 template<typename ExpressionT>
1011 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
1012 return Generic::Not<ExpressionT>( *this );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001013 }
1014
1015 namespace StdString {
1016
1017 inline std::string makeString( std::string const& str ) { return str; }
1018 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
1019
1020 struct CasedString
1021 {
1022 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
1023 : m_caseSensitivity( caseSensitivity ),
1024 m_str( adjustString( str ) )
1025 {}
1026 std::string adjustString( std::string const& str ) const {
1027 return m_caseSensitivity == CaseSensitive::No
1028 ? toLower( str )
1029 : str;
1030
1031 }
1032 std::string toStringSuffix() const
1033 {
1034 return m_caseSensitivity == CaseSensitive::No
1035 ? " (case insensitive)"
1036 : "";
1037 }
1038 CaseSensitive::Choice m_caseSensitivity;
1039 std::string m_str;
1040 };
1041
1042 struct Equals : MatcherImpl<Equals, std::string> {
1043 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1044 : m_data( str, caseSensitivity )
1045 {}
1046 Equals( Equals const& other ) : m_data( other.m_data ){}
1047
1048 virtual ~Equals();
1049
1050 virtual bool match( std::string const& expr ) const {
1051 return m_data.m_str == m_data.adjustString( expr );;
1052 }
1053 virtual std::string toString() const {
1054 return "equals: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1055 }
1056
1057 CasedString m_data;
1058 };
1059
1060 struct Contains : MatcherImpl<Contains, std::string> {
1061 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1062 : m_data( substr, caseSensitivity ){}
1063 Contains( Contains const& other ) : m_data( other.m_data ){}
1064
1065 virtual ~Contains();
1066
1067 virtual bool match( std::string const& expr ) const {
1068 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1069 }
1070 virtual std::string toString() const {
1071 return "contains: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1072 }
1073
1074 CasedString m_data;
1075 };
1076
1077 struct StartsWith : MatcherImpl<StartsWith, std::string> {
1078 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1079 : m_data( substr, caseSensitivity ){}
1080
1081 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
1082
1083 virtual ~StartsWith();
1084
1085 virtual bool match( std::string const& expr ) const {
Phil Nashc7243562016-01-22 07:52:07 +00001086 return startsWith( m_data.adjustString( expr ), m_data.m_str );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001087 }
1088 virtual std::string toString() const {
1089 return "starts with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1090 }
1091
1092 CasedString m_data;
1093 };
1094
1095 struct EndsWith : MatcherImpl<EndsWith, std::string> {
1096 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1097 : m_data( substr, caseSensitivity ){}
1098 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
1099
1100 virtual ~EndsWith();
1101
1102 virtual bool match( std::string const& expr ) const {
Phil Nashc7243562016-01-22 07:52:07 +00001103 return endsWith( m_data.adjustString( expr ), m_data.m_str );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001104 }
1105 virtual std::string toString() const {
1106 return "ends with: \"" + m_data.m_str + "\"" + m_data.toStringSuffix();
1107 }
1108
1109 CasedString m_data;
1110 };
1111 } // namespace StdString
1112 } // namespace Impl
1113
1114 // The following functions create the actual matcher objects.
1115 // This allows the types to be inferred
1116 template<typename ExpressionT>
Phil Nashd234ed12015-08-24 06:28:25 +01001117 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
1118 return Impl::Generic::Not<ExpressionT>( m );
1119 }
1120
1121 template<typename ExpressionT>
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001122 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1123 Impl::Matcher<ExpressionT> const& m2 ) {
1124 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
1125 }
1126 template<typename ExpressionT>
1127 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1128 Impl::Matcher<ExpressionT> const& m2,
1129 Impl::Matcher<ExpressionT> const& m3 ) {
1130 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1131 }
1132 template<typename ExpressionT>
1133 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1134 Impl::Matcher<ExpressionT> const& m2 ) {
1135 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1136 }
1137 template<typename ExpressionT>
1138 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1139 Impl::Matcher<ExpressionT> const& m2,
1140 Impl::Matcher<ExpressionT> const& m3 ) {
1141 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1142 }
1143
1144 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1145 return Impl::StdString::Equals( str, caseSensitivity );
1146 }
1147 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1148 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1149 }
1150 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1151 return Impl::StdString::Contains( substr, caseSensitivity );
1152 }
1153 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1154 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1155 }
1156 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
1157 return Impl::StdString::StartsWith( substr );
1158 }
1159 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
1160 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1161 }
1162 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
1163 return Impl::StdString::EndsWith( substr );
1164 }
1165 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
1166 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1167 }
1168
1169} // namespace Matchers
1170
1171using namespace Matchers;
1172
1173} // namespace Catch
1174
Phil Nashab036682014-06-02 07:48:03 +01001175namespace Catch {
1176
1177 struct TestFailureException{};
1178
1179 template<typename T> class ExpressionLhs;
1180
1181 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
1182
1183 struct CopyableStream {
1184 CopyableStream() {}
1185 CopyableStream( CopyableStream const& other ) {
1186 oss << other.oss.str();
1187 }
1188 CopyableStream& operator=( CopyableStream const& other ) {
1189 oss.str("");
1190 oss << other.oss.str();
1191 return *this;
1192 }
1193 std::ostringstream oss;
1194 };
1195
1196 class ResultBuilder {
1197 public:
1198 ResultBuilder( char const* macroName,
1199 SourceLineInfo const& lineInfo,
1200 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01001201 ResultDisposition::Flags resultDisposition,
1202 char const* secondArg = "" );
Phil Nashab036682014-06-02 07:48:03 +01001203
1204 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001205 ExpressionLhs<T const&> operator <= ( T const& operand );
1206 ExpressionLhs<bool> operator <= ( bool value );
Phil Nashab036682014-06-02 07:48:03 +01001207
1208 template<typename T>
1209 ResultBuilder& operator << ( T const& value ) {
1210 m_stream.oss << value;
1211 return *this;
1212 }
1213
1214 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1215 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
1216
1217 ResultBuilder& setResultType( ResultWas::OfType result );
1218 ResultBuilder& setResultType( bool result );
1219 ResultBuilder& setLhs( std::string const& lhs );
1220 ResultBuilder& setRhs( std::string const& rhs );
1221 ResultBuilder& setOp( std::string const& op );
1222
1223 void endExpression();
1224
1225 std::string reconstructExpression() const;
1226 AssertionResult build() const;
1227
1228 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1229 void captureResult( ResultWas::OfType resultType );
1230 void captureExpression();
Phil Nash93a842e2015-07-13 06:36:07 +01001231 void captureExpectedException( std::string const& expectedMessage );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001232 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
Phil Nash93a842e2015-07-13 06:36:07 +01001233 void handleResult( AssertionResult const& result );
Phil Nashab036682014-06-02 07:48:03 +01001234 void react();
1235 bool shouldDebugBreak() const;
1236 bool allowThrows() const;
1237
1238 private:
1239 AssertionInfo m_assertionInfo;
1240 AssertionResultData m_data;
1241 struct ExprComponents {
1242 ExprComponents() : testFalse( false ) {}
1243 bool testFalse;
1244 std::string lhs, rhs, op;
1245 } m_exprComponents;
1246 CopyableStream m_stream;
1247
1248 bool m_shouldDebugBreak;
1249 bool m_shouldThrow;
1250 };
1251
1252} // namespace Catch
1253
1254// Include after due to circular dependency:
1255// #included from: catch_expression_lhs.hpp
1256#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1257
Phil Nash89d1e6c2011-05-24 08:23:02 +01001258// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001259#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001260
Phil Nashdd26e882013-03-25 09:25:31 +00001261#ifdef _MSC_VER
1262#pragma warning(push)
1263#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1264#endif
1265
Phil Nash17404952014-04-23 18:19:49 +01001266#include <cstddef>
1267
Phil Nash89d2a3f2012-05-16 15:09:17 +01001268namespace Catch {
1269namespace Internal {
1270
1271 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001272 IsEqualTo,
1273 IsNotEqualTo,
1274 IsLessThan,
1275 IsGreaterThan,
1276 IsLessThanOrEqualTo,
1277 IsGreaterThanOrEqualTo
1278 };
1279
Phil Nash371db8b2012-05-21 18:52:09 +01001280 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1281 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1282 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1283 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1284 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1285 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1286 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +01001287
Phil Nash471eba22013-04-22 18:55:12 +01001288 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001289 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +01001290
1291// nullptr_t support based on pull request #154 from Konstantin Baumann
1292#ifdef CATCH_CONFIG_CPP11_NULLPTR
1293 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1294#endif // CATCH_CONFIG_CPP11_NULLPTR
1295
Phil Nash89d1e6c2011-05-24 08:23:02 +01001296 // So the compare overloads can be operator agnostic we convey the operator as a template
1297 // enum, which is used to specialise an Evaluator for doing the comparison.
1298 template<typename T1, typename T2, Operator Op>
1299 class Evaluator{};
1300
1301 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001302 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001303 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001304 return bool( opCast( lhs ) == opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001305 }
1306 };
1307 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001308 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001309 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001310 return bool( opCast( lhs ) != opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001311 }
1312 };
1313 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001314 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001315 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001316 return bool( opCast( lhs ) < opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001317 }
1318 };
1319 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001320 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001321 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001322 return bool( opCast( lhs ) > opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001323 }
1324 };
1325 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001326 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001327 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001328 return bool( opCast( lhs ) >= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001329 }
1330 };
1331 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001332 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001333 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001334 return bool( opCast( lhs ) <= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001335 }
1336 };
1337
1338 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001339 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001340 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1341 }
1342
Phil Nash90a35942012-11-13 22:04:29 +00001343 // This level of indirection allows us to specialise for integer types
1344 // to avoid signed/ unsigned warnings
1345
Phil Nash89d1e6c2011-05-24 08:23:02 +01001346 // "base" overload
1347 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001348 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001349 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1350 }
1351
1352 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001353 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001354 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1355 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001356 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001357 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1358 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001359 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001360 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1361 }
1362
1363 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001364 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001365 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1366 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001367 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001368 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1369 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001370 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001371 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1372 }
1373
1374 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001375 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001376 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1377 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001378 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001379 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1380 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001381 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001382 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1383 }
1384
1385 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001386 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001387 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001388 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001389 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001390 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001391 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001392 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001393 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001394 }
1395
Phil Nash06e959b2012-05-25 08:52:05 +01001396 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001397 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001398 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001399 }
Phil Nash90a35942012-11-13 22:04:29 +00001400 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001401 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001402 }
1403
Phil Nash06e959b2012-05-25 08:52:05 +01001404 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001405 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001406 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1407 }
Phil Nash90a35942012-11-13 22:04:29 +00001408 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001409 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1410 }
1411
Phil Nash2f6371f2015-07-23 23:06:26 +01001412#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1413 // long long to unsigned X
1414 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1415 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1416 }
1417 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1418 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1419 }
1420 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1421 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1422 }
1423 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1424 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1425 }
1426
1427 // unsigned long long to X
1428 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1429 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1430 }
1431 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1432 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1433 }
1434 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1435 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1436 }
1437 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1438 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1439 }
1440
1441 // pointer to long long (when comparing against NULL)
1442 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1443 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1444 }
1445 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1446 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1447 }
1448#endif // CATCH_CONFIG_CPP11_LONG_LONG
1449
Phil Nash471eba22013-04-22 18:55:12 +01001450#ifdef CATCH_CONFIG_CPP11_NULLPTR
1451 // pointer to nullptr_t (when comparing against nullptr)
1452 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001453 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
Phil Nash471eba22013-04-22 18:55:12 +01001454 }
1455 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001456 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
Phil Nash471eba22013-04-22 18:55:12 +01001457 }
1458#endif // CATCH_CONFIG_CPP11_NULLPTR
1459
Phil Nash89d1e6c2011-05-24 08:23:02 +01001460} // end of namespace Internal
1461} // end of namespace Catch
1462
Phil Nashdd26e882013-03-25 09:25:31 +00001463#ifdef _MSC_VER
1464#pragma warning(pop)
1465#endif
1466
Phil Nashab036682014-06-02 07:48:03 +01001467// #included from: catch_tostring.h
1468#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1469
Phil Nashab036682014-06-02 07:48:03 +01001470#include <sstream>
1471#include <iomanip>
1472#include <limits>
1473#include <vector>
1474#include <cstddef>
1475
1476#ifdef __OBJC__
1477// #included from: catch_objc_arc.hpp
1478#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1479
1480#import <Foundation/Foundation.h>
1481
1482#ifdef __has_feature
1483#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1484#else
1485#define CATCH_ARC_ENABLED 0
1486#endif
1487
1488void arcSafeRelease( NSObject* obj );
1489id performOptionalSelector( id obj, SEL sel );
1490
1491#if !CATCH_ARC_ENABLED
1492inline void arcSafeRelease( NSObject* obj ) {
1493 [obj release];
1494}
1495inline id performOptionalSelector( id obj, SEL sel ) {
1496 if( [obj respondsToSelector: sel] )
1497 return [obj performSelector: sel];
1498 return nil;
1499}
1500#define CATCH_UNSAFE_UNRETAINED
1501#define CATCH_ARC_STRONG
1502#else
1503inline void arcSafeRelease( NSObject* ){}
1504inline id performOptionalSelector( id obj, SEL sel ) {
1505#ifdef __clang__
1506#pragma clang diagnostic push
1507#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1508#endif
1509 if( [obj respondsToSelector: sel] )
1510 return [obj performSelector: sel];
1511#ifdef __clang__
1512#pragma clang diagnostic pop
1513#endif
1514 return nil;
1515}
1516#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1517#define CATCH_ARC_STRONG __strong
1518#endif
1519
1520#endif
1521
Phil Nash318c9362015-05-19 18:40:00 +01001522#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001523#include <tuple>
Phil Nash318c9362015-05-19 18:40:00 +01001524#endif
1525
1526#ifdef CATCH_CONFIG_CPP11_IS_ENUM
Phil Nash7f561522014-12-30 18:47:29 +00001527#include <type_traits>
1528#endif
1529
Phil Nashab036682014-06-02 07:48:03 +01001530namespace Catch {
Phil Nash4caabfa2014-09-03 19:23:22 +01001531
1532// Why we're here.
1533template<typename T>
1534std::string toString( T const& value );
1535
Phil Nash7f561522014-12-30 18:47:29 +00001536// Built in overloads
1537
1538std::string toString( std::string const& value );
1539std::string toString( std::wstring const& value );
1540std::string toString( const char* const value );
1541std::string toString( char* const value );
1542std::string toString( const wchar_t* const value );
1543std::string toString( wchar_t* const value );
1544std::string toString( int value );
1545std::string toString( unsigned long value );
1546std::string toString( unsigned int value );
1547std::string toString( const double value );
1548std::string toString( const float value );
1549std::string toString( bool value );
1550std::string toString( char value );
1551std::string toString( signed char value );
1552std::string toString( unsigned char value );
1553
Phil Nash2f6371f2015-07-23 23:06:26 +01001554#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1555std::string toString( long long value );
1556std::string toString( unsigned long long value );
1557#endif
1558
Phil Nash7f561522014-12-30 18:47:29 +00001559#ifdef CATCH_CONFIG_CPP11_NULLPTR
1560std::string toString( std::nullptr_t );
1561#endif
1562
1563#ifdef __OBJC__
1564 std::string toString( NSString const * const& nsstring );
1565 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1566 std::string toString( NSObject* const& nsObject );
1567#endif
1568
Phil Nashab036682014-06-02 07:48:03 +01001569namespace Detail {
1570
Phil Nash2f6371f2015-07-23 23:06:26 +01001571 extern const std::string unprintableString;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001572
Phil Nashab036682014-06-02 07:48:03 +01001573 struct BorgType {
1574 template<typename T> BorgType( T const& );
1575 };
1576
Phil Nash3b18d9e2015-06-30 18:26:09 +01001577 struct TrueType { char sizer[1]; };
1578 struct FalseType { char sizer[2]; };
1579
Phil Nashab036682014-06-02 07:48:03 +01001580 TrueType& testStreamable( std::ostream& );
1581 FalseType testStreamable( FalseType );
1582
1583 FalseType operator<<( std::ostream const&, BorgType const& );
1584
1585 template<typename T>
1586 struct IsStreamInsertable {
1587 static std::ostream &s;
1588 static T const&t;
1589 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1590 };
1591
Phil Nash318c9362015-05-19 18:40:00 +01001592#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001593 template<typename T,
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001594 bool IsEnum = std::is_enum<T>::value
Phil Nash4caabfa2014-09-03 19:23:22 +01001595 >
1596 struct EnumStringMaker
1597 {
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001598 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001599 };
1600
1601 template<typename T>
1602 struct EnumStringMaker<T,true>
1603 {
1604 static std::string convert( T const& v )
1605 {
1606 return ::Catch::toString(
1607 static_cast<typename std::underlying_type<T>::type>(v)
1608 );
1609 }
1610 };
1611#endif
Phil Nashab036682014-06-02 07:48:03 +01001612 template<bool C>
1613 struct StringMakerBase {
Phil Nash318c9362015-05-19 18:40:00 +01001614#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001615 template<typename T>
1616 static std::string convert( T const& v )
1617 {
1618 return EnumStringMaker<T>::convert( v );
1619 }
1620#else
Phil Nashab036682014-06-02 07:48:03 +01001621 template<typename T>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001622 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001623#endif
Phil Nashab036682014-06-02 07:48:03 +01001624 };
1625
1626 template<>
1627 struct StringMakerBase<true> {
1628 template<typename T>
1629 static std::string convert( T const& _value ) {
1630 std::ostringstream oss;
1631 oss << _value;
1632 return oss.str();
1633 }
1634 };
1635
1636 std::string rawMemoryToString( const void *object, std::size_t size );
1637
1638 template<typename T>
1639 inline std::string rawMemoryToString( const T& object ) {
1640 return rawMemoryToString( &object, sizeof(object) );
Phil Nash67305122012-10-09 11:48:55 +01001641 }
1642
Phil Nashab036682014-06-02 07:48:03 +01001643} // end namespace Detail
Phil Nashce612bf2012-11-01 08:27:09 +00001644
Phil Nashab036682014-06-02 07:48:03 +01001645template<typename T>
Phil Nashab036682014-06-02 07:48:03 +01001646struct StringMaker :
1647 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nashcd688302013-06-29 12:11:32 +01001648
Phil Nashab036682014-06-02 07:48:03 +01001649template<typename T>
1650struct StringMaker<T*> {
1651 template<typename U>
1652 static std::string convert( U* p ) {
1653 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001654 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001655 else
1656 return Detail::rawMemoryToString( p );
1657 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001658};
1659
Phil Nashab036682014-06-02 07:48:03 +01001660template<typename R, typename C>
1661struct StringMaker<R C::*> {
1662 static std::string convert( R C::* p ) {
1663 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001664 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001665 else
1666 return Detail::rawMemoryToString( p );
1667 }
1668};
1669
1670namespace Detail {
1671 template<typename InputIterator>
1672 std::string rangeToString( InputIterator first, InputIterator last );
1673}
1674
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001675//template<typename T, typename Allocator>
1676//struct StringMaker<std::vector<T, Allocator> > {
1677// static std::string convert( std::vector<T,Allocator> const& v ) {
1678// return Detail::rangeToString( v.begin(), v.end() );
1679// }
1680//};
1681
Phil Nashab036682014-06-02 07:48:03 +01001682template<typename T, typename Allocator>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001683std::string toString( std::vector<T,Allocator> const& v ) {
1684 return Detail::rangeToString( v.begin(), v.end() );
1685}
Phil Nashab036682014-06-02 07:48:03 +01001686
Phil Nash318c9362015-05-19 18:40:00 +01001687#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash572911d2015-03-04 18:33:31 +00001688
1689// toString for tuples
Phil Nash7f561522014-12-30 18:47:29 +00001690namespace TupleDetail {
1691 template<
1692 typename Tuple,
1693 std::size_t N = 0,
1694 bool = (N < std::tuple_size<Tuple>::value)
1695 >
1696 struct ElementPrinter {
1697 static void print( const Tuple& tuple, std::ostream& os )
1698 {
1699 os << ( N ? ", " : " " )
1700 << Catch::toString(std::get<N>(tuple));
1701 ElementPrinter<Tuple,N+1>::print(tuple,os);
1702 }
1703 };
1704
1705 template<
1706 typename Tuple,
1707 std::size_t N
1708 >
1709 struct ElementPrinter<Tuple,N,false> {
1710 static void print( const Tuple&, std::ostream& ) {}
1711 };
1712
1713}
1714
1715template<typename ...Types>
1716struct StringMaker<std::tuple<Types...>> {
1717
1718 static std::string convert( const std::tuple<Types...>& tuple )
1719 {
1720 std::ostringstream os;
1721 os << '{';
1722 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1723 os << " }";
1724 return os.str();
1725 }
1726};
Phil Nash318c9362015-05-19 18:40:00 +01001727#endif // CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001728
Phil Nashab036682014-06-02 07:48:03 +01001729namespace Detail {
1730 template<typename T>
1731 std::string makeString( T const& value ) {
1732 return StringMaker<T>::convert( value );
1733 }
1734} // end namespace Detail
1735
1736/// \brief converts any type to a string
1737///
1738/// The default template forwards on to ostringstream - except when an
1739/// ostringstream overload does not exist - in which case it attempts to detect
1740/// that and writes {?}.
1741/// Overload (not specialise) this template for custom typs that you don't want
1742/// to provide an ostream overload for.
1743template<typename T>
1744std::string toString( T const& value ) {
1745 return StringMaker<T>::convert( value );
1746}
1747
Phil Nashab036682014-06-02 07:48:03 +01001748 namespace Detail {
1749 template<typename InputIterator>
1750 std::string rangeToString( InputIterator first, InputIterator last ) {
1751 std::ostringstream oss;
1752 oss << "{ ";
1753 if( first != last ) {
Phil Nash13f98432014-12-12 08:11:18 +00001754 oss << Catch::toString( *first );
1755 for( ++first ; first != last ; ++first )
1756 oss << ", " << Catch::toString( *first );
Phil Nashab036682014-06-02 07:48:03 +01001757 }
1758 oss << " }";
1759 return oss.str();
1760 }
1761}
1762
Phil Nashd31737f2012-05-09 19:04:00 +01001763} // end namespace Catch
1764
Phil Nash89d2a3f2012-05-16 15:09:17 +01001765namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001766
Phil Nashd7e17902014-04-18 08:49:35 +01001767// Wraps the LHS of an expression and captures the operator and RHS (if any) -
Phil Nashab036682014-06-02 07:48:03 +01001768// wrapping them all in a ResultBuilder object
Phil Nash176eb812012-05-11 08:17:16 +01001769template<typename T>
Phil Nashce612bf2012-11-01 08:27:09 +00001770class ExpressionLhs {
Phil Nashd7e17902014-04-18 08:49:35 +01001771 ExpressionLhs& operator = ( ExpressionLhs const& );
Phil Nash318c9362015-05-19 18:40:00 +01001772# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01001773 ExpressionLhs& operator = ( ExpressionLhs && ) = delete;
1774# endif
Phil Nash176eb812012-05-11 08:17:16 +01001775
1776public:
Phil Nashab036682014-06-02 07:48:03 +01001777 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ) {}
Phil Nash318c9362015-05-19 18:40:00 +01001778# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01001779 ExpressionLhs( ExpressionLhs const& ) = default;
1780 ExpressionLhs( ExpressionLhs && ) = default;
1781# endif
Phil Nash176eb812012-05-11 08:17:16 +01001782
1783 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001784 ResultBuilder& operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001785 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001786 }
1787
1788 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001789 ResultBuilder& operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001790 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001791 }
1792
1793 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001794 ResultBuilder& operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001795 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001796 }
1797
1798 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001799 ResultBuilder& operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001800 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001801 }
1802
1803 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001804 ResultBuilder& operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001805 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001806 }
1807
1808 template<typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001809 ResultBuilder& operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001810 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001811 }
1812
Phil Nashab036682014-06-02 07:48:03 +01001813 ResultBuilder& operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001814 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001815 }
1816
Phil Nashab036682014-06-02 07:48:03 +01001817 ResultBuilder& operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001818 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001819 }
1820
Phil Nashab036682014-06-02 07:48:03 +01001821 void endExpression() {
Phil Nashce612bf2012-11-01 08:27:09 +00001822 bool value = m_lhs ? true : false;
Phil Nashab036682014-06-02 07:48:03 +01001823 m_rb
Phil Nashce612bf2012-11-01 08:27:09 +00001824 .setLhs( Catch::toString( value ) )
1825 .setResultType( value )
Phil Nashab036682014-06-02 07:48:03 +01001826 .endExpression();
Phil Nash176eb812012-05-11 08:17:16 +01001827 }
1828
Phil Nashce612bf2012-11-01 08:27:09 +00001829 // Only simple binary expressions are allowed on the LHS.
1830 // If more complex compositions are required then place the sub expression in parentheses
Phil Nash8defc712013-04-24 19:10:02 +01001831 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( RhsT const& );
1832 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( RhsT const& );
1833 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( RhsT const& );
1834 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( RhsT const& );
Phil Nashcd688302013-06-29 12:11:32 +01001835 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( RhsT const& );
1836 template<typename RhsT> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( RhsT const& );
Phil Nash176eb812012-05-11 08:17:16 +01001837
1838private:
Phil Nash9902ac92012-10-09 20:58:33 +01001839 template<Internal::Operator Op, typename RhsT>
Phil Nashab036682014-06-02 07:48:03 +01001840 ResultBuilder& captureExpression( RhsT const& rhs ) {
1841 return m_rb
Phil Nashce612bf2012-11-01 08:27:09 +00001842 .setResultType( Internal::compare<Op>( m_lhs, rhs ) )
1843 .setLhs( Catch::toString( m_lhs ) )
Phil Nash9902ac92012-10-09 20:58:33 +01001844 .setRhs( Catch::toString( rhs ) )
1845 .setOp( Internal::OperatorTraits<Op>::getName() );
1846 }
1847
1848private:
Phil Nashab036682014-06-02 07:48:03 +01001849 ResultBuilder& m_rb;
Phil Nash176eb812012-05-11 08:17:16 +01001850 T m_lhs;
1851};
1852
Phil Nash176eb812012-05-11 08:17:16 +01001853} // end namespace Catch
1854
Phil Nashab036682014-06-02 07:48:03 +01001855
Phil Nash89d2a3f2012-05-16 15:09:17 +01001856namespace Catch {
1857
Phil Nash89d2a3f2012-05-16 15:09:17 +01001858 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001859 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
Phil Nashab036682014-06-02 07:48:03 +01001860 return ExpressionLhs<T const&>( *this, operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001861 }
1862
Phil Nash21f7ef62015-06-29 18:05:23 +01001863 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
Phil Nashab036682014-06-02 07:48:03 +01001864 return ExpressionLhs<bool>( *this, value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001865 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001866
Phil Nashab036682014-06-02 07:48:03 +01001867} // namespace Catch
Phil Nash89d2a3f2012-05-16 15:09:17 +01001868
Phil Nasha2773812013-02-02 20:37:58 +00001869// #included from: catch_message.h
1870#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1871
1872#include <string>
1873
1874namespace Catch {
1875
1876 struct MessageInfo {
1877 MessageInfo( std::string const& _macroName,
1878 SourceLineInfo const& _lineInfo,
1879 ResultWas::OfType _type );
1880
1881 std::string macroName;
1882 SourceLineInfo lineInfo;
1883 ResultWas::OfType type;
1884 std::string message;
1885 unsigned int sequence;
1886
1887 bool operator == ( MessageInfo const& other ) const {
1888 return sequence == other.sequence;
1889 }
1890 bool operator < ( MessageInfo const& other ) const {
1891 return sequence < other.sequence;
1892 }
1893 private:
1894 static unsigned int globalCount;
1895 };
1896
Phil Nashb5fd5a62013-06-28 17:09:57 +01001897 struct MessageBuilder {
1898 MessageBuilder( std::string const& macroName,
1899 SourceLineInfo const& lineInfo,
1900 ResultWas::OfType type )
1901 : m_info( macroName, lineInfo, type )
1902 {}
Phil Nasha2773812013-02-02 20:37:58 +00001903
1904 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01001905 MessageBuilder& operator << ( T const& value ) {
1906 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00001907 return *this;
1908 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01001909
1910 MessageInfo m_info;
1911 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00001912 };
1913
Phil Nashb5fd5a62013-06-28 17:09:57 +01001914 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00001915 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01001916 ScopedMessage( MessageBuilder const& builder );
Phil Nash9241e432014-05-20 18:50:59 +01001917 ScopedMessage( ScopedMessage const& other );
Phil Nashb5fd5a62013-06-28 17:09:57 +01001918 ~ScopedMessage();
1919
1920 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00001921 };
1922
1923} // end namespace Catch
1924
Phil Nashd31737f2012-05-09 19:04:00 +01001925// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01001926#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001927
Phil Nashd31737f2012-05-09 19:04:00 +01001928#include <string>
1929
Phil Nash89d2a3f2012-05-16 15:09:17 +01001930namespace Catch {
1931
Phil Nasha1fbfea2012-12-01 23:57:18 +00001932 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00001933 class AssertionResult;
1934 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001935 struct SectionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07001936 struct SectionEndInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001937 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00001938 class ScopedMessageBuilder;
Phil Nash3649fdf2013-12-03 18:53:55 +00001939 struct Counts;
Phil Nashd31737f2012-05-09 19:04:00 +01001940
Phil Nash89d2a3f2012-05-16 15:09:17 +01001941 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01001942
Phil Nasha695eb92012-08-13 07:46:10 +01001943 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001944
Phil Nasha2773812013-02-02 20:37:58 +00001945 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00001946 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01001947 Counts& assertions ) = 0;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07001948 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
1949 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01001950 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
1951 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00001952
Phil Nash89d2a3f2012-05-16 15:09:17 +01001953 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00001954 virtual const AssertionResult* getLastResult() const = 0;
Phil Nash93b61e12014-08-22 19:35:41 +01001955
1956 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01001957 };
Phil Nashab036682014-06-02 07:48:03 +01001958
1959 IResultCapture& getResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01001960}
1961
Phil Nash3649fdf2013-12-03 18:53:55 +00001962// #included from: catch_debugger.h
1963#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01001964
Phil Nash04a33642013-08-16 19:09:09 +01001965// #included from: catch_platform.h
1966#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
1967
Phil Nashd31737f2012-05-09 19:04:00 +01001968#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
1969#define CATCH_PLATFORM_MAC
1970#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
1971#define CATCH_PLATFORM_IPHONE
Phil Nash04a33642013-08-16 19:09:09 +01001972#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Phil Nashd31737f2012-05-09 19:04:00 +01001973#define CATCH_PLATFORM_WINDOWS
1974#endif
1975
Phil Nash3649fdf2013-12-03 18:53:55 +00001976#include <string>
1977
1978namespace Catch{
1979
1980 bool isDebuggerActive();
1981 void writeToDebugConsole( std::string const& text );
1982}
1983
Phil Nashd31737f2012-05-09 19:04:00 +01001984#ifdef CATCH_PLATFORM_MAC
1985
Phil Nash3649fdf2013-12-03 18:53:55 +00001986 // The following code snippet based on:
Phil Nashd31737f2012-05-09 19:04:00 +01001987 // http://cocoawithlove.com/2008/03/break-into-debugger.html
1988 #ifdef DEBUG
1989 #if defined(__ppc64__) || defined(__ppc__)
Phil Nash3649fdf2013-12-03 18:53:55 +00001990 #define CATCH_BREAK_INTO_DEBUGGER() \
1991 if( Catch::isDebuggerActive() ) { \
1992 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
1993 : : : "memory","r0","r3","r4" ); \
1994 }
Phil Nashd31737f2012-05-09 19:04:00 +01001995 #else
Phil Nash3649fdf2013-12-03 18:53:55 +00001996 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) {__asm__("int $3\n" : : );}
Phil Nashd31737f2012-05-09 19:04:00 +01001997 #endif
Phil Nashd31737f2012-05-09 19:04:00 +01001998 #endif
1999
2000#elif defined(_MSC_VER)
Phil Nash3649fdf2013-12-03 18:53:55 +00002001 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { __debugbreak(); }
Phil Nash176eb812012-05-11 08:17:16 +01002002#elif defined(__MINGW32__)
Phil Nash176eb812012-05-11 08:17:16 +01002003 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
Phil Nash3649fdf2013-12-03 18:53:55 +00002004 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { DebugBreak(); }
Phil Nashd31737f2012-05-09 19:04:00 +01002005#endif
2006
Phil Nash3649fdf2013-12-03 18:53:55 +00002007#ifndef CATCH_BREAK_INTO_DEBUGGER
Phil Nashab036682014-06-02 07:48:03 +01002008#define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
Phil Nash3649fdf2013-12-03 18:53:55 +00002009#endif
Phil Nashd31737f2012-05-09 19:04:00 +01002010
Phil Nashab036682014-06-02 07:48:03 +01002011// #included from: catch_interfaces_runner.h
2012#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash37186a12013-03-13 12:19:30 +00002013
Phil Nasha70fbe32012-08-31 08:10:36 +01002014namespace Catch {
Phil Nash3649fdf2013-12-03 18:53:55 +00002015 class TestCase;
Phil Nasha70fbe32012-08-31 08:10:36 +01002016
Phil Nashab036682014-06-02 07:48:03 +01002017 struct IRunner {
2018 virtual ~IRunner();
2019 virtual bool aborting() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002020 };
2021}
2022
Phil Nashce612bf2012-11-01 08:27:09 +00002023///////////////////////////////////////////////////////////////////////////////
Phil Nashab036682014-06-02 07:48:03 +01002024// In the event of a failure works out if the debugger needs to be invoked
2025// and/or an exception thrown and takes appropriate action.
2026// This needs to be done as a macro so the debugger will stop in the user
2027// source code rather than in Catch library code
2028#define INTERNAL_CATCH_REACT( resultBuilder ) \
2029 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2030 resultBuilder.react();
Phil Nashce612bf2012-11-01 08:27:09 +00002031
2032///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002033#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002034 do { \
Phil Nashab036682014-06-02 07:48:03 +01002035 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002036 try { \
Phil Nashae5ee2c2016-02-29 08:17:18 +00002037 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
Phil Nash21f7ef62015-06-29 18:05:23 +01002038 ( __catchResult <= expr ).endExpression(); \
Phil Nashce612bf2012-11-01 08:27:09 +00002039 } \
Phil Nashab036682014-06-02 07:48:03 +01002040 catch( ... ) { \
2041 __catchResult.useActiveException( Catch::ResultDisposition::Normal ); \
2042 } \
2043 INTERNAL_CATCH_REACT( __catchResult ) \
Phil Nash3b4edd72016-02-10 19:24:48 +00002044 } 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
Phil Nashce612bf2012-11-01 08:27:09 +00002045
2046///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002047#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2048 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2049 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002050
2051///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002052#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2053 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2054 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002055
2056///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002057#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002058 do { \
Phil Nashab036682014-06-02 07:48:03 +01002059 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002060 try { \
2061 expr; \
Phil Nashab036682014-06-02 07:48:03 +01002062 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002063 } \
2064 catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002065 __catchResult.useActiveException( resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002066 } \
Phil Nashab036682014-06-02 07:48:03 +01002067 INTERNAL_CATCH_REACT( __catchResult ) \
2068 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002069
2070///////////////////////////////////////////////////////////////////////////////
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002071#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002072 do { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002073 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002074 if( __catchResult.allowThrows() ) \
2075 try { \
Phil Nashab036682014-06-02 07:48:03 +01002076 expr; \
Phil Nashacdd3b52014-06-30 07:35:36 +01002077 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2078 } \
2079 catch( ... ) { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002080 __catchResult.captureExpectedException( matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002081 } \
2082 else \
Phil Nashab036682014-06-02 07:48:03 +01002083 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002084 INTERNAL_CATCH_REACT( __catchResult ) \
2085 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002086
2087///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002088#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002089 do { \
Phil Nashab036682014-06-02 07:48:03 +01002090 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002091 if( __catchResult.allowThrows() ) \
2092 try { \
Phil Nashab036682014-06-02 07:48:03 +01002093 expr; \
Phil Nashacdd3b52014-06-30 07:35:36 +01002094 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2095 } \
2096 catch( exceptionType ) { \
2097 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2098 } \
2099 catch( ... ) { \
2100 __catchResult.useActiveException( resultDisposition ); \
2101 } \
2102 else \
Phil Nashab036682014-06-02 07:48:03 +01002103 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002104 INTERNAL_CATCH_REACT( __catchResult ) \
2105 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002106
2107///////////////////////////////////////////////////////////////////////////////
Phil Nash859760a2013-12-14 14:34:05 +00002108#ifdef CATCH_CONFIG_VARIADIC_MACROS
2109 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2110 do { \
Phil Nashab036682014-06-02 07:48:03 +01002111 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2112 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2113 __catchResult.captureResult( messageType ); \
2114 INTERNAL_CATCH_REACT( __catchResult ) \
2115 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002116#else
2117 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2118 do { \
Phil Nashab036682014-06-02 07:48:03 +01002119 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2120 __catchResult << log + ::Catch::StreamEndStop(); \
2121 __catchResult.captureResult( messageType ); \
2122 INTERNAL_CATCH_REACT( __catchResult ) \
2123 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002124#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002125
2126///////////////////////////////////////////////////////////////////////////////
Phil Nashb5fd5a62013-06-28 17:09:57 +01002127#define INTERNAL_CATCH_INFO( log, macroName ) \
2128 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00002129
2130///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002131#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002132 do { \
Phil Nash7424b232015-12-28 15:07:32 +00002133 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002134 try { \
Phil Nash08844e72015-11-05 18:52:18 +00002135 std::string matcherAsString = (matcher).toString(); \
Phil Nashab036682014-06-02 07:48:03 +01002136 __catchResult \
2137 .setLhs( Catch::toString( arg ) ) \
Phil Nash6a8e8ad2014-09-15 18:40:24 +01002138 .setRhs( matcherAsString == Catch::Detail::unprintableString ? #matcher : matcherAsString ) \
Phil Nashab036682014-06-02 07:48:03 +01002139 .setOp( "matches" ) \
Phil Nash08844e72015-11-05 18:52:18 +00002140 .setResultType( (matcher).match( arg ) ); \
Phil Nashab036682014-06-02 07:48:03 +01002141 __catchResult.captureExpression(); \
Phil Nashce612bf2012-11-01 08:27:09 +00002142 } catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002143 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002144 } \
Phil Nashab036682014-06-02 07:48:03 +01002145 INTERNAL_CATCH_REACT( __catchResult ) \
2146 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002147
Phil Nash3649fdf2013-12-03 18:53:55 +00002148// #included from: internal/catch_section.h
2149#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2150
2151// #included from: catch_section_info.h
2152#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2153
Phil Nash3649fdf2013-12-03 18:53:55 +00002154// #included from: catch_totals.hpp
2155#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2156
2157#include <cstddef>
2158
2159namespace Catch {
2160
2161 struct Counts {
Phil Nash52e1e742014-07-03 08:11:38 +01002162 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
Phil Nash3649fdf2013-12-03 18:53:55 +00002163
2164 Counts operator - ( Counts const& other ) const {
2165 Counts diff;
2166 diff.passed = passed - other.passed;
2167 diff.failed = failed - other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002168 diff.failedButOk = failedButOk - other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002169 return diff;
2170 }
2171 Counts& operator += ( Counts const& other ) {
2172 passed += other.passed;
2173 failed += other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002174 failedButOk += other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002175 return *this;
2176 }
2177
2178 std::size_t total() const {
Phil Nash52e1e742014-07-03 08:11:38 +01002179 return passed + failed + failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002180 }
Phil Nash28c2e072014-07-09 19:22:49 +01002181 bool allPassed() const {
2182 return failed == 0 && failedButOk == 0;
2183 }
Phil Nashd76e0812014-12-30 18:26:07 +00002184 bool allOk() const {
2185 return failed == 0;
2186 }
Phil Nash3649fdf2013-12-03 18:53:55 +00002187
2188 std::size_t passed;
2189 std::size_t failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002190 std::size_t failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002191 };
2192
2193 struct Totals {
2194
2195 Totals operator - ( Totals const& other ) const {
2196 Totals diff;
2197 diff.assertions = assertions - other.assertions;
2198 diff.testCases = testCases - other.testCases;
2199 return diff;
2200 }
2201
2202 Totals delta( Totals const& prevTotals ) const {
2203 Totals diff = *this - prevTotals;
2204 if( diff.assertions.failed > 0 )
2205 ++diff.testCases.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002206 else if( diff.assertions.failedButOk > 0 )
2207 ++diff.testCases.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002208 else
2209 ++diff.testCases.passed;
2210 return diff;
2211 }
2212
2213 Totals& operator += ( Totals const& other ) {
2214 assertions += other.assertions;
2215 testCases += other.testCases;
2216 return *this;
2217 }
2218
2219 Counts assertions;
2220 Counts testCases;
2221 };
2222}
Phil Nashce612bf2012-11-01 08:27:09 +00002223
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002224namespace Catch {
2225
2226 struct SectionInfo {
2227 SectionInfo
2228 ( SourceLineInfo const& _lineInfo,
2229 std::string const& _name,
2230 std::string const& _description = std::string() );
2231
2232 std::string name;
2233 std::string description;
2234 SourceLineInfo lineInfo;
2235 };
2236
2237 struct SectionEndInfo {
2238 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2239 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2240 {}
2241
2242 SectionInfo sectionInfo;
2243 Counts prevAssertions;
2244 double durationInSeconds;
2245 };
2246
2247} // end namespace Catch
2248
Phil Nashaa7123b2013-08-15 19:01:00 +01002249// #included from: catch_timer.h
2250#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2251
Phil Nash04a33642013-08-16 19:09:09 +01002252#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01002253typedef unsigned long long uint64_t;
2254#else
2255#include <stdint.h>
2256#endif
2257
2258namespace Catch {
2259
2260 class Timer {
2261 public:
2262 Timer() : m_ticks( 0 ) {}
2263 void start();
Phil Nash4caabfa2014-09-03 19:23:22 +01002264 unsigned int getElapsedMicroseconds() const;
Phil Nashaa7123b2013-08-15 19:01:00 +01002265 unsigned int getElapsedMilliseconds() const;
2266 double getElapsedSeconds() const;
2267
2268 private:
2269 uint64_t m_ticks;
2270 };
2271
2272} // namespace Catch
2273
Phil Nashce612bf2012-11-01 08:27:09 +00002274#include <string>
2275
2276namespace Catch {
2277
Phil Nashe54ac702014-10-21 07:25:26 +01002278 class Section : NonCopyable {
Phil Nashce612bf2012-11-01 08:27:09 +00002279 public:
Phil Nashce562092014-07-09 07:40:37 +01002280 Section( SectionInfo const& info );
Phil Nash3649fdf2013-12-03 18:53:55 +00002281 ~Section();
Phil Nashce612bf2012-11-01 08:27:09 +00002282
2283 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01002284 operator bool() const;
Phil Nashce612bf2012-11-01 08:27:09 +00002285
2286 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002287 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00002288
2289 std::string m_name;
2290 Counts m_assertions;
2291 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01002292 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00002293 };
2294
2295} // end namespace Catch
2296
Phil Nash93906752013-03-16 20:21:51 +00002297#ifdef CATCH_CONFIG_VARIADIC_MACROS
2298 #define INTERNAL_CATCH_SECTION( ... ) \
Phil Nashce562092014-07-09 07:40:37 +01002299 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) )
Phil Nash93906752013-03-16 20:21:51 +00002300#else
2301 #define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashce562092014-07-09 07:40:37 +01002302 if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, name, desc ) )
Phil Nash93906752013-03-16 20:21:51 +00002303#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002304
2305// #included from: internal/catch_generators.hpp
2306#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2307
2308#include <iterator>
2309#include <vector>
2310#include <string>
2311#include <stdlib.h>
2312
2313namespace Catch {
2314
2315template<typename T>
2316struct IGenerator {
2317 virtual ~IGenerator() {}
2318 virtual T getValue( std::size_t index ) const = 0;
2319 virtual std::size_t size () const = 0;
2320};
2321
2322template<typename T>
2323class BetweenGenerator : public IGenerator<T> {
2324public:
2325 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2326
2327 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00002328 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00002329 }
2330
2331 virtual std::size_t size() const {
2332 return static_cast<std::size_t>( 1+m_to-m_from );
2333 }
2334
2335private:
2336
2337 T m_from;
2338 T m_to;
2339};
2340
2341template<typename T>
2342class ValuesGenerator : public IGenerator<T> {
2343public:
2344 ValuesGenerator(){}
2345
2346 void add( T value ) {
2347 m_values.push_back( value );
2348 }
2349
2350 virtual T getValue( std::size_t index ) const {
2351 return m_values[index];
2352 }
2353
2354 virtual std::size_t size() const {
2355 return m_values.size();
2356 }
2357
2358private:
2359 std::vector<T> m_values;
2360};
2361
2362template<typename T>
2363class CompositeGenerator {
2364public:
2365 CompositeGenerator() : m_totalSize( 0 ) {}
2366
Phil Nasha04981b2013-03-08 09:30:25 +00002367 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00002368 CompositeGenerator( CompositeGenerator& other )
2369 : m_fileInfo( other.m_fileInfo ),
2370 m_totalSize( 0 )
2371 {
Phil Nasha04981b2013-03-08 09:30:25 +00002372 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00002373 }
2374
2375 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2376 m_fileInfo = fileInfo;
2377 return *this;
2378 }
2379
2380 ~CompositeGenerator() {
2381 deleteAll( m_composed );
2382 }
2383
2384 operator T () const {
2385 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2386
2387 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2388 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2389 for( size_t index = 0; it != itEnd; ++it )
2390 {
2391 const IGenerator<T>* generator = *it;
2392 if( overallIndex >= index && overallIndex < index + generator->size() )
2393 {
2394 return generator->getValue( overallIndex-index );
2395 }
2396 index += generator->size();
2397 }
2398 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00002399 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
Phil Nashce612bf2012-11-01 08:27:09 +00002400 }
2401
2402 void add( const IGenerator<T>* generator ) {
2403 m_totalSize += generator->size();
2404 m_composed.push_back( generator );
2405 }
2406
2407 CompositeGenerator& then( CompositeGenerator& other ) {
2408 move( other );
2409 return *this;
2410 }
2411
2412 CompositeGenerator& then( T value ) {
2413 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2414 valuesGen->add( value );
2415 add( valuesGen );
2416 return *this;
2417 }
2418
2419private:
2420
2421 void move( CompositeGenerator& other ) {
2422 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2423 m_totalSize += other.m_totalSize;
2424 other.m_composed.clear();
2425 }
2426
2427 std::vector<const IGenerator<T>*> m_composed;
2428 std::string m_fileInfo;
2429 size_t m_totalSize;
2430};
2431
2432namespace Generators
2433{
2434 template<typename T>
2435 CompositeGenerator<T> between( T from, T to ) {
2436 CompositeGenerator<T> generators;
2437 generators.add( new BetweenGenerator<T>( from, to ) );
2438 return generators;
2439 }
2440
2441 template<typename T>
2442 CompositeGenerator<T> values( T val1, T val2 ) {
2443 CompositeGenerator<T> generators;
2444 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2445 valuesGen->add( val1 );
2446 valuesGen->add( val2 );
2447 generators.add( valuesGen );
2448 return generators;
2449 }
2450
2451 template<typename T>
2452 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2453 CompositeGenerator<T> generators;
2454 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2455 valuesGen->add( val1 );
2456 valuesGen->add( val2 );
2457 valuesGen->add( val3 );
2458 generators.add( valuesGen );
2459 return generators;
2460 }
2461
2462 template<typename T>
2463 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2464 CompositeGenerator<T> generators;
2465 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2466 valuesGen->add( val1 );
2467 valuesGen->add( val2 );
2468 valuesGen->add( val3 );
2469 valuesGen->add( val4 );
2470 generators.add( valuesGen );
2471 return generators;
2472 }
2473
2474} // end namespace Generators
2475
2476using namespace Generators;
2477
2478} // end namespace Catch
2479
2480#define INTERNAL_CATCH_LINESTR2( line ) #line
2481#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2482
2483#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2484
2485// #included from: internal/catch_interfaces_exception.h
2486#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2487
2488#include <string>
Phil Nashe4fa62a2015-11-18 08:39:54 +00002489#include <vector>
2490
Phil Nashab036682014-06-02 07:48:03 +01002491// #included from: catch_interfaces_registry_hub.h
2492#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2493
2494#include <string>
2495
2496namespace Catch {
2497
2498 class TestCase;
2499 struct ITestCaseRegistry;
2500 struct IExceptionTranslatorRegistry;
2501 struct IExceptionTranslator;
2502 struct IReporterRegistry;
2503 struct IReporterFactory;
2504
2505 struct IRegistryHub {
2506 virtual ~IRegistryHub();
2507
2508 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2509 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2510 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2511 };
2512
2513 struct IMutableRegistryHub {
2514 virtual ~IMutableRegistryHub();
Phil Nashe73583d2015-08-07 17:30:34 +01002515 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2516 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
Phil Nashab036682014-06-02 07:48:03 +01002517 virtual void registerTest( TestCase const& testInfo ) = 0;
2518 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2519 };
2520
2521 IRegistryHub& getRegistryHub();
2522 IMutableRegistryHub& getMutableRegistryHub();
2523 void cleanUp();
2524 std::string translateActiveException();
2525
2526}
2527
Phil Nash89d2a3f2012-05-16 15:09:17 +01002528namespace Catch {
2529
Phil Nash89d1e6c2011-05-24 08:23:02 +01002530 typedef std::string(*exceptionTranslateFunction)();
2531
Phil Nashe4fa62a2015-11-18 08:39:54 +00002532 struct IExceptionTranslator;
2533 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2534
Phil Nash89d2a3f2012-05-16 15:09:17 +01002535 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002536 virtual ~IExceptionTranslator();
Phil Nashe4fa62a2015-11-18 08:39:54 +00002537 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002538 };
2539
Phil Nash89d2a3f2012-05-16 15:09:17 +01002540 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002541 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002542
Phil Nash89d2a3f2012-05-16 15:09:17 +01002543 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002544 };
2545
Phil Nash89d2a3f2012-05-16 15:09:17 +01002546 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002547 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002548 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002549 public:
2550
Phil Nash89d2a3f2012-05-16 15:09:17 +01002551 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002552 : m_translateFunction( translateFunction )
2553 {}
2554
Phil Nashe4fa62a2015-11-18 08:39:54 +00002555 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002556 try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00002557 if( it == itEnd )
2558 throw;
2559 else
2560 return (*it)->translate( it+1, itEnd );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002561 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002562 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002563 return m_translateFunction( ex );
2564 }
2565 }
2566
2567 protected:
2568 std::string(*m_translateFunction)( T& );
2569 };
2570
2571 public:
2572 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002573 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002574 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002575 ( new ExceptionTranslator<T>( translateFunction ) );
2576 }
2577 };
2578}
2579
2580///////////////////////////////////////////////////////////////////////////////
2581#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) \
2582 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature ); \
2583 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ) ); }\
2584 static std::string INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator )( signature )
2585
2586// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002587#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002588
Phil Nash89d1e6c2011-05-24 08:23:02 +01002589#include <cmath>
2590#include <limits>
2591
Phil Nash89d2a3f2012-05-16 15:09:17 +01002592namespace Catch {
2593namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002594
Phil Nash89d2a3f2012-05-16 15:09:17 +01002595 class Approx {
2596 public:
2597 explicit Approx ( double value )
2598 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2599 m_scale( 1.0 ),
2600 m_value( value )
2601 {}
Phil Nashf721a962011-06-07 14:13:57 +01002602
Phil Nash8defc712013-04-24 19:10:02 +01002603 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01002604 : m_epsilon( other.m_epsilon ),
2605 m_scale( other.m_scale ),
2606 m_value( other.m_value )
2607 {}
Phil Nashf721a962011-06-07 14:13:57 +01002608
Phil Nash89d2a3f2012-05-16 15:09:17 +01002609 static Approx custom() {
2610 return Approx( 0 );
2611 }
Phil Nashf721a962011-06-07 14:13:57 +01002612
Phil Nash89d2a3f2012-05-16 15:09:17 +01002613 Approx operator()( double value ) {
2614 Approx approx( value );
2615 approx.epsilon( m_epsilon );
2616 approx.scale( m_scale );
2617 return approx;
2618 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002619
Phil Nash8defc712013-04-24 19:10:02 +01002620 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002621 // Thanks to Richard Harris for his help refining this formula
2622 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2623 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002624
Phil Nash8defc712013-04-24 19:10:02 +01002625 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002626 return operator==( rhs, lhs );
2627 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002628
Phil Nash8defc712013-04-24 19:10:02 +01002629 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002630 return !operator==( lhs, rhs );
2631 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002632
Phil Nash8defc712013-04-24 19:10:02 +01002633 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002634 return !operator==( rhs, lhs );
2635 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002636
Phil Nash89d2a3f2012-05-16 15:09:17 +01002637 Approx& epsilon( double newEpsilon ) {
2638 m_epsilon = newEpsilon;
2639 return *this;
2640 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002641
Phil Nash89d2a3f2012-05-16 15:09:17 +01002642 Approx& scale( double newScale ) {
2643 m_scale = newScale;
2644 return *this;
2645 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002646
Phil Nash89d2a3f2012-05-16 15:09:17 +01002647 std::string toString() const {
2648 std::ostringstream oss;
Phil Nashf385a0b2013-12-19 18:42:25 +00002649 oss << "Approx( " << Catch::toString( m_value ) << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002650 return oss.str();
2651 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002652
Phil Nash89d2a3f2012-05-16 15:09:17 +01002653 private:
2654 double m_epsilon;
2655 double m_scale;
2656 double m_value;
2657 };
2658}
2659
2660template<>
Phil Nash8defc712013-04-24 19:10:02 +01002661inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002662 return value.toString();
2663}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002664
2665} // end namespace Catch
2666
Phil Nashacdd3b52014-06-30 07:35:36 +01002667// #included from: internal/catch_interfaces_tag_alias_registry.h
2668#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2669
2670// #included from: catch_tag_alias.h
2671#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2672
2673#include <string>
2674
2675namespace Catch {
2676
2677 struct TagAlias {
2678 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
2679
2680 std::string tag;
2681 SourceLineInfo lineInfo;
2682 };
2683
2684 struct RegistrarForTagAliases {
2685 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
2686 };
2687
2688} // end namespace Catch
2689
2690#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2691// #included from: catch_option.hpp
2692#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2693
2694namespace Catch {
2695
2696 // An optional type
2697 template<typename T>
2698 class Option {
2699 public:
Phil Nashb971fe72015-07-02 08:21:38 +01002700 Option() : nullableValue( CATCH_NULL ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01002701 Option( T const& _value )
2702 : nullableValue( new( storage ) T( _value ) )
2703 {}
2704 Option( Option const& _other )
Phil Nashb971fe72015-07-02 08:21:38 +01002705 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
Phil Nashacdd3b52014-06-30 07:35:36 +01002706 {}
2707
2708 ~Option() {
2709 reset();
2710 }
2711
2712 Option& operator= ( Option const& _other ) {
2713 if( &_other != this ) {
2714 reset();
2715 if( _other )
2716 nullableValue = new( storage ) T( *_other );
2717 }
2718 return *this;
2719 }
2720 Option& operator = ( T const& _value ) {
2721 reset();
2722 nullableValue = new( storage ) T( _value );
2723 return *this;
2724 }
2725
2726 void reset() {
2727 if( nullableValue )
2728 nullableValue->~T();
Phil Nashb971fe72015-07-02 08:21:38 +01002729 nullableValue = CATCH_NULL;
Phil Nashacdd3b52014-06-30 07:35:36 +01002730 }
2731
2732 T& operator*() { return *nullableValue; }
2733 T const& operator*() const { return *nullableValue; }
2734 T* operator->() { return nullableValue; }
2735 const T* operator->() const { return nullableValue; }
2736
2737 T valueOr( T const& defaultValue ) const {
2738 return nullableValue ? *nullableValue : defaultValue;
2739 }
2740
Phil Nashb971fe72015-07-02 08:21:38 +01002741 bool some() const { return nullableValue != CATCH_NULL; }
2742 bool none() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01002743
Phil Nashb971fe72015-07-02 08:21:38 +01002744 bool operator !() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01002745 operator SafeBool::type() const {
2746 return SafeBool::makeSafe( some() );
2747 }
2748
2749 private:
2750 T* nullableValue;
2751 char storage[sizeof(T)];
2752 };
2753
2754} // end namespace Catch
2755
2756namespace Catch {
2757
2758 struct ITagAliasRegistry {
2759 virtual ~ITagAliasRegistry();
2760 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
2761 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
2762
2763 static ITagAliasRegistry const& get();
2764 };
2765
2766} // end namespace Catch
2767
Phil Nash0f9c5512012-06-02 23:12:42 +01002768// These files are included here so the single_include script doesn't put them
2769// in the conditionally compiled sections
Phil Nash3649fdf2013-12-03 18:53:55 +00002770// #included from: internal/catch_test_case_info.h
2771#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01002772
2773#include <string>
Phil Nash3649fdf2013-12-03 18:53:55 +00002774#include <set>
2775
2776#ifdef __clang__
2777#pragma clang diagnostic push
2778#pragma clang diagnostic ignored "-Wpadded"
2779#endif
2780
2781namespace Catch {
2782
2783 struct ITestCase;
2784
2785 struct TestCaseInfo {
Phil Nash52e1e742014-07-03 08:11:38 +01002786 enum SpecialProperties{
2787 None = 0,
2788 IsHidden = 1 << 1,
2789 ShouldFail = 1 << 2,
2790 MayFail = 1 << 3,
2791 Throws = 1 << 4
2792 };
2793
Phil Nash3649fdf2013-12-03 18:53:55 +00002794 TestCaseInfo( std::string const& _name,
2795 std::string const& _className,
2796 std::string const& _description,
2797 std::set<std::string> const& _tags,
Phil Nash3649fdf2013-12-03 18:53:55 +00002798 SourceLineInfo const& _lineInfo );
2799
2800 TestCaseInfo( TestCaseInfo const& other );
2801
Phil Nashb971fe72015-07-02 08:21:38 +01002802 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
2803
Phil Nash52e1e742014-07-03 08:11:38 +01002804 bool isHidden() const;
2805 bool throws() const;
2806 bool okToFail() const;
2807 bool expectedToFail() const;
2808
Phil Nash3649fdf2013-12-03 18:53:55 +00002809 std::string name;
2810 std::string className;
2811 std::string description;
2812 std::set<std::string> tags;
Phil Nash9241e432014-05-20 18:50:59 +01002813 std::set<std::string> lcaseTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00002814 std::string tagsAsString;
2815 SourceLineInfo lineInfo;
Phil Nash52e1e742014-07-03 08:11:38 +01002816 SpecialProperties properties;
Phil Nash3649fdf2013-12-03 18:53:55 +00002817 };
2818
Phil Nash65cc14c2014-05-16 18:54:48 +01002819 class TestCase : public TestCaseInfo {
Phil Nash3649fdf2013-12-03 18:53:55 +00002820 public:
2821
2822 TestCase( ITestCase* testCase, TestCaseInfo const& info );
2823 TestCase( TestCase const& other );
2824
2825 TestCase withName( std::string const& _newName ) const;
2826
2827 void invoke() const;
2828
2829 TestCaseInfo const& getTestCaseInfo() const;
2830
Phil Nash3649fdf2013-12-03 18:53:55 +00002831 void swap( TestCase& other );
2832 bool operator == ( TestCase const& other ) const;
2833 bool operator < ( TestCase const& other ) const;
2834 TestCase& operator = ( TestCase const& other );
2835
2836 private:
2837 Ptr<ITestCase> test;
2838 };
2839
2840 TestCase makeTestCase( ITestCase* testCase,
2841 std::string const& className,
2842 std::string const& name,
2843 std::string const& description,
2844 SourceLineInfo const& lineInfo );
2845}
2846
2847#ifdef __clang__
2848#pragma clang diagnostic pop
2849#endif
2850
Phil Nash0f9c5512012-06-02 23:12:42 +01002851
Phil Nash371db8b2012-05-21 18:52:09 +01002852#ifdef __OBJC__
2853// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002854#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01002855
Phil Nash371db8b2012-05-21 18:52:09 +01002856#import <objc/runtime.h>
2857
2858#include <string>
2859
2860// NB. Any general catch headers included here must be included
2861// in catch.hpp first to make sure they are included by the single
2862// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01002863
Phil Nash83224e62011-08-12 18:53:28 +01002864///////////////////////////////////////////////////////////////////////////////
2865// This protocol is really only here for (self) documenting purposes, since
2866// all its methods are optional.
2867@protocol OcFixture
2868
2869@optional
2870
2871-(void) setUp;
2872-(void) tearDown;
2873
2874@end
2875
Phil Nash89d2a3f2012-05-16 15:09:17 +01002876namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01002877
Phil Nash5bc030d2012-08-16 18:48:50 +01002878 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002879
2880 public:
2881 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
2882
2883 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00002884 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01002885
Phil Nash53c990a2012-03-17 18:20:06 +00002886 performOptionalSelector( obj, @selector(setUp) );
2887 performOptionalSelector( obj, m_sel );
2888 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01002889
Phil Nash53c990a2012-03-17 18:20:06 +00002890 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01002891 }
Phil Nash83224e62011-08-12 18:53:28 +01002892 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01002893 virtual ~OcMethod() {}
2894
Phil Nash83224e62011-08-12 18:53:28 +01002895 Class m_cls;
2896 SEL m_sel;
2897 };
2898
Phil Nash89d2a3f2012-05-16 15:09:17 +01002899 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01002900
Phil Nash89d2a3f2012-05-16 15:09:17 +01002901 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01002902 std::string const& annotationName,
2903 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01002904 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
2905 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00002906 arcSafeRelease( selStr );
2907 id value = performOptionalSelector( cls, sel );
2908 if( value )
2909 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01002910 return "";
2911 }
2912 }
2913
Phil Nash89d2a3f2012-05-16 15:09:17 +01002914 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01002915 size_t noTestMethods = 0;
Phil Nashb971fe72015-07-02 08:21:38 +01002916 int noClasses = objc_getClassList( CATCH_NULL, 0 );
Phil Nash83224e62011-08-12 18:53:28 +01002917
Phil Nash861a1e72012-04-28 12:29:52 +01002918 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00002919 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01002920
Phil Nash89d2a3f2012-05-16 15:09:17 +01002921 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002922 Class cls = classes[c];
2923 {
2924 u_int count;
2925 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01002926 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01002927 SEL selector = method_getName(methods[m]);
2928 std::string methodName = sel_getName(selector);
Phil Nash3649fdf2013-12-03 18:53:55 +00002929 if( startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01002930 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00002931 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
2932 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00002933 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01002934
Phil Nash5bdae842013-02-19 19:47:18 +00002935 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01002936 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01002937 }
2938 }
2939 free(methods);
2940 }
2941 }
2942 return noTestMethods;
2943 }
Phil Nash78d95a02012-03-04 21:22:36 +00002944
Phil Nash89d2a3f2012-05-16 15:09:17 +01002945 namespace Matchers {
2946 namespace Impl {
2947 namespace NSStringMatchers {
2948
Phil Nasha8c65432013-02-19 08:46:09 +00002949 template<typename MatcherT>
2950 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00002951 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00002952 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01002953 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00002954 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002955 }
2956
2957 NSString* m_substr;
2958 };
2959
Phil Nasha8c65432013-02-19 08:46:09 +00002960 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00002961 Equals( NSString* substr ) : StringHolder( substr ){}
2962
Phil Nasha8c65432013-02-19 08:46:09 +00002963 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002964 return (str != nil || m_substr == nil ) &&
2965 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00002966 }
2967
Phil Nasha8c65432013-02-19 08:46:09 +00002968 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01002969 return "equals string: " + Catch::toString( m_substr );
Phil Nash8d18d162012-03-14 20:06:14 +00002970 }
2971 };
2972
Phil Nasha8c65432013-02-19 08:46:09 +00002973 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00002974 Contains( NSString* substr ) : StringHolder( substr ){}
2975
Phil Nasha8c65432013-02-19 08:46:09 +00002976 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002977 return (str != nil || m_substr == nil ) &&
2978 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00002979 }
2980
Phil Nasha8c65432013-02-19 08:46:09 +00002981 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01002982 return "contains string: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002983 }
2984 };
2985
Phil Nasha8c65432013-02-19 08:46:09 +00002986 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00002987 StartsWith( NSString* substr ) : StringHolder( substr ){}
2988
Phil Nasha8c65432013-02-19 08:46:09 +00002989 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01002990 return (str != nil || m_substr == nil ) &&
2991 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00002992 }
2993
Phil Nasha8c65432013-02-19 08:46:09 +00002994 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01002995 return "starts with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00002996 }
2997 };
Phil Nasha8c65432013-02-19 08:46:09 +00002998 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00002999 EndsWith( NSString* substr ) : StringHolder( substr ){}
3000
Phil Nasha8c65432013-02-19 08:46:09 +00003001 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003002 return (str != nil || m_substr == nil ) &&
3003 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00003004 }
3005
Phil Nasha8c65432013-02-19 08:46:09 +00003006 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003007 return "ends with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003008 }
3009 };
3010
3011 } // namespace NSStringMatchers
3012 } // namespace Impl
3013
Phil Nash8d18d162012-03-14 20:06:14 +00003014 inline Impl::NSStringMatchers::Equals
3015 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3016
Phil Nash78d95a02012-03-04 21:22:36 +00003017 inline Impl::NSStringMatchers::Contains
3018 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003019
Phil Nash78d95a02012-03-04 21:22:36 +00003020 inline Impl::NSStringMatchers::StartsWith
3021 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003022
Phil Nash78d95a02012-03-04 21:22:36 +00003023 inline Impl::NSStringMatchers::EndsWith
3024 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3025
3026 } // namespace Matchers
3027
3028 using namespace Matchers;
3029
3030} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003031
3032///////////////////////////////////////////////////////////////////////////////
3033#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003034+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003035{\
Phil Nash53c990a2012-03-17 18:20:06 +00003036return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003037}\
Phil Nash53c990a2012-03-17 18:20:06 +00003038+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003039{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003040return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003041} \
3042-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3043
3044#endif
3045
Phil Nash576aff62014-12-21 00:21:23 +00003046#ifdef CATCH_IMPL
Phil Nasha695eb92012-08-13 07:46:10 +01003047// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003048#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003049
3050// Collect all the implementation files together here
3051// These are the equivalent of what would usually be cpp files
3052
Phil Nash5bc030d2012-08-16 18:48:50 +01003053#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003054#pragma clang diagnostic push
3055#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003056#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003057
Phil Nashe73583d2015-08-07 17:30:34 +01003058// #included from: ../catch_session.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003059#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003060
Phil Nasha695eb92012-08-13 07:46:10 +01003061// #included from: internal/catch_commandline.hpp
3062#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3063
Phil Nash3649fdf2013-12-03 18:53:55 +00003064// #included from: catch_config.hpp
3065#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3066
Phil Nash65cc14c2014-05-16 18:54:48 +01003067// #included from: catch_test_spec_parser.hpp
3068#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003069
3070#ifdef __clang__
Phil Nash65cc14c2014-05-16 18:54:48 +01003071#pragma clang diagnostic push
Phil Nash3649fdf2013-12-03 18:53:55 +00003072#pragma clang diagnostic ignored "-Wpadded"
3073#endif
3074
Phil Nash65cc14c2014-05-16 18:54:48 +01003075// #included from: catch_test_spec.hpp
3076#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003077
Phil Nash65cc14c2014-05-16 18:54:48 +01003078#ifdef __clang__
3079#pragma clang diagnostic push
3080#pragma clang diagnostic ignored "-Wpadded"
3081#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00003082
Phil Nash8342ae82015-07-13 15:03:26 +01003083// #included from: catch_wildcard_pattern.hpp
3084#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3085
3086namespace Catch
3087{
3088 class WildcardPattern {
3089 enum WildcardPosition {
3090 NoWildcard = 0,
3091 WildcardAtStart = 1,
3092 WildcardAtEnd = 2,
3093 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3094 };
3095
3096 public:
3097
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003098 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
Phil Nash8342ae82015-07-13 15:03:26 +01003099 : m_caseSensitivity( caseSensitivity ),
3100 m_wildcard( NoWildcard ),
3101 m_pattern( adjustCase( pattern ) )
3102 {
3103 if( startsWith( m_pattern, "*" ) ) {
3104 m_pattern = m_pattern.substr( 1 );
3105 m_wildcard = WildcardAtStart;
3106 }
3107 if( endsWith( m_pattern, "*" ) ) {
3108 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3109 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3110 }
3111 }
3112 virtual ~WildcardPattern();
3113 virtual bool matches( std::string const& str ) const {
3114 switch( m_wildcard ) {
3115 case NoWildcard:
3116 return m_pattern == adjustCase( str );
3117 case WildcardAtStart:
3118 return endsWith( adjustCase( str ), m_pattern );
3119 case WildcardAtEnd:
3120 return startsWith( adjustCase( str ), m_pattern );
3121 case WildcardAtBothEnds:
3122 return contains( adjustCase( str ), m_pattern );
3123 }
3124
3125#ifdef __clang__
3126#pragma clang diagnostic push
3127#pragma clang diagnostic ignored "-Wunreachable-code"
3128#endif
3129 throw std::logic_error( "Unknown enum" );
3130#ifdef __clang__
3131#pragma clang diagnostic pop
3132#endif
3133 }
3134 private:
3135 std::string adjustCase( std::string const& str ) const {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003136 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
Phil Nash8342ae82015-07-13 15:03:26 +01003137 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003138 CaseSensitive::Choice m_caseSensitivity;
Phil Nash8342ae82015-07-13 15:03:26 +01003139 WildcardPosition m_wildcard;
3140 std::string m_pattern;
3141 };
3142}
3143
Phil Nash3649fdf2013-12-03 18:53:55 +00003144#include <string>
3145#include <vector>
3146
3147namespace Catch {
3148
Phil Nash65cc14c2014-05-16 18:54:48 +01003149 class TestSpec {
3150 struct Pattern : SharedImpl<> {
3151 virtual ~Pattern();
3152 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3153 };
3154 class NamePattern : public Pattern {
Phil Nash65cc14c2014-05-16 18:54:48 +01003155 public:
Phil Nash8342ae82015-07-13 15:03:26 +01003156 NamePattern( std::string const& name )
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003157 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
Phil Nash8342ae82015-07-13 15:03:26 +01003158 {}
Phil Nash65cc14c2014-05-16 18:54:48 +01003159 virtual ~NamePattern();
3160 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash8342ae82015-07-13 15:03:26 +01003161 return m_wildcardPattern.matches( toLower( testCase.name ) );
Phil Nash65cc14c2014-05-16 18:54:48 +01003162 }
3163 private:
Phil Nash8342ae82015-07-13 15:03:26 +01003164 WildcardPattern m_wildcardPattern;
Phil Nash65cc14c2014-05-16 18:54:48 +01003165 };
Phil Nash8342ae82015-07-13 15:03:26 +01003166
Phil Nash65cc14c2014-05-16 18:54:48 +01003167 class TagPattern : public Pattern {
3168 public:
3169 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3170 virtual ~TagPattern();
3171 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash9241e432014-05-20 18:50:59 +01003172 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
Phil Nash65cc14c2014-05-16 18:54:48 +01003173 }
3174 private:
3175 std::string m_tag;
3176 };
Phil Nash8342ae82015-07-13 15:03:26 +01003177
Phil Nash65cc14c2014-05-16 18:54:48 +01003178 class ExcludedPattern : public Pattern {
3179 public:
3180 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3181 virtual ~ExcludedPattern();
3182 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3183 private:
3184 Ptr<Pattern> m_underlyingPattern;
3185 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003186
Phil Nash65cc14c2014-05-16 18:54:48 +01003187 struct Filter {
3188 std::vector<Ptr<Pattern> > m_patterns;
3189
3190 bool matches( TestCaseInfo const& testCase ) const {
3191 // All patterns in a filter must match for the filter to be a match
3192 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it )
3193 if( !(*it)->matches( testCase ) )
3194 return false;
3195 return true;
3196 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003197 };
3198
3199 public:
Phil Nash65cc14c2014-05-16 18:54:48 +01003200 bool hasFilters() const {
3201 return !m_filters.empty();
3202 }
3203 bool matches( TestCaseInfo const& testCase ) const {
3204 // A TestSpec matches if any filter matches
3205 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3206 if( it->matches( testCase ) )
3207 return true;
3208 return false;
3209 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003210
3211 private:
Phil Nash65cc14c2014-05-16 18:54:48 +01003212 std::vector<Filter> m_filters;
Phil Nash3649fdf2013-12-03 18:53:55 +00003213
Phil Nash65cc14c2014-05-16 18:54:48 +01003214 friend class TestSpecParser;
Phil Nash3649fdf2013-12-03 18:53:55 +00003215 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003216}
3217
Phil Nash65cc14c2014-05-16 18:54:48 +01003218#ifdef __clang__
3219#pragma clang diagnostic pop
3220#endif
3221
3222namespace Catch {
3223
3224 class TestSpecParser {
3225 enum Mode{ None, Name, QuotedName, Tag };
3226 Mode m_mode;
3227 bool m_exclusion;
3228 std::size_t m_start, m_pos;
3229 std::string m_arg;
3230 TestSpec::Filter m_currentFilter;
3231 TestSpec m_testSpec;
Phil Nash52e1e742014-07-03 08:11:38 +01003232 ITagAliasRegistry const* m_tagAliases;
Phil Nash65cc14c2014-05-16 18:54:48 +01003233
3234 public:
Phil Nash52e1e742014-07-03 08:11:38 +01003235 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003236
3237 TestSpecParser& parse( std::string const& arg ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01003238 m_mode = None;
3239 m_exclusion = false;
3240 m_start = std::string::npos;
Phil Nash52e1e742014-07-03 08:11:38 +01003241 m_arg = m_tagAliases->expandAliases( arg );
Phil Nash65cc14c2014-05-16 18:54:48 +01003242 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3243 visitChar( m_arg[m_pos] );
3244 if( m_mode == Name )
3245 addPattern<TestSpec::NamePattern>();
3246 return *this;
3247 }
3248 TestSpec testSpec() {
Phil Nash9241e432014-05-20 18:50:59 +01003249 addFilter();
Phil Nash65cc14c2014-05-16 18:54:48 +01003250 return m_testSpec;
3251 }
3252 private:
3253 void visitChar( char c ) {
3254 if( m_mode == None ) {
3255 switch( c ) {
3256 case ' ': return;
3257 case '~': m_exclusion = true; return;
3258 case '[': return startNewMode( Tag, ++m_pos );
3259 case '"': return startNewMode( QuotedName, ++m_pos );
3260 default: startNewMode( Name, m_pos ); break;
3261 }
3262 }
3263 if( m_mode == Name ) {
3264 if( c == ',' ) {
3265 addPattern<TestSpec::NamePattern>();
3266 addFilter();
3267 }
3268 else if( c == '[' ) {
3269 if( subString() == "exclude:" )
3270 m_exclusion = true;
3271 else
3272 addPattern<TestSpec::NamePattern>();
3273 startNewMode( Tag, ++m_pos );
3274 }
3275 }
3276 else if( m_mode == QuotedName && c == '"' )
3277 addPattern<TestSpec::NamePattern>();
3278 else if( m_mode == Tag && c == ']' )
3279 addPattern<TestSpec::TagPattern>();
3280 }
3281 void startNewMode( Mode mode, std::size_t start ) {
3282 m_mode = mode;
3283 m_start = start;
3284 }
3285 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3286 template<typename T>
3287 void addPattern() {
3288 std::string token = subString();
3289 if( startsWith( token, "exclude:" ) ) {
3290 m_exclusion = true;
3291 token = token.substr( 8 );
3292 }
3293 if( !token.empty() ) {
3294 Ptr<TestSpec::Pattern> pattern = new T( token );
3295 if( m_exclusion )
3296 pattern = new TestSpec::ExcludedPattern( pattern );
3297 m_currentFilter.m_patterns.push_back( pattern );
3298 }
3299 m_exclusion = false;
3300 m_mode = None;
3301 }
3302 void addFilter() {
3303 if( !m_currentFilter.m_patterns.empty() ) {
3304 m_testSpec.m_filters.push_back( m_currentFilter );
3305 m_currentFilter = TestSpec::Filter();
3306 }
3307 }
3308 };
3309 inline TestSpec parseTestSpec( std::string const& arg ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003310 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01003311 }
3312
3313} // namespace Catch
3314
3315#ifdef __clang__
3316#pragma clang diagnostic pop
3317#endif
3318
Phil Nashab036682014-06-02 07:48:03 +01003319// #included from: catch_interfaces_config.h
3320#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3321
3322#include <iostream>
3323#include <string>
3324#include <vector>
3325
3326namespace Catch {
3327
3328 struct Verbosity { enum Level {
3329 NoOutput = 0,
3330 Quiet,
3331 Normal
3332 }; };
3333
3334 struct WarnAbout { enum What {
3335 Nothing = 0x00,
3336 NoAssertions = 0x01
3337 }; };
3338
3339 struct ShowDurations { enum OrNot {
3340 DefaultForReporter,
3341 Always,
3342 Never
3343 }; };
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003344 struct RunTests { enum InWhatOrder {
3345 InDeclarationOrder,
3346 InLexicographicalOrder,
3347 InRandomOrder
3348 }; };
Phil Nashae5ee2c2016-02-29 08:17:18 +00003349 struct UseColour { enum YesOrNo {
3350 Auto,
3351 Yes,
3352 No
3353 }; };
Phil Nashab036682014-06-02 07:48:03 +01003354
3355 class TestSpec;
3356
3357 struct IConfig : IShared {
3358
3359 virtual ~IConfig();
3360
3361 virtual bool allowThrows() const = 0;
3362 virtual std::ostream& stream() const = 0;
3363 virtual std::string name() const = 0;
3364 virtual bool includeSuccessfulResults() const = 0;
3365 virtual bool shouldDebugBreak() const = 0;
3366 virtual bool warnAboutMissingAssertions() const = 0;
3367 virtual int abortAfter() const = 0;
3368 virtual bool showInvisibles() const = 0;
3369 virtual ShowDurations::OrNot showDurations() const = 0;
3370 virtual TestSpec const& testSpec() const = 0;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003371 virtual RunTests::InWhatOrder runOrder() const = 0;
3372 virtual unsigned int rngSeed() const = 0;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003373 virtual UseColour::YesOrNo useColour() const = 0;
Phil Nashab036682014-06-02 07:48:03 +01003374 };
3375}
3376
Phil Nash3649fdf2013-12-03 18:53:55 +00003377// #included from: catch_stream.h
3378#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3379
Phil Nash7e346192015-11-03 08:00:43 +00003380// #included from: catch_streambuf.h
3381#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003382
Phil Nash7e346192015-11-03 08:00:43 +00003383#include <streambuf>
Phil Nash3649fdf2013-12-03 18:53:55 +00003384
3385namespace Catch {
3386
Phil Nash7e346192015-11-03 08:00:43 +00003387 class StreamBufBase : public std::streambuf {
Phil Nash3649fdf2013-12-03 18:53:55 +00003388 public:
Phil Nash7e346192015-11-03 08:00:43 +00003389 virtual ~StreamBufBase() CATCH_NOEXCEPT;
Phil Nash3649fdf2013-12-03 18:53:55 +00003390 };
Phil Nash7e346192015-11-03 08:00:43 +00003391}
3392
3393#include <streambuf>
3394#include <ostream>
3395#include <fstream>
3396
3397namespace Catch {
Phil Nash383d7c02014-10-02 19:08:19 +01003398
3399 std::ostream& cout();
3400 std::ostream& cerr();
Phil Nash7e346192015-11-03 08:00:43 +00003401
3402 struct IStream {
3403 virtual ~IStream() CATCH_NOEXCEPT;
3404 virtual std::ostream& stream() const = 0;
3405 };
3406
3407 class FileStream : public IStream {
3408 mutable std::ofstream m_ofs;
3409 public:
3410 FileStream( std::string const& filename );
Phil Nashece529a2015-11-03 17:37:43 +00003411 virtual ~FileStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003412 public: // IStream
3413 virtual std::ostream& stream() const CATCH_OVERRIDE;
3414 };
3415
3416 class CoutStream : public IStream {
3417 mutable std::ostream m_os;
3418 public:
3419 CoutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003420 virtual ~CoutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003421
3422 public: // IStream
3423 virtual std::ostream& stream() const CATCH_OVERRIDE;
3424 };
3425
3426 class DebugOutStream : public IStream {
3427 std::auto_ptr<StreamBufBase> m_streamBuf;
3428 mutable std::ostream m_os;
3429 public:
3430 DebugOutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003431 virtual ~DebugOutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003432
3433 public: // IStream
3434 virtual std::ostream& stream() const CATCH_OVERRIDE;
3435 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003436}
3437
3438#include <memory>
3439#include <vector>
3440#include <string>
3441#include <iostream>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003442#include <ctime>
Phil Nash3649fdf2013-12-03 18:53:55 +00003443
3444#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3445#define CATCH_CONFIG_CONSOLE_WIDTH 80
3446#endif
3447
3448namespace Catch {
3449
3450 struct ConfigData {
3451
3452 ConfigData()
3453 : listTests( false ),
3454 listTags( false ),
3455 listReporters( false ),
3456 listTestNamesOnly( false ),
3457 showSuccessfulTests( false ),
3458 shouldDebugBreak( false ),
3459 noThrow( false ),
3460 showHelp( false ),
Phil Nashaef6cd52014-04-23 07:10:10 +01003461 showInvisibles( false ),
Phil Nashb971fe72015-07-02 08:21:38 +01003462 filenamesAsTags( false ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003463 abortAfter( -1 ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003464 rngSeed( 0 ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003465 verbosity( Verbosity::Normal ),
3466 warnings( WarnAbout::Nothing ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003467 showDurations( ShowDurations::DefaultForReporter ),
Phil Nashae5ee2c2016-02-29 08:17:18 +00003468 runOrder( RunTests::InDeclarationOrder ),
3469 useColour( UseColour::Auto )
Phil Nash3649fdf2013-12-03 18:53:55 +00003470 {}
3471
3472 bool listTests;
3473 bool listTags;
3474 bool listReporters;
3475 bool listTestNamesOnly;
3476
3477 bool showSuccessfulTests;
3478 bool shouldDebugBreak;
3479 bool noThrow;
3480 bool showHelp;
Phil Nashaef6cd52014-04-23 07:10:10 +01003481 bool showInvisibles;
Phil Nashb971fe72015-07-02 08:21:38 +01003482 bool filenamesAsTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003483
3484 int abortAfter;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003485 unsigned int rngSeed;
Phil Nash3649fdf2013-12-03 18:53:55 +00003486
3487 Verbosity::Level verbosity;
3488 WarnAbout::What warnings;
3489 ShowDurations::OrNot showDurations;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003490 RunTests::InWhatOrder runOrder;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003491 UseColour::YesOrNo useColour;
Phil Nash3649fdf2013-12-03 18:53:55 +00003492
Phil Nash3649fdf2013-12-03 18:53:55 +00003493 std::string outputFilename;
3494 std::string name;
3495 std::string processName;
3496
Phil Nashe73583d2015-08-07 17:30:34 +01003497 std::vector<std::string> reporterNames;
Phil Nash3649fdf2013-12-03 18:53:55 +00003498 std::vector<std::string> testsOrTags;
3499 };
3500
3501 class Config : public SharedImpl<IConfig> {
3502 private:
3503 Config( Config const& other );
3504 Config& operator = ( Config const& other );
3505 virtual void dummy();
3506 public:
3507
3508 Config()
Phil Nash3649fdf2013-12-03 18:53:55 +00003509 {}
3510
3511 Config( ConfigData const& data )
3512 : m_data( data ),
Phil Nash7e346192015-11-03 08:00:43 +00003513 m_stream( openStream() )
Phil Nash3649fdf2013-12-03 18:53:55 +00003514 {
3515 if( !data.testsOrTags.empty() ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003516 TestSpecParser parser( ITagAliasRegistry::get() );
Phil Nash65cc14c2014-05-16 18:54:48 +01003517 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3518 parser.parse( data.testsOrTags[i] );
3519 m_testSpec = parser.testSpec();
Phil Nash3649fdf2013-12-03 18:53:55 +00003520 }
3521 }
3522
3523 virtual ~Config() {
Phil Nash3649fdf2013-12-03 18:53:55 +00003524 }
3525
3526 std::string const& getFilename() const {
3527 return m_data.outputFilename ;
3528 }
3529
3530 bool listTests() const { return m_data.listTests; }
3531 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
3532 bool listTags() const { return m_data.listTags; }
3533 bool listReporters() const { return m_data.listReporters; }
3534
Phil Nash65cc14c2014-05-16 18:54:48 +01003535 std::string getProcessName() const { return m_data.processName; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003536
Phil Nash65cc14c2014-05-16 18:54:48 +01003537 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003538
Phil Nashe73583d2015-08-07 17:30:34 +01003539 std::vector<std::string> getReporterNames() const { return m_data.reporterNames; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003540
Phil Nash65cc14c2014-05-16 18:54:48 +01003541 int abortAfter() const { return m_data.abortAfter; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003542
Phil Nash65cc14c2014-05-16 18:54:48 +01003543 TestSpec const& testSpec() const { return m_testSpec; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003544
3545 bool showHelp() const { return m_data.showHelp; }
Phil Nashaef6cd52014-04-23 07:10:10 +01003546 bool showInvisibles() const { return m_data.showInvisibles; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003547
3548 // IConfig interface
3549 virtual bool allowThrows() const { return !m_data.noThrow; }
Phil Nash7e346192015-11-03 08:00:43 +00003550 virtual std::ostream& stream() const { return m_stream->stream(); }
Phil Nash3649fdf2013-12-03 18:53:55 +00003551 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
3552 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
3553 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
3554 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003555 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
3556 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
Phil Nashae5ee2c2016-02-29 08:17:18 +00003557 virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003558
3559 private:
Phil Nash7e346192015-11-03 08:00:43 +00003560
3561 IStream const* openStream() {
3562 if( m_data.outputFilename.empty() )
3563 return new CoutStream();
3564 else if( m_data.outputFilename[0] == '%' ) {
3565 if( m_data.outputFilename == "%debug" )
3566 return new DebugOutStream();
3567 else
3568 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
3569 }
3570 else
3571 return new FileStream( m_data.outputFilename );
3572 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003573 ConfigData m_data;
3574
Phil Nash7e346192015-11-03 08:00:43 +00003575 std::auto_ptr<IStream const> m_stream;
Phil Nash65cc14c2014-05-16 18:54:48 +01003576 TestSpec m_testSpec;
Phil Nash3649fdf2013-12-03 18:53:55 +00003577 };
3578
3579} // end namespace Catch
3580
Phil Nash1c2fbe12014-02-11 18:12:41 +00003581// #included from: catch_clara.h
3582#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3583
Phil Nashb9fea752014-03-06 08:16:06 +00003584// Use Catch's value for console width (store Clara's off to the side, if present)
3585#ifdef CLARA_CONFIG_CONSOLE_WIDTH
3586#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3587#undef CLARA_CONFIG_CONSOLE_WIDTH
3588#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00003589#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3590
3591// Declare Clara inside the Catch namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003592#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
Phil Nash472dc2a2014-03-17 18:40:58 +00003593// #included from: ../external/clara.h
Phil Nasha695eb92012-08-13 07:46:10 +01003594
Phil Nash3b4edd72016-02-10 19:24:48 +00003595// Version 0.0.1.1
3596
Phil Nash1c2fbe12014-02-11 18:12:41 +00003597// Only use header guard if we are not using an outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003598#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3599
3600#ifndef STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003601#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00003602#define STITCH_CLARA_OPEN_NAMESPACE
3603#define STITCH_CLARA_CLOSE_NAMESPACE
3604#else
3605#define STITCH_CLARA_CLOSE_NAMESPACE }
Phil Nash1c2fbe12014-02-11 18:12:41 +00003606#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00003607
Phil Nashb9fea752014-03-06 08:16:06 +00003608#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003609
3610// ----------- #included from tbc_text_format.h -----------
3611
Phil Nash1c2fbe12014-02-11 18:12:41 +00003612// Only use header guard if we are not using an outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003613#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3614#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3615#define TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00003616#endif
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003617
Phil Nash38f7eef2013-03-29 13:44:33 +00003618#include <string>
3619#include <vector>
Phil Nash1c2fbe12014-02-11 18:12:41 +00003620#include <sstream>
Phil Nash3b4edd72016-02-10 19:24:48 +00003621#include <algorithm>
Phil Nash38f7eef2013-03-29 13:44:33 +00003622
Phil Nash1c2fbe12014-02-11 18:12:41 +00003623// Use optional outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003624#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3625namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
Phil Nash1c2fbe12014-02-11 18:12:41 +00003626#endif
3627
3628namespace Tbc {
3629
3630#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3631 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3632#else
3633 const unsigned int consoleWidth = 80;
3634#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01003635
Phil Nash19279252013-04-20 21:07:32 +01003636 struct TextAttributes {
3637 TextAttributes()
3638 : initialIndent( std::string::npos ),
3639 indent( 0 ),
Phil Nash1c2fbe12014-02-11 18:12:41 +00003640 width( consoleWidth-1 ),
Phil Nash19279252013-04-20 21:07:32 +01003641 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003642 {}
Phil Nash3b80af72012-08-09 07:47:30 +01003643
Phil Nash19279252013-04-20 21:07:32 +01003644 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
3645 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3646 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3647 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003648
Phil Nash19279252013-04-20 21:07:32 +01003649 std::size_t initialIndent; // indent of first line, or npos
3650 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3651 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3652 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01003653 };
3654
Phil Nash19279252013-04-20 21:07:32 +01003655 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01003656 public:
Phil Nash1c2fbe12014-02-11 18:12:41 +00003657 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3658 : attr( _attr )
3659 {
3660 std::string wrappableChars = " [({.,/|\\-";
3661 std::size_t indent = _attr.initialIndent != std::string::npos
3662 ? _attr.initialIndent
3663 : _attr.indent;
3664 std::string remainder = _str;
3665
3666 while( !remainder.empty() ) {
3667 if( lines.size() >= 1000 ) {
3668 lines.push_back( "... message truncated due to excessive size" );
3669 return;
3670 }
3671 std::size_t tabPos = std::string::npos;
3672 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3673 std::size_t pos = remainder.find_first_of( '\n' );
3674 if( pos <= width ) {
3675 width = pos;
3676 }
3677 pos = remainder.find_last_of( _attr.tabChar, width );
3678 if( pos != std::string::npos ) {
3679 tabPos = pos;
3680 if( remainder[width] == '\n' )
3681 width--;
3682 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3683 }
3684
3685 if( width == remainder.size() ) {
3686 spliceLine( indent, remainder, width );
3687 }
3688 else if( remainder[width] == '\n' ) {
3689 spliceLine( indent, remainder, width );
3690 if( width <= 1 || remainder.size() != 1 )
3691 remainder = remainder.substr( 1 );
3692 indent = _attr.indent;
3693 }
3694 else {
3695 pos = remainder.find_last_of( wrappableChars, width );
3696 if( pos != std::string::npos && pos > 0 ) {
3697 spliceLine( indent, remainder, pos );
3698 if( remainder[0] == ' ' )
3699 remainder = remainder.substr( 1 );
3700 }
3701 else {
3702 spliceLine( indent, remainder, width-1 );
3703 lines.back() += "-";
3704 }
3705 if( lines.size() == 1 )
3706 indent = _attr.indent;
3707 if( tabPos != std::string::npos )
3708 indent += tabPos;
3709 }
3710 }
3711 }
3712
3713 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
3714 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
3715 _remainder = _remainder.substr( _pos );
3716 }
Phil Nasha695eb92012-08-13 07:46:10 +01003717
Phil Nash38f7eef2013-03-29 13:44:33 +00003718 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01003719
Phil Nash38f7eef2013-03-29 13:44:33 +00003720 const_iterator begin() const { return lines.begin(); }
3721 const_iterator end() const { return lines.end(); }
3722 std::string const& last() const { return lines.back(); }
3723 std::size_t size() const { return lines.size(); }
3724 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00003725 std::string toString() const {
3726 std::ostringstream oss;
3727 oss << *this;
3728 return oss.str();
3729 }
Phil Nasha695eb92012-08-13 07:46:10 +01003730
Phil Nash1c2fbe12014-02-11 18:12:41 +00003731 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
3732 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
3733 it != itEnd; ++it ) {
3734 if( it != _text.begin() )
3735 _stream << "\n";
3736 _stream << *it;
3737 }
3738 return _stream;
3739 }
Phil Nasha695eb92012-08-13 07:46:10 +01003740
Phil Nasha695eb92012-08-13 07:46:10 +01003741 private:
Phil Nash19279252013-04-20 21:07:32 +01003742 std::string str;
3743 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00003744 std::vector<std::string> lines;
3745 };
3746
Phil Nash1c2fbe12014-02-11 18:12:41 +00003747} // end namespace Tbc
3748
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003749#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00003750} // end outer namespace
3751#endif
3752
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003753#endif // TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00003754
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003755// ----------- end of #include from tbc_text_format.h -----------
Phil Nash3b4edd72016-02-10 19:24:48 +00003756// ........... back in clara.h
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003757
Phil Nashb9fea752014-03-06 08:16:06 +00003758#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003759
Phil Nash3b4edd72016-02-10 19:24:48 +00003760// ----------- #included from clara_compilers.h -----------
3761
3762#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3763#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3764
3765// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
3766// The following features are defined:
3767//
3768// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
3769// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
3770// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
3771// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
3772// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
3773
3774// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
3775
3776// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
3777
3778// In general each macro has a _NO_<feature name> form
3779// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
3780// Many features, at point of detection, define an _INTERNAL_ macro, so they
3781// can be combined, en-mass, with the _NO_ forms later.
3782
3783// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
3784
3785#ifdef __clang__
3786
3787#if __has_feature(cxx_nullptr)
3788#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3789#endif
3790
3791#if __has_feature(cxx_noexcept)
3792#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3793#endif
3794
3795#endif // __clang__
3796
3797////////////////////////////////////////////////////////////////////////////////
3798// GCC
3799#ifdef __GNUC__
3800
3801#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
3802#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3803#endif
3804
3805// - otherwise more recent versions define __cplusplus >= 201103L
3806// and will get picked up below
3807
3808#endif // __GNUC__
3809
3810////////////////////////////////////////////////////////////////////////////////
3811// Visual C++
3812#ifdef _MSC_VER
3813
3814#if (_MSC_VER >= 1600)
3815#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3816#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3817#endif
3818
3819#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
3820#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3821#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3822#endif
3823
3824#endif // _MSC_VER
3825
3826////////////////////////////////////////////////////////////////////////////////
3827// C++ language feature support
3828
3829// catch all support for C++11
3830#if defined(__cplusplus) && __cplusplus >= 201103L
3831
3832#define CLARA_CPP11_OR_GREATER
3833
3834#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
3835#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
3836#endif
3837
3838#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3839#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
3840#endif
3841
3842#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3843#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
3844#endif
3845
3846#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
3847#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
3848#endif
3849#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
3850#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
3851#endif
3852
3853#endif // __cplusplus >= 201103L
3854
3855// Now set the actual defines based on the above + anything the user has configured
3856#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
3857#define CLARA_CONFIG_CPP11_NULLPTR
3858#endif
3859#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
3860#define CLARA_CONFIG_CPP11_NOEXCEPT
3861#endif
3862#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)
3863#define CLARA_CONFIG_CPP11_GENERATED_METHODS
3864#endif
3865#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
3866#define CLARA_CONFIG_CPP11_OVERRIDE
3867#endif
3868#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)
3869#define CLARA_CONFIG_CPP11_UNIQUE_PTR
3870#endif
3871
3872// noexcept support:
3873#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
3874#define CLARA_NOEXCEPT noexcept
3875# define CLARA_NOEXCEPT_IS(x) noexcept(x)
3876#else
3877#define CLARA_NOEXCEPT throw()
3878# define CLARA_NOEXCEPT_IS(x)
3879#endif
3880
3881// nullptr support
3882#ifdef CLARA_CONFIG_CPP11_NULLPTR
3883#define CLARA_NULL nullptr
3884#else
3885#define CLARA_NULL NULL
3886#endif
3887
3888// override support
3889#ifdef CLARA_CONFIG_CPP11_OVERRIDE
3890#define CLARA_OVERRIDE override
3891#else
3892#define CLARA_OVERRIDE
3893#endif
3894
3895// unique_ptr support
3896#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
3897# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
3898#else
3899# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
3900#endif
3901
3902#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
3903
3904// ----------- end of #include from clara_compilers.h -----------
3905// ........... back in clara.h
3906
Phil Nash1c2fbe12014-02-11 18:12:41 +00003907#include <map>
Phil Nash1c2fbe12014-02-11 18:12:41 +00003908#include <stdexcept>
3909#include <memory>
3910
3911// Use optional outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003912#ifdef STITCH_CLARA_OPEN_NAMESPACE
3913STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00003914#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00003915
Phil Nash786959d2013-06-07 19:07:50 +01003916namespace Clara {
Phil Nashb9fea752014-03-06 08:16:06 +00003917
3918 struct UnpositionalTag {};
3919
3920 extern UnpositionalTag _;
3921
3922#ifdef CLARA_CONFIG_MAIN
3923 UnpositionalTag _;
3924#endif
3925
Phil Nash786959d2013-06-07 19:07:50 +01003926 namespace Detail {
Phil Nash1c2fbe12014-02-11 18:12:41 +00003927
3928#ifdef CLARA_CONSOLE_WIDTH
3929 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
3930#else
3931 const unsigned int consoleWidth = 80;
3932#endif
3933
Phil Nash3b4edd72016-02-10 19:24:48 +00003934 // Use this to try and stop compiler from warning about unreachable code
3935 inline bool isTrue( bool value ) { return value; }
3936
Phil Nashb9fea752014-03-06 08:16:06 +00003937 using namespace Tbc;
3938
3939 inline bool startsWith( std::string const& str, std::string const& prefix ) {
3940 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
3941 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00003942
Phil Nash786959d2013-06-07 19:07:50 +01003943 template<typename T> struct RemoveConstRef{ typedef T type; };
3944 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
3945 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
3946 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
3947
3948 template<typename T> struct IsBool { static const bool value = false; };
3949 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01003950
3951 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01003952 void convertInto( std::string const& _source, T& _dest ) {
3953 std::stringstream ss;
3954 ss << _source;
3955 ss >> _dest;
3956 if( ss.fail() )
3957 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01003958 }
Phil Nash786959d2013-06-07 19:07:50 +01003959 inline void convertInto( std::string const& _source, std::string& _dest ) {
3960 _dest = _source;
3961 }
3962 inline void convertInto( std::string const& _source, bool& _dest ) {
3963 std::string sourceLC = _source;
3964 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), ::tolower );
Phil Nash46118712013-08-16 19:01:32 +01003965 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01003966 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01003967 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01003968 _dest = false;
3969 else
Phil Nash46118712013-08-16 19:01:32 +01003970 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01003971 }
3972 inline void convertInto( bool _source, bool& _dest ) {
3973 _dest = _source;
3974 }
3975 template<typename T>
3976 inline void convertInto( bool, T& ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00003977 if( isTrue( true ) )
3978 throw std::runtime_error( "Invalid conversion" );
Phil Nash786959d2013-06-07 19:07:50 +01003979 }
Phil Nasha695eb92012-08-13 07:46:10 +01003980
Phil Nash786959d2013-06-07 19:07:50 +01003981 template<typename ConfigT>
3982 struct IArgFunction {
3983 virtual ~IArgFunction() {}
Phil Nash3b4edd72016-02-10 19:24:48 +00003984#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01003985 IArgFunction() = default;
3986 IArgFunction( IArgFunction const& ) = default;
Phil Nash3b4edd72016-02-10 19:24:48 +00003987#endif
Phil Nash786959d2013-06-07 19:07:50 +01003988 virtual void set( ConfigT& config, std::string const& value ) const = 0;
3989 virtual void setFlag( ConfigT& config ) const = 0;
3990 virtual bool takesArg() const = 0;
3991 virtual IArgFunction* clone() const = 0;
3992 };
3993
3994 template<typename ConfigT>
3995 class BoundArgFunction {
3996 public:
Phil Nash3b4edd72016-02-10 19:24:48 +00003997 BoundArgFunction() : functionObj( CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01003998 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
Phil Nash3b4edd72016-02-10 19:24:48 +00003999 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004000 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004001 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01004002 delete functionObj;
4003 functionObj = newFunctionObj;
4004 return *this;
4005 }
4006 ~BoundArgFunction() { delete functionObj; }
4007
4008 void set( ConfigT& config, std::string const& value ) const {
4009 functionObj->set( config, value );
4010 }
4011 void setFlag( ConfigT& config ) const {
4012 functionObj->setFlag( config );
4013 }
4014 bool takesArg() const { return functionObj->takesArg(); }
Phil Nashaf8cd982014-03-24 18:15:04 +00004015
4016 bool isSet() const {
Phil Nash3b4edd72016-02-10 19:24:48 +00004017 return functionObj != CLARA_NULL;
Phil Nashaf8cd982014-03-24 18:15:04 +00004018 }
Phil Nash786959d2013-06-07 19:07:50 +01004019 private:
4020 IArgFunction<ConfigT>* functionObj;
4021 };
4022
4023 template<typename C>
4024 struct NullBinder : IArgFunction<C>{
4025 virtual void set( C&, std::string const& ) const {}
4026 virtual void setFlag( C& ) const {}
4027 virtual bool takesArg() const { return true; }
4028 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4029 };
4030
4031 template<typename C, typename M>
4032 struct BoundDataMember : IArgFunction<C>{
4033 BoundDataMember( M C::* _member ) : member( _member ) {}
4034 virtual void set( C& p, std::string const& stringValue ) const {
4035 convertInto( stringValue, p.*member );
4036 }
4037 virtual void setFlag( C& p ) const {
4038 convertInto( true, p.*member );
4039 }
4040 virtual bool takesArg() const { return !IsBool<M>::value; }
4041 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4042 M C::* member;
4043 };
4044 template<typename C, typename M>
4045 struct BoundUnaryMethod : IArgFunction<C>{
4046 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4047 virtual void set( C& p, std::string const& stringValue ) const {
4048 typename RemoveConstRef<M>::type value;
4049 convertInto( stringValue, value );
4050 (p.*member)( value );
4051 }
4052 virtual void setFlag( C& p ) const {
4053 typename RemoveConstRef<M>::type value;
4054 convertInto( true, value );
4055 (p.*member)( value );
4056 }
4057 virtual bool takesArg() const { return !IsBool<M>::value; }
4058 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4059 void (C::*member)( M );
4060 };
4061 template<typename C>
4062 struct BoundNullaryMethod : IArgFunction<C>{
4063 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4064 virtual void set( C& p, std::string const& stringValue ) const {
4065 bool value;
4066 convertInto( stringValue, value );
4067 if( value )
4068 (p.*member)();
4069 }
4070 virtual void setFlag( C& p ) const {
4071 (p.*member)();
4072 }
4073 virtual bool takesArg() const { return false; }
4074 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4075 void (C::*member)();
4076 };
4077
4078 template<typename C>
4079 struct BoundUnaryFunction : IArgFunction<C>{
4080 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4081 virtual void set( C& obj, std::string const& stringValue ) const {
4082 bool value;
4083 convertInto( stringValue, value );
4084 if( value )
4085 function( obj );
4086 }
4087 virtual void setFlag( C& p ) const {
4088 function( p );
4089 }
4090 virtual bool takesArg() const { return false; }
4091 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4092 void (*function)( C& );
4093 };
4094
4095 template<typename C, typename T>
4096 struct BoundBinaryFunction : IArgFunction<C>{
4097 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4098 virtual void set( C& obj, std::string const& stringValue ) const {
4099 typename RemoveConstRef<T>::type value;
4100 convertInto( stringValue, value );
4101 function( obj, value );
4102 }
4103 virtual void setFlag( C& obj ) const {
4104 typename RemoveConstRef<T>::type value;
4105 convertInto( true, value );
4106 function( obj, value );
4107 }
4108 virtual bool takesArg() const { return !IsBool<T>::value; }
4109 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4110 void (*function)( C&, T );
4111 };
4112
Phil Nash786959d2013-06-07 19:07:50 +01004113 } // namespace Detail
4114
4115 struct Parser {
4116 Parser() : separators( " \t=:" ) {}
4117
4118 struct Token {
4119 enum Type { Positional, ShortOpt, LongOpt };
4120 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4121 Type type;
4122 std::string data;
4123 };
4124
Phil Nash3b4edd72016-02-10 19:24:48 +00004125 void parseIntoTokens( int argc, char const* const argv[], std::vector<Parser::Token>& tokens ) const {
Phil Nashe45e3a12013-12-23 10:24:06 +00004126 const std::string doubleDash = "--";
4127 for( int i = 1; i < argc && argv[i] != doubleDash; ++i )
Phil Nash786959d2013-06-07 19:07:50 +01004128 parseIntoTokens( argv[i] , tokens);
4129 }
4130 void parseIntoTokens( std::string arg, std::vector<Parser::Token>& tokens ) const {
4131 while( !arg.empty() ) {
4132 Parser::Token token( Parser::Token::Positional, arg );
4133 arg = "";
4134 if( token.data[0] == '-' ) {
4135 if( token.data.size() > 1 && token.data[1] == '-' ) {
4136 token = Parser::Token( Parser::Token::LongOpt, token.data.substr( 2 ) );
4137 }
4138 else {
4139 token = Parser::Token( Parser::Token::ShortOpt, token.data.substr( 1 ) );
4140 if( token.data.size() > 1 && separators.find( token.data[1] ) == std::string::npos ) {
4141 arg = "-" + token.data.substr( 1 );
4142 token.data = token.data.substr( 0, 1 );
4143 }
4144 }
4145 }
4146 if( token.type != Parser::Token::Positional ) {
4147 std::size_t pos = token.data.find_first_of( separators );
4148 if( pos != std::string::npos ) {
4149 arg = token.data.substr( pos+1 );
4150 token.data = token.data.substr( 0, pos );
4151 }
4152 }
4153 tokens.push_back( token );
4154 }
4155 }
4156 std::string separators;
Phil Nasha695eb92012-08-13 07:46:10 +01004157 };
4158
Phil Nash786959d2013-06-07 19:07:50 +01004159 template<typename ConfigT>
Phil Nash472dc2a2014-03-17 18:40:58 +00004160 struct CommonArgProperties {
4161 CommonArgProperties() {}
4162 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4163
4164 Detail::BoundArgFunction<ConfigT> boundField;
4165 std::string description;
Phil Nashaf8cd982014-03-24 18:15:04 +00004166 std::string detail;
Phil Nash472dc2a2014-03-17 18:40:58 +00004167 std::string placeholder; // Only value if boundField takes an arg
4168
4169 bool takesArg() const {
4170 return !placeholder.empty();
4171 }
Phil Nashaf8cd982014-03-24 18:15:04 +00004172 void validate() const {
4173 if( !boundField.isSet() )
4174 throw std::logic_error( "option not bound" );
4175 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004176 };
4177 struct OptionArgProperties {
4178 std::vector<std::string> shortNames;
4179 std::string longName;
4180
4181 bool hasShortName( std::string const& shortName ) const {
4182 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4183 }
4184 bool hasLongName( std::string const& _longName ) const {
4185 return _longName == longName;
4186 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004187 };
4188 struct PositionalArgProperties {
4189 PositionalArgProperties() : position( -1 ) {}
4190 int position; // -1 means non-positional (floating)
4191
4192 bool isFixedPositional() const {
4193 return position != -1;
4194 }
4195 };
4196
4197 template<typename ConfigT>
Phil Nash786959d2013-06-07 19:07:50 +01004198 class CommandLine {
4199
Phil Nash472dc2a2014-03-17 18:40:58 +00004200 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4201 Arg() {}
4202 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004203
Phil Nash472dc2a2014-03-17 18:40:58 +00004204 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4205
Phil Nash786959d2013-06-07 19:07:50 +01004206 std::string dbgName() const {
4207 if( !longName.empty() )
4208 return "--" + longName;
4209 if( !shortNames.empty() )
4210 return "-" + shortNames[0];
4211 return "positional args";
4212 }
Phil Nash786959d2013-06-07 19:07:50 +01004213 std::string commands() const {
4214 std::ostringstream oss;
4215 bool first = true;
4216 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4217 for(; it != itEnd; ++it ) {
4218 if( first )
4219 first = false;
4220 else
4221 oss << ", ";
4222 oss << "-" << *it;
4223 }
4224 if( !longName.empty() ) {
4225 if( !first )
4226 oss << ", ";
4227 oss << "--" << longName;
4228 }
Phil Nashb9fea752014-03-06 08:16:06 +00004229 if( !placeholder.empty() )
4230 oss << " <" << placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004231 return oss.str();
4232 }
Phil Nash786959d2013-06-07 19:07:50 +01004233 };
4234
Phil Nash3b4edd72016-02-10 19:24:48 +00004235 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
Phil Nash5ecb72b2013-11-26 20:57:45 +00004236
Phil Nash472dc2a2014-03-17 18:40:58 +00004237 friend void addOptName( Arg& arg, std::string const& optName )
4238 {
4239 if( optName.empty() )
4240 return;
4241 if( Detail::startsWith( optName, "--" ) ) {
4242 if( !arg.longName.empty() )
4243 throw std::logic_error( "Only one long opt may be specified. '"
4244 + arg.longName
4245 + "' already specified, now attempting to add '"
4246 + optName + "'" );
4247 arg.longName = optName.substr( 2 );
4248 }
4249 else if( Detail::startsWith( optName, "-" ) )
4250 arg.shortNames.push_back( optName.substr( 1 ) );
4251 else
4252 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4253 }
4254 friend void setPositionalArg( Arg& arg, int position )
4255 {
4256 arg.position = position;
4257 }
4258
Phil Nashb9fea752014-03-06 08:16:06 +00004259 class ArgBuilder {
Phil Nash786959d2013-06-07 19:07:50 +01004260 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004261 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004262
Phil Nash472dc2a2014-03-17 18:40:58 +00004263 // Bind a non-boolean data member (requires placeholder string)
4264 template<typename C, typename M>
4265 void bind( M C::* field, std::string const& placeholder ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004266 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4267 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004268 }
4269 // Bind a boolean data member (no placeholder required)
4270 template<typename C>
4271 void bind( bool C::* field ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004272 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
Phil Nash472dc2a2014-03-17 18:40:58 +00004273 }
4274
4275 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4276 template<typename C, typename M>
Phil Nashaf8cd982014-03-24 18:15:04 +00004277 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4278 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4279 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004280 }
4281
4282 // Bind a method taking a single, boolean argument (no placeholder string required)
4283 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004284 void bind( void (C::* unaryMethod)( bool ) ) {
4285 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004286 }
4287
4288 // Bind a method that takes no arguments (will be called if opt is present)
4289 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004290 void bind( void (C::* nullaryMethod)() ) {
4291 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004292 }
4293
4294 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4295 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004296 void bind( void (* unaryFunction)( C& ) ) {
4297 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
Phil Nash472dc2a2014-03-17 18:40:58 +00004298 }
4299
4300 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4301 template<typename C, typename T>
Phil Nashaf8cd982014-03-24 18:15:04 +00004302 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4303 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4304 m_arg->placeholder = placeholder;
Phil Nash786959d2013-06-07 19:07:50 +01004305 }
Phil Nashb9fea752014-03-06 08:16:06 +00004306
4307 ArgBuilder& describe( std::string const& description ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004308 m_arg->description = description;
Phil Nash786959d2013-06-07 19:07:50 +01004309 return *this;
4310 }
Phil Nash3b4edd72016-02-10 19:24:48 +00004311 ArgBuilder& detail( std::string const& detail ) {
4312 m_arg->detail = detail;
Phil Nash786959d2013-06-07 19:07:50 +01004313 return *this;
4314 }
Phil Nashb9fea752014-03-06 08:16:06 +00004315
Phil Nash472dc2a2014-03-17 18:40:58 +00004316 protected:
Phil Nashaf8cd982014-03-24 18:15:04 +00004317 Arg* m_arg;
Phil Nash786959d2013-06-07 19:07:50 +01004318 };
Phil Nash472dc2a2014-03-17 18:40:58 +00004319
Phil Nashb9fea752014-03-06 08:16:06 +00004320 class OptBuilder : public ArgBuilder {
4321 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004322 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004323 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4324
4325 OptBuilder& operator[]( std::string const& optName ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004326 addOptName( *ArgBuilder::m_arg, optName );
Phil Nashb9fea752014-03-06 08:16:06 +00004327 return *this;
4328 }
4329 };
Phil Nash786959d2013-06-07 19:07:50 +01004330
4331 public:
4332
4333 CommandLine()
4334 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004335 m_highestSpecifiedArgPosition( 0 ),
4336 m_throwOnUnrecognisedTokens( false )
Phil Nash786959d2013-06-07 19:07:50 +01004337 {}
4338 CommandLine( CommandLine const& other )
4339 : m_boundProcessName( other.m_boundProcessName ),
4340 m_options ( other.m_options ),
4341 m_positionalArgs( other.m_positionalArgs ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004342 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4343 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
Phil Nash786959d2013-06-07 19:07:50 +01004344 {
Phil Nash472dc2a2014-03-17 18:40:58 +00004345 if( other.m_floatingArg.get() )
Phil Nash85b4e942014-10-02 18:51:05 +01004346 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
Phil Nash786959d2013-06-07 19:07:50 +01004347 }
4348
Phil Nash91ef5f72013-12-20 19:06:26 +00004349 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4350 m_throwOnUnrecognisedTokens = shouldThrow;
4351 return *this;
4352 }
4353
Phil Nashb9fea752014-03-06 08:16:06 +00004354 OptBuilder operator[]( std::string const& optName ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004355 m_options.push_back( Arg() );
4356 addOptName( m_options.back(), optName );
Phil Nashaf8cd982014-03-24 18:15:04 +00004357 OptBuilder builder( &m_options.back() );
Phil Nashb9fea752014-03-06 08:16:06 +00004358 return builder;
Phil Nash786959d2013-06-07 19:07:50 +01004359 }
Phil Nashb9fea752014-03-06 08:16:06 +00004360
4361 ArgBuilder operator[]( int position ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004362 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4363 if( position > m_highestSpecifiedArgPosition )
4364 m_highestSpecifiedArgPosition = position;
4365 setPositionalArg( m_positionalArgs[position], position );
Phil Nashaf8cd982014-03-24 18:15:04 +00004366 ArgBuilder builder( &m_positionalArgs[position] );
Phil Nashb9fea752014-03-06 08:16:06 +00004367 return builder;
4368 }
4369
4370 // Invoke this with the _ instance
4371 ArgBuilder operator[]( UnpositionalTag ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004372 if( m_floatingArg.get() )
4373 throw std::logic_error( "Only one unpositional argument can be added" );
Phil Nash85b4e942014-10-02 18:51:05 +01004374 m_floatingArg.reset( new Arg() );
Phil Nashaf8cd982014-03-24 18:15:04 +00004375 ArgBuilder builder( m_floatingArg.get() );
Phil Nashb9fea752014-03-06 08:16:06 +00004376 return builder;
4377 }
4378
Phil Nash472dc2a2014-03-17 18:40:58 +00004379 template<typename C, typename M>
4380 void bindProcessName( M C::* field ) {
4381 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4382 }
4383 template<typename C, typename M>
4384 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4385 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
Phil Nash786959d2013-06-07 19:07:50 +01004386 }
4387
Phil Nash1c2fbe12014-02-11 18:12:41 +00004388 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
Phil Nash786959d2013-06-07 19:07:50 +01004389 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4390 std::size_t maxWidth = 0;
4391 for( it = itBegin; it != itEnd; ++it )
4392 maxWidth = (std::max)( maxWidth, it->commands().size() );
4393
4394 for( it = itBegin; it != itEnd; ++it ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004395 Detail::Text usage( it->commands(), Detail::TextAttributes()
Phil Nash786959d2013-06-07 19:07:50 +01004396 .setWidth( maxWidth+indent )
4397 .setIndent( indent ) );
Phil Nash1c2fbe12014-02-11 18:12:41 +00004398 Detail::Text desc( it->description, Detail::TextAttributes()
Phil Nashaf8cd982014-03-24 18:15:04 +00004399 .setWidth( width - maxWidth - 3 ) );
Phil Nash786959d2013-06-07 19:07:50 +01004400
Phil Nash3b4edd72016-02-10 19:24:48 +00004401 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4402 std::string usageCol = i < usage.size() ? usage[i] : "";
Phil Nash786959d2013-06-07 19:07:50 +01004403 os << usageCol;
4404
4405 if( i < desc.size() && !desc[i].empty() )
4406 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4407 << desc[i];
4408 os << "\n";
4409 }
4410 }
4411 }
4412 std::string optUsage() const {
4413 std::ostringstream oss;
4414 optUsage( oss );
4415 return oss.str();
4416 }
4417
4418 void argSynopsis( std::ostream& os ) const {
4419 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4420 if( i > 1 )
4421 os << " ";
4422 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4423 if( it != m_positionalArgs.end() )
Phil Nashb9fea752014-03-06 08:16:06 +00004424 os << "<" << it->second.placeholder << ">";
Phil Nash472dc2a2014-03-17 18:40:58 +00004425 else if( m_floatingArg.get() )
4426 os << "<" << m_floatingArg->placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004427 else
4428 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4429 }
4430 // !TBD No indication of mandatory args
Phil Nash472dc2a2014-03-17 18:40:58 +00004431 if( m_floatingArg.get() ) {
Phil Nash786959d2013-06-07 19:07:50 +01004432 if( m_highestSpecifiedArgPosition > 1 )
4433 os << " ";
Phil Nash472dc2a2014-03-17 18:40:58 +00004434 os << "[<" << m_floatingArg->placeholder << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01004435 }
4436 }
4437 std::string argSynopsis() const {
4438 std::ostringstream oss;
4439 argSynopsis( oss );
4440 return oss.str();
4441 }
4442
4443 void usage( std::ostream& os, std::string const& procName ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004444 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004445 os << "usage:\n " << procName << " ";
4446 argSynopsis( os );
4447 if( !m_options.empty() ) {
4448 os << " [options]\n\nwhere options are: \n";
4449 optUsage( os, 2 );
4450 }
4451 os << "\n";
4452 }
4453 std::string usage( std::string const& procName ) const {
4454 std::ostringstream oss;
4455 usage( oss, procName );
4456 return oss.str();
4457 }
4458
Phil Nash3b4edd72016-02-10 19:24:48 +00004459 ConfigT parse( int argc, char const* const argv[] ) const {
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004460 ConfigT config;
4461 parseInto( argc, argv, config );
4462 return config;
4463 }
4464
Phil Nash3b4edd72016-02-10 19:24:48 +00004465 std::vector<Parser::Token> parseInto( int argc, char const* argv[], ConfigT& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01004466 std::string processName = argv[0];
4467 std::size_t lastSlash = processName.find_last_of( "/\\" );
4468 if( lastSlash != std::string::npos )
4469 processName = processName.substr( lastSlash+1 );
4470 m_boundProcessName.set( config, processName );
4471 std::vector<Parser::Token> tokens;
4472 Parser parser;
4473 parser.parseIntoTokens( argc, argv, tokens );
4474 return populate( tokens, config );
4475 }
4476
4477 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004478 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004479 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4480 unusedTokens = populateFixedArgs( unusedTokens, config );
4481 unusedTokens = populateFloatingArgs( unusedTokens, config );
4482 return unusedTokens;
4483 }
4484
4485 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4486 std::vector<Parser::Token> unusedTokens;
Phil Nash91ef5f72013-12-20 19:06:26 +00004487 std::vector<std::string> errors;
Phil Nash786959d2013-06-07 19:07:50 +01004488 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4489 Parser::Token const& token = tokens[i];
4490 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4491 for(; it != itEnd; ++it ) {
4492 Arg const& arg = *it;
4493
4494 try {
4495 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4496 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4497 if( arg.takesArg() ) {
4498 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
Phil Nash91ef5f72013-12-20 19:06:26 +00004499 errors.push_back( "Expected argument to option: " + token.data );
4500 else
4501 arg.boundField.set( config, tokens[++i].data );
Phil Nash786959d2013-06-07 19:07:50 +01004502 }
4503 else {
4504 arg.boundField.setFlag( config );
4505 }
4506 break;
4507 }
4508 }
4509 catch( std::exception& ex ) {
Phil Nash91ef5f72013-12-20 19:06:26 +00004510 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01004511 }
4512 }
Phil Nash91ef5f72013-12-20 19:06:26 +00004513 if( it == itEnd ) {
4514 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4515 unusedTokens.push_back( token );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004516 else if( errors.empty() && m_throwOnUnrecognisedTokens )
Phil Nash91ef5f72013-12-20 19:06:26 +00004517 errors.push_back( "unrecognised option: " + token.data );
4518 }
4519 }
4520 if( !errors.empty() ) {
4521 std::ostringstream oss;
4522 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4523 it != itEnd;
4524 ++it ) {
4525 if( it != errors.begin() )
4526 oss << "\n";
4527 oss << *it;
4528 }
4529 throw std::runtime_error( oss.str() );
Phil Nash786959d2013-06-07 19:07:50 +01004530 }
4531 return unusedTokens;
4532 }
4533 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4534 std::vector<Parser::Token> unusedTokens;
4535 int position = 1;
4536 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4537 Parser::Token const& token = tokens[i];
4538 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4539 if( it != m_positionalArgs.end() )
4540 it->second.boundField.set( config, token.data );
4541 else
4542 unusedTokens.push_back( token );
4543 if( token.type == Parser::Token::Positional )
4544 position++;
4545 }
4546 return unusedTokens;
4547 }
4548 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nash472dc2a2014-03-17 18:40:58 +00004549 if( !m_floatingArg.get() )
Phil Nash786959d2013-06-07 19:07:50 +01004550 return tokens;
4551 std::vector<Parser::Token> unusedTokens;
4552 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4553 Parser::Token const& token = tokens[i];
4554 if( token.type == Parser::Token::Positional )
Phil Nash472dc2a2014-03-17 18:40:58 +00004555 m_floatingArg->boundField.set( config, token.data );
Phil Nash786959d2013-06-07 19:07:50 +01004556 else
4557 unusedTokens.push_back( token );
4558 }
4559 return unusedTokens;
4560 }
4561
Phil Nashaf8cd982014-03-24 18:15:04 +00004562 void validate() const
4563 {
4564 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4565 throw std::logic_error( "No options or arguments specified" );
4566
4567 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4568 itEnd = m_options.end();
4569 it != itEnd; ++it )
4570 it->validate();
4571 }
4572
Phil Nash786959d2013-06-07 19:07:50 +01004573 private:
4574 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4575 std::vector<Arg> m_options;
4576 std::map<int, Arg> m_positionalArgs;
Phil Nash472dc2a2014-03-17 18:40:58 +00004577 ArgAutoPtr m_floatingArg;
Phil Nash786959d2013-06-07 19:07:50 +01004578 int m_highestSpecifiedArgPosition;
Phil Nash91ef5f72013-12-20 19:06:26 +00004579 bool m_throwOnUnrecognisedTokens;
Phil Nash786959d2013-06-07 19:07:50 +01004580 };
4581
4582} // end namespace Clara
4583
Phil Nashb9fea752014-03-06 08:16:06 +00004584STITCH_CLARA_CLOSE_NAMESPACE
4585#undef STITCH_CLARA_OPEN_NAMESPACE
4586#undef STITCH_CLARA_CLOSE_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004587
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004588#endif // TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00004589#undef STITCH_CLARA_OPEN_NAMESPACE
4590
4591// Restore Clara's value for console width, if present
4592#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4593#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4594#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4595#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00004596
Phil Nash5ecb72b2013-11-26 20:57:45 +00004597#include <fstream>
4598
Phil Nash786959d2013-06-07 19:07:50 +01004599namespace Catch {
4600
4601 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4602 inline void abortAfterX( ConfigData& config, int x ) {
4603 if( x < 1 )
4604 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4605 config.abortAfter = x;
4606 }
4607 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
Phil Nashe73583d2015-08-07 17:30:34 +01004608 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
Phil Nash786959d2013-06-07 19:07:50 +01004609
4610 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4611 if( _warning == "NoAssertions" )
Phil Nashce562092014-07-09 07:40:37 +01004612 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01004613 else
4614 throw std::runtime_error( "Unrecognised warning: '" + _warning + "'" );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004615 }
4616 inline void setOrder( ConfigData& config, std::string const& order ) {
4617 if( startsWith( "declared", order ) )
4618 config.runOrder = RunTests::InDeclarationOrder;
4619 else if( startsWith( "lexical", order ) )
4620 config.runOrder = RunTests::InLexicographicalOrder;
4621 else if( startsWith( "random", order ) )
4622 config.runOrder = RunTests::InRandomOrder;
4623 else
4624 throw std::runtime_error( "Unrecognised ordering: '" + order + "'" );
4625 }
4626 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
4627 if( seed == "time" ) {
4628 config.rngSeed = static_cast<unsigned int>( std::time(0) );
4629 }
4630 else {
4631 std::stringstream ss;
4632 ss << seed;
4633 ss >> config.rngSeed;
4634 if( ss.fail() )
4635 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
4636 }
Phil Nash786959d2013-06-07 19:07:50 +01004637 }
4638 inline void setVerbosity( ConfigData& config, int level ) {
4639 // !TBD: accept strings?
Phil Nashce562092014-07-09 07:40:37 +01004640 config.verbosity = static_cast<Verbosity::Level>( level );
Phil Nashaa7123b2013-08-15 19:01:00 +01004641 }
4642 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4643 config.showDurations = _showDurations
4644 ? ShowDurations::Always
4645 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01004646 }
Phil Nashae5ee2c2016-02-29 08:17:18 +00004647 inline void setUseColour( ConfigData& config, std::string const& value ) {
4648 std::string mode = toLower( value );
4649
4650 if( mode == "yes" )
4651 config.useColour = UseColour::Yes;
4652 else if( mode == "no" )
4653 config.useColour = UseColour::No;
4654 else if( mode == "auto" )
4655 config.useColour = UseColour::Auto;
4656 else
4657 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
4658 }
4659 inline void forceColour( ConfigData& config ) {
4660 config.useColour = UseColour::Yes;
4661 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00004662 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
4663 std::ifstream f( _filename.c_str() );
4664 if( !f.is_open() )
4665 throw std::domain_error( "Unable to load input file: " + _filename );
4666
4667 std::string line;
4668 while( std::getline( f, line ) ) {
4669 line = trim(line);
4670 if( !line.empty() && !startsWith( line, "#" ) )
Phil Nash9241e432014-05-20 18:50:59 +01004671 addTestOrTags( config, "\"" + line + "\"," );
Phil Nash5ecb72b2013-11-26 20:57:45 +00004672 }
4673 }
Phil Nash786959d2013-06-07 19:07:50 +01004674
4675 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4676
Phil Nashb9fea752014-03-06 08:16:06 +00004677 using namespace Clara;
4678 CommandLine<ConfigData> cli;
Phil Nash786959d2013-06-07 19:07:50 +01004679
4680 cli.bindProcessName( &ConfigData::processName );
4681
Phil Nashb9fea752014-03-06 08:16:06 +00004682 cli["-?"]["-h"]["--help"]
Phil Nash786959d2013-06-07 19:07:50 +01004683 .describe( "display usage information" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004684 .bind( &ConfigData::showHelp );
Phil Nash786959d2013-06-07 19:07:50 +01004685
Phil Nashb9fea752014-03-06 08:16:06 +00004686 cli["-l"]["--list-tests"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004687 .describe( "list all/matching test cases" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004688 .bind( &ConfigData::listTests );
Phil Nash786959d2013-06-07 19:07:50 +01004689
Phil Nashb9fea752014-03-06 08:16:06 +00004690 cli["-t"]["--list-tags"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004691 .describe( "list all/matching tags" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004692 .bind( &ConfigData::listTags );
Phil Nash786959d2013-06-07 19:07:50 +01004693
Phil Nashb9fea752014-03-06 08:16:06 +00004694 cli["-s"]["--success"]
Phil Nash786959d2013-06-07 19:07:50 +01004695 .describe( "include successful tests in output" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004696 .bind( &ConfigData::showSuccessfulTests );
Phil Nash786959d2013-06-07 19:07:50 +01004697
Phil Nashb9fea752014-03-06 08:16:06 +00004698 cli["-b"]["--break"]
Phil Nash786959d2013-06-07 19:07:50 +01004699 .describe( "break into debugger on failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004700 .bind( &ConfigData::shouldDebugBreak );
Phil Nash786959d2013-06-07 19:07:50 +01004701
Phil Nashb9fea752014-03-06 08:16:06 +00004702 cli["-e"]["--nothrow"]
Phil Nash7d5f2712013-06-07 21:15:25 +01004703 .describe( "skip exception tests" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004704 .bind( &ConfigData::noThrow );
Phil Nash786959d2013-06-07 19:07:50 +01004705
Phil Nashaef6cd52014-04-23 07:10:10 +01004706 cli["-i"]["--invisibles"]
4707 .describe( "show invisibles (tabs, newlines)" )
4708 .bind( &ConfigData::showInvisibles );
4709
Phil Nashb9fea752014-03-06 08:16:06 +00004710 cli["-o"]["--out"]
Phil Nash786959d2013-06-07 19:07:50 +01004711 .describe( "output filename" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004712 .bind( &ConfigData::outputFilename, "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01004713
Phil Nashb9fea752014-03-06 08:16:06 +00004714 cli["-r"]["--reporter"]
4715// .placeholder( "name[:filename]" )
Phil Nash5ecb72b2013-11-26 20:57:45 +00004716 .describe( "reporter to use (defaults to console)" )
Phil Nashe73583d2015-08-07 17:30:34 +01004717 .bind( &addReporterName, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01004718
Phil Nashb9fea752014-03-06 08:16:06 +00004719 cli["-n"]["--name"]
Phil Nash786959d2013-06-07 19:07:50 +01004720 .describe( "suite name" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004721 .bind( &ConfigData::name, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01004722
Phil Nashb9fea752014-03-06 08:16:06 +00004723 cli["-a"]["--abort"]
Phil Nash786959d2013-06-07 19:07:50 +01004724 .describe( "abort at first failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004725 .bind( &abortAfterFirst );
Phil Nash786959d2013-06-07 19:07:50 +01004726
Phil Nashb9fea752014-03-06 08:16:06 +00004727 cli["-x"]["--abortx"]
Phil Nash786959d2013-06-07 19:07:50 +01004728 .describe( "abort after x failures" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004729 .bind( &abortAfterX, "no. failures" );
Phil Nash786959d2013-06-07 19:07:50 +01004730
Phil Nashb9fea752014-03-06 08:16:06 +00004731 cli["-w"]["--warn"]
Phil Nash786959d2013-06-07 19:07:50 +01004732 .describe( "enable warnings" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004733 .bind( &addWarning, "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01004734
Phil Nashb9fea752014-03-06 08:16:06 +00004735// - needs updating if reinstated
4736// cli.into( &setVerbosity )
Phil Nash786959d2013-06-07 19:07:50 +01004737// .describe( "level of verbosity (0=no output)" )
4738// .shortOpt( "v")
4739// .longOpt( "verbosity" )
Phil Nashb9fea752014-03-06 08:16:06 +00004740// .placeholder( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01004741
Phil Nashb9fea752014-03-06 08:16:06 +00004742 cli[_]
Phil Nash786959d2013-06-07 19:07:50 +01004743 .describe( "which test or tests to use" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004744 .bind( &addTestOrTags, "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01004745
Phil Nashb9fea752014-03-06 08:16:06 +00004746 cli["-d"]["--durations"]
Phil Nashaa7123b2013-08-15 19:01:00 +01004747 .describe( "show test durations" )
Phil Nashae5ee2c2016-02-29 08:17:18 +00004748 .bind( &setShowDurations, "yes|no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01004749
Phil Nashb9fea752014-03-06 08:16:06 +00004750 cli["-f"]["--input-file"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004751 .describe( "load test names to run from a file" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004752 .bind( &loadTestNamesFromFile, "filename" );
Phil Nash5ecb72b2013-11-26 20:57:45 +00004753
Phil Nashe6b365d2015-07-07 08:25:15 +01004754 cli["-#"]["--filenames-as-tags"]
4755 .describe( "adds a tag for the filename" )
4756 .bind( &ConfigData::filenamesAsTags );
4757
Phil Nash5ecb72b2013-11-26 20:57:45 +00004758 // Less common commands which don't have a short form
Phil Nashb9fea752014-03-06 08:16:06 +00004759 cli["--list-test-names-only"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004760 .describe( "list all/matching test cases names only" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004761 .bind( &ConfigData::listTestNamesOnly );
Phil Nash5ecb72b2013-11-26 20:57:45 +00004762
Phil Nashb9fea752014-03-06 08:16:06 +00004763 cli["--list-reporters"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004764 .describe( "list all reporters" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004765 .bind( &ConfigData::listReporters );
Phil Nash5ecb72b2013-11-26 20:57:45 +00004766
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004767 cli["--order"]
4768 .describe( "test case order (defaults to decl)" )
4769 .bind( &setOrder, "decl|lex|rand" );
4770
4771 cli["--rng-seed"]
4772 .describe( "set a specific seed for random numbers" )
4773 .bind( &setRngSeed, "'time'|number" );
4774
Phil Nasha806c3e2015-03-04 08:23:40 +00004775 cli["--force-colour"]
Phil Nashae5ee2c2016-02-29 08:17:18 +00004776 .describe( "force colourised output (deprecated)" )
4777 .bind( &forceColour );
4778
4779 cli["--use-colour"]
4780 .describe( "should output be colourised" )
4781 .bind( &setUseColour, "yes|no" );
Phil Nasha806c3e2015-03-04 08:23:40 +00004782
Phil Nash786959d2013-06-07 19:07:50 +01004783 return cli;
4784 }
4785
Phil Nasha695eb92012-08-13 07:46:10 +01004786} // end namespace Catch
4787
4788// #included from: internal/catch_list.hpp
4789#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
4790
Phil Nash1c2fbe12014-02-11 18:12:41 +00004791// #included from: catch_text.h
4792#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
4793
4794#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4795
4796#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
Phil Nash472dc2a2014-03-17 18:40:58 +00004797// #included from: ../external/tbc_text_format.h
Phil Nash1c2fbe12014-02-11 18:12:41 +00004798// Only use header guard if we are not using an outer namespace
4799#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4800# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4801# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4802# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4803# endif
4804# else
4805# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
4806# endif
4807#endif
4808#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4809#include <string>
4810#include <vector>
4811#include <sstream>
4812
4813// Use optional outer namespace
4814#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4815namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
4816#endif
4817
4818namespace Tbc {
4819
4820#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4821 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4822#else
4823 const unsigned int consoleWidth = 80;
4824#endif
4825
4826 struct TextAttributes {
4827 TextAttributes()
4828 : initialIndent( std::string::npos ),
4829 indent( 0 ),
4830 width( consoleWidth-1 ),
4831 tabChar( '\t' )
4832 {}
4833
4834 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4835 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4836 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4837 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
4838
4839 std::size_t initialIndent; // indent of first line, or npos
4840 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4841 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4842 char tabChar; // If this char is seen the indent is changed to current pos
4843 };
4844
4845 class Text {
4846 public:
4847 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4848 : attr( _attr )
4849 {
4850 std::string wrappableChars = " [({.,/|\\-";
4851 std::size_t indent = _attr.initialIndent != std::string::npos
4852 ? _attr.initialIndent
4853 : _attr.indent;
4854 std::string remainder = _str;
4855
4856 while( !remainder.empty() ) {
4857 if( lines.size() >= 1000 ) {
4858 lines.push_back( "... message truncated due to excessive size" );
4859 return;
4860 }
4861 std::size_t tabPos = std::string::npos;
4862 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4863 std::size_t pos = remainder.find_first_of( '\n' );
4864 if( pos <= width ) {
4865 width = pos;
4866 }
4867 pos = remainder.find_last_of( _attr.tabChar, width );
4868 if( pos != std::string::npos ) {
4869 tabPos = pos;
4870 if( remainder[width] == '\n' )
4871 width--;
4872 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4873 }
4874
4875 if( width == remainder.size() ) {
4876 spliceLine( indent, remainder, width );
4877 }
4878 else if( remainder[width] == '\n' ) {
4879 spliceLine( indent, remainder, width );
4880 if( width <= 1 || remainder.size() != 1 )
4881 remainder = remainder.substr( 1 );
4882 indent = _attr.indent;
4883 }
4884 else {
4885 pos = remainder.find_last_of( wrappableChars, width );
4886 if( pos != std::string::npos && pos > 0 ) {
4887 spliceLine( indent, remainder, pos );
4888 if( remainder[0] == ' ' )
4889 remainder = remainder.substr( 1 );
4890 }
4891 else {
4892 spliceLine( indent, remainder, width-1 );
4893 lines.back() += "-";
4894 }
4895 if( lines.size() == 1 )
4896 indent = _attr.indent;
4897 if( tabPos != std::string::npos )
4898 indent += tabPos;
4899 }
4900 }
4901 }
4902
4903 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4904 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4905 _remainder = _remainder.substr( _pos );
4906 }
4907
4908 typedef std::vector<std::string>::const_iterator const_iterator;
4909
4910 const_iterator begin() const { return lines.begin(); }
4911 const_iterator end() const { return lines.end(); }
4912 std::string const& last() const { return lines.back(); }
4913 std::size_t size() const { return lines.size(); }
4914 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
4915 std::string toString() const {
4916 std::ostringstream oss;
4917 oss << *this;
4918 return oss.str();
4919 }
4920
4921 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4922 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4923 it != itEnd; ++it ) {
4924 if( it != _text.begin() )
4925 _stream << "\n";
4926 _stream << *it;
4927 }
4928 return _stream;
4929 }
4930
4931 private:
4932 std::string str;
4933 TextAttributes attr;
4934 std::vector<std::string> lines;
4935 };
4936
4937} // end namespace Tbc
4938
4939#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4940} // end outer namespace
4941#endif
4942
4943#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
4944#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4945
4946namespace Catch {
4947 using Tbc::Text;
4948 using Tbc::TextAttributes;
4949}
4950
Phil Nash5c7d3d72013-04-01 11:27:10 +01004951// #included from: catch_console_colour.hpp
4952#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01004953
4954namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01004955
Phil Nash12c16ff2013-04-05 20:58:01 +01004956 struct Colour {
4957 enum Code {
4958 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004959
Phil Nash12c16ff2013-04-05 20:58:01 +01004960 White,
4961 Red,
4962 Green,
4963 Blue,
4964 Cyan,
4965 Yellow,
4966 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004967
Phil Nash12c16ff2013-04-05 20:58:01 +01004968 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01004969
Phil Nash12c16ff2013-04-05 20:58:01 +01004970 BrightRed = Bright | Red,
4971 BrightGreen = Bright | Green,
4972 LightGrey = Bright | Grey,
4973 BrightWhite = Bright | White,
4974
4975 // By intention
4976 FileName = LightGrey,
Phil Nash52e1e742014-07-03 08:11:38 +01004977 Warning = Yellow,
Phil Nash12c16ff2013-04-05 20:58:01 +01004978 ResultError = BrightRed,
4979 ResultSuccess = BrightGreen,
Phil Nash52e1e742014-07-03 08:11:38 +01004980 ResultExpectedFailure = Warning,
Phil Nash12c16ff2013-04-05 20:58:01 +01004981
4982 Error = BrightRed,
4983 Success = Green,
4984
4985 OriginalExpression = Cyan,
4986 ReconstructedExpression = Yellow,
4987
4988 SecondaryText = LightGrey,
4989 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01004990 };
4991
Phil Nash12c16ff2013-04-05 20:58:01 +01004992 // Use constructed object for RAII guard
4993 Colour( Code _colourCode );
Phil Nashce562092014-07-09 07:40:37 +01004994 Colour( Colour const& other );
Phil Nash12c16ff2013-04-05 20:58:01 +01004995 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01004996
Phil Nash12c16ff2013-04-05 20:58:01 +01004997 // Use static method for one-shot changes
4998 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01004999
5000 private:
Phil Nashce562092014-07-09 07:40:37 +01005001 bool m_moved;
Phil Nash5c7d3d72013-04-01 11:27:10 +01005002 };
5003
Phil Nash52e1e742014-07-03 08:11:38 +01005004 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5005
Phil Nash5c7d3d72013-04-01 11:27:10 +01005006} // end namespace Catch
5007
Phil Nash3649fdf2013-12-03 18:53:55 +00005008// #included from: catch_interfaces_reporter.h
5009#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5010
Phil Nash3649fdf2013-12-03 18:53:55 +00005011#include <string>
5012#include <ostream>
5013#include <map>
5014#include <assert.h>
5015
5016namespace Catch
5017{
5018 struct ReporterConfig {
Phil Nash7e346192015-11-03 08:00:43 +00005019 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
Phil Nash3649fdf2013-12-03 18:53:55 +00005020 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5021
Phil Nash7e346192015-11-03 08:00:43 +00005022 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
Phil Nash3649fdf2013-12-03 18:53:55 +00005023 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5024
5025 std::ostream& stream() const { return *m_stream; }
Phil Nash7e346192015-11-03 08:00:43 +00005026 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005027
5028 private:
5029 std::ostream* m_stream;
Phil Nash7e346192015-11-03 08:00:43 +00005030 Ptr<IConfig const> m_fullConfig;
Phil Nash3649fdf2013-12-03 18:53:55 +00005031 };
5032
5033 struct ReporterPreferences {
5034 ReporterPreferences()
5035 : shouldRedirectStdOut( false )
5036 {}
5037
5038 bool shouldRedirectStdOut;
5039 };
5040
5041 template<typename T>
5042 struct LazyStat : Option<T> {
5043 LazyStat() : used( false ) {}
5044 LazyStat& operator=( T const& _value ) {
5045 Option<T>::operator=( _value );
5046 used = false;
5047 return *this;
5048 }
5049 void reset() {
5050 Option<T>::reset();
5051 used = false;
5052 }
5053 bool used;
5054 };
5055
5056 struct TestRunInfo {
5057 TestRunInfo( std::string const& _name ) : name( _name ) {}
5058 std::string name;
5059 };
5060 struct GroupInfo {
5061 GroupInfo( std::string const& _name,
5062 std::size_t _groupIndex,
5063 std::size_t _groupsCount )
5064 : name( _name ),
5065 groupIndex( _groupIndex ),
5066 groupsCounts( _groupsCount )
5067 {}
5068
5069 std::string name;
5070 std::size_t groupIndex;
5071 std::size_t groupsCounts;
5072 };
5073
5074 struct AssertionStats {
5075 AssertionStats( AssertionResult const& _assertionResult,
5076 std::vector<MessageInfo> const& _infoMessages,
5077 Totals const& _totals )
5078 : assertionResult( _assertionResult ),
5079 infoMessages( _infoMessages ),
5080 totals( _totals )
5081 {
5082 if( assertionResult.hasMessage() ) {
5083 // Copy message into messages list.
5084 // !TBD This should have been done earlier, somewhere
5085 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5086 builder << assertionResult.getMessage();
5087 builder.m_info.message = builder.m_stream.str();
5088
5089 infoMessages.push_back( builder.m_info );
5090 }
5091 }
5092 virtual ~AssertionStats();
5093
Phil Nash318c9362015-05-19 18:40:00 +01005094# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005095 AssertionStats( AssertionStats const& ) = default;
5096 AssertionStats( AssertionStats && ) = default;
5097 AssertionStats& operator = ( AssertionStats const& ) = default;
5098 AssertionStats& operator = ( AssertionStats && ) = default;
5099# endif
5100
Phil Nash3649fdf2013-12-03 18:53:55 +00005101 AssertionResult assertionResult;
5102 std::vector<MessageInfo> infoMessages;
5103 Totals totals;
5104 };
5105
5106 struct SectionStats {
5107 SectionStats( SectionInfo const& _sectionInfo,
5108 Counts const& _assertions,
5109 double _durationInSeconds,
5110 bool _missingAssertions )
5111 : sectionInfo( _sectionInfo ),
5112 assertions( _assertions ),
5113 durationInSeconds( _durationInSeconds ),
5114 missingAssertions( _missingAssertions )
5115 {}
5116 virtual ~SectionStats();
Phil Nash318c9362015-05-19 18:40:00 +01005117# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005118 SectionStats( SectionStats const& ) = default;
5119 SectionStats( SectionStats && ) = default;
5120 SectionStats& operator = ( SectionStats const& ) = default;
5121 SectionStats& operator = ( SectionStats && ) = default;
5122# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005123
5124 SectionInfo sectionInfo;
5125 Counts assertions;
5126 double durationInSeconds;
5127 bool missingAssertions;
5128 };
5129
5130 struct TestCaseStats {
5131 TestCaseStats( TestCaseInfo const& _testInfo,
5132 Totals const& _totals,
5133 std::string const& _stdOut,
5134 std::string const& _stdErr,
5135 bool _aborting )
5136 : testInfo( _testInfo ),
5137 totals( _totals ),
5138 stdOut( _stdOut ),
5139 stdErr( _stdErr ),
5140 aborting( _aborting )
5141 {}
5142 virtual ~TestCaseStats();
5143
Phil Nash318c9362015-05-19 18:40:00 +01005144# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005145 TestCaseStats( TestCaseStats const& ) = default;
5146 TestCaseStats( TestCaseStats && ) = default;
5147 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5148 TestCaseStats& operator = ( TestCaseStats && ) = default;
5149# endif
5150
Phil Nash3649fdf2013-12-03 18:53:55 +00005151 TestCaseInfo testInfo;
5152 Totals totals;
5153 std::string stdOut;
5154 std::string stdErr;
5155 bool aborting;
5156 };
5157
5158 struct TestGroupStats {
5159 TestGroupStats( GroupInfo const& _groupInfo,
5160 Totals const& _totals,
5161 bool _aborting )
5162 : groupInfo( _groupInfo ),
5163 totals( _totals ),
5164 aborting( _aborting )
5165 {}
5166 TestGroupStats( GroupInfo const& _groupInfo )
5167 : groupInfo( _groupInfo ),
5168 aborting( false )
5169 {}
5170 virtual ~TestGroupStats();
5171
Phil Nash318c9362015-05-19 18:40:00 +01005172# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005173 TestGroupStats( TestGroupStats const& ) = default;
5174 TestGroupStats( TestGroupStats && ) = default;
5175 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5176 TestGroupStats& operator = ( TestGroupStats && ) = default;
5177# endif
5178
Phil Nash3649fdf2013-12-03 18:53:55 +00005179 GroupInfo groupInfo;
5180 Totals totals;
5181 bool aborting;
5182 };
5183
5184 struct TestRunStats {
5185 TestRunStats( TestRunInfo const& _runInfo,
5186 Totals const& _totals,
5187 bool _aborting )
5188 : runInfo( _runInfo ),
5189 totals( _totals ),
5190 aborting( _aborting )
5191 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005192 virtual ~TestRunStats();
5193
Phil Nash318c9362015-05-19 18:40:00 +01005194# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3649fdf2013-12-03 18:53:55 +00005195 TestRunStats( TestRunStats const& _other )
5196 : runInfo( _other.runInfo ),
5197 totals( _other.totals ),
5198 aborting( _other.aborting )
5199 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005200# else
5201 TestRunStats( TestRunStats const& ) = default;
5202 TestRunStats( TestRunStats && ) = default;
5203 TestRunStats& operator = ( TestRunStats const& ) = default;
5204 TestRunStats& operator = ( TestRunStats && ) = default;
5205# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005206
5207 TestRunInfo runInfo;
5208 Totals totals;
5209 bool aborting;
5210 };
5211
5212 struct IStreamingReporter : IShared {
5213 virtual ~IStreamingReporter();
5214
5215 // Implementing class must also provide the following static method:
5216 // static std::string getDescription();
5217
5218 virtual ReporterPreferences getPreferences() const = 0;
5219
5220 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5221
5222 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5223 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5224
5225 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5226 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5227
5228 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5229
Phil Nash576aff62014-12-21 00:21:23 +00005230 // The return value indicates if the messages buffer should be cleared:
Phil Nash3649fdf2013-12-03 18:53:55 +00005231 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005232
Phil Nash3649fdf2013-12-03 18:53:55 +00005233 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5234 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5235 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5236 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nash92f08362014-12-22 20:18:05 +00005237
5238 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005239 };
5240
Phil Nashe73583d2015-08-07 17:30:34 +01005241 struct IReporterFactory : IShared {
Phil Nash3649fdf2013-12-03 18:53:55 +00005242 virtual ~IReporterFactory();
5243 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5244 virtual std::string getDescription() const = 0;
5245 };
5246
5247 struct IReporterRegistry {
Phil Nashe73583d2015-08-07 17:30:34 +01005248 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5249 typedef std::vector<Ptr<IReporterFactory> > Listeners;
Phil Nash3649fdf2013-12-03 18:53:55 +00005250
5251 virtual ~IReporterRegistry();
Phil Nash7e346192015-11-03 08:00:43 +00005252 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005253 virtual FactoryMap const& getFactories() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005254 virtual Listeners const& getListeners() const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005255 };
5256
Phil Nashe73583d2015-08-07 17:30:34 +01005257 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5258
Phil Nash3649fdf2013-12-03 18:53:55 +00005259}
5260
Phil Nasha695eb92012-08-13 07:46:10 +01005261#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00005262#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01005263
5264namespace Catch {
Phil Nasha695eb92012-08-13 07:46:10 +01005265
Phil Nash786959d2013-06-07 19:07:50 +01005266 inline std::size_t listTests( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005267
5268 TestSpec testSpec = config.testSpec();
5269 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005270 Catch::cout() << "Matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005271 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005272 Catch::cout() << "All available test cases:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005273 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005274 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005275
5276 std::size_t matchedTests = 0;
Phil Nash8d44f2d2013-11-13 08:10:45 +00005277 TextAttributes nameAttr, tagsAttr;
5278 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5279 tagsAttr.setIndent( 6 );
5280
Phil Nashe73583d2015-08-07 17:30:34 +01005281 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005282 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005283 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005284 ++it ) {
5285 matchedTests++;
5286 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Phil Nash52e1e742014-07-03 08:11:38 +01005287 Colour::Code colour = testCaseInfo.isHidden()
Phil Nash20cad7c2014-04-15 18:44:37 +01005288 ? Colour::SecondaryText
5289 : Colour::None;
5290 Colour colourGuard( colour );
Phil Nash38f7eef2013-03-29 13:44:33 +00005291
Phil Nash383d7c02014-10-02 19:08:19 +01005292 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005293 if( !testCaseInfo.tags.empty() )
Phil Nash383d7c02014-10-02 19:08:19 +01005294 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005295 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00005296
Phil Nash65cc14c2014-05-16 18:54:48 +01005297 if( !config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005298 Catch::cout() << pluralise( matchedTests, "test case" ) << "\n" << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00005299 else
Phil Nash383d7c02014-10-02 19:08:19 +01005300 Catch::cout() << pluralise( matchedTests, "matching test case" ) << "\n" << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005301 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00005302 }
Phil Nasha695eb92012-08-13 07:46:10 +01005303
Phil Nash5ecb72b2013-11-26 20:57:45 +00005304 inline std::size_t listTestsNamesOnly( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005305 TestSpec testSpec = config.testSpec();
5306 if( !config.testSpec().hasFilters() )
Phil Nashacdd3b52014-06-30 07:35:36 +01005307 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005308 std::size_t matchedTests = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005309 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005310 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005311 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005312 ++it ) {
5313 matchedTests++;
5314 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Phil Nash383d7c02014-10-02 19:08:19 +01005315 Catch::cout() << testCaseInfo.name << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005316 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005317 return matchedTests;
5318 }
5319
Phil Nash48fac9c2014-05-20 19:02:37 +01005320 struct TagInfo {
5321 TagInfo() : count ( 0 ) {}
5322 void add( std::string const& spelling ) {
5323 ++count;
5324 spellings.insert( spelling );
5325 }
5326 std::string all() const {
5327 std::string out;
5328 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5329 it != itEnd;
5330 ++it )
5331 out += "[" + *it + "]";
5332 return out;
5333 }
5334 std::set<std::string> spellings;
5335 std::size_t count;
5336 };
5337
Phil Nash786959d2013-06-07 19:07:50 +01005338 inline std::size_t listTags( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005339 TestSpec testSpec = config.testSpec();
5340 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005341 Catch::cout() << "Tags for matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005342 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005343 Catch::cout() << "All available tags:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005344 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005345 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005346
Phil Nash9241e432014-05-20 18:50:59 +01005347 std::map<std::string, TagInfo> tagCounts;
Phil Nash38f7eef2013-03-29 13:44:33 +00005348
Phil Nashe73583d2015-08-07 17:30:34 +01005349 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005350 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005351 it != itEnd;
5352 ++it ) {
Phil Nash20cad7c2014-04-15 18:44:37 +01005353 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5354 tagItEnd = it->getTestCaseInfo().tags.end();
5355 tagIt != tagItEnd;
5356 ++tagIt ) {
5357 std::string tagName = *tagIt;
Phil Nash9241e432014-05-20 18:50:59 +01005358 std::string lcaseTagName = toLower( tagName );
5359 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
Phil Nash20cad7c2014-04-15 18:44:37 +01005360 if( countIt == tagCounts.end() )
Phil Nash9241e432014-05-20 18:50:59 +01005361 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5362 countIt->second.add( tagName );
Phil Nash38f7eef2013-03-29 13:44:33 +00005363 }
Phil Nasha695eb92012-08-13 07:46:10 +01005364 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005365
Phil Nash9241e432014-05-20 18:50:59 +01005366 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5367 countItEnd = tagCounts.end();
Phil Nash38f7eef2013-03-29 13:44:33 +00005368 countIt != countItEnd;
5369 ++countIt ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00005370 std::ostringstream oss;
Phil Nash9241e432014-05-20 18:50:59 +01005371 oss << " " << std::setw(2) << countIt->second.count << " ";
5372 Text wrapper( countIt->second.all(), TextAttributes()
5373 .setInitialIndent( 0 )
5374 .setIndent( oss.str().size() )
5375 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
Phil Nash383d7c02014-10-02 19:08:19 +01005376 Catch::cout() << oss.str() << wrapper << "\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005377 }
Phil Nash383d7c02014-10-02 19:08:19 +01005378 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << "\n" << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005379 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005380 }
5381
Phil Nash786959d2013-06-07 19:07:50 +01005382 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash576aff62014-12-21 00:21:23 +00005383 Catch::cout() << "Available reporters:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005384 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01005385 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5386 std::size_t maxNameLen = 0;
5387 for(it = itBegin; it != itEnd; ++it )
5388 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5389
5390 for(it = itBegin; it != itEnd; ++it ) {
5391 Text wrapper( it->second->getDescription(), TextAttributes()
5392 .setInitialIndent( 0 )
5393 .setIndent( 7+maxNameLen )
5394 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
Phil Nash383d7c02014-10-02 19:08:19 +01005395 Catch::cout() << " "
Phil Nash786959d2013-06-07 19:07:50 +01005396 << it->first
5397 << ":"
5398 << std::string( maxNameLen - it->first.size() + 2, ' ' )
5399 << wrapper << "\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005400 }
Phil Nash383d7c02014-10-02 19:08:19 +01005401 Catch::cout() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005402 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005403 }
5404
Phil Nash786959d2013-06-07 19:07:50 +01005405 inline Option<std::size_t> list( Config const& config ) {
5406 Option<std::size_t> listedCount;
5407 if( config.listTests() )
5408 listedCount = listedCount.valueOr(0) + listTests( config );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005409 if( config.listTestNamesOnly() )
5410 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
Phil Nash786959d2013-06-07 19:07:50 +01005411 if( config.listTags() )
5412 listedCount = listedCount.valueOr(0) + listTags( config );
5413 if( config.listReporters() )
5414 listedCount = listedCount.valueOr(0) + listReporters( config );
5415 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01005416 }
5417
5418} // end namespace Catch
5419
Phil Nashe73583d2015-08-07 17:30:34 +01005420// #included from: internal/catch_run_context.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005421#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005422
Phil Nash8a52a392013-07-25 08:12:03 +01005423// #included from: catch_test_case_tracker.hpp
5424#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005425
5426#include <map>
5427#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01005428#include <assert.h>
Phil Nash7e346192015-11-03 08:00:43 +00005429#include <vector>
Phil Nasha695eb92012-08-13 07:46:10 +01005430
5431namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +00005432namespace TestCaseTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01005433
Phil Nash7e346192015-11-03 08:00:43 +00005434 struct ITracker : SharedImpl<> {
5435 virtual ~ITracker();
Phil Nash8a52a392013-07-25 08:12:03 +01005436
Phil Nash7e346192015-11-03 08:00:43 +00005437 // static queries
5438 virtual std::string name() const = 0;
Phil Nash8a52a392013-07-25 08:12:03 +01005439
Phil Nash7e346192015-11-03 08:00:43 +00005440 // dynamic queries
5441 virtual bool isComplete() const = 0; // Successfully completed or failed
5442 virtual bool isSuccessfullyCompleted() const = 0;
5443 virtual bool isOpen() const = 0; // Started but not complete
5444 virtual bool hasChildren() const = 0;
5445
5446 virtual ITracker& parent() = 0;
5447
5448 // actions
5449 virtual void close() = 0; // Successfully complete
5450 virtual void fail() = 0;
5451 virtual void markAsNeedingAnotherRun() = 0;
5452
5453 virtual void addChild( Ptr<ITracker> const& child ) = 0;
5454 virtual ITracker* findChild( std::string const& name ) = 0;
5455 virtual void openChild() = 0;
5456 };
5457
5458 class TrackerContext {
5459
Phil Nash8a52a392013-07-25 08:12:03 +01005460 enum RunState {
5461 NotStarted,
5462 Executing,
Phil Nash7e346192015-11-03 08:00:43 +00005463 CompletedCycle
Phil Nasha695eb92012-08-13 07:46:10 +01005464 };
5465
Phil Nash7e346192015-11-03 08:00:43 +00005466 Ptr<ITracker> m_rootTracker;
5467 ITracker* m_currentTracker;
5468 RunState m_runState;
5469
5470 public:
5471
5472 static TrackerContext& instance() {
5473 static TrackerContext s_instance;
5474 return s_instance;
5475 }
5476
5477 TrackerContext()
5478 : m_currentTracker( CATCH_NULL ),
5479 m_runState( NotStarted )
Phil Nasha695eb92012-08-13 07:46:10 +01005480 {}
5481
Phil Nash7e346192015-11-03 08:00:43 +00005482 ITracker& startRun();
Phil Nasha695eb92012-08-13 07:46:10 +01005483
Phil Nash7e346192015-11-03 08:00:43 +00005484 void endRun() {
5485 m_rootTracker.reset();
5486 m_currentTracker = CATCH_NULL;
5487 m_runState = NotStarted;
Phil Nasha695eb92012-08-13 07:46:10 +01005488 }
Phil Nash3b18d9e2015-06-30 18:26:09 +01005489
Phil Nash7e346192015-11-03 08:00:43 +00005490 void startCycle() {
5491 m_currentTracker = m_rootTracker.get();
5492 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01005493 }
Phil Nash7e346192015-11-03 08:00:43 +00005494 void completeCycle() {
5495 m_runState = CompletedCycle;
5496 }
5497
5498 bool completedCycle() const {
5499 return m_runState == CompletedCycle;
5500 }
5501 ITracker& currentTracker() {
5502 return *m_currentTracker;
5503 }
5504 void setCurrentTracker( ITracker* tracker ) {
5505 m_currentTracker = tracker;
5506 }
5507 };
5508
5509 class TrackerBase : public ITracker {
5510 protected:
5511 enum CycleState {
5512 NotStarted,
5513 Executing,
5514 ExecutingChildren,
5515 NeedsAnotherRun,
5516 CompletedSuccessfully,
5517 Failed
5518 };
5519 class TrackerHasName {
5520 std::string m_name;
5521 public:
5522 TrackerHasName( std::string const& name ) : m_name( name ) {}
5523 bool operator ()( Ptr<ITracker> const& tracker ) {
5524 return tracker->name() == m_name;
5525 }
5526 };
5527 typedef std::vector<Ptr<ITracker> > Children;
5528 std::string m_name;
5529 TrackerContext& m_ctx;
5530 ITracker* m_parent;
5531 Children m_children;
5532 CycleState m_runState;
5533 public:
5534 TrackerBase( std::string const& name, TrackerContext& ctx, ITracker* parent )
5535 : m_name( name ),
5536 m_ctx( ctx ),
5537 m_parent( parent ),
5538 m_runState( NotStarted )
5539 {}
5540 virtual ~TrackerBase();
5541
5542 virtual std::string name() const CATCH_OVERRIDE {
5543 return m_name;
5544 }
5545 virtual bool isComplete() const CATCH_OVERRIDE {
5546 return m_runState == CompletedSuccessfully || m_runState == Failed;
5547 }
5548 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
5549 return m_runState == CompletedSuccessfully;
5550 }
5551 virtual bool isOpen() const CATCH_OVERRIDE {
5552 return m_runState != NotStarted && !isComplete();
5553 }
5554 virtual bool hasChildren() const CATCH_OVERRIDE {
Phil Nash8a52a392013-07-25 08:12:03 +01005555 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00005556 }
5557
Phil Nash7e346192015-11-03 08:00:43 +00005558 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
5559 m_children.push_back( child );
5560 }
Phil Nasha695eb92012-08-13 07:46:10 +01005561
Phil Nash7e346192015-11-03 08:00:43 +00005562 virtual ITracker* findChild( std::string const& name ) CATCH_OVERRIDE {
5563 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( name ) );
5564 return( it != m_children.end() )
5565 ? it->get()
5566 : CATCH_NULL;
5567 }
5568 virtual ITracker& parent() CATCH_OVERRIDE {
5569 assert( m_parent ); // Should always be non-null except for root
5570 return *m_parent;
5571 }
5572
5573 virtual void openChild() CATCH_OVERRIDE {
5574 if( m_runState != ExecutingChildren ) {
Phil Nash3b18d9e2015-06-30 18:26:09 +01005575 m_runState = ExecutingChildren;
Phil Nash7e346192015-11-03 08:00:43 +00005576 if( m_parent )
5577 m_parent->openChild();
Phil Nash3b18d9e2015-06-30 18:26:09 +01005578 }
Phil Nasha695eb92012-08-13 07:46:10 +01005579 }
Phil Nash7e346192015-11-03 08:00:43 +00005580 void open() {
5581 m_runState = Executing;
5582 moveToThis();
5583 if( m_parent )
5584 m_parent->openChild();
Phil Nasha695eb92012-08-13 07:46:10 +01005585 }
5586
Phil Nash7e346192015-11-03 08:00:43 +00005587 virtual void close() CATCH_OVERRIDE {
Phil Nasha695eb92012-08-13 07:46:10 +01005588
Phil Nash7e346192015-11-03 08:00:43 +00005589 // Close any still open children (e.g. generators)
5590 while( &m_ctx.currentTracker() != this )
5591 m_ctx.currentTracker().close();
5592
5593 switch( m_runState ) {
5594 case NotStarted:
5595 case CompletedSuccessfully:
5596 case Failed:
5597 throw std::logic_error( "Illogical state" );
5598
5599 case NeedsAnotherRun:
5600 break;;
5601
5602 case Executing:
5603 m_runState = CompletedSuccessfully;
5604 break;
5605 case ExecutingChildren:
5606 if( m_children.empty() || m_children.back()->isComplete() )
5607 m_runState = CompletedSuccessfully;
5608 break;
5609
5610 default:
5611 throw std::logic_error( "Unexpected state" );
Phil Nash8a52a392013-07-25 08:12:03 +01005612 }
Phil Nash7e346192015-11-03 08:00:43 +00005613 moveToParent();
5614 m_ctx.completeCycle();
5615 }
5616 virtual void fail() CATCH_OVERRIDE {
5617 m_runState = Failed;
5618 if( m_parent )
5619 m_parent->markAsNeedingAnotherRun();
5620 moveToParent();
5621 m_ctx.completeCycle();
5622 }
5623 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
5624 m_runState = NeedsAnotherRun;
5625 }
Phil Nasha695eb92012-08-13 07:46:10 +01005626 private:
Phil Nash7e346192015-11-03 08:00:43 +00005627 void moveToParent() {
5628 assert( m_parent );
5629 m_ctx.setCurrentTracker( m_parent );
Phil Nash8a52a392013-07-25 08:12:03 +01005630 }
Phil Nash7e346192015-11-03 08:00:43 +00005631 void moveToThis() {
5632 m_ctx.setCurrentTracker( this );
Phil Nash8a52a392013-07-25 08:12:03 +01005633 }
Phil Nasha695eb92012-08-13 07:46:10 +01005634 };
Phil Nash8a52a392013-07-25 08:12:03 +01005635
Phil Nash7e346192015-11-03 08:00:43 +00005636 class SectionTracker : public TrackerBase {
5637 public:
5638 SectionTracker( std::string const& name, TrackerContext& ctx, ITracker* parent )
5639 : TrackerBase( name, ctx, parent )
5640 {}
5641 virtual ~SectionTracker();
Phil Nash8a52a392013-07-25 08:12:03 +01005642
Phil Nash7e346192015-11-03 08:00:43 +00005643 static SectionTracker& acquire( TrackerContext& ctx, std::string const& name ) {
5644 SectionTracker* section = CATCH_NULL;
5645
5646 ITracker& currentTracker = ctx.currentTracker();
5647 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5648 section = dynamic_cast<SectionTracker*>( childTracker );
5649 assert( section );
5650 }
5651 else {
5652 section = new SectionTracker( name, ctx, &currentTracker );
5653 currentTracker.addChild( section );
5654 }
5655 if( !ctx.completedCycle() && !section->isComplete() ) {
5656
5657 section->open();
5658 }
5659 return *section;
5660 }
5661 };
5662
5663 class IndexTracker : public TrackerBase {
5664 int m_size;
5665 int m_index;
5666 public:
5667 IndexTracker( std::string const& name, TrackerContext& ctx, ITracker* parent, int size )
5668 : TrackerBase( name, ctx, parent ),
5669 m_size( size ),
5670 m_index( -1 )
5671 {}
5672 virtual ~IndexTracker();
5673
5674 static IndexTracker& acquire( TrackerContext& ctx, std::string const& name, int size ) {
5675 IndexTracker* tracker = CATCH_NULL;
5676
5677 ITracker& currentTracker = ctx.currentTracker();
5678 if( ITracker* childTracker = currentTracker.findChild( name ) ) {
5679 tracker = dynamic_cast<IndexTracker*>( childTracker );
5680 assert( tracker );
5681 }
5682 else {
5683 tracker = new IndexTracker( name, ctx, &currentTracker, size );
5684 currentTracker.addChild( tracker );
5685 }
5686
5687 if( !ctx.completedCycle() && !tracker->isComplete() ) {
5688 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
5689 tracker->moveNext();
5690 tracker->open();
5691 }
5692
5693 return *tracker;
5694 }
5695
5696 int index() const { return m_index; }
5697
5698 void moveNext() {
5699 m_index++;
5700 m_children.clear();
5701 }
5702
5703 virtual void close() CATCH_OVERRIDE {
5704 TrackerBase::close();
5705 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
5706 m_runState = Executing;
5707 }
5708 };
5709
5710 inline ITracker& TrackerContext::startRun() {
5711 m_rootTracker = new SectionTracker( "{root}", *this, CATCH_NULL );
5712 m_currentTracker = CATCH_NULL;
5713 m_runState = Executing;
5714 return *m_rootTracker;
5715 }
5716
5717} // namespace TestCaseTracking
5718
5719using TestCaseTracking::ITracker;
5720using TestCaseTracking::TrackerContext;
5721using TestCaseTracking::SectionTracker;
5722using TestCaseTracking::IndexTracker;
Phil Nash8a52a392013-07-25 08:12:03 +01005723
5724} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01005725
Phil Nash93b61e12014-08-22 19:35:41 +01005726// #included from: catch_fatal_condition.hpp
5727#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
5728
5729namespace Catch {
5730
5731 // Report the error condition then exit the process
5732 inline void fatal( std::string const& message, int exitCode ) {
5733 IContext& context = Catch::getCurrentContext();
5734 IResultCapture* resultCapture = context.getResultCapture();
5735 resultCapture->handleFatalErrorCondition( message );
5736
5737 if( Catch::alwaysTrue() ) // avoids "no return" warnings
5738 exit( exitCode );
5739 }
5740
5741} // namespace Catch
5742
5743#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
5744
5745namespace Catch {
5746
Phil Nashe54ac702014-10-21 07:25:26 +01005747 struct FatalConditionHandler {
5748 void reset() {}
5749 };
Phil Nash93b61e12014-08-22 19:35:41 +01005750
5751} // namespace Catch
5752
5753#else // Not Windows - assumed to be POSIX compatible //////////////////////////
5754
5755#include <signal.h>
5756
5757namespace Catch {
5758
5759 struct SignalDefs { int id; const char* name; };
5760 extern SignalDefs signalDefs[];
5761 SignalDefs signalDefs[] = {
5762 { SIGINT, "SIGINT - Terminal interrupt signal" },
5763 { SIGILL, "SIGILL - Illegal instruction signal" },
5764 { SIGFPE, "SIGFPE - Floating point error signal" },
5765 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
5766 { SIGTERM, "SIGTERM - Termination request signal" },
5767 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
5768 };
5769
5770 struct FatalConditionHandler {
5771
5772 static void handleSignal( int sig ) {
5773 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5774 if( sig == signalDefs[i].id )
5775 fatal( signalDefs[i].name, -sig );
5776 fatal( "<unknown signal>", -sig );
5777 }
5778
Phil Nash85b4e942014-10-02 18:51:05 +01005779 FatalConditionHandler() : m_isSet( true ) {
Phil Nash93b61e12014-08-22 19:35:41 +01005780 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5781 signal( signalDefs[i].id, handleSignal );
5782 }
5783 ~FatalConditionHandler() {
Phil Nash85b4e942014-10-02 18:51:05 +01005784 reset();
Phil Nash93b61e12014-08-22 19:35:41 +01005785 }
Phil Nash85b4e942014-10-02 18:51:05 +01005786 void reset() {
5787 if( m_isSet ) {
5788 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i )
5789 signal( signalDefs[i].id, SIG_DFL );
5790 m_isSet = false;
5791 }
5792 }
5793
5794 bool m_isSet;
Phil Nash93b61e12014-08-22 19:35:41 +01005795 };
5796
5797} // namespace Catch
5798
5799#endif // not Windows
5800
Phil Nasha695eb92012-08-13 07:46:10 +01005801#include <set>
5802#include <string>
5803
5804namespace Catch {
5805
5806 class StreamRedirect {
5807
5808 public:
5809 StreamRedirect( std::ostream& stream, std::string& targetString )
5810 : m_stream( stream ),
5811 m_prevBuf( stream.rdbuf() ),
5812 m_targetString( targetString )
5813 {
5814 stream.rdbuf( m_oss.rdbuf() );
5815 }
5816
5817 ~StreamRedirect() {
5818 m_targetString += m_oss.str();
5819 m_stream.rdbuf( m_prevBuf );
5820 }
5821
5822 private:
5823 std::ostream& m_stream;
5824 std::streambuf* m_prevBuf;
5825 std::ostringstream m_oss;
5826 std::string& m_targetString;
5827 };
5828
5829 ///////////////////////////////////////////////////////////////////////////
5830
Phil Nash786959d2013-06-07 19:07:50 +01005831 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01005832
Phil Nash786959d2013-06-07 19:07:50 +01005833 RunContext( RunContext const& );
5834 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01005835
5836 public:
5837
Phil Nashb971fe72015-07-02 08:21:38 +01005838 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
5839 : m_runInfo( _config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00005840 m_context( getCurrentMutableContext() ),
Phil Nashb971fe72015-07-02 08:21:38 +01005841 m_activeTestCase( CATCH_NULL ),
5842 m_config( _config ),
Phil Nash7e346192015-11-03 08:00:43 +00005843 m_reporter( reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01005844 {
5845 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01005846 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01005847 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005848 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01005849 }
5850
Phil Nash786959d2013-06-07 19:07:50 +01005851 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00005852 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01005853 }
5854
Phil Nash2e7d9662013-01-16 09:44:43 +00005855 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
5856 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005857 }
Phil Nash2e7d9662013-01-16 09:44:43 +00005858 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
5859 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005860 }
Phil Nasha695eb92012-08-13 07:46:10 +01005861
Phil Nash8defc712013-04-24 19:10:02 +01005862 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005863 Totals prevTotals = m_totals;
5864
5865 std::string redirectedCout;
5866 std::string redirectedCerr;
5867
Phil Nasha1fbfea2012-12-01 23:57:18 +00005868 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01005869
Phil Nasha1fbfea2012-12-01 23:57:18 +00005870 m_reporter->testCaseStarting( testInfo );
5871
Phil Nash8a52a392013-07-25 08:12:03 +01005872 m_activeTestCase = &testCase;
Phil Nasha695eb92012-08-13 07:46:10 +01005873
5874 do {
Phil Nash7e346192015-11-03 08:00:43 +00005875 m_trackerContext.startRun();
Phil Nasha695eb92012-08-13 07:46:10 +01005876 do {
Phil Nash7e346192015-11-03 08:00:43 +00005877 m_trackerContext.startCycle();
5878 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, testInfo.name );
Phil Nasha695eb92012-08-13 07:46:10 +01005879 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01005880 }
Phil Nash7e346192015-11-03 08:00:43 +00005881 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01005882 }
Phil Nash7e346192015-11-03 08:00:43 +00005883 // !TBD: deprecated - this will be replaced by indexed trackers
Phil Nasha695eb92012-08-13 07:46:10 +01005884 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
5885
Phil Nash28463672012-11-21 18:06:13 +00005886 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nash28463672012-11-21 18:06:13 +00005887 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00005888 m_reporter->testCaseEnded( TestCaseStats( testInfo,
5889 deltaTotals,
5890 redirectedCout,
5891 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00005892 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00005893
Phil Nashb971fe72015-07-02 08:21:38 +01005894 m_activeTestCase = CATCH_NULL;
Phil Nash7e346192015-11-03 08:00:43 +00005895 m_testCaseTracker = CATCH_NULL;
Phil Nasha695eb92012-08-13 07:46:10 +01005896
Phil Nash5bc030d2012-08-16 18:48:50 +01005897 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01005898 }
5899
Phil Nash786959d2013-06-07 19:07:50 +01005900 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01005901 return m_config;
5902 }
5903
5904 private: // IResultCapture
5905
Phil Nash8defc712013-04-24 19:10:02 +01005906 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005907 if( result.getResultType() == ResultWas::Ok ) {
5908 m_totals.assertions.passed++;
5909 }
Phil Nash90a35942012-11-13 22:04:29 +00005910 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01005911 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01005912 }
5913
Phil Nashb5fd5a62013-06-28 17:09:57 +01005914 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
5915 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00005916
Phil Nasha2773812013-02-02 20:37:58 +00005917 // Reset working state
5918 m_lastAssertionInfo = AssertionInfo( "", m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nashab036682014-06-02 07:48:03 +01005919 m_lastResult = result;
Phil Nasha695eb92012-08-13 07:46:10 +01005920 }
5921
5922 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00005923 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01005924 Counts& assertions
5925 )
5926 {
5927 std::ostringstream oss;
Phil Nasha1fbfea2012-12-01 23:57:18 +00005928 oss << sectionInfo.name << "@" << sectionInfo.lineInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01005929
Phil Nash7e346192015-11-03 08:00:43 +00005930 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, oss.str() );
5931 if( !sectionTracker.isOpen() )
Phil Nasha695eb92012-08-13 07:46:10 +01005932 return false;
Phil Nash7e346192015-11-03 08:00:43 +00005933 m_activeSections.push_back( &sectionTracker );
Phil Nasha695eb92012-08-13 07:46:10 +01005934
Phil Nasha1fbfea2012-12-01 23:57:18 +00005935 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00005936
Phil Nasha1fbfea2012-12-01 23:57:18 +00005937 m_reporter->sectionStarting( sectionInfo );
5938
Phil Nasha695eb92012-08-13 07:46:10 +01005939 assertions = m_totals.assertions;
5940
5941 return true;
5942 }
Phil Nashaa7123b2013-08-15 19:01:00 +01005943 bool testForMissingAssertions( Counts& assertions ) {
Phil Nash7e346192015-11-03 08:00:43 +00005944 if( assertions.total() != 0 )
5945 return false;
Phil Nash9e421532015-11-03 17:06:54 +00005946 if( !m_config->warnAboutMissingAssertions() )
Phil Nash7e346192015-11-03 08:00:43 +00005947 return false;
5948 if( m_trackerContext.currentTracker().hasChildren() )
Phil Nashaa7123b2013-08-15 19:01:00 +01005949 return false;
5950 m_totals.assertions.failed++;
5951 assertions.failed++;
5952 return true;
5953 }
Phil Nasha695eb92012-08-13 07:46:10 +01005954
Phil Nash0c1c9fa2015-09-27 03:28:14 -07005955 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
5956 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01005957 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00005958
Phil Nash7e346192015-11-03 08:00:43 +00005959 if( !m_activeSections.empty() ) {
5960 m_activeSections.back()->close();
5961 m_activeSections.pop_back();
5962 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00005963
Phil Nash0c1c9fa2015-09-27 03:28:14 -07005964 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00005965 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01005966 }
5967
Phil Nash0c1c9fa2015-09-27 03:28:14 -07005968 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
Phil Nash7e346192015-11-03 08:00:43 +00005969 if( m_unfinishedSections.empty() )
5970 m_activeSections.back()->fail();
5971 else
5972 m_activeSections.back()->close();
5973 m_activeSections.pop_back();
5974
Phil Nash0c1c9fa2015-09-27 03:28:14 -07005975 m_unfinishedSections.push_back( endInfo );
5976 }
5977
Phil Nashb5fd5a62013-06-28 17:09:57 +01005978 virtual void pushScopedMessage( MessageInfo const& message ) {
5979 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01005980 }
5981
Phil Nashb5fd5a62013-06-28 17:09:57 +01005982 virtual void popScopedMessage( MessageInfo const& message ) {
5983 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01005984 }
5985
Phil Nasha695eb92012-08-13 07:46:10 +01005986 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01005987 return m_activeTestCase
5988 ? m_activeTestCase->getTestCaseInfo().name
Phil Nasha695eb92012-08-13 07:46:10 +01005989 : "";
5990 }
5991
Phil Nashce612bf2012-11-01 08:27:09 +00005992 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01005993 return &m_lastResult;
5994 }
5995
Phil Nash93b61e12014-08-22 19:35:41 +01005996 virtual void handleFatalErrorCondition( std::string const& message ) {
5997 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
5998 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
5999 resultBuilder << message;
6000 resultBuilder.captureExpression();
6001
6002 handleUnfinishedSections();
6003
6004 // Recreate section for test case (as we will lose the one that was in scope)
6005 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6006 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6007
6008 Counts assertions;
6009 assertions.failed = 1;
6010 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6011 m_reporter->sectionEnded( testCaseSectionStats );
6012
6013 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6014
6015 Totals deltaTotals;
6016 deltaTotals.testCases.failed = 1;
6017 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6018 deltaTotals,
6019 "",
6020 "",
6021 false ) );
6022 m_totals.testCases.failed++;
6023 testGroupEnded( "", m_totals, 1, 1 );
6024 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6025 }
6026
Phil Nash56d5c422012-08-23 20:08:50 +01006027 public:
6028 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01006029 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01006030 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01006031 }
6032
Phil Nash56d5c422012-08-23 20:08:50 +01006033 private:
6034
Phil Nasha695eb92012-08-13 07:46:10 +01006035 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006036 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
Phil Nashce562092014-07-09 07:40:37 +01006037 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01006038 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01006039 Counts prevAssertions = m_totals.assertions;
6040 double duration = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01006041 try {
Phil Nash8a52a392013-07-25 08:12:03 +01006042 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, "", ResultDisposition::Normal );
Phil Nashd768b1b2013-02-04 00:05:16 +00006043
Phil Nash8f66e342015-07-02 23:03:13 +01006044 seedRng( *m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006045
Phil Nashaa7123b2013-08-15 19:01:00 +01006046 Timer timer;
6047 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006048 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006049 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6050 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
Phil Nash93b61e12014-08-22 19:35:41 +01006051 invokeActiveTestCase();
Phil Nasha695eb92012-08-13 07:46:10 +01006052 }
6053 else {
Phil Nash93b61e12014-08-22 19:35:41 +01006054 invokeActiveTestCase();
Phil Nasha70fbe32012-08-31 08:10:36 +01006055 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006056 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01006057 }
6058 catch( TestFailureException& ) {
6059 // This just means the test was aborted due to failure
6060 }
6061 catch(...) {
Phil Nash93b61e12014-08-22 19:35:41 +01006062 makeUnexpectedResultBuilder().useActiveException();
Phil Nasha695eb92012-08-13 07:46:10 +01006063 }
Phil Nash7e346192015-11-03 08:00:43 +00006064 m_testCaseTracker->close();
Phil Nash93b61e12014-08-22 19:35:41 +01006065 handleUnfinishedSections();
Phil Nashd768b1b2013-02-04 00:05:16 +00006066 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01006067
6068 Counts assertions = m_totals.assertions - prevAssertions;
6069 bool missingAssertions = testForMissingAssertions( assertions );
6070
Phil Nash52e1e742014-07-03 08:11:38 +01006071 if( testCaseInfo.okToFail() ) {
6072 std::swap( assertions.failedButOk, assertions.failed );
6073 m_totals.assertions.failed -= assertions.failedButOk;
6074 m_totals.assertions.failedButOk += assertions.failedButOk;
6075 }
6076
Phil Nashaa7123b2013-08-15 19:01:00 +01006077 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01006078 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01006079 }
6080
Phil Nash93b61e12014-08-22 19:35:41 +01006081 void invokeActiveTestCase() {
6082 FatalConditionHandler fatalConditionHandler; // Handle signals
6083 m_activeTestCase->invoke();
Phil Nash85b4e942014-10-02 18:51:05 +01006084 fatalConditionHandler.reset();
Phil Nash93b61e12014-08-22 19:35:41 +01006085 }
6086
Phil Nasha695eb92012-08-13 07:46:10 +01006087 private:
Phil Nash93b61e12014-08-22 19:35:41 +01006088
6089 ResultBuilder makeUnexpectedResultBuilder() const {
6090 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6091 m_lastAssertionInfo.lineInfo,
6092 m_lastAssertionInfo.capturedExpression.c_str(),
6093 m_lastAssertionInfo.resultDisposition );
6094 }
6095
6096 void handleUnfinishedSections() {
6097 // If sections ended prematurely due to an exception we stored their
6098 // infos here so we can tear them down outside the unwind process.
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006099 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
Phil Nash93b61e12014-08-22 19:35:41 +01006100 itEnd = m_unfinishedSections.rend();
6101 it != itEnd;
6102 ++it )
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006103 sectionEnded( *it );
Phil Nash93b61e12014-08-22 19:35:41 +01006104 m_unfinishedSections.clear();
6105 }
6106
Phil Nasha1fbfea2012-12-01 23:57:18 +00006107 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01006108 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01006109 TestCase const* m_activeTestCase;
Phil Nash7e346192015-11-03 08:00:43 +00006110 ITracker* m_testCaseTracker;
6111 ITracker* m_currentSectionTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00006112 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01006113
Phil Nash786959d2013-06-07 19:07:50 +01006114 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01006115 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006116 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00006117 std::vector<MessageInfo> m_messages;
Phil Nash90a35942012-11-13 22:04:29 +00006118 AssertionInfo m_lastAssertionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006119 std::vector<SectionEndInfo> m_unfinishedSections;
Phil Nash7e346192015-11-03 08:00:43 +00006120 std::vector<ITracker*> m_activeSections;
6121 TrackerContext m_trackerContext;
Phil Nasha695eb92012-08-13 07:46:10 +01006122 };
6123
Phil Nashab036682014-06-02 07:48:03 +01006124 IResultCapture& getResultCapture() {
6125 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6126 return *capture;
6127 else
6128 throw std::logic_error( "No result capture instance" );
6129 }
6130
Phil Nasha695eb92012-08-13 07:46:10 +01006131} // end namespace Catch
6132
Phil Nash7673a302012-11-15 22:15:41 +00006133// #included from: internal/catch_version.h
6134#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6135
6136namespace Catch {
6137
6138 // Versioning information
6139 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006140 Version( unsigned int _majorVersion,
6141 unsigned int _minorVersion,
Phil Nash21f7ef62015-06-29 18:05:23 +01006142 unsigned int _patchNumber,
6143 std::string const& _branchName,
6144 unsigned int _buildNumber );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006145
Phil Nash9d469b62014-04-18 08:30:31 +01006146 unsigned int const majorVersion;
6147 unsigned int const minorVersion;
Phil Nash21f7ef62015-06-29 18:05:23 +01006148 unsigned int const patchNumber;
6149
6150 // buildNumber is only used if branchName is not null
6151 std::string const branchName;
Phil Nash9d469b62014-04-18 08:30:31 +01006152 unsigned int const buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01006153
6154 friend std::ostream& operator << ( std::ostream& os, Version const& version );
Phil Nashdd26e882013-03-25 09:25:31 +00006155
Phil Nash503d5d02013-07-03 08:25:11 +01006156 private:
6157 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00006158 };
6159
6160 extern Version libraryVersion;
6161}
6162
Phil Nash89d1e6c2011-05-24 08:23:02 +01006163#include <fstream>
6164#include <stdlib.h>
6165#include <limits>
6166
Phil Nash89d2a3f2012-05-16 15:09:17 +01006167namespace Catch {
6168
Phil Nashe73583d2015-08-07 17:30:34 +01006169 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006170 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6171 if( !reporter ) {
6172 std::ostringstream oss;
6173 oss << "No reporter registered with name: '" << reporterName << "'";
6174 throw std::domain_error( oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01006175 }
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006176 return reporter;
6177 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006178
Phil Nashe73583d2015-08-07 17:30:34 +01006179 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6180 std::vector<std::string> reporters = config->getReporterNames();
6181 if( reporters.empty() )
6182 reporters.push_back( "console" );
6183
6184 Ptr<IStreamingReporter> reporter;
6185 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6186 it != itEnd;
6187 ++it )
6188 reporter = addReporter( reporter, createReporter( *it, config ) );
6189 return reporter;
6190 }
Phil Nash7e346192015-11-03 08:00:43 +00006191 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
Phil Nashe73583d2015-08-07 17:30:34 +01006192 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6193 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6194 it != itEnd;
6195 ++it )
6196 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6197 return reporters;
6198 }
6199
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006200 Totals runTests( Ptr<Config> const& config ) {
6201
Phil Nash7e346192015-11-03 08:00:43 +00006202 Ptr<IConfig const> iconfig = config.get();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006203
Phil Nash7e346192015-11-03 08:00:43 +00006204 Ptr<IStreamingReporter> reporter = makeReporter( config );
6205 reporter = addListeners( iconfig, reporter );
6206
6207 RunContext context( iconfig, reporter );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006208
6209 Totals totals;
6210
6211 context.testGroupStarting( config->name(), 1, 1 );
6212
6213 TestSpec testSpec = config->testSpec();
6214 if( !testSpec.hasFilters() )
6215 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6216
Phil Nash7e346192015-11-03 08:00:43 +00006217 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
Phil Nashe73583d2015-08-07 17:30:34 +01006218 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006219 it != itEnd;
6220 ++it ) {
Phil Nash7e346192015-11-03 08:00:43 +00006221 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006222 totals += context.runTest( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006223 else
6224 reporter->skipTest( *it );
Phil Nash5bc030d2012-08-16 18:48:50 +01006225 }
Phil Nash06e959b2012-05-25 08:52:05 +01006226
Phil Nash7e346192015-11-03 08:00:43 +00006227 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006228 return totals;
6229 }
Phil Nash56d5c422012-08-23 20:08:50 +01006230
Phil Nashe73583d2015-08-07 17:30:34 +01006231 void applyFilenamesAsTags( IConfig const& config ) {
6232 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
Phil Nashb971fe72015-07-02 08:21:38 +01006233 for(std::size_t i = 0; i < tests.size(); ++i ) {
6234 TestCase& test = const_cast<TestCase&>( tests[i] );
6235 std::set<std::string> tags = test.tags;
Phil Nash786959d2013-06-07 19:07:50 +01006236
Phil Nashb971fe72015-07-02 08:21:38 +01006237 std::string filename = test.lineInfo.file;
Phil Nashc1ca0fd2015-07-03 18:30:25 +01006238 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
Phil Nashb971fe72015-07-02 08:21:38 +01006239 if( lastSlash != std::string::npos )
6240 filename = filename.substr( lastSlash+1 );
Phil Nash56d5c422012-08-23 20:08:50 +01006241
Phil Nashb971fe72015-07-02 08:21:38 +01006242 std::string::size_type lastDot = filename.find_last_of( "." );
6243 if( lastDot != std::string::npos )
6244 filename = filename.substr( 0, lastDot );
Phil Nash65cc14c2014-05-16 18:54:48 +01006245
Phil Nashe6b365d2015-07-07 08:25:15 +01006246 tags.insert( "#" + filename );
Phil Nashb971fe72015-07-02 08:21:38 +01006247 setTags( test, tags );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006248 }
Phil Nashb971fe72015-07-02 08:21:38 +01006249 }
Phil Nash56d5c422012-08-23 20:08:50 +01006250
Phil Nashe54ac702014-10-21 07:25:26 +01006251 class Session : NonCopyable {
Phil Nash786959d2013-06-07 19:07:50 +01006252 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01006253
Phil Nash786959d2013-06-07 19:07:50 +01006254 public:
Phil Nash56d5c422012-08-23 20:08:50 +01006255
Phil Nash786959d2013-06-07 19:07:50 +01006256 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6257
6258 Session()
6259 : m_cli( makeCommandLineParser() ) {
6260 if( alreadyInstantiated ) {
6261 std::string msg = "Only one instance of Catch::Session can ever be used";
Phil Nash383d7c02014-10-02 19:08:19 +01006262 Catch::cerr() << msg << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006263 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01006264 }
Phil Nash786959d2013-06-07 19:07:50 +01006265 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01006266 }
Phil Nash786959d2013-06-07 19:07:50 +01006267 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01006268 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006269 }
6270
Phil Nash786959d2013-06-07 19:07:50 +01006271 void showHelp( std::string const& processName ) {
Phil Nash21f7ef62015-06-29 18:05:23 +01006272 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01006273
Phil Nash383d7c02014-10-02 19:08:19 +01006274 m_cli.usage( Catch::cout(), processName );
6275 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01006276 }
Phil Nash3b80af72012-08-09 07:47:30 +01006277
Phil Nash3b4edd72016-02-10 19:24:48 +00006278 int applyCommandLine( int argc, char const* argv[], OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
Phil Nash786959d2013-06-07 19:07:50 +01006279 try {
Phil Nash91ef5f72013-12-20 19:06:26 +00006280 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
Phil Nash786959d2013-06-07 19:07:50 +01006281 m_unusedTokens = m_cli.parseInto( argc, argv, m_configData );
Phil Nash786959d2013-06-07 19:07:50 +01006282 if( m_configData.showHelp )
6283 showHelp( m_configData.processName );
6284 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01006285 }
Phil Nash786959d2013-06-07 19:07:50 +01006286 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01006287 {
6288 Colour colourGuard( Colour::Red );
Phil Nash21f7ef62015-06-29 18:05:23 +01006289 Catch::cerr()
6290 << "\nError(s) in input:\n"
6291 << Text( ex.what(), TextAttributes().setIndent(2) )
6292 << "\n\n";
Phil Nash46118712013-08-16 19:01:32 +01006293 }
Phil Nash383d7c02014-10-02 19:08:19 +01006294 m_cli.usage( Catch::cout(), m_configData.processName );
Phil Nash786959d2013-06-07 19:07:50 +01006295 return (std::numeric_limits<int>::max)();
6296 }
6297 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006298 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01006299
Phil Nash786959d2013-06-07 19:07:50 +01006300 void useConfigData( ConfigData const& _configData ) {
6301 m_configData = _configData;
6302 m_config.reset();
6303 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01006304
Phil Nash3b4edd72016-02-10 19:24:48 +00006305 int run( int argc, char const* argv[] ) {
Phil Nash786959d2013-06-07 19:07:50 +01006306
6307 int returnCode = applyCommandLine( argc, argv );
6308 if( returnCode == 0 )
6309 returnCode = run();
6310 return returnCode;
6311 }
Phil Nash3b4edd72016-02-10 19:24:48 +00006312 int run( int argc, char* argv[] ) {
6313 return run( argc, const_cast<char const**>( argv ) );
6314 }
Phil Nash786959d2013-06-07 19:07:50 +01006315
6316 int run() {
6317 if( m_configData.showHelp )
6318 return 0;
6319
6320 try
6321 {
6322 config(); // Force config to be constructed
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006323
Phil Nash8f66e342015-07-02 23:03:13 +01006324 seedRng( *m_config );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006325
Phil Nashe73583d2015-08-07 17:30:34 +01006326 if( m_configData.filenamesAsTags )
6327 applyFilenamesAsTags( *m_config );
Phil Nash786959d2013-06-07 19:07:50 +01006328
6329 // Handle list request
6330 if( Option<std::size_t> listed = list( config() ) )
6331 return static_cast<int>( *listed );
6332
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006333 return static_cast<int>( runTests( m_config ).assertions.failed );
Phil Nash786959d2013-06-07 19:07:50 +01006334 }
6335 catch( std::exception& ex ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006336 Catch::cerr() << ex.what() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006337 return (std::numeric_limits<int>::max)();
6338 }
6339 }
6340
6341 Clara::CommandLine<ConfigData> const& cli() const {
6342 return m_cli;
6343 }
6344 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6345 return m_unusedTokens;
6346 }
6347 ConfigData& configData() {
6348 return m_configData;
6349 }
6350 Config& config() {
6351 if( !m_config )
6352 m_config = new Config( m_configData );
6353 return *m_config;
6354 }
Phil Nash786959d2013-06-07 19:07:50 +01006355 private:
6356 Clara::CommandLine<ConfigData> m_cli;
6357 std::vector<Clara::Parser::Token> m_unusedTokens;
6358 ConfigData m_configData;
6359 Ptr<Config> m_config;
6360 };
6361
6362 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006363
6364} // end namespace Catch
6365
6366// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006367#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01006368
Phil Nash89d1e6c2011-05-24 08:23:02 +01006369// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006370#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006371
6372#include <vector>
6373#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01006374#include <sstream>
6375#include <iostream>
Phil Nash96304542014-09-15 23:32:13 +01006376#include <algorithm>
Phil Nash3b80af72012-08-09 07:47:30 +01006377
6378namespace Catch {
6379
Phil Nashe73583d2015-08-07 17:30:34 +01006380 struct LexSort {
6381 bool operator() (TestCase i,TestCase j) const { return (i<j);}
6382 };
6383 struct RandomNumberGenerator {
6384 int operator()( int n ) const { return std::rand() % n; }
6385 };
Phil Nashee3b2652014-09-18 18:25:10 +01006386
Phil Nashe73583d2015-08-07 17:30:34 +01006387 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
6388
6389 std::vector<TestCase> sorted = unsortedTestCases;
6390
6391 switch( config.runOrder() ) {
6392 case RunTests::InLexicographicalOrder:
6393 std::sort( sorted.begin(), sorted.end(), LexSort() );
6394 break;
6395 case RunTests::InRandomOrder:
6396 {
6397 seedRng( config );
6398
6399 RandomNumberGenerator rng;
6400 std::random_shuffle( sorted.begin(), sorted.end(), rng );
6401 }
6402 break;
6403 case RunTests::InDeclarationOrder:
6404 // already in declaration order
6405 break;
6406 }
6407 return sorted;
6408 }
6409 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
6410 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
6411 }
Phil Nashe73583d2015-08-07 17:30:34 +01006412
6413 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
6414 std::set<TestCase> seenFunctions;
6415 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6416 it != itEnd;
6417 ++it ) {
6418 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
6419 if( !prev.second ){
6420 Catch::cerr()
6421 << Colour( Colour::Red )
6422 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
6423 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"
6424 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6425 exit(1);
6426 }
6427 }
6428 }
6429
6430 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
6431 std::vector<TestCase> filtered;
Phil Nash8a05f462015-08-07 17:53:29 +01006432 filtered.reserve( testCases.size() );
6433 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6434 it != itEnd;
6435 ++it )
6436 if( matchTest( *it, testSpec, config ) )
6437 filtered.push_back( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006438 return filtered;
6439 }
6440 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
6441 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6442 }
6443
6444 class TestRegistry : public ITestCaseRegistry {
Phil Nash3b80af72012-08-09 07:47:30 +01006445 public:
Phil Nash981347b2015-12-09 18:11:48 +00006446 TestRegistry()
6447 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6448 m_unnamedCount( 0 )
6449 {}
Phil Nash3b80af72012-08-09 07:47:30 +01006450 virtual ~TestRegistry();
6451
Phil Nash8defc712013-04-24 19:10:02 +01006452 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006453 std::string name = testCase.getTestCaseInfo().name;
6454 if( name == "" ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006455 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00006456 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006457 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01006458 }
Phil Nashe73583d2015-08-07 17:30:34 +01006459 m_functions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01006460 }
6461
Phil Nash8defc712013-04-24 19:10:02 +01006462 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nashe73583d2015-08-07 17:30:34 +01006463 return m_functions;
Phil Nash3b80af72012-08-09 07:47:30 +01006464 }
Phil Nashe73583d2015-08-07 17:30:34 +01006465 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
6466 if( m_sortedFunctions.empty() )
6467 enforceNoDuplicateTestCases( m_functions );
Phil Nash3b80af72012-08-09 07:47:30 +01006468
Phil Nashe73583d2015-08-07 17:30:34 +01006469 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6470 m_sortedFunctions = sortTests( config, m_functions );
6471 m_currentSortOrder = config.runOrder();
Phil Nash3b80af72012-08-09 07:47:30 +01006472 }
Phil Nashe73583d2015-08-07 17:30:34 +01006473 return m_sortedFunctions;
Phil Nash92f08362014-12-22 20:18:05 +00006474 }
6475
6476 private:
Phil Nashe73583d2015-08-07 17:30:34 +01006477 std::vector<TestCase> m_functions;
6478 mutable RunTests::InWhatOrder m_currentSortOrder;
6479 mutable std::vector<TestCase> m_sortedFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01006480 size_t m_unnamedCount;
Phil Nash93a842e2015-07-13 06:36:07 +01006481 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
Phil Nash3b80af72012-08-09 07:47:30 +01006482 };
6483
6484 ///////////////////////////////////////////////////////////////////////////
6485
6486 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
6487 public:
6488
6489 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
6490
6491 virtual void invoke() const {
6492 m_fun();
6493 }
6494
6495 private:
6496 virtual ~FreeFunctionTestCase();
6497
6498 TestFunction m_fun;
6499 };
6500
Phil Nash8defc712013-04-24 19:10:02 +01006501 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00006502 std::string className = classOrQualifiedMethodName;
Phil Nashf7378ee2013-09-07 12:07:38 +01006503 if( startsWith( className, "&" ) )
Phil Nash90a35942012-11-13 22:04:29 +00006504 {
6505 std::size_t lastColons = className.rfind( "::" );
6506 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
6507 if( penultimateColons == std::string::npos )
6508 penultimateColons = 1;
6509 className = className.substr( penultimateColons, lastColons-penultimateColons );
6510 }
6511 return className;
6512 }
6513
Phil Nash7e15d9b2015-11-20 16:59:14 +00006514 void registerTestCase
6515 ( ITestCase* testCase,
6516 char const* classOrQualifiedMethodName,
6517 NameAndDesc const& nameAndDesc,
6518 SourceLineInfo const& lineInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006519
Phil Nash7e15d9b2015-11-20 16:59:14 +00006520 getMutableRegistryHub().registerTest
6521 ( makeTestCase
6522 ( testCase,
6523 extractClassName( classOrQualifiedMethodName ),
6524 nameAndDesc.name,
6525 nameAndDesc.description,
6526 lineInfo ) );
6527 }
6528 void registerTestCaseFunction
6529 ( TestFunction function,
6530 SourceLineInfo const& lineInfo,
6531 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01006532 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01006533 }
6534
Phil Nash7e15d9b2015-11-20 16:59:14 +00006535 ///////////////////////////////////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01006536
Phil Nash7e15d9b2015-11-20 16:59:14 +00006537 AutoReg::AutoReg
6538 ( TestFunction function,
6539 SourceLineInfo const& lineInfo,
6540 NameAndDesc const& nameAndDesc ) {
6541 registerTestCaseFunction( function, lineInfo, nameAndDesc );
Phil Nash3b80af72012-08-09 07:47:30 +01006542 }
6543
Phil Nash7e15d9b2015-11-20 16:59:14 +00006544 AutoReg::~AutoReg() {}
6545
Phil Nash3b80af72012-08-09 07:47:30 +01006546} // end namespace Catch
6547
6548// #included from: catch_reporter_registry.hpp
6549#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
6550
6551#include <map>
6552
6553namespace Catch {
6554
6555 class ReporterRegistry : public IReporterRegistry {
6556
6557 public:
6558
Phil Nash19520152015-08-10 07:32:48 +01006559 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
Phil Nash3b80af72012-08-09 07:47:30 +01006560
Phil Nash7e346192015-11-03 08:00:43 +00006561 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006562 FactoryMap::const_iterator it = m_factories.find( name );
6563 if( it == m_factories.end() )
Phil Nashb971fe72015-07-02 08:21:38 +01006564 return CATCH_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01006565 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01006566 }
6567
Phil Nashe73583d2015-08-07 17:30:34 +01006568 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006569 m_factories.insert( std::make_pair( name, factory ) );
6570 }
Phil Nashe73583d2015-08-07 17:30:34 +01006571 void registerListener( Ptr<IReporterFactory> const& factory ) {
6572 m_listeners.push_back( factory );
6573 }
Phil Nash3b80af72012-08-09 07:47:30 +01006574
Phil Nash19520152015-08-10 07:32:48 +01006575 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006576 return m_factories;
6577 }
Phil Nash19520152015-08-10 07:32:48 +01006578 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01006579 return m_listeners;
6580 }
Phil Nash3b80af72012-08-09 07:47:30 +01006581
6582 private:
6583 FactoryMap m_factories;
Phil Nashe73583d2015-08-07 17:30:34 +01006584 Listeners m_listeners;
Phil Nash3b80af72012-08-09 07:47:30 +01006585 };
6586}
6587
6588// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006589#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01006590
6591#ifdef __OBJC__
6592#import "Foundation/Foundation.h"
6593#endif
6594
6595namespace Catch {
6596
6597 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
6598 public:
6599 ~ExceptionTranslatorRegistry() {
6600 deleteAll( m_translators );
6601 }
6602
6603 virtual void registerTranslator( const IExceptionTranslator* translator ) {
6604 m_translators.push_back( translator );
6605 }
6606
6607 virtual std::string translateActiveException() const {
6608 try {
6609#ifdef __OBJC__
6610 // In Objective-C try objective-c exceptions first
6611 @try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00006612 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01006613 }
6614 @catch (NSException *exception) {
Phil Nash13f98432014-12-12 08:11:18 +00006615 return Catch::toString( [exception description] );
Phil Nash3b80af72012-08-09 07:47:30 +01006616 }
6617#else
Phil Nashe4fa62a2015-11-18 08:39:54 +00006618 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01006619#endif
6620 }
Phil Nashab036682014-06-02 07:48:03 +01006621 catch( TestFailureException& ) {
6622 throw;
6623 }
Phil Nash3b80af72012-08-09 07:47:30 +01006624 catch( std::exception& ex ) {
6625 return ex.what();
6626 }
6627 catch( std::string& msg ) {
6628 return msg;
6629 }
6630 catch( const char* msg ) {
6631 return msg;
6632 }
6633 catch(...) {
Phil Nashe4fa62a2015-11-18 08:39:54 +00006634 return "Unknown exception";
Phil Nash3b80af72012-08-09 07:47:30 +01006635 }
6636 }
6637
Phil Nashe4fa62a2015-11-18 08:39:54 +00006638 std::string tryTranslators() const {
6639 if( m_translators.empty() )
6640 throw;
6641 else
6642 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
Phil Nash3b80af72012-08-09 07:47:30 +01006643 }
6644
6645 private:
6646 std::vector<const IExceptionTranslator*> m_translators;
6647 };
6648}
6649
6650namespace Catch {
6651
6652 namespace {
6653
6654 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
6655
Phil Nash8defc712013-04-24 19:10:02 +01006656 RegistryHub( RegistryHub const& );
6657 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01006658
6659 public: // IRegistryHub
6660 RegistryHub() {
6661 }
Phil Nash19520152015-08-10 07:32:48 +01006662 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006663 return m_reporterRegistry;
6664 }
Phil Nash19520152015-08-10 07:32:48 +01006665 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006666 return m_testCaseRegistry;
6667 }
Phil Nash19520152015-08-10 07:32:48 +01006668 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006669 return m_exceptionTranslatorRegistry;
6670 }
6671
6672 public: // IMutableRegistryHub
Phil Nash19520152015-08-10 07:32:48 +01006673 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006674 m_reporterRegistry.registerReporter( name, factory );
6675 }
Phil Nash19520152015-08-10 07:32:48 +01006676 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01006677 m_reporterRegistry.registerListener( factory );
6678 }
Phil Nash19520152015-08-10 07:32:48 +01006679 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006680 m_testCaseRegistry.registerTest( testInfo );
6681 }
Phil Nash19520152015-08-10 07:32:48 +01006682 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01006683 m_exceptionTranslatorRegistry.registerTranslator( translator );
6684 }
6685
6686 private:
6687 TestRegistry m_testCaseRegistry;
6688 ReporterRegistry m_reporterRegistry;
6689 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
6690 };
6691
6692 // Single, global, instance
6693 inline RegistryHub*& getTheRegistryHub() {
Phil Nashb971fe72015-07-02 08:21:38 +01006694 static RegistryHub* theRegistryHub = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01006695 if( !theRegistryHub )
6696 theRegistryHub = new RegistryHub();
6697 return theRegistryHub;
6698 }
6699 }
6700
6701 IRegistryHub& getRegistryHub() {
6702 return *getTheRegistryHub();
6703 }
6704 IMutableRegistryHub& getMutableRegistryHub() {
6705 return *getTheRegistryHub();
6706 }
6707 void cleanUp() {
6708 delete getTheRegistryHub();
Phil Nashb971fe72015-07-02 08:21:38 +01006709 getTheRegistryHub() = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01006710 cleanUpContext();
6711 }
Phil Nashce612bf2012-11-01 08:27:09 +00006712 std::string translateActiveException() {
6713 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
6714 }
Phil Nash3b80af72012-08-09 07:47:30 +01006715
6716} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04006717
Phil Nash3b80af72012-08-09 07:47:30 +01006718// #included from: catch_notimplemented_exception.hpp
6719#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
6720
6721#include <ostream>
6722
6723namespace Catch {
6724
Phil Nash8defc712013-04-24 19:10:02 +01006725 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01006726 : m_lineInfo( lineInfo ) {
6727 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00006728 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01006729 oss << "not implemented";
6730 m_what = oss.str();
6731 }
6732
Phil Nashd7e17902014-04-18 08:49:35 +01006733 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
Phil Nash3b80af72012-08-09 07:47:30 +01006734 return m_what.c_str();
6735 }
6736
6737} // end namespace Catch
6738
6739// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006740#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01006741
Phil Nash3649fdf2013-12-03 18:53:55 +00006742// #included from: catch_stream.hpp
6743#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
6744
Phil Nash3649fdf2013-12-03 18:53:55 +00006745#include <stdexcept>
6746#include <cstdio>
Phil Nash383d7c02014-10-02 19:08:19 +01006747#include <iostream>
Phil Nash3649fdf2013-12-03 18:53:55 +00006748
6749namespace Catch {
6750
6751 template<typename WriterF, size_t bufferSize=256>
6752 class StreamBufImpl : public StreamBufBase {
6753 char data[bufferSize];
6754 WriterF m_writer;
6755
6756 public:
6757 StreamBufImpl() {
6758 setp( data, data + sizeof(data) );
6759 }
6760
Phil Nashd7e17902014-04-18 08:49:35 +01006761 ~StreamBufImpl() CATCH_NOEXCEPT {
Phil Nash3649fdf2013-12-03 18:53:55 +00006762 sync();
6763 }
6764
6765 private:
6766 int overflow( int c ) {
6767 sync();
6768
6769 if( c != EOF ) {
6770 if( pbase() == epptr() )
6771 m_writer( std::string( 1, static_cast<char>( c ) ) );
6772 else
6773 sputc( static_cast<char>( c ) );
6774 }
6775 return 0;
6776 }
6777
6778 int sync() {
6779 if( pbase() != pptr() ) {
6780 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
6781 setp( pbase(), epptr() );
6782 }
6783 return 0;
6784 }
6785 };
6786
6787 ///////////////////////////////////////////////////////////////////////////
6788
Phil Nash7e346192015-11-03 08:00:43 +00006789 FileStream::FileStream( std::string const& filename ) {
6790 m_ofs.open( filename.c_str() );
6791 if( m_ofs.fail() ) {
6792 std::ostringstream oss;
6793 oss << "Unable to open file: '" << filename << "'";
6794 throw std::domain_error( oss.str() );
6795 }
6796 }
6797
6798 std::ostream& FileStream::stream() const {
6799 return m_ofs;
6800 }
6801
Phil Nash3649fdf2013-12-03 18:53:55 +00006802 struct OutputDebugWriter {
6803
6804 void operator()( std::string const&str ) {
6805 writeToDebugConsole( str );
6806 }
6807 };
6808
Phil Nash7e346192015-11-03 08:00:43 +00006809 DebugOutStream::DebugOutStream()
6810 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
6811 m_os( m_streamBuf.get() )
Phil Nash3649fdf2013-12-03 18:53:55 +00006812 {}
6813
Phil Nash7e346192015-11-03 08:00:43 +00006814 std::ostream& DebugOutStream::stream() const {
6815 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00006816 }
Phil Nash383d7c02014-10-02 19:08:19 +01006817
Phil Nash7e346192015-11-03 08:00:43 +00006818 // Store the streambuf from cout up-front because
6819 // cout may get redirected when running tests
6820 CoutStream::CoutStream()
6821 : m_os( Catch::cout().rdbuf() )
Phil Nash3649fdf2013-12-03 18:53:55 +00006822 {}
6823
Phil Nash7e346192015-11-03 08:00:43 +00006824 std::ostream& CoutStream::stream() const {
6825 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00006826 }
Phil Nash383d7c02014-10-02 19:08:19 +01006827
Phil Nashfdc42d02015-12-04 10:19:08 +00006828#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
Phil Nash383d7c02014-10-02 19:08:19 +01006829 std::ostream& cout() {
6830 return std::cout;
6831 }
6832 std::ostream& cerr() {
6833 return std::cerr;
6834 }
6835#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00006836}
6837
Phil Nash3b80af72012-08-09 07:47:30 +01006838namespace Catch {
6839
6840 class Context : public IMutableContext {
6841
Phil Nashb971fe72015-07-02 08:21:38 +01006842 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01006843 Context( Context const& );
6844 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01006845
6846 public: // IContext
Phil Nash9241e432014-05-20 18:50:59 +01006847 virtual IResultCapture* getResultCapture() {
6848 return m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01006849 }
Phil Nash9241e432014-05-20 18:50:59 +01006850 virtual IRunner* getRunner() {
6851 return m_runner;
Phil Nash3b80af72012-08-09 07:47:30 +01006852 }
Phil Nash8defc712013-04-24 19:10:02 +01006853 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006854 return getGeneratorsForCurrentTest()
6855 .getGeneratorInfo( fileInfo, totalSize )
6856 .getCurrentIndex();
6857 }
6858 virtual bool advanceGeneratorsForCurrentTest() {
6859 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6860 return generators && generators->moveNext();
6861 }
6862
Phil Nash786959d2013-06-07 19:07:50 +01006863 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01006864 return m_config;
6865 }
6866
6867 public: // IMutableContext
6868 virtual void setResultCapture( IResultCapture* resultCapture ) {
6869 m_resultCapture = resultCapture;
6870 }
6871 virtual void setRunner( IRunner* runner ) {
6872 m_runner = runner;
6873 }
Phil Nash786959d2013-06-07 19:07:50 +01006874 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006875 m_config = config;
6876 }
6877
6878 friend IMutableContext& getCurrentMutableContext();
6879
6880 private:
6881 IGeneratorsForTest* findGeneratorsForCurrentTest() {
Phil Nash9241e432014-05-20 18:50:59 +01006882 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01006883
6884 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
Phil Nasha806c3e2015-03-04 08:23:40 +00006885 m_generatorsByTestName.find( testName );
Phil Nash3b80af72012-08-09 07:47:30 +01006886 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01006887 ? it->second
Phil Nashb971fe72015-07-02 08:21:38 +01006888 : CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01006889 }
6890
6891 IGeneratorsForTest& getGeneratorsForCurrentTest() {
6892 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
6893 if( !generators ) {
Phil Nash9241e432014-05-20 18:50:59 +01006894 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01006895 generators = createGeneratorsForTest();
6896 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
6897 }
6898 return *generators;
6899 }
6900
6901 private:
Phil Nash93a945c2013-10-23 15:35:07 +01006902 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01006903 IRunner* m_runner;
6904 IResultCapture* m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01006905 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
6906 };
6907
6908 namespace {
Phil Nashb971fe72015-07-02 08:21:38 +01006909 Context* currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01006910 }
6911 IMutableContext& getCurrentMutableContext() {
6912 if( !currentContext )
6913 currentContext = new Context();
6914 return *currentContext;
6915 }
6916 IContext& getCurrentContext() {
6917 return getCurrentMutableContext();
6918 }
6919
Phil Nash3b80af72012-08-09 07:47:30 +01006920 void cleanUpContext() {
6921 delete currentContext;
Phil Nashb971fe72015-07-02 08:21:38 +01006922 currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01006923 }
6924}
Matt Wozniskif29c8982012-09-17 01:42:29 -04006925
Phil Nash3b80af72012-08-09 07:47:30 +01006926// #included from: catch_console_colour_impl.hpp
6927#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
6928
Phil Nashe54ac702014-10-21 07:25:26 +01006929namespace Catch {
6930 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01006931
Phil Nashe54ac702014-10-21 07:25:26 +01006932 struct IColourImpl {
6933 virtual ~IColourImpl() {}
6934 virtual void use( Colour::Code _colourCode ) = 0;
6935 };
6936
6937 struct NoColourImpl : IColourImpl {
6938 void use( Colour::Code ) {}
6939
6940 static IColourImpl* instance() {
6941 static NoColourImpl s_instance;
6942 return &s_instance;
6943 }
6944 };
6945
6946 } // anon namespace
6947} // namespace Catch
6948
6949#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
6950# ifdef CATCH_PLATFORM_WINDOWS
6951# define CATCH_CONFIG_COLOUR_WINDOWS
6952# else
6953# define CATCH_CONFIG_COLOUR_ANSI
6954# endif
6955#endif
6956
6957#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01006958
Phil Nash4b5e0082013-06-29 20:31:17 +01006959#ifndef NOMINMAX
Phil Nash23520432013-06-28 14:11:28 +01006960#define NOMINMAX
Phil Nash4b5e0082013-06-29 20:31:17 +01006961#endif
Phil Nash39075592013-07-01 19:02:29 +01006962
6963#ifdef __AFXDLL
6964#include <AfxWin.h>
6965#else
Phil Nash3b80af72012-08-09 07:47:30 +01006966#include <windows.h>
Phil Nash39075592013-07-01 19:02:29 +01006967#endif
Phil Nash3b80af72012-08-09 07:47:30 +01006968
6969namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00006970namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01006971
Phil Nashe54ac702014-10-21 07:25:26 +01006972 class Win32ColourImpl : public IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01006973 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01006974 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01006975 {
Phil Nash12c16ff2013-04-05 20:58:01 +01006976 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
6977 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
Phil Nash584032d2015-07-06 06:22:28 +01006978 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
6979 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
Phil Nash3b80af72012-08-09 07:47:30 +01006980 }
Phil Nash3b80af72012-08-09 07:47:30 +01006981
Phil Nash12c16ff2013-04-05 20:58:01 +01006982 virtual void use( Colour::Code _colourCode ) {
6983 switch( _colourCode ) {
Phil Nash584032d2015-07-06 06:22:28 +01006984 case Colour::None: return setTextAttribute( originalForegroundAttributes );
Phil Nash12c16ff2013-04-05 20:58:01 +01006985 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
6986 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
6987 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
6988 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
6989 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
6990 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
6991 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01006992
Phil Nash12c16ff2013-04-05 20:58:01 +01006993 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
6994 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
6995 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01006996 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01006997
Phil Nash12c16ff2013-04-05 20:58:01 +01006998 case Colour::Bright: throw std::logic_error( "not a colour" );
6999 }
Phil Nash3b80af72012-08-09 07:47:30 +01007000 }
Phil Nash3b80af72012-08-09 07:47:30 +01007001
7002 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01007003 void setTextAttribute( WORD _textAttribute ) {
Phil Nash584032d2015-07-06 06:22:28 +01007004 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
Phil Nash3b80af72012-08-09 07:47:30 +01007005 }
Phil Nash12c16ff2013-04-05 20:58:01 +01007006 HANDLE stdoutHandle;
Phil Nash584032d2015-07-06 06:22:28 +01007007 WORD originalForegroundAttributes;
7008 WORD originalBackgroundAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01007009 };
7010
Phil Nashe54ac702014-10-21 07:25:26 +01007011 IColourImpl* platformColourInstance() {
Phil Nash20cad7c2014-04-15 18:44:37 +01007012 static Win32ColourImpl s_instance;
Phil Nashae5ee2c2016-02-29 08:17:18 +00007013
7014 Ptr<IConfig const> config = getCurrentContext().getConfig();
7015 UseColour::YesOrNo colourMode = config
7016 ? config->useColour()
7017 : UseColour::Auto;
7018 if( colourMode == UseColour::Auto )
7019 colourMode = !isDebuggerActive()
7020 ? UseColour::Yes
7021 : UseColour::No;
7022 return colourMode == UseColour::Yes
7023 ? &s_instance
7024 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007025 }
Phil Nash3df6c0d2013-03-11 18:38:29 +00007026
7027} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01007028} // end namespace Catch
7029
Phil Nashe54ac702014-10-21 07:25:26 +01007030#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00007031
7032#include <unistd.h>
7033
7034namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007035namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00007036
7037 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01007038 // Thanks to Adam Strzelecki for original contribution
7039 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00007040 // https://github.com/philsquared/Catch/pull/131
Phil Nashe54ac702014-10-21 07:25:26 +01007041 class PosixColourImpl : public IColourImpl {
Phil Nash12c16ff2013-04-05 20:58:01 +01007042 public:
7043 virtual void use( Colour::Code _colourCode ) {
7044 switch( _colourCode ) {
7045 case Colour::None:
7046 case Colour::White: return setColour( "[0m" );
7047 case Colour::Red: return setColour( "[0;31m" );
7048 case Colour::Green: return setColour( "[0;32m" );
7049 case Colour::Blue: return setColour( "[0:34m" );
7050 case Colour::Cyan: return setColour( "[0;36m" );
7051 case Colour::Yellow: return setColour( "[0;33m" );
7052 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007053
Phil Nash12c16ff2013-04-05 20:58:01 +01007054 case Colour::LightGrey: return setColour( "[0;37m" );
7055 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01007056 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007057 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007058
Phil Nash12c16ff2013-04-05 20:58:01 +01007059 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00007060 }
7061 }
Phil Nashe54ac702014-10-21 07:25:26 +01007062 static IColourImpl* instance() {
7063 static PosixColourImpl s_instance;
7064 return &s_instance;
7065 }
7066
Phil Nash12c16ff2013-04-05 20:58:01 +01007067 private:
7068 void setColour( const char* _escapeCode ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007069 Catch::cout() << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00007070 }
7071 };
7072
Phil Nashe54ac702014-10-21 07:25:26 +01007073 IColourImpl* platformColourInstance() {
Phil Nasha806c3e2015-03-04 08:23:40 +00007074 Ptr<IConfig const> config = getCurrentContext().getConfig();
Phil Nashae5ee2c2016-02-29 08:17:18 +00007075 UseColour::YesOrNo colourMode = config
7076 ? config->useColour()
7077 : UseColour::Auto;
7078 if( colourMode == UseColour::Auto )
7079 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7080 ? UseColour::Yes
7081 : UseColour::No;
7082 return colourMode == UseColour::Yes
Phil Nashe54ac702014-10-21 07:25:26 +01007083 ? PosixColourImpl::instance()
7084 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007085 }
Phil Nashce612bf2012-11-01 08:27:09 +00007086
Phil Nash12c16ff2013-04-05 20:58:01 +01007087} // end anon namespace
7088} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01007089
Phil Nashe54ac702014-10-21 07:25:26 +01007090#else // not Windows or ANSI ///////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007091
7092namespace Catch {
7093
Phil Nashe54ac702014-10-21 07:25:26 +01007094 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
Phil Nash20cad7c2014-04-15 18:44:37 +01007095
Phil Nashe54ac702014-10-21 07:25:26 +01007096} // end namespace Catch
7097
7098#endif // Windows/ ANSI/ None
7099
7100namespace Catch {
Phil Nash3b80af72012-08-09 07:47:30 +01007101
Phil Nashce562092014-07-09 07:40:37 +01007102 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7103 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7104 Colour::~Colour(){ if( !m_moved ) use( None ); }
Phil Nash3b80af72012-08-09 07:47:30 +01007105
Phil Nashe54ac702014-10-21 07:25:26 +01007106 void Colour::use( Code _colourCode ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00007107 static IColourImpl* impl = platformColourInstance();
Phil Nashe54ac702014-10-21 07:25:26 +01007108 impl->use( _colourCode );
Phil Nash20cad7c2014-04-15 18:44:37 +01007109 }
Phil Nash3b80af72012-08-09 07:47:30 +01007110
7111} // end namespace Catch
7112
Phil Nash3b80af72012-08-09 07:47:30 +01007113// #included from: catch_generators_impl.hpp
7114#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7115
7116#include <vector>
7117#include <string>
7118#include <map>
7119
7120namespace Catch {
7121
7122 struct GeneratorInfo : IGeneratorInfo {
7123
7124 GeneratorInfo( std::size_t size )
7125 : m_size( size ),
7126 m_currentIndex( 0 )
7127 {}
7128
7129 bool moveNext() {
7130 if( ++m_currentIndex == m_size ) {
7131 m_currentIndex = 0;
7132 return false;
7133 }
7134 return true;
7135 }
7136
7137 std::size_t getCurrentIndex() const {
7138 return m_currentIndex;
7139 }
7140
7141 std::size_t m_size;
7142 std::size_t m_currentIndex;
7143 };
7144
7145 ///////////////////////////////////////////////////////////////////////////
7146
7147 class GeneratorsForTest : public IGeneratorsForTest {
7148
7149 public:
7150 ~GeneratorsForTest() {
7151 deleteAll( m_generatorsInOrder );
7152 }
7153
Phil Nash8defc712013-04-24 19:10:02 +01007154 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007155 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7156 if( it == m_generatorsByName.end() ) {
7157 IGeneratorInfo* info = new GeneratorInfo( size );
7158 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7159 m_generatorsInOrder.push_back( info );
7160 return *info;
7161 }
7162 return *it->second;
7163 }
7164
7165 bool moveNext() {
7166 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7167 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7168 for(; it != itEnd; ++it ) {
7169 if( (*it)->moveNext() )
7170 return true;
7171 }
7172 return false;
7173 }
7174
7175 private:
7176 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7177 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7178 };
7179
7180 IGeneratorsForTest* createGeneratorsForTest()
7181 {
7182 return new GeneratorsForTest();
7183 }
7184
7185} // end namespace Catch
7186
Phil Nashce612bf2012-11-01 08:27:09 +00007187// #included from: catch_assertionresult.hpp
7188#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007189
7190namespace Catch {
7191
Phil Nash8defc712013-04-24 19:10:02 +01007192 AssertionInfo::AssertionInfo( std::string const& _macroName,
7193 SourceLineInfo const& _lineInfo,
7194 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00007195 ResultDisposition::Flags _resultDisposition )
7196 : macroName( _macroName ),
7197 lineInfo( _lineInfo ),
7198 capturedExpression( _capturedExpression ),
7199 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01007200 {}
Phil Nash90a35942012-11-13 22:04:29 +00007201
Phil Nashce612bf2012-11-01 08:27:09 +00007202 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007203
Phil Nash8defc712013-04-24 19:10:02 +01007204 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00007205 : m_info( info ),
7206 m_resultData( data )
7207 {}
Phil Nash3b80af72012-08-09 07:47:30 +01007208
Phil Nashce612bf2012-11-01 08:27:09 +00007209 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007210
Phil Nash90a35942012-11-13 22:04:29 +00007211 // Result was a success
7212 bool AssertionResult::succeeded() const {
7213 return Catch::isOk( m_resultData.resultType );
7214 }
7215
7216 // Result was a success, or failure is suppressed
7217 bool AssertionResult::isOk() const {
7218 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01007219 }
7220
Phil Nashce612bf2012-11-01 08:27:09 +00007221 ResultWas::OfType AssertionResult::getResultType() const {
7222 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01007223 }
7224
Phil Nashce612bf2012-11-01 08:27:09 +00007225 bool AssertionResult::hasExpression() const {
7226 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007227 }
7228
Phil Nashce612bf2012-11-01 08:27:09 +00007229 bool AssertionResult::hasMessage() const {
7230 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007231 }
7232
Phil Nashce612bf2012-11-01 08:27:09 +00007233 std::string AssertionResult::getExpression() const {
Phil Nashab036682014-06-02 07:48:03 +01007234 if( isFalseTest( m_info.resultDisposition ) )
Phil Nash786959d2013-06-07 19:07:50 +01007235 return "!" + m_info.capturedExpression;
7236 else
7237 return m_info.capturedExpression;
7238 }
7239 std::string AssertionResult::getExpressionInMacro() const {
7240 if( m_info.macroName.empty() )
7241 return m_info.capturedExpression;
7242 else
7243 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01007244 }
7245
Phil Nashce612bf2012-11-01 08:27:09 +00007246 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01007247 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01007248 }
7249
Phil Nashce612bf2012-11-01 08:27:09 +00007250 std::string AssertionResult::getExpandedExpression() const {
7251 return m_resultData.reconstructedExpression;
Phil Nash3b80af72012-08-09 07:47:30 +01007252 }
7253
Phil Nashce612bf2012-11-01 08:27:09 +00007254 std::string AssertionResult::getMessage() const {
7255 return m_resultData.message;
7256 }
7257 SourceLineInfo AssertionResult::getSourceInfo() const {
7258 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01007259 }
7260
Phil Nashce612bf2012-11-01 08:27:09 +00007261 std::string AssertionResult::getTestMacroName() const {
7262 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01007263 }
7264
7265} // end namespace Catch
7266
Phil Nash5bc030d2012-08-16 18:48:50 +01007267// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007268#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01007269
7270namespace Catch {
7271
Phil Nash52e1e742014-07-03 08:11:38 +01007272 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
Phil Nash91c17f32014-12-15 07:26:31 +00007273 if( startsWith( tag, "." ) ||
Phil Nash52e1e742014-07-03 08:11:38 +01007274 tag == "hide" ||
7275 tag == "!hide" )
7276 return TestCaseInfo::IsHidden;
7277 else if( tag == "!throws" )
7278 return TestCaseInfo::Throws;
7279 else if( tag == "!shouldfail" )
7280 return TestCaseInfo::ShouldFail;
7281 else if( tag == "!mayfail" )
7282 return TestCaseInfo::MayFail;
7283 else
7284 return TestCaseInfo::None;
Phil Nash20cad7c2014-04-15 18:44:37 +01007285 }
7286 inline bool isReservedTag( std::string const& tag ) {
Phil Nash37e55612015-03-27 18:02:28 +00007287 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
Phil Nash20cad7c2014-04-15 18:44:37 +01007288 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007289 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7290 if( isReservedTag( tag ) ) {
7291 {
7292 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01007293 Catch::cerr()
Phil Nash65cc14c2014-05-16 18:54:48 +01007294 << "Tag name [" << tag << "] not allowed.\n"
7295 << "Tag names starting with non alpha-numeric characters are reserved\n";
7296 }
7297 {
7298 Colour colourGuard( Colour::FileName );
Phil Nash383d7c02014-10-02 19:08:19 +01007299 Catch::cerr() << _lineInfo << std::endl;
Phil Nash65cc14c2014-05-16 18:54:48 +01007300 }
7301 exit(1);
7302 }
7303 }
Phil Nash20cad7c2014-04-15 18:44:37 +01007304
Phil Nasha1fbfea2012-12-01 23:57:18 +00007305 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01007306 std::string const& _className,
7307 std::string const& _name,
7308 std::string const& _descOrTags,
7309 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01007310 {
Phil Nash5ecb72b2013-11-26 20:57:45 +00007311 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nash65cc14c2014-05-16 18:54:48 +01007312
7313 // Parse out tags
Phil Nasha1fbfea2012-12-01 23:57:18 +00007314 std::set<std::string> tags;
Phil Nash65cc14c2014-05-16 18:54:48 +01007315 std::string desc, tag;
7316 bool inTag = false;
7317 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7318 char c = _descOrTags[i];
7319 if( !inTag ) {
7320 if( c == '[' )
7321 inTag = true;
7322 else
7323 desc += c;
Phil Nash20cad7c2014-04-15 18:44:37 +01007324 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007325 else {
7326 if( c == ']' ) {
Phil Nash91c17f32014-12-15 07:26:31 +00007327 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7328 if( prop == TestCaseInfo::IsHidden )
Phil Nashebd48882014-05-19 18:22:59 +01007329 isHidden = true;
Phil Nash91c17f32014-12-15 07:26:31 +00007330 else if( prop == TestCaseInfo::None )
7331 enforceNotReservedTag( tag, _lineInfo );
7332
7333 tags.insert( tag );
Phil Nash65cc14c2014-05-16 18:54:48 +01007334 tag.clear();
Phil Nash91c17f32014-12-15 07:26:31 +00007335 inTag = false;
Phil Nash65cc14c2014-05-16 18:54:48 +01007336 }
7337 else
7338 tag += c;
7339 }
Phil Nashde49ec42013-12-04 20:25:14 +00007340 }
Phil Nash9241e432014-05-20 18:50:59 +01007341 if( isHidden ) {
7342 tags.insert( "hide" );
7343 tags.insert( "." );
7344 }
7345
Phil Nash52e1e742014-07-03 08:11:38 +01007346 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
Phil Nasha1fbfea2012-12-01 23:57:18 +00007347 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01007348 }
Phil Nash5bc030d2012-08-16 18:48:50 +01007349
Phil Nashb971fe72015-07-02 08:21:38 +01007350 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
7351 {
7352 testCaseInfo.tags = tags;
7353 testCaseInfo.lcaseTags.clear();
7354
7355 std::ostringstream oss;
7356 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
7357 oss << "[" << *it << "]";
7358 std::string lcaseTag = toLower( *it );
7359 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7360 testCaseInfo.lcaseTags.insert( lcaseTag );
7361 }
7362 testCaseInfo.tagsAsString = oss.str();
7363 }
7364
Phil Nash8defc712013-04-24 19:10:02 +01007365 TestCaseInfo::TestCaseInfo( std::string const& _name,
7366 std::string const& _className,
7367 std::string const& _description,
7368 std::set<std::string> const& _tags,
Phil Nash8defc712013-04-24 19:10:02 +01007369 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007370 : name( _name ),
7371 className( _className ),
7372 description( _description ),
Phil Nashff03cdf2012-12-06 08:44:51 +00007373 lineInfo( _lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01007374 properties( None )
Phil Nash38f7eef2013-03-29 13:44:33 +00007375 {
Phil Nashb971fe72015-07-02 08:21:38 +01007376 setTags( *this, _tags );
Phil Nash38f7eef2013-03-29 13:44:33 +00007377 }
Phil Nash5bc030d2012-08-16 18:48:50 +01007378
Phil Nash8defc712013-04-24 19:10:02 +01007379 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007380 : name( other.name ),
7381 className( other.className ),
7382 description( other.description ),
7383 tags( other.tags ),
Phil Nash9241e432014-05-20 18:50:59 +01007384 lcaseTags( other.lcaseTags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00007385 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00007386 lineInfo( other.lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01007387 properties( other.properties )
Phil Nash5bc030d2012-08-16 18:48:50 +01007388 {}
7389
Phil Nash52e1e742014-07-03 08:11:38 +01007390 bool TestCaseInfo::isHidden() const {
7391 return ( properties & IsHidden ) != 0;
7392 }
7393 bool TestCaseInfo::throws() const {
7394 return ( properties & Throws ) != 0;
7395 }
7396 bool TestCaseInfo::okToFail() const {
7397 return ( properties & (ShouldFail | MayFail ) ) != 0;
7398 }
7399 bool TestCaseInfo::expectedToFail() const {
7400 return ( properties & (ShouldFail ) ) != 0;
7401 }
7402
Phil Nash8defc712013-04-24 19:10:02 +01007403 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007404
Phil Nash8defc712013-04-24 19:10:02 +01007405 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007406 : TestCaseInfo( other ),
7407 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01007408 {}
7409
Phil Nash8defc712013-04-24 19:10:02 +01007410 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007411 TestCase other( *this );
7412 other.name = _newName;
7413 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01007414 }
7415
Phil Nash9241e432014-05-20 18:50:59 +01007416 void TestCase::swap( TestCase& other ) {
7417 test.swap( other.test );
7418 name.swap( other.name );
7419 className.swap( other.className );
7420 description.swap( other.description );
7421 tags.swap( other.tags );
7422 lcaseTags.swap( other.lcaseTags );
7423 tagsAsString.swap( other.tagsAsString );
Phil Nash52e1e742014-07-03 08:11:38 +01007424 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
Phil Nash9241e432014-05-20 18:50:59 +01007425 std::swap( lineInfo, other.lineInfo );
7426 }
7427
Phil Nasha1fbfea2012-12-01 23:57:18 +00007428 void TestCase::invoke() const {
7429 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01007430 }
7431
Phil Nash8defc712013-04-24 19:10:02 +01007432 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007433 return test.get() == other.test.get() &&
7434 name == other.name &&
7435 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01007436 }
7437
Phil Nash8defc712013-04-24 19:10:02 +01007438 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007439 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01007440 }
Phil Nash8defc712013-04-24 19:10:02 +01007441 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007442 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01007443 swap( temp );
7444 return *this;
7445 }
Phil Nash799ecf92012-09-24 08:30:13 +01007446
Phil Nash8defc712013-04-24 19:10:02 +01007447 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00007448 {
7449 return *this;
7450 }
7451
Phil Nash799ecf92012-09-24 08:30:13 +01007452} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01007453
Phil Nash7673a302012-11-15 22:15:41 +00007454// #included from: catch_version.hpp
7455#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7456
7457namespace Catch {
7458
Phil Nash21f7ef62015-06-29 18:05:23 +01007459 Version::Version
7460 ( unsigned int _majorVersion,
7461 unsigned int _minorVersion,
7462 unsigned int _patchNumber,
7463 std::string const& _branchName,
7464 unsigned int _buildNumber )
7465 : majorVersion( _majorVersion ),
7466 minorVersion( _minorVersion ),
7467 patchNumber( _patchNumber ),
7468 branchName( _branchName ),
7469 buildNumber( _buildNumber )
7470 {}
7471
7472 std::ostream& operator << ( std::ostream& os, Version const& version ) {
7473 os << version.majorVersion << "."
7474 << version.minorVersion << "."
7475 << version.patchNumber;
7476
7477 if( !version.branchName.empty() ) {
7478 os << "-" << version.branchName
7479 << "." << version.buildNumber;
7480 }
7481 return os;
7482 }
7483
Phil Nash02af70e2016-03-11 18:31:52 +00007484 Version libraryVersion( 1, 3, 6, "", 0 );
Phil Nash21f7ef62015-06-29 18:05:23 +01007485
Phil Nash7673a302012-11-15 22:15:41 +00007486}
7487
Phil Nasha2773812013-02-02 20:37:58 +00007488// #included from: catch_message.hpp
7489#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
7490
7491namespace Catch {
7492
7493 MessageInfo::MessageInfo( std::string const& _macroName,
7494 SourceLineInfo const& _lineInfo,
7495 ResultWas::OfType _type )
7496 : macroName( _macroName ),
7497 lineInfo( _lineInfo ),
7498 type( _type ),
7499 sequence( ++globalCount )
7500 {}
7501
7502 // This may need protecting if threading support is added
7503 unsigned int MessageInfo::globalCount = 0;
7504
7505 ////////////////////////////////////////////////////////////////////////////
7506
Phil Nashb5fd5a62013-06-28 17:09:57 +01007507 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
7508 : m_info( builder.m_info )
7509 {
7510 m_info.message = builder.m_stream.str();
7511 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00007512 }
Phil Nash9241e432014-05-20 18:50:59 +01007513 ScopedMessage::ScopedMessage( ScopedMessage const& other )
7514 : m_info( other.m_info )
7515 {}
7516
Phil Nashb5fd5a62013-06-28 17:09:57 +01007517 ScopedMessage::~ScopedMessage() {
7518 getResultCapture().popScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00007519 }
7520
7521} // end namespace Catch
7522
Phil Nash243f2d22013-04-12 10:43:06 +01007523// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01007524#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
7525
7526// #included from: catch_legacy_reporter_adapter.h
7527#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
7528
7529namespace Catch
7530{
Phil Nash3649fdf2013-12-03 18:53:55 +00007531 // Deprecated
7532 struct IReporter : IShared {
7533 virtual ~IReporter();
7534
7535 virtual bool shouldRedirectStdout() const = 0;
7536
7537 virtual void StartTesting() = 0;
7538 virtual void EndTesting( Totals const& totals ) = 0;
7539 virtual void StartGroup( std::string const& groupName ) = 0;
7540 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
7541 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
7542 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
7543 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
7544 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
7545 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
7546 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
7547 virtual void Aborted() = 0;
7548 virtual void Result( AssertionResult const& result ) = 0;
7549 };
7550
Phil Nash87641772013-04-08 11:50:41 +01007551 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
7552 {
7553 public:
Phil Nash786959d2013-06-07 19:07:50 +01007554 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01007555 virtual ~LegacyReporterAdapter();
7556
7557 virtual ReporterPreferences getPreferences() const;
7558 virtual void noMatchingTestCases( std::string const& );
7559 virtual void testRunStarting( TestRunInfo const& );
7560 virtual void testGroupStarting( GroupInfo const& groupInfo );
7561 virtual void testCaseStarting( TestCaseInfo const& testInfo );
7562 virtual void sectionStarting( SectionInfo const& sectionInfo );
7563 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01007564 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01007565 virtual void sectionEnded( SectionStats const& sectionStats );
7566 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
7567 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
7568 virtual void testRunEnded( TestRunStats const& testRunStats );
Phil Nash92f08362014-12-22 20:18:05 +00007569 virtual void skipTest( TestCaseInfo const& );
Phil Nash87641772013-04-08 11:50:41 +01007570
7571 private:
7572 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01007573 };
7574}
7575
7576namespace Catch
7577{
Phil Nash786959d2013-06-07 19:07:50 +01007578 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
7579 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01007580 {}
7581 LegacyReporterAdapter::~LegacyReporterAdapter() {}
7582
7583 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
7584 ReporterPreferences prefs;
7585 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
7586 return prefs;
7587 }
7588
7589 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
7590 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
7591 m_legacyReporter->StartTesting();
7592 }
7593 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
7594 m_legacyReporter->StartGroup( groupInfo.name );
7595 }
7596 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
7597 m_legacyReporter->StartTestCase( testInfo );
7598 }
7599 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
7600 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
7601 }
7602 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
7603 // Not on legacy interface
7604 }
7605
Phil Nashb5fd5a62013-06-28 17:09:57 +01007606 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01007607 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
7608 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
7609 it != itEnd;
7610 ++it ) {
7611 if( it->type == ResultWas::Info ) {
Phil Nashab036682014-06-02 07:48:03 +01007612 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
7613 rb << it->message;
7614 rb.setResultType( ResultWas::Info );
7615 AssertionResult result = rb.build();
Phil Nash87641772013-04-08 11:50:41 +01007616 m_legacyReporter->Result( result );
7617 }
7618 }
7619 }
7620 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01007621 return true;
Phil Nash87641772013-04-08 11:50:41 +01007622 }
7623 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
7624 if( sectionStats.missingAssertions )
7625 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
7626 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
7627 }
7628 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01007629 m_legacyReporter->EndTestCase
7630 ( testCaseStats.testInfo,
7631 testCaseStats.totals,
7632 testCaseStats.stdOut,
7633 testCaseStats.stdErr );
7634 }
7635 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
7636 if( testGroupStats.aborting )
7637 m_legacyReporter->Aborted();
7638 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
7639 }
7640 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
7641 m_legacyReporter->EndTesting( testRunStats.totals );
7642 }
Phil Nash92f08362014-12-22 20:18:05 +00007643 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
7644 }
Phil Nash87641772013-04-08 11:50:41 +01007645}
7646
Phil Nashaa7123b2013-08-15 19:01:00 +01007647// #included from: catch_timer.hpp
7648
7649#ifdef __clang__
7650#pragma clang diagnostic push
7651#pragma clang diagnostic ignored "-Wc++11-long-long"
7652#endif
7653
Phil Nash04a33642013-08-16 19:09:09 +01007654#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01007655#include <windows.h>
7656#else
7657#include <sys/time.h>
7658#endif
7659
7660namespace Catch {
7661
7662 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01007663#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01007664 uint64_t getCurrentTicks() {
7665 static uint64_t hz=0, hzo=0;
7666 if (!hz) {
Phil Nash37e55612015-03-27 18:02:28 +00007667 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
7668 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01007669 }
7670 uint64_t t;
Phil Nash37e55612015-03-27 18:02:28 +00007671 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01007672 return ((t-hzo)*1000000)/hz;
7673 }
7674#else
7675 uint64_t getCurrentTicks() {
7676 timeval t;
Phil Nashb971fe72015-07-02 08:21:38 +01007677 gettimeofday(&t,CATCH_NULL);
Phil Nashce562092014-07-09 07:40:37 +01007678 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
Phil Nashaa7123b2013-08-15 19:01:00 +01007679 }
7680#endif
7681 }
7682
7683 void Timer::start() {
7684 m_ticks = getCurrentTicks();
7685 }
Phil Nash4caabfa2014-09-03 19:23:22 +01007686 unsigned int Timer::getElapsedMicroseconds() const {
Phil Nashce562092014-07-09 07:40:37 +01007687 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
Phil Nashaa7123b2013-08-15 19:01:00 +01007688 }
7689 unsigned int Timer::getElapsedMilliseconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01007690 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
Phil Nashaa7123b2013-08-15 19:01:00 +01007691 }
7692 double Timer::getElapsedSeconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01007693 return getElapsedMicroseconds()/1000000.0;
Phil Nashaa7123b2013-08-15 19:01:00 +01007694 }
7695
7696} // namespace Catch
7697
7698#ifdef __clang__
7699#pragma clang diagnostic pop
7700#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00007701// #included from: catch_common.hpp
7702#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
7703
7704namespace Catch {
7705
7706 bool startsWith( std::string const& s, std::string const& prefix ) {
7707 return s.size() >= prefix.size() && s.substr( 0, prefix.size() ) == prefix;
7708 }
7709 bool endsWith( std::string const& s, std::string const& suffix ) {
7710 return s.size() >= suffix.size() && s.substr( s.size()-suffix.size(), suffix.size() ) == suffix;
7711 }
7712 bool contains( std::string const& s, std::string const& infix ) {
7713 return s.find( infix ) != std::string::npos;
7714 }
7715 void toLowerInPlace( std::string& s ) {
7716 std::transform( s.begin(), s.end(), s.begin(), ::tolower );
7717 }
7718 std::string toLower( std::string const& s ) {
7719 std::string lc = s;
7720 toLowerInPlace( lc );
7721 return lc;
7722 }
7723 std::string trim( std::string const& str ) {
7724 static char const* whitespaceChars = "\n\r\t ";
7725 std::string::size_type start = str.find_first_not_of( whitespaceChars );
7726 std::string::size_type end = str.find_last_not_of( whitespaceChars );
7727
7728 return start != std::string::npos ? str.substr( start, 1+end-start ) : "";
7729 }
7730
Phil Nash576aff62014-12-21 00:21:23 +00007731 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
7732 bool replaced = false;
7733 std::size_t i = str.find( replaceThis );
7734 while( i != std::string::npos ) {
7735 replaced = true;
7736 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
7737 if( i < str.size()-withThis.size() )
7738 i = str.find( replaceThis, i+withThis.size() );
7739 else
7740 i = std::string::npos;
7741 }
7742 return replaced;
7743 }
7744
Phil Nash3649fdf2013-12-03 18:53:55 +00007745 pluralise::pluralise( std::size_t count, std::string const& label )
7746 : m_count( count ),
7747 m_label( label )
7748 {}
7749
7750 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
7751 os << pluraliser.m_count << " " << pluraliser.m_label;
7752 if( pluraliser.m_count != 1 )
7753 os << "s";
7754 return os;
7755 }
7756
7757 SourceLineInfo::SourceLineInfo() : line( 0 ){}
Phil Nashde49ec42013-12-04 20:25:14 +00007758 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
Phil Nash3649fdf2013-12-03 18:53:55 +00007759 : file( _file ),
7760 line( _line )
7761 {}
7762 SourceLineInfo::SourceLineInfo( SourceLineInfo const& other )
7763 : file( other.file ),
7764 line( other.line )
7765 {}
7766 bool SourceLineInfo::empty() const {
7767 return file.empty();
7768 }
7769 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
7770 return line == other.line && file == other.file;
7771 }
Phil Nasha806c3e2015-03-04 08:23:40 +00007772 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
7773 return line < other.line || ( line == other.line && file < other.file );
7774 }
Phil Nash3649fdf2013-12-03 18:53:55 +00007775
Phil Nash8f66e342015-07-02 23:03:13 +01007776 void seedRng( IConfig const& config ) {
7777 if( config.rngSeed() != 0 )
7778 std::srand( config.rngSeed() );
7779 }
7780 unsigned int rngSeed() {
7781 return getCurrentContext().getConfig()->rngSeed();
7782 }
7783
Phil Nash3649fdf2013-12-03 18:53:55 +00007784 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
7785#ifndef __GNUG__
7786 os << info.file << "(" << info.line << ")";
7787#else
7788 os << info.file << ":" << info.line;
7789#endif
7790 return os;
7791 }
7792
7793 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
7794 std::ostringstream oss;
7795 oss << locationInfo << ": Internal Catch error: '" << message << "'";
Phil Nashab036682014-06-02 07:48:03 +01007796 if( alwaysTrue() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007797 throw std::logic_error( oss.str() );
7798 }
7799}
7800
7801// #included from: catch_section.hpp
7802#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
7803
7804namespace Catch {
7805
Phil Nashce562092014-07-09 07:40:37 +01007806 SectionInfo::SectionInfo
7807 ( SourceLineInfo const& _lineInfo,
7808 std::string const& _name,
7809 std::string const& _description )
7810 : name( _name ),
7811 description( _description ),
7812 lineInfo( _lineInfo )
7813 {}
7814
7815 Section::Section( SectionInfo const& info )
7816 : m_info( info ),
Phil Nash9241e432014-05-20 18:50:59 +01007817 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nash3649fdf2013-12-03 18:53:55 +00007818 {
7819 m_timer.start();
7820 }
7821
7822 Section::~Section() {
Phil Nash0c1c9fa2015-09-27 03:28:14 -07007823 if( m_sectionIncluded ) {
7824 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
7825 if( std::uncaught_exception() )
7826 getResultCapture().sectionEndedEarly( endInfo );
7827 else
7828 getResultCapture().sectionEnded( endInfo );
7829 }
Phil Nash3649fdf2013-12-03 18:53:55 +00007830 }
7831
7832 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01007833 Section::operator bool() const {
Phil Nash3649fdf2013-12-03 18:53:55 +00007834 return m_sectionIncluded;
7835 }
7836
7837} // end namespace Catch
7838
7839// #included from: catch_debugger.hpp
7840#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
7841
7842#include <iostream>
7843
7844#ifdef CATCH_PLATFORM_MAC
7845
7846 #include <assert.h>
7847 #include <stdbool.h>
7848 #include <sys/types.h>
7849 #include <unistd.h>
7850 #include <sys/sysctl.h>
7851
7852 namespace Catch{
7853
7854 // The following function is taken directly from the following technical note:
7855 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
7856
7857 // Returns true if the current process is being debugged (either
7858 // running under the debugger or has a debugger attached post facto).
7859 bool isDebuggerActive(){
7860
Phil Nash3649fdf2013-12-03 18:53:55 +00007861 int mib[4];
7862 struct kinfo_proc info;
7863 size_t size;
7864
7865 // Initialize the flags so that, if sysctl fails for some bizarre
7866 // reason, we get a predictable result.
7867
7868 info.kp_proc.p_flag = 0;
7869
7870 // Initialize mib, which tells sysctl the info we want, in this case
7871 // we're looking for information about a specific process ID.
7872
7873 mib[0] = CTL_KERN;
7874 mib[1] = KERN_PROC;
7875 mib[2] = KERN_PROC_PID;
7876 mib[3] = getpid();
7877
7878 // Call sysctl.
7879
7880 size = sizeof(info);
Phil Nashb971fe72015-07-02 08:21:38 +01007881 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007882 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
Phil Nash7eb5acc2014-01-08 17:17:31 +00007883 return false;
7884 }
Phil Nash3649fdf2013-12-03 18:53:55 +00007885
7886 // We're being debugged if the P_TRACED flag is set.
7887
7888 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
7889 }
7890 } // namespace Catch
7891
7892#elif defined(_MSC_VER)
7893 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7894 namespace Catch {
7895 bool isDebuggerActive() {
7896 return IsDebuggerPresent() != 0;
7897 }
7898 }
7899#elif defined(__MINGW32__)
7900 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
7901 namespace Catch {
7902 bool isDebuggerActive() {
7903 return IsDebuggerPresent() != 0;
7904 }
7905 }
7906#else
7907 namespace Catch {
7908 inline bool isDebuggerActive() { return false; }
7909 }
7910#endif // Platform
7911
7912#ifdef CATCH_PLATFORM_WINDOWS
7913 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
7914 namespace Catch {
7915 void writeToDebugConsole( std::string const& text ) {
7916 ::OutputDebugStringA( text.c_str() );
7917 }
7918 }
7919#else
7920 namespace Catch {
7921 void writeToDebugConsole( std::string const& text ) {
7922 // !TBD: Need a version for Mac/ XCode and other IDEs
Phil Nash383d7c02014-10-02 19:08:19 +01007923 Catch::cout() << text;
Phil Nash3649fdf2013-12-03 18:53:55 +00007924 }
7925 }
7926#endif // Platform
7927
Phil Nashaef6cd52014-04-23 07:10:10 +01007928// #included from: catch_tostring.hpp
7929#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
7930
7931namespace Catch {
7932
Phil Nashab036682014-06-02 07:48:03 +01007933namespace Detail {
7934
Phil Nash2f6371f2015-07-23 23:06:26 +01007935 const std::string unprintableString = "{?}";
Phil Nash6a8e8ad2014-09-15 18:40:24 +01007936
Phil Nashab036682014-06-02 07:48:03 +01007937 namespace {
Phil Nash2f6371f2015-07-23 23:06:26 +01007938 const int hexThreshold = 255;
7939
Phil Nashab036682014-06-02 07:48:03 +01007940 struct Endianness {
7941 enum Arch { Big, Little };
7942
7943 static Arch which() {
7944 union _{
7945 int asInt;
7946 char asChar[sizeof (int)];
7947 } u;
7948
7949 u.asInt = 1;
7950 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
7951 }
7952 };
7953 }
7954
7955 std::string rawMemoryToString( const void *object, std::size_t size )
7956 {
7957 // Reverse order for little endian architectures
7958 int i = 0, end = static_cast<int>( size ), inc = 1;
7959 if( Endianness::which() == Endianness::Little ) {
7960 i = end-1;
7961 end = inc = -1;
7962 }
7963
7964 unsigned char const *bytes = static_cast<unsigned char const *>(object);
7965 std::ostringstream os;
7966 os << "0x" << std::setfill('0') << std::hex;
7967 for( ; i != end; i += inc )
7968 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
7969 return os.str();
7970 }
7971}
7972
Phil Nashaef6cd52014-04-23 07:10:10 +01007973std::string toString( std::string const& value ) {
7974 std::string s = value;
7975 if( getCurrentContext().getConfig()->showInvisibles() ) {
7976 for(size_t i = 0; i < s.size(); ++i ) {
7977 std::string subs;
7978 switch( s[i] ) {
7979 case '\n': subs = "\\n"; break;
7980 case '\t': subs = "\\t"; break;
7981 default: break;
7982 }
7983 if( !subs.empty() ) {
7984 s = s.substr( 0, i ) + subs + s.substr( i+1 );
7985 ++i;
7986 }
7987 }
7988 }
7989 return "\"" + s + "\"";
7990}
7991std::string toString( std::wstring const& value ) {
7992
7993 std::string s;
7994 s.reserve( value.size() );
7995 for(size_t i = 0; i < value.size(); ++i )
7996 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
Phil Nash13f98432014-12-12 08:11:18 +00007997 return Catch::toString( s );
Phil Nashaef6cd52014-04-23 07:10:10 +01007998}
7999
8000std::string toString( const char* const value ) {
8001 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8002}
8003
8004std::string toString( char* const value ) {
8005 return Catch::toString( static_cast<const char*>( value ) );
8006}
8007
Phil Nash544bf332014-08-20 08:09:32 +01008008std::string toString( const wchar_t* const value )
8009{
8010 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
8011}
8012
8013std::string toString( wchar_t* const value )
8014{
8015 return Catch::toString( static_cast<const wchar_t*>( value ) );
8016}
8017
Phil Nashaef6cd52014-04-23 07:10:10 +01008018std::string toString( int value ) {
8019 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008020 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008021 if( value > Detail::hexThreshold )
Phil Nashc51e8682015-05-21 06:16:15 +01008022 oss << " (0x" << std::hex << value << ")";
Phil Nashaef6cd52014-04-23 07:10:10 +01008023 return oss.str();
8024}
8025
8026std::string toString( unsigned long value ) {
8027 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008028 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008029 if( value > Detail::hexThreshold )
Phil Nashc51e8682015-05-21 06:16:15 +01008030 oss << " (0x" << std::hex << value << ")";
Phil Nashaef6cd52014-04-23 07:10:10 +01008031 return oss.str();
8032}
8033
8034std::string toString( unsigned int value ) {
Phil Nash13f98432014-12-12 08:11:18 +00008035 return Catch::toString( static_cast<unsigned long>( value ) );
Phil Nashaef6cd52014-04-23 07:10:10 +01008036}
8037
Phil Nash28c2e072014-07-09 19:22:49 +01008038template<typename T>
8039std::string fpToString( T value, int precision ) {
Phil Nashaef6cd52014-04-23 07:10:10 +01008040 std::ostringstream oss;
Phil Nash28c2e072014-07-09 19:22:49 +01008041 oss << std::setprecision( precision )
Phil Nashaef6cd52014-04-23 07:10:10 +01008042 << std::fixed
8043 << value;
8044 std::string d = oss.str();
8045 std::size_t i = d.find_last_not_of( '0' );
8046 if( i != std::string::npos && i != d.size()-1 ) {
8047 if( d[i] == '.' )
8048 i++;
8049 d = d.substr( 0, i+1 );
8050 }
8051 return d;
8052}
8053
Phil Nash28c2e072014-07-09 19:22:49 +01008054std::string toString( const double value ) {
8055 return fpToString( value, 10 );
8056}
8057std::string toString( const float value ) {
8058 return fpToString( value, 5 ) + "f";
8059}
8060
Phil Nashaef6cd52014-04-23 07:10:10 +01008061std::string toString( bool value ) {
8062 return value ? "true" : "false";
8063}
8064
8065std::string toString( char value ) {
8066 return value < ' '
8067 ? toString( static_cast<unsigned int>( value ) )
8068 : Detail::makeString( value );
8069}
8070
8071std::string toString( signed char value ) {
8072 return toString( static_cast<char>( value ) );
8073}
8074
8075std::string toString( unsigned char value ) {
8076 return toString( static_cast<char>( value ) );
8077}
8078
Phil Nash2f6371f2015-07-23 23:06:26 +01008079#ifdef CATCH_CONFIG_CPP11_LONG_LONG
8080std::string toString( long long value ) {
8081 std::ostringstream oss;
8082 oss << value;
8083 if( value > Detail::hexThreshold )
8084 oss << " (0x" << std::hex << value << ")";
8085 return oss.str();
8086}
8087std::string toString( unsigned long long value ) {
8088 std::ostringstream oss;
8089 oss << value;
8090 if( value > Detail::hexThreshold )
8091 oss << " (0x" << std::hex << value << ")";
8092 return oss.str();
8093}
8094#endif
8095
Phil Nashaef6cd52014-04-23 07:10:10 +01008096#ifdef CATCH_CONFIG_CPP11_NULLPTR
8097std::string toString( std::nullptr_t ) {
8098 return "nullptr";
8099}
8100#endif
8101
8102#ifdef __OBJC__
8103 std::string toString( NSString const * const& nsstring ) {
8104 if( !nsstring )
8105 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008106 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008107 }
8108 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8109 if( !nsstring )
8110 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008111 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008112 }
8113 std::string toString( NSObject* const& nsObject ) {
8114 return toString( [nsObject description] );
8115 }
8116#endif
8117
8118} // end namespace Catch
8119
Phil Nashab036682014-06-02 07:48:03 +01008120// #included from: catch_result_builder.hpp
8121#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8122
8123namespace Catch {
8124
Phil Nash93a842e2015-07-13 06:36:07 +01008125 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008126 return secondArg.empty() || secondArg == "\"\""
Phil Nash93a842e2015-07-13 06:36:07 +01008127 ? capturedExpression
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008128 : capturedExpression + ", " + secondArg;
Phil Nash93a842e2015-07-13 06:36:07 +01008129 }
Phil Nashab036682014-06-02 07:48:03 +01008130 ResultBuilder::ResultBuilder( char const* macroName,
8131 SourceLineInfo const& lineInfo,
8132 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01008133 ResultDisposition::Flags resultDisposition,
8134 char const* secondArg )
8135 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
Phil Nashab036682014-06-02 07:48:03 +01008136 m_shouldDebugBreak( false ),
8137 m_shouldThrow( false )
8138 {}
8139
8140 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
8141 m_data.resultType = result;
8142 return *this;
8143 }
8144 ResultBuilder& ResultBuilder::setResultType( bool result ) {
8145 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
8146 return *this;
8147 }
8148 ResultBuilder& ResultBuilder::setLhs( std::string const& lhs ) {
8149 m_exprComponents.lhs = lhs;
8150 return *this;
8151 }
8152 ResultBuilder& ResultBuilder::setRhs( std::string const& rhs ) {
8153 m_exprComponents.rhs = rhs;
8154 return *this;
8155 }
8156 ResultBuilder& ResultBuilder::setOp( std::string const& op ) {
8157 m_exprComponents.op = op;
8158 return *this;
8159 }
8160
8161 void ResultBuilder::endExpression() {
8162 m_exprComponents.testFalse = isFalseTest( m_assertionInfo.resultDisposition );
8163 captureExpression();
8164 }
8165
8166 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
8167 m_assertionInfo.resultDisposition = resultDisposition;
8168 m_stream.oss << Catch::translateActiveException();
8169 captureResult( ResultWas::ThrewException );
8170 }
8171
8172 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
8173 setResultType( resultType );
8174 captureExpression();
8175 }
Phil Nash93a842e2015-07-13 06:36:07 +01008176 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008177 if( expectedMessage.empty() )
8178 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
8179 else
8180 captureExpectedException( Matchers::Equals( expectedMessage ) );
8181 }
8182
8183 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
8184
Phil Nash93a842e2015-07-13 06:36:07 +01008185 assert( m_exprComponents.testFalse == false );
8186 AssertionResultData data = m_data;
8187 data.resultType = ResultWas::Ok;
8188 data.reconstructedExpression = m_assertionInfo.capturedExpression;
Phil Nash93a842e2015-07-13 06:36:07 +01008189
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008190 std::string actualMessage = Catch::translateActiveException();
8191 if( !matcher.match( actualMessage ) ) {
8192 data.resultType = ResultWas::ExpressionFailed;
8193 data.reconstructedExpression = actualMessage;
Phil Nash93a842e2015-07-13 06:36:07 +01008194 }
8195 AssertionResult result( m_assertionInfo, data );
8196 handleResult( result );
8197 }
Phil Nashab036682014-06-02 07:48:03 +01008198
8199 void ResultBuilder::captureExpression() {
8200 AssertionResult result = build();
Phil Nash93a842e2015-07-13 06:36:07 +01008201 handleResult( result );
8202 }
8203 void ResultBuilder::handleResult( AssertionResult const& result )
8204 {
Phil Nashab036682014-06-02 07:48:03 +01008205 getResultCapture().assertionEnded( result );
8206
8207 if( !result.isOk() ) {
8208 if( getCurrentContext().getConfig()->shouldDebugBreak() )
8209 m_shouldDebugBreak = true;
Phil Nash318c9362015-05-19 18:40:00 +01008210 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
Phil Nashab036682014-06-02 07:48:03 +01008211 m_shouldThrow = true;
8212 }
8213 }
8214 void ResultBuilder::react() {
8215 if( m_shouldThrow )
8216 throw Catch::TestFailureException();
8217 }
8218
8219 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
8220 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
8221
8222 AssertionResult ResultBuilder::build() const
8223 {
8224 assert( m_data.resultType != ResultWas::Unknown );
8225
8226 AssertionResultData data = m_data;
8227
8228 // Flip bool results if testFalse is set
8229 if( m_exprComponents.testFalse ) {
8230 if( data.resultType == ResultWas::Ok )
8231 data.resultType = ResultWas::ExpressionFailed;
8232 else if( data.resultType == ResultWas::ExpressionFailed )
8233 data.resultType = ResultWas::Ok;
8234 }
8235
8236 data.message = m_stream.oss.str();
8237 data.reconstructedExpression = reconstructExpression();
8238 if( m_exprComponents.testFalse ) {
8239 if( m_exprComponents.op == "" )
8240 data.reconstructedExpression = "!" + data.reconstructedExpression;
8241 else
8242 data.reconstructedExpression = "!(" + data.reconstructedExpression + ")";
8243 }
8244 return AssertionResult( m_assertionInfo, data );
8245 }
8246 std::string ResultBuilder::reconstructExpression() const {
8247 if( m_exprComponents.op == "" )
8248 return m_exprComponents.lhs.empty() ? m_assertionInfo.capturedExpression : m_exprComponents.op + m_exprComponents.lhs;
8249 else if( m_exprComponents.op == "matches" )
8250 return m_exprComponents.lhs + " " + m_exprComponents.rhs;
8251 else if( m_exprComponents.op != "!" ) {
8252 if( m_exprComponents.lhs.size() + m_exprComponents.rhs.size() < 40 &&
8253 m_exprComponents.lhs.find("\n") == std::string::npos &&
8254 m_exprComponents.rhs.find("\n") == std::string::npos )
8255 return m_exprComponents.lhs + " " + m_exprComponents.op + " " + m_exprComponents.rhs;
8256 else
8257 return m_exprComponents.lhs + "\n" + m_exprComponents.op + "\n" + m_exprComponents.rhs;
8258 }
8259 else
8260 return "{can't expand - use " + m_assertionInfo.macroName + "_FALSE( " + m_assertionInfo.capturedExpression.substr(1) + " ) instead of " + m_assertionInfo.macroName + "( " + m_assertionInfo.capturedExpression + " ) for better diagnostics}";
8261 }
8262
8263} // end namespace Catch
8264
Phil Nashacdd3b52014-06-30 07:35:36 +01008265// #included from: catch_tag_alias_registry.hpp
8266#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8267
8268// #included from: catch_tag_alias_registry.h
8269#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8270
8271#include <map>
8272
8273namespace Catch {
8274
8275 class TagAliasRegistry : public ITagAliasRegistry {
8276 public:
8277 virtual ~TagAliasRegistry();
8278 virtual Option<TagAlias> find( std::string const& alias ) const;
8279 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
8280 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
8281 static TagAliasRegistry& get();
8282
8283 private:
8284 std::map<std::string, TagAlias> m_registry;
8285 };
8286
8287} // end namespace Catch
8288
8289#include <map>
8290#include <iostream>
8291
8292namespace Catch {
8293
8294 TagAliasRegistry::~TagAliasRegistry() {}
8295
8296 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
8297 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8298 if( it != m_registry.end() )
8299 return it->second;
8300 else
8301 return Option<TagAlias>();
8302 }
8303
8304 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
8305 std::string expandedTestSpec = unexpandedTestSpec;
8306 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8307 it != itEnd;
8308 ++it ) {
8309 std::size_t pos = expandedTestSpec.find( it->first );
8310 if( pos != std::string::npos ) {
8311 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
8312 it->second.tag +
8313 expandedTestSpec.substr( pos + it->first.size() );
8314 }
8315 }
8316 return expandedTestSpec;
8317 }
8318
8319 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8320
8321 if( !startsWith( alias, "[@" ) || !endsWith( alias, "]" ) ) {
8322 std::ostringstream oss;
8323 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
8324 throw std::domain_error( oss.str().c_str() );
8325 }
8326 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
8327 std::ostringstream oss;
8328 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
8329 << "\tFirst seen at " << find(alias)->lineInfo << "\n"
8330 << "\tRedefined at " << lineInfo;
8331 throw std::domain_error( oss.str().c_str() );
8332 }
8333 }
8334
8335 TagAliasRegistry& TagAliasRegistry::get() {
8336 static TagAliasRegistry instance;
8337 return instance;
8338
8339 }
8340
8341 ITagAliasRegistry::~ITagAliasRegistry() {}
8342 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
8343
8344 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8345 try {
8346 TagAliasRegistry::get().add( alias, tag, lineInfo );
8347 }
8348 catch( std::exception& ex ) {
8349 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01008350 Catch::cerr() << ex.what() << std::endl;
Phil Nashacdd3b52014-06-30 07:35:36 +01008351 exit(1);
8352 }
8353 }
8354
8355} // end namespace Catch
8356
Phil Nashe73583d2015-08-07 17:30:34 +01008357// #included from: ../reporters/catch_reporter_multi.hpp
8358#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
8359
8360namespace Catch {
8361
8362class MultipleReporters : public SharedImpl<IStreamingReporter> {
8363 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
8364 Reporters m_reporters;
8365
8366public:
8367 void add( Ptr<IStreamingReporter> const& reporter ) {
8368 m_reporters.push_back( reporter );
8369 }
8370
8371public: // IStreamingReporter
8372
8373 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8374 return m_reporters[0]->getPreferences();
8375 }
8376
8377 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
8378 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8379 it != itEnd;
8380 ++it )
8381 (*it)->noMatchingTestCases( spec );
8382 }
8383
8384 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
8385 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8386 it != itEnd;
8387 ++it )
8388 (*it)->testRunStarting( testRunInfo );
8389 }
8390
8391 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
8392 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8393 it != itEnd;
8394 ++it )
8395 (*it)->testGroupStarting( groupInfo );
8396 }
8397
8398 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
8399 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8400 it != itEnd;
8401 ++it )
8402 (*it)->testCaseStarting( testInfo );
8403 }
8404
8405 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
8406 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8407 it != itEnd;
8408 ++it )
8409 (*it)->sectionStarting( sectionInfo );
8410 }
8411
8412 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
8413 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8414 it != itEnd;
8415 ++it )
8416 (*it)->assertionStarting( assertionInfo );
8417 }
8418
8419 // The return value indicates if the messages buffer should be cleared:
8420 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
8421 bool clearBuffer = false;
8422 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8423 it != itEnd;
8424 ++it )
8425 clearBuffer |= (*it)->assertionEnded( assertionStats );
8426 return clearBuffer;
8427 }
8428
8429 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
8430 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8431 it != itEnd;
8432 ++it )
8433 (*it)->sectionEnded( sectionStats );
8434 }
8435
8436 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
8437 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8438 it != itEnd;
8439 ++it )
8440 (*it)->testCaseEnded( testCaseStats );
8441 }
8442
8443 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
8444 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8445 it != itEnd;
8446 ++it )
8447 (*it)->testGroupEnded( testGroupStats );
8448 }
8449
8450 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
8451 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8452 it != itEnd;
8453 ++it )
8454 (*it)->testRunEnded( testRunStats );
8455 }
8456
8457 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
8458 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8459 it != itEnd;
8460 ++it )
8461 (*it)->skipTest( testInfo );
8462 }
8463};
8464
8465Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
8466 Ptr<IStreamingReporter> resultingReporter;
8467
8468 if( existingReporter ) {
8469 MultipleReporters* multi = dynamic_cast<MultipleReporters*>( existingReporter.get() );
8470 if( !multi ) {
8471 multi = new MultipleReporters;
8472 resultingReporter = Ptr<IStreamingReporter>( multi );
8473 if( existingReporter )
8474 multi->add( existingReporter );
8475 }
8476 else
8477 resultingReporter = existingReporter;
8478 multi->add( additionalReporter );
8479 }
8480 else
8481 resultingReporter = additionalReporter;
8482
8483 return resultingReporter;
8484}
8485
8486} // end namespace Catch
8487
Phil Nash3faa4122013-08-15 19:09:07 +01008488// #included from: ../reporters/catch_reporter_xml.hpp
8489#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01008490
Phil Nash3649fdf2013-12-03 18:53:55 +00008491// #included from: catch_reporter_bases.hpp
8492#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
8493
Phil Nashb7713942014-12-22 07:42:57 +00008494#include <cstring>
8495
Phil Nash3649fdf2013-12-03 18:53:55 +00008496namespace Catch {
8497
8498 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
8499
8500 StreamingReporterBase( ReporterConfig const& _config )
8501 : m_config( _config.fullConfig() ),
8502 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01008503 {
8504 m_reporterPrefs.shouldRedirectStdOut = false;
8505 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008506
Phil Nashe73583d2015-08-07 17:30:34 +01008507 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8508 return m_reporterPrefs;
8509 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008510
Phil Nashe73583d2015-08-07 17:30:34 +01008511 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
Phil Nash3649fdf2013-12-03 18:53:55 +00008512
Phil Nashe73583d2015-08-07 17:30:34 +01008513 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
8514
8515 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008516 currentTestRunInfo = _testRunInfo;
8517 }
Phil Nashe73583d2015-08-07 17:30:34 +01008518 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008519 currentGroupInfo = _groupInfo;
8520 }
8521
Phil Nashe73583d2015-08-07 17:30:34 +01008522 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008523 currentTestCaseInfo = _testInfo;
8524 }
Phil Nashe73583d2015-08-07 17:30:34 +01008525 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008526 m_sectionStack.push_back( _sectionInfo );
8527 }
8528
Phil Nashe73583d2015-08-07 17:30:34 +01008529 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008530 m_sectionStack.pop_back();
8531 }
Phil Nashe73583d2015-08-07 17:30:34 +01008532 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008533 currentTestCaseInfo.reset();
Phil Nash3649fdf2013-12-03 18:53:55 +00008534 }
Phil Nashe73583d2015-08-07 17:30:34 +01008535 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008536 currentGroupInfo.reset();
8537 }
Phil Nashe73583d2015-08-07 17:30:34 +01008538 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008539 currentTestCaseInfo.reset();
8540 currentGroupInfo.reset();
8541 currentTestRunInfo.reset();
8542 }
8543
Phil Nashe73583d2015-08-07 17:30:34 +01008544 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
Phil Nash92f08362014-12-22 20:18:05 +00008545 // Don't do anything with this by default.
8546 // It can optionally be overridden in the derived class.
8547 }
8548
Phil Nash7e346192015-11-03 08:00:43 +00008549 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00008550 std::ostream& stream;
8551
8552 LazyStat<TestRunInfo> currentTestRunInfo;
8553 LazyStat<GroupInfo> currentGroupInfo;
8554 LazyStat<TestCaseInfo> currentTestCaseInfo;
8555
8556 std::vector<SectionInfo> m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01008557 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00008558 };
8559
8560 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
8561 template<typename T, typename ChildNodeT>
8562 struct Node : SharedImpl<> {
8563 explicit Node( T const& _value ) : value( _value ) {}
8564 virtual ~Node() {}
8565
8566 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
8567 T value;
8568 ChildNodes children;
8569 };
8570 struct SectionNode : SharedImpl<> {
8571 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
8572 virtual ~SectionNode();
8573
8574 bool operator == ( SectionNode const& other ) const {
8575 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
8576 }
8577 bool operator == ( Ptr<SectionNode> const& other ) const {
8578 return operator==( *other );
8579 }
8580
8581 SectionStats stats;
8582 typedef std::vector<Ptr<SectionNode> > ChildSections;
8583 typedef std::vector<AssertionStats> Assertions;
8584 ChildSections childSections;
8585 Assertions assertions;
8586 std::string stdOut;
8587 std::string stdErr;
8588 };
Phil Nasheb760f62013-12-18 08:38:33 +00008589
8590 struct BySectionInfo {
8591 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
Phil Nash9241e432014-05-20 18:50:59 +01008592 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
Phil Nasheb760f62013-12-18 08:38:33 +00008593 bool operator() ( Ptr<SectionNode> const& node ) const {
8594 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
8595 }
8596 private:
Phil Nash9241e432014-05-20 18:50:59 +01008597 void operator=( BySectionInfo const& );
Phil Nasheb760f62013-12-18 08:38:33 +00008598 SectionInfo const& m_other;
8599 };
Phil Nash3649fdf2013-12-03 18:53:55 +00008600
8601 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
8602 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
8603 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
8604
8605 CumulativeReporterBase( ReporterConfig const& _config )
8606 : m_config( _config.fullConfig() ),
8607 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01008608 {
8609 m_reporterPrefs.shouldRedirectStdOut = false;
8610 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008611 ~CumulativeReporterBase();
8612
Phil Nashe73583d2015-08-07 17:30:34 +01008613 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8614 return m_reporterPrefs;
8615 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008616
Phil Nashe73583d2015-08-07 17:30:34 +01008617 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
8618 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00008619
Phil Nashe73583d2015-08-07 17:30:34 +01008620 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
8621
8622 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008623 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
8624 Ptr<SectionNode> node;
8625 if( m_sectionStack.empty() ) {
8626 if( !m_rootSection )
8627 m_rootSection = new SectionNode( incompleteStats );
8628 node = m_rootSection;
8629 }
8630 else {
8631 SectionNode& parentNode = *m_sectionStack.back();
8632 SectionNode::ChildSections::const_iterator it =
Phil Nasheb760f62013-12-18 08:38:33 +00008633 std::find_if( parentNode.childSections.begin(),
8634 parentNode.childSections.end(),
8635 BySectionInfo( sectionInfo ) );
Phil Nash3649fdf2013-12-03 18:53:55 +00008636 if( it == parentNode.childSections.end() ) {
8637 node = new SectionNode( incompleteStats );
8638 parentNode.childSections.push_back( node );
8639 }
8640 else
8641 node = *it;
8642 }
8643 m_sectionStack.push_back( node );
8644 m_deepestSection = node;
8645 }
8646
Phil Nashe73583d2015-08-07 17:30:34 +01008647 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00008648
8649 virtual bool assertionEnded( AssertionStats const& assertionStats ) {
8650 assert( !m_sectionStack.empty() );
8651 SectionNode& sectionNode = *m_sectionStack.back();
8652 sectionNode.assertions.push_back( assertionStats );
8653 return true;
8654 }
Phil Nashe73583d2015-08-07 17:30:34 +01008655 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008656 assert( !m_sectionStack.empty() );
8657 SectionNode& node = *m_sectionStack.back();
8658 node.stats = sectionStats;
8659 m_sectionStack.pop_back();
8660 }
Phil Nashe73583d2015-08-07 17:30:34 +01008661 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008662 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
8663 assert( m_sectionStack.size() == 0 );
8664 node->children.push_back( m_rootSection );
8665 m_testCases.push_back( node );
8666 m_rootSection.reset();
8667
8668 assert( m_deepestSection );
8669 m_deepestSection->stdOut = testCaseStats.stdOut;
8670 m_deepestSection->stdErr = testCaseStats.stdErr;
8671 }
Phil Nashe73583d2015-08-07 17:30:34 +01008672 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008673 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
8674 node->children.swap( m_testCases );
8675 m_testGroups.push_back( node );
8676 }
Phil Nashe73583d2015-08-07 17:30:34 +01008677 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00008678 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
8679 node->children.swap( m_testGroups );
8680 m_testRuns.push_back( node );
Phil Nasha6d74bd2013-12-11 08:28:15 +00008681 testRunEndedCumulative();
Phil Nash3649fdf2013-12-03 18:53:55 +00008682 }
Phil Nasha6d74bd2013-12-11 08:28:15 +00008683 virtual void testRunEndedCumulative() = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00008684
Phil Nashe73583d2015-08-07 17:30:34 +01008685 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
Phil Nash92f08362014-12-22 20:18:05 +00008686
Phil Nash7e346192015-11-03 08:00:43 +00008687 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00008688 std::ostream& stream;
8689 std::vector<AssertionStats> m_assertions;
8690 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
8691 std::vector<Ptr<TestCaseNode> > m_testCases;
8692 std::vector<Ptr<TestGroupNode> > m_testGroups;
8693
8694 std::vector<Ptr<TestRunNode> > m_testRuns;
8695
8696 Ptr<SectionNode> m_rootSection;
8697 Ptr<SectionNode> m_deepestSection;
8698 std::vector<Ptr<SectionNode> > m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01008699 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00008700
8701 };
8702
Phil Nash576aff62014-12-21 00:21:23 +00008703 template<char C>
8704 char const* getLineOfChars() {
8705 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
8706 if( !*line ) {
8707 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
8708 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
8709 }
8710 return line;
8711 }
8712
Phil Nashe73583d2015-08-07 17:30:34 +01008713 struct TestEventListenerBase : StreamingReporterBase {
8714 TestEventListenerBase( ReporterConfig const& _config )
8715 : StreamingReporterBase( _config )
8716 {}
8717
8718 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash08844e72015-11-05 18:52:18 +00008719 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01008720 return false;
8721 }
8722 };
8723
Phil Nash3649fdf2013-12-03 18:53:55 +00008724} // end namespace Catch
8725
Phil Nash56d5c422012-08-23 20:08:50 +01008726// #included from: ../internal/catch_reporter_registrars.hpp
8727#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
8728
8729namespace Catch {
8730
8731 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00008732 class LegacyReporterRegistrar {
8733
8734 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01008735 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01008736 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00008737 }
8738
8739 virtual std::string getDescription() const {
8740 return T::getDescription();
8741 }
8742 };
8743
8744 public:
8745
Phil Nash8defc712013-04-24 19:10:02 +01008746 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008747 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
8748 }
8749 };
8750
8751 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01008752 class ReporterRegistrar {
8753
Phil Nashe73583d2015-08-07 17:30:34 +01008754 class ReporterFactory : public SharedImpl<IReporterFactory> {
Phil Nash56d5c422012-08-23 20:08:50 +01008755
Phil Nasha1fbfea2012-12-01 23:57:18 +00008756 // *** Please Note ***:
8757 // - If you end up here looking at a compiler error because it's trying to register
8758 // your custom reporter class be aware that the native reporter interface has changed
8759 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
8760 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
8761 // However please consider updating to the new interface as the old one is now
8762 // deprecated and will probably be removed quite soon!
8763 // Please contact me via github if you have any questions at all about this.
8764 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
8765 // no idea who is actually using custom reporters at all (possibly no-one!).
8766 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01008767 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01008768 return new T( config );
8769 }
8770
8771 virtual std::string getDescription() const {
8772 return T::getDescription();
8773 }
8774 };
8775
8776 public:
8777
Phil Nash8defc712013-04-24 19:10:02 +01008778 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008779 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
8780 }
8781 };
Phil Nashe73583d2015-08-07 17:30:34 +01008782
8783 template<typename T>
8784 class ListenerRegistrar {
8785
8786 class ListenerFactory : public SharedImpl<IReporterFactory> {
8787
8788 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
8789 return new T( config );
8790 }
8791 virtual std::string getDescription() const {
8792 return "";
8793 }
8794 };
8795
8796 public:
8797
8798 ListenerRegistrar() {
8799 getMutableRegistryHub().registerListener( new ListenerFactory() );
8800 }
8801 };
Phil Nash56d5c422012-08-23 20:08:50 +01008802}
8803
Phil Nasha1fbfea2012-12-01 23:57:18 +00008804#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01008805 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nashe73583d2015-08-07 17:30:34 +01008806
Phil Nash56d5c422012-08-23 20:08:50 +01008807#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01008808 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01008809
Phil Nashe73583d2015-08-07 17:30:34 +01008810#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
8811 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
8812
Phil Nash56d5c422012-08-23 20:08:50 +01008813// #included from: ../internal/catch_xmlwriter.hpp
8814#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
8815
8816#include <sstream>
8817#include <string>
8818#include <vector>
Phil Nash2f6371f2015-07-23 23:06:26 +01008819#include <iomanip>
Phil Nash56d5c422012-08-23 20:08:50 +01008820
8821namespace Catch {
8822
Phil Nash2f6371f2015-07-23 23:06:26 +01008823 class XmlEncode {
8824 public:
8825 enum ForWhat { ForTextNodes, ForAttributes };
8826
8827 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
8828 : m_str( str ),
8829 m_forWhat( forWhat )
8830 {}
8831
8832 void encodeTo( std::ostream& os ) const {
8833
8834 // Apostrophe escaping not necessary if we always use " to write attributes
8835 // (see: http://www.w3.org/TR/xml/#syntax)
8836
8837 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
8838 char c = m_str[i];
8839 switch( c ) {
8840 case '<': os << "&lt;"; break;
8841 case '&': os << "&amp;"; break;
8842
8843 case '>':
8844 // See: http://www.w3.org/TR/xml/#syntax
8845 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
8846 os << "&gt;";
8847 else
8848 os << c;
8849 break;
8850
8851 case '\"':
8852 if( m_forWhat == ForAttributes )
8853 os << "&quot;";
8854 else
8855 os << c;
8856 break;
8857
8858 default:
8859 // Escape control chars - based on contribution by @espenalb in PR #465
8860 if ( ( c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
8861 os << "&#x" << std::uppercase << std::hex << static_cast<int>( c );
8862 else
8863 os << c;
8864 }
8865 }
8866 }
8867
8868 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
8869 xmlEncode.encodeTo( os );
8870 return os;
8871 }
8872
8873 private:
8874 std::string m_str;
8875 ForWhat m_forWhat;
8876 };
8877
Phil Nash56d5c422012-08-23 20:08:50 +01008878 class XmlWriter {
8879 public:
8880
8881 class ScopedElement {
8882 public:
8883 ScopedElement( XmlWriter* writer )
8884 : m_writer( writer )
8885 {}
8886
Phil Nash8defc712013-04-24 19:10:02 +01008887 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01008888 : m_writer( other.m_writer ){
Phil Nashb971fe72015-07-02 08:21:38 +01008889 other.m_writer = CATCH_NULL;
Phil Nash56d5c422012-08-23 20:08:50 +01008890 }
8891
8892 ~ScopedElement() {
8893 if( m_writer )
8894 m_writer->endElement();
8895 }
8896
Phil Nash8defc712013-04-24 19:10:02 +01008897 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008898 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01008899 return *this;
8900 }
8901
8902 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01008903 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008904 m_writer->writeAttribute( name, attribute );
8905 return *this;
8906 }
8907
8908 private:
8909 mutable XmlWriter* m_writer;
8910 };
8911
8912 XmlWriter()
8913 : m_tagIsOpen( false ),
8914 m_needsNewline( false ),
Phil Nash383d7c02014-10-02 19:08:19 +01008915 m_os( &Catch::cout() )
Phil Nash56d5c422012-08-23 20:08:50 +01008916 {}
8917
8918 XmlWriter( std::ostream& os )
8919 : m_tagIsOpen( false ),
8920 m_needsNewline( false ),
8921 m_os( &os )
8922 {}
8923
8924 ~XmlWriter() {
8925 while( !m_tags.empty() )
8926 endElement();
8927 }
8928
Phil Nash8defc712013-04-24 19:10:02 +01008929 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008930 ensureTagClosed();
8931 newlineIfNecessary();
8932 stream() << m_indent << "<" << name;
8933 m_tags.push_back( name );
8934 m_indent += " ";
8935 m_tagIsOpen = true;
8936 return *this;
8937 }
8938
Phil Nash8defc712013-04-24 19:10:02 +01008939 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008940 ScopedElement scoped( this );
8941 startElement( name );
8942 return scoped;
8943 }
8944
8945 XmlWriter& endElement() {
8946 newlineIfNecessary();
8947 m_indent = m_indent.substr( 0, m_indent.size()-2 );
8948 if( m_tagIsOpen ) {
8949 stream() << "/>\n";
8950 m_tagIsOpen = false;
8951 }
8952 else {
8953 stream() << m_indent << "</" << m_tags.back() << ">\n";
8954 }
8955 m_tags.pop_back();
8956 return *this;
8957 }
8958
Phil Nash8defc712013-04-24 19:10:02 +01008959 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01008960 if( !name.empty() && !attribute.empty() )
8961 stream() << " " << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << "\"";
Phil Nash56d5c422012-08-23 20:08:50 +01008962 return *this;
8963 }
8964
Phil Nash8defc712013-04-24 19:10:02 +01008965 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008966 stream() << " " << name << "=\"" << ( attribute ? "true" : "false" ) << "\"";
8967 return *this;
8968 }
8969
8970 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01008971 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01008972 std::ostringstream oss;
8973 oss << attribute;
8974 return writeAttribute( name, oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01008975 }
8976
Phil Nash8defc712013-04-24 19:10:02 +01008977 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008978 if( !text.empty() ){
8979 bool tagWasOpen = m_tagIsOpen;
8980 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00008981 if( tagWasOpen && indent )
Phil Nash56d5c422012-08-23 20:08:50 +01008982 stream() << m_indent;
Phil Nash2f6371f2015-07-23 23:06:26 +01008983 stream() << XmlEncode( text );
Phil Nash56d5c422012-08-23 20:08:50 +01008984 m_needsNewline = true;
8985 }
8986 return *this;
8987 }
8988
Phil Nash8defc712013-04-24 19:10:02 +01008989 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01008990 ensureTagClosed();
8991 stream() << m_indent << "<!--" << text << "-->";
8992 m_needsNewline = true;
8993 return *this;
8994 }
8995
8996 XmlWriter& writeBlankLine() {
8997 ensureTagClosed();
8998 stream() << "\n";
8999 return *this;
9000 }
9001
Phil Nash9241e432014-05-20 18:50:59 +01009002 void setStream( std::ostream& os ) {
9003 m_os = &os;
9004 }
9005
Phil Nash56d5c422012-08-23 20:08:50 +01009006 private:
Phil Nash9241e432014-05-20 18:50:59 +01009007 XmlWriter( XmlWriter const& );
9008 void operator=( XmlWriter const& );
Phil Nash56d5c422012-08-23 20:08:50 +01009009
9010 std::ostream& stream() {
9011 return *m_os;
9012 }
9013
9014 void ensureTagClosed() {
9015 if( m_tagIsOpen ) {
9016 stream() << ">\n";
9017 m_tagIsOpen = false;
9018 }
9019 }
9020
9021 void newlineIfNecessary() {
9022 if( m_needsNewline ) {
9023 stream() << "\n";
9024 m_needsNewline = false;
9025 }
9026 }
9027
Phil Nash56d5c422012-08-23 20:08:50 +01009028 bool m_tagIsOpen;
9029 bool m_needsNewline;
9030 std::vector<std::string> m_tags;
9031 std::string m_indent;
9032 std::ostream* m_os;
9033 };
9034
9035}
Phil Nash2f6371f2015-07-23 23:06:26 +01009036// #included from: catch_reenable_warnings.h
9037
9038#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9039
9040#ifdef __clang__
9041# ifdef __ICC // icpc defines the __clang__ macro
9042# pragma warning(pop)
9043# else
9044# pragma clang diagnostic pop
9045# endif
9046#elif defined __GNUC__
9047# pragma GCC diagnostic pop
9048#endif
9049
9050
Phil Nash56d5c422012-08-23 20:08:50 +01009051namespace Catch {
Phil Nashd76e0812014-12-30 18:26:07 +00009052 class XmlReporter : public StreamingReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01009053 public:
Phil Nashd76e0812014-12-30 18:26:07 +00009054 XmlReporter( ReporterConfig const& _config )
9055 : StreamingReporterBase( _config ),
9056 m_sectionDepth( 0 )
Phil Nashe73583d2015-08-07 17:30:34 +01009057 {
9058 m_reporterPrefs.shouldRedirectStdOut = true;
9059 }
Phil Nashd76e0812014-12-30 18:26:07 +00009060
Phil Nashe73583d2015-08-07 17:30:34 +01009061 virtual ~XmlReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +01009062
9063 static std::string getDescription() {
9064 return "Reports test results as an XML document";
9065 }
Phil Nash56d5c422012-08-23 20:08:50 +01009066
Phil Nashd76e0812014-12-30 18:26:07 +00009067 public: // StreamingReporterBase
Phil Nash56d5c422012-08-23 20:08:50 +01009068
Phil Nashe73583d2015-08-07 17:30:34 +01009069 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009070 StreamingReporterBase::noMatchingTestCases( s );
9071 }
9072
Phil Nashe73583d2015-08-07 17:30:34 +01009073 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009074 StreamingReporterBase::testRunStarting( testInfo );
9075 m_xml.setStream( stream );
Phil Nash56d5c422012-08-23 20:08:50 +01009076 m_xml.startElement( "Catch" );
Phil Nashd76e0812014-12-30 18:26:07 +00009077 if( !m_config->name().empty() )
9078 m_xml.writeAttribute( "name", m_config->name() );
Phil Nash56d5c422012-08-23 20:08:50 +01009079 }
9080
Phil Nashe73583d2015-08-07 17:30:34 +01009081 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009082 StreamingReporterBase::testGroupStarting( groupInfo );
Phil Nash56d5c422012-08-23 20:08:50 +01009083 m_xml.startElement( "Group" )
Phil Nashd76e0812014-12-30 18:26:07 +00009084 .writeAttribute( "name", groupInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +01009085 }
9086
Phil Nashe73583d2015-08-07 17:30:34 +01009087 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009088 StreamingReporterBase::testCaseStarting(testInfo);
9089 m_xml.startElement( "TestCase" ).writeAttribute( "name", trim( testInfo.name ) );
9090
9091 if ( m_config->showDurations() == ShowDurations::Always )
9092 m_testCaseTimer.start();
Phil Nash56d5c422012-08-23 20:08:50 +01009093 }
9094
Phil Nashe73583d2015-08-07 17:30:34 +01009095 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009096 StreamingReporterBase::sectionStarting( sectionInfo );
Phil Nash8a52a392013-07-25 08:12:03 +01009097 if( m_sectionDepth++ > 0 ) {
9098 m_xml.startElement( "Section" )
Phil Nashd76e0812014-12-30 18:26:07 +00009099 .writeAttribute( "name", trim( sectionInfo.name ) )
9100 .writeAttribute( "description", sectionInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01009101 }
Phil Nash56d5c422012-08-23 20:08:50 +01009102 }
9103
Phil Nashe73583d2015-08-07 17:30:34 +01009104 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
Phil Nash56d5c422012-08-23 20:08:50 +01009105
Phil Nashe73583d2015-08-07 17:30:34 +01009106 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009107 const AssertionResult& assertionResult = assertionStats.assertionResult;
Phil Nash56d5c422012-08-23 20:08:50 +01009108
Phil Nashd76e0812014-12-30 18:26:07 +00009109 // Print any info messages in <Info> tags.
9110 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
9111 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
9112 it != itEnd;
9113 ++it ) {
9114 if( it->type == ResultWas::Info ) {
9115 m_xml.scopedElement( "Info" )
9116 .writeText( it->message );
9117 } else if ( it->type == ResultWas::Warning ) {
9118 m_xml.scopedElement( "Warning" )
9119 .writeText( it->message );
9120 }
9121 }
9122 }
9123
9124 // Drop out if result was successful but we're not printing them.
9125 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
9126 return true;
9127
9128 // Print the expression if there is one.
Phil Nashce612bf2012-11-01 08:27:09 +00009129 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009130 m_xml.startElement( "Expression" )
Phil Nash90a35942012-11-13 22:04:29 +00009131 .writeAttribute( "success", assertionResult.succeeded() )
Phil Nashd76e0812014-12-30 18:26:07 +00009132 .writeAttribute( "type", assertionResult.getTestMacroName() )
Phil Nashce612bf2012-11-01 08:27:09 +00009133 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9134 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01009135
9136 m_xml.scopedElement( "Original" )
Phil Nashce612bf2012-11-01 08:27:09 +00009137 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009138 m_xml.scopedElement( "Expanded" )
Phil Nashce612bf2012-11-01 08:27:09 +00009139 .writeText( assertionResult.getExpandedExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009140 }
9141
Phil Nashd76e0812014-12-30 18:26:07 +00009142 // And... Print a result applicable to each result type.
Phil Nashce612bf2012-11-01 08:27:09 +00009143 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009144 case ResultWas::ThrewException:
9145 m_xml.scopedElement( "Exception" )
Phil Nashce612bf2012-11-01 08:27:09 +00009146 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9147 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9148 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009149 break;
Phil Nash93b61e12014-08-22 19:35:41 +01009150 case ResultWas::FatalErrorCondition:
9151 m_xml.scopedElement( "Fatal Error Condition" )
9152 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9153 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9154 .writeText( assertionResult.getMessage() );
Phil Nash93b61e12014-08-22 19:35:41 +01009155 break;
Phil Nash56d5c422012-08-23 20:08:50 +01009156 case ResultWas::Info:
9157 m_xml.scopedElement( "Info" )
Phil Nashce612bf2012-11-01 08:27:09 +00009158 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009159 break;
9160 case ResultWas::Warning:
Phil Nashd76e0812014-12-30 18:26:07 +00009161 // Warning will already have been written
Phil Nash56d5c422012-08-23 20:08:50 +01009162 break;
9163 case ResultWas::ExplicitFailure:
9164 m_xml.scopedElement( "Failure" )
Phil Nashce612bf2012-11-01 08:27:09 +00009165 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009166 break;
Phil Nashd76e0812014-12-30 18:26:07 +00009167 default:
Phil Nash56d5c422012-08-23 20:08:50 +01009168 break;
9169 }
Phil Nashd76e0812014-12-30 18:26:07 +00009170
Phil Nashce612bf2012-11-01 08:27:09 +00009171 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01009172 m_xml.endElement();
Phil Nashd76e0812014-12-30 18:26:07 +00009173
9174 return true;
Phil Nash56d5c422012-08-23 20:08:50 +01009175 }
9176
Phil Nashe73583d2015-08-07 17:30:34 +01009177 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009178 StreamingReporterBase::sectionEnded( sectionStats );
9179 if( --m_sectionDepth > 0 ) {
9180 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
9181 e.writeAttribute( "successes", sectionStats.assertions.passed );
9182 e.writeAttribute( "failures", sectionStats.assertions.failed );
9183 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
9184
9185 if ( m_config->showDurations() == ShowDurations::Always )
9186 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
9187
9188 m_xml.endElement();
9189 }
Phil Nash56d5c422012-08-23 20:08:50 +01009190 }
9191
Phil Nashe73583d2015-08-07 17:30:34 +01009192 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009193 StreamingReporterBase::testCaseEnded( testCaseStats );
9194 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
9195 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
9196
9197 if ( m_config->showDurations() == ShowDurations::Always )
9198 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
9199
9200 m_xml.endElement();
9201 }
9202
Phil Nashe73583d2015-08-07 17:30:34 +01009203 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009204 StreamingReporterBase::testGroupEnded( testGroupStats );
9205 // TODO: Check testGroupStats.aborting and act accordingly.
9206 m_xml.scopedElement( "OverallResults" )
9207 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
9208 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
9209 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
9210 m_xml.endElement();
9211 }
9212
Phil Nashe73583d2015-08-07 17:30:34 +01009213 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009214 StreamingReporterBase::testRunEnded( testRunStats );
9215 m_xml.scopedElement( "OverallResults" )
9216 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
9217 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
9218 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
Phil Nash56d5c422012-08-23 20:08:50 +01009219 m_xml.endElement();
9220 }
9221
9222 private:
Phil Nashd76e0812014-12-30 18:26:07 +00009223 Timer m_testCaseTimer;
Phil Nash56d5c422012-08-23 20:08:50 +01009224 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +01009225 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +01009226 };
9227
Phil Nashd76e0812014-12-30 18:26:07 +00009228 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
9229
Phil Nash56d5c422012-08-23 20:08:50 +01009230} // end namespace Catch
9231
9232// #included from: ../reporters/catch_reporter_junit.hpp
9233#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
9234
Phil Nashf276a052012-12-02 00:05:51 +00009235#include <assert.h>
9236
Phil Nash56d5c422012-08-23 20:08:50 +01009237namespace Catch {
9238
Phil Nashaa7123b2013-08-15 19:01:00 +01009239 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01009240 public:
Phil Nashaa7123b2013-08-15 19:01:00 +01009241 JunitReporter( ReporterConfig const& _config )
9242 : CumulativeReporterBase( _config ),
9243 xml( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009244 {
9245 m_reporterPrefs.shouldRedirectStdOut = true;
9246 }
Phil Nashaa7123b2013-08-15 19:01:00 +01009247
Phil Nashe73583d2015-08-07 17:30:34 +01009248 virtual ~JunitReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +01009249
9250 static std::string getDescription() {
9251 return "Reports test results in an XML format that looks like Ant's junitreport target";
9252 }
9253
Phil Nashe73583d2015-08-07 17:30:34 +01009254 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
Phil Nash56d5c422012-08-23 20:08:50 +01009255
Phil Nashe73583d2015-08-07 17:30:34 +01009256 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009257 CumulativeReporterBase::testRunStarting( runInfo );
9258 xml.startElement( "testsuites" );
9259 }
Phil Nash56d5c422012-08-23 20:08:50 +01009260
Phil Nashe73583d2015-08-07 17:30:34 +01009261 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009262 suiteTimer.start();
9263 stdOutForSuite.str("");
9264 stdErrForSuite.str("");
9265 unexpectedExceptions = 0;
9266 CumulativeReporterBase::testGroupStarting( groupInfo );
9267 }
9268
Phil Nashe73583d2015-08-07 17:30:34 +01009269 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009270 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
9271 unexpectedExceptions++;
9272 return CumulativeReporterBase::assertionEnded( assertionStats );
9273 }
9274
Phil Nashe73583d2015-08-07 17:30:34 +01009275 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009276 stdOutForSuite << testCaseStats.stdOut;
9277 stdErrForSuite << testCaseStats.stdErr;
9278 CumulativeReporterBase::testCaseEnded( testCaseStats );
9279 }
9280
Phil Nashe73583d2015-08-07 17:30:34 +01009281 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009282 double suiteTime = suiteTimer.getElapsedSeconds();
9283 CumulativeReporterBase::testGroupEnded( testGroupStats );
9284 writeGroup( *m_testGroups.back(), suiteTime );
9285 }
9286
Phil Nashe73583d2015-08-07 17:30:34 +01009287 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009288 xml.endElement();
9289 }
9290
9291 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
9292 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
9293 TestGroupStats const& stats = groupNode.value;
9294 xml.writeAttribute( "name", stats.groupInfo.name );
9295 xml.writeAttribute( "errors", unexpectedExceptions );
9296 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
9297 xml.writeAttribute( "tests", stats.totals.assertions.total() );
9298 xml.writeAttribute( "hostname", "tbd" ); // !TBD
9299 if( m_config->showDurations() == ShowDurations::Never )
9300 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +00009301 else
Phil Nashaa7123b2013-08-15 19:01:00 +01009302 xml.writeAttribute( "time", suiteTime );
9303 xml.writeAttribute( "timestamp", "tbd" ); // !TBD
9304
9305 // Write test cases
9306 for( TestGroupNode::ChildNodes::const_iterator
9307 it = groupNode.children.begin(), itEnd = groupNode.children.end();
9308 it != itEnd;
9309 ++it )
9310 writeTestCase( **it );
9311
9312 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
9313 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +01009314 }
9315
Phil Nashaa7123b2013-08-15 19:01:00 +01009316 void writeTestCase( TestCaseNode const& testCaseNode ) {
9317 TestCaseStats const& stats = testCaseNode.value;
9318
9319 // All test cases have exactly one section - which represents the
9320 // test case itself. That section may have 0-n nested sections
9321 assert( testCaseNode.children.size() == 1 );
9322 SectionNode const& rootSection = *testCaseNode.children.front();
9323
9324 std::string className = stats.testInfo.className;
9325
9326 if( className.empty() ) {
9327 if( rootSection.childSections.empty() )
9328 className = "global";
9329 }
9330 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +01009331 }
9332
Phil Nashaa7123b2013-08-15 19:01:00 +01009333 void writeSection( std::string const& className,
9334 std::string const& rootName,
9335 SectionNode const& sectionNode ) {
9336 std::string name = trim( sectionNode.stats.sectionInfo.name );
9337 if( !rootName.empty() )
9338 name = rootName + "/" + name;
Phil Nash56d5c422012-08-23 20:08:50 +01009339
Phil Nashaa7123b2013-08-15 19:01:00 +01009340 if( !sectionNode.assertions.empty() ||
9341 !sectionNode.stdOut.empty() ||
9342 !sectionNode.stdErr.empty() ) {
9343 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
9344 if( className.empty() ) {
9345 xml.writeAttribute( "classname", name );
9346 xml.writeAttribute( "name", "root" );
9347 }
9348 else {
9349 xml.writeAttribute( "classname", className );
9350 xml.writeAttribute( "name", name );
9351 }
Phil Nash13f98432014-12-12 08:11:18 +00009352 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +01009353
Phil Nashaa7123b2013-08-15 19:01:00 +01009354 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +01009355
Phil Nashaa7123b2013-08-15 19:01:00 +01009356 if( !sectionNode.stdOut.empty() )
9357 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
9358 if( !sectionNode.stdErr.empty() )
9359 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
9360 }
9361 for( SectionNode::ChildSections::const_iterator
9362 it = sectionNode.childSections.begin(),
9363 itEnd = sectionNode.childSections.end();
9364 it != itEnd;
9365 ++it )
9366 if( className.empty() )
9367 writeSection( name, "", **it );
9368 else
9369 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +01009370 }
9371
Phil Nashaa7123b2013-08-15 19:01:00 +01009372 void writeAssertions( SectionNode const& sectionNode ) {
9373 for( SectionNode::Assertions::const_iterator
9374 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
9375 it != itEnd;
9376 ++it )
9377 writeAssertion( *it );
9378 }
9379 void writeAssertion( AssertionStats const& stats ) {
9380 AssertionResult const& result = stats.assertionResult;
9381 if( !result.isOk() ) {
9382 std::string elementName;
9383 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009384 case ResultWas::ThrewException:
Phil Nash93b61e12014-08-22 19:35:41 +01009385 case ResultWas::FatalErrorCondition:
Phil Nashaa7123b2013-08-15 19:01:00 +01009386 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +01009387 break;
9388 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +01009389 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01009390 break;
9391 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +01009392 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +01009393 break;
Phil Nash243f2d22013-04-12 10:43:06 +01009394 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +01009395 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +01009396 break;
Phil Nashaa7123b2013-08-15 19:01:00 +01009397
9398 // We should never see these here:
9399 case ResultWas::Info:
9400 case ResultWas::Warning:
9401 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +01009402 case ResultWas::Unknown:
9403 case ResultWas::FailureBit:
9404 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +01009405 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +01009406 break;
9407 }
Phil Nashaa7123b2013-08-15 19:01:00 +01009408
9409 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
9410
9411 xml.writeAttribute( "message", result.getExpandedExpression() );
9412 xml.writeAttribute( "type", result.getTestMacroName() );
9413
9414 std::ostringstream oss;
9415 if( !result.getMessage().empty() )
9416 oss << result.getMessage() << "\n";
9417 for( std::vector<MessageInfo>::const_iterator
9418 it = stats.infoMessages.begin(),
9419 itEnd = stats.infoMessages.end();
9420 it != itEnd;
9421 ++it )
9422 if( it->type == ResultWas::Info )
9423 oss << it->message << "\n";
9424
9425 oss << "at " << result.getSourceInfo();
9426 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +01009427 }
9428 }
9429
Phil Nashaa7123b2013-08-15 19:01:00 +01009430 XmlWriter xml;
9431 Timer suiteTimer;
9432 std::ostringstream stdOutForSuite;
9433 std::ostringstream stdErrForSuite;
9434 unsigned int unexpectedExceptions;
Phil Nash56d5c422012-08-23 20:08:50 +01009435 };
9436
Phil Nashaa7123b2013-08-15 19:01:00 +01009437 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
9438
Phil Nash56d5c422012-08-23 20:08:50 +01009439} // end namespace Catch
9440
Phil Nashff03cdf2012-12-06 08:44:51 +00009441// #included from: ../reporters/catch_reporter_console.hpp
9442#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
9443
9444namespace Catch {
9445
Phil Nash2e7d9662013-01-16 09:44:43 +00009446 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +00009447 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +00009448 : StreamingReporterBase( _config ),
Phil Nash08e52962014-07-03 19:08:44 +01009449 m_headerPrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +00009450 {}
9451
Phil Nashe73583d2015-08-07 17:30:34 +01009452 virtual ~ConsoleReporter() CATCH_OVERRIDE;
Phil Nashff03cdf2012-12-06 08:44:51 +00009453 static std::string getDescription() {
9454 return "Reports test results as plain lines of text";
9455 }
Phil Nashff03cdf2012-12-06 08:44:51 +00009456
Phil Nashe73583d2015-08-07 17:30:34 +01009457 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
Phil Nash37186a12013-03-13 12:19:30 +00009458 stream << "No test cases matched '" << spec << "'" << std::endl;
9459 }
9460
Phil Nashe73583d2015-08-07 17:30:34 +01009461 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
Phil Nashff03cdf2012-12-06 08:44:51 +00009462 }
Phil Nashbcad0932012-12-10 08:54:57 +00009463
Phil Nashe73583d2015-08-07 17:30:34 +01009464 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +00009465 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +00009466
Phil Nash8d44f2d2013-11-13 08:10:45 +00009467 bool printInfoMessages = true;
9468
Phil Nashbcad0932012-12-10 08:54:57 +00009469 // Drop out if result was successful and we're not printing those
Phil Nash8d44f2d2013-11-13 08:10:45 +00009470 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9471 if( result.getResultType() != ResultWas::Warning )
9472 return false;
9473 printInfoMessages = false;
9474 }
Phil Nashbcad0932012-12-10 08:54:57 +00009475
9476 lazyPrint();
9477
Phil Nash8d44f2d2013-11-13 08:10:45 +00009478 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
Phil Nashe4756452013-01-26 20:18:30 +00009479 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +00009480 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +01009481 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +00009482 }
9483
Phil Nashe73583d2015-08-07 17:30:34 +01009484 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nasha04981b2013-03-08 09:30:25 +00009485 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +00009486 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +00009487 }
Phil Nashe73583d2015-08-07 17:30:34 +01009488 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +00009489 if( _sectionStats.missingAssertions ) {
9490 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +01009491 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +01009492 if( m_sectionStack.size() > 1 )
9493 stream << "\nNo assertions in section";
9494 else
9495 stream << "\nNo assertions in test case";
9496 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00009497 }
Phil Nash46118712013-08-16 19:01:32 +01009498 if( m_headerPrinted ) {
9499 if( m_config->showDurations() == ShowDurations::Always )
9500 stream << "Completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
9501 m_headerPrinted = false;
9502 }
Phil Nashf7378ee2013-09-07 12:07:38 +01009503 else {
9504 if( m_config->showDurations() == ShowDurations::Always )
9505 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << "s" << std::endl;
9506 }
Phil Nash2e7d9662013-01-16 09:44:43 +00009507 StreamingReporterBase::sectionEnded( _sectionStats );
9508 }
9509
Phil Nashe73583d2015-08-07 17:30:34 +01009510 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +00009511 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +00009512 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +00009513 }
Phil Nashe73583d2015-08-07 17:30:34 +01009514 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009515 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +00009516 printSummaryDivider();
9517 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
9518 printTotals( _testGroupStats.totals );
9519 stream << "\n" << std::endl;
9520 }
9521 StreamingReporterBase::testGroupEnded( _testGroupStats );
9522 }
Phil Nashe73583d2015-08-07 17:30:34 +01009523 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
Phil Nash52e1e742014-07-03 08:11:38 +01009524 printTotalsDivider( _testRunStats.totals );
Phil Nash2e7d9662013-01-16 09:44:43 +00009525 printTotals( _testRunStats.totals );
Phil Nash52e1e742014-07-03 08:11:38 +01009526 stream << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00009527 StreamingReporterBase::testRunEnded( _testRunStats );
9528 }
9529
9530 private:
Phil Nashe4756452013-01-26 20:18:30 +00009531
9532 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +01009533 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +00009534 public:
Phil Nash8d44f2d2013-11-13 08:10:45 +00009535 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00009536 : stream( _stream ),
9537 stats( _stats ),
9538 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +01009539 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +00009540 message( result.getMessage() ),
Phil Nash8d44f2d2013-11-13 08:10:45 +00009541 messages( _stats.infoMessages ),
9542 printInfoMessages( _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +00009543 {
9544 switch( result.getResultType() ) {
9545 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +01009546 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00009547 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +00009548 //if( result.hasMessage() )
9549 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00009550 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00009551 if( _stats.infoMessages.size() > 1 )
9552 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00009553 break;
9554 case ResultWas::ExpressionFailed:
9555 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01009556 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +00009557 passOrFail = "FAILED - but was ok";
9558 }
9559 else {
Phil Nash12c16ff2013-04-05 20:58:01 +01009560 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00009561 passOrFail = "FAILED";
9562 }
Phil Nasha2773812013-02-02 20:37:58 +00009563 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +00009564 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +00009565 if( _stats.infoMessages.size() > 1 )
9566 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +00009567 break;
9568 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +01009569 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00009570 passOrFail = "FAILED";
9571 messageLabel = "due to unexpected exception with message";
9572 break;
Phil Nash93b61e12014-08-22 19:35:41 +01009573 case ResultWas::FatalErrorCondition:
9574 colour = Colour::Error;
9575 passOrFail = "FAILED";
9576 messageLabel = "due to a fatal error condition";
9577 break;
Phil Nashe4756452013-01-26 20:18:30 +00009578 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +01009579 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00009580 passOrFail = "FAILED";
9581 messageLabel = "because no exception was thrown where one was expected";
9582 break;
9583 case ResultWas::Info:
9584 messageLabel = "info";
9585 break;
9586 case ResultWas::Warning:
9587 messageLabel = "warning";
9588 break;
9589 case ResultWas::ExplicitFailure:
9590 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +01009591 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +00009592 if( _stats.infoMessages.size() == 1 )
9593 messageLabel = "explicitly with message";
9594 if( _stats.infoMessages.size() > 1 )
9595 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +00009596 break;
Phil Nashe4756452013-01-26 20:18:30 +00009597 // These cases are here to prevent compiler warnings
9598 case ResultWas::Unknown:
9599 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +01009600 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +00009601 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +01009602 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +00009603 break;
9604 }
9605 }
9606
9607 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +01009608 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +00009609 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +01009610 if( result.isOk() )
9611 stream << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00009612 printResultType();
9613 printOriginalExpression();
9614 printReconstructedExpression();
9615 }
Phil Nash767f1582013-03-04 12:19:15 +01009616 else {
9617 stream << "\n";
9618 }
Phil Nashe4756452013-01-26 20:18:30 +00009619 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +00009620 }
9621
9622 private:
9623 void printResultType() const {
9624 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01009625 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +00009626 stream << passOrFail << ":\n";
9627 }
9628 }
9629 void printOriginalExpression() const {
9630 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01009631 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +00009632 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +01009633 stream << result.getExpressionInMacro();
Phil Nashe4756452013-01-26 20:18:30 +00009634 stream << "\n";
9635 }
9636 }
9637 void printReconstructedExpression() const {
9638 if( result.hasExpandedExpression() ) {
9639 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01009640 Colour colourGuard( Colour::ReconstructedExpression );
Phil Nash19279252013-04-20 21:07:32 +01009641 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << "\n";
Phil Nashe4756452013-01-26 20:18:30 +00009642 }
9643 }
9644 void printMessage() const {
9645 if( !messageLabel.empty() )
9646 stream << messageLabel << ":" << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00009647 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
9648 it != itEnd;
9649 ++it ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00009650 // If this assertion is a warning ignore any INFO messages
9651 if( printInfoMessages || it->type != ResultWas::Info )
9652 stream << Text( it->message, TextAttributes().setIndent(2) ) << "\n";
Phil Nasha2773812013-02-02 20:37:58 +00009653 }
Phil Nashe4756452013-01-26 20:18:30 +00009654 }
9655 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +01009656 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +01009657 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +00009658 }
9659
Phil Nashe4756452013-01-26 20:18:30 +00009660 std::ostream& stream;
9661 AssertionStats const& stats;
9662 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +01009663 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +00009664 std::string passOrFail;
9665 std::string messageLabel;
9666 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +00009667 std::vector<MessageInfo> messages;
Phil Nash8d44f2d2013-11-13 08:10:45 +00009668 bool printInfoMessages;
Phil Nashe4756452013-01-26 20:18:30 +00009669 };
Phil Nash2e7d9662013-01-16 09:44:43 +00009670
9671 void lazyPrint() {
9672
Phil Nashaa7123b2013-08-15 19:01:00 +01009673 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00009674 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +01009675 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +00009676 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +00009677
Phil Nasha04981b2013-03-08 09:30:25 +00009678 if( !m_headerPrinted ) {
9679 printTestCaseAndSectionHeader();
9680 m_headerPrinted = true;
9681 }
Phil Nash2e7d9662013-01-16 09:44:43 +00009682 }
9683 void lazyPrintRunInfo() {
Phil Nashaef6cd52014-04-23 07:10:10 +01009684 stream << "\n" << getLineOfChars<'~'>() << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01009685 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +01009686 stream << currentTestRunInfo->name
Phil Nash21f7ef62015-06-29 18:05:23 +01009687 << " is a Catch v" << libraryVersion << " host application.\n"
Phil Nash2e7d9662013-01-16 09:44:43 +00009688 << "Run with -? for options\n\n";
9689
Phil Nash6a8e8ad2014-09-15 18:40:24 +01009690 if( m_config->rngSeed() != 0 )
9691 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
9692
Phil Nashaa7123b2013-08-15 19:01:00 +01009693 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00009694 }
9695 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +01009696 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
9697 printClosedHeader( "Group: " + currentGroupInfo->name );
9698 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +00009699 }
9700 }
Phil Nasha04981b2013-03-08 09:30:25 +00009701 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +01009702 assert( !m_sectionStack.empty() );
9703 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +00009704
Phil Nashaa7123b2013-08-15 19:01:00 +01009705 if( m_sectionStack.size() > 1 ) {
9706 Colour colourGuard( Colour::Headers );
9707
9708 std::vector<SectionInfo>::const_iterator
9709 it = m_sectionStack.begin()+1, // Skip first section (test case)
9710 itEnd = m_sectionStack.end();
9711 for( ; it != itEnd; ++it )
9712 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +00009713 }
Phil Nashaa7123b2013-08-15 19:01:00 +01009714
9715 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +01009716
9717 if( !lineInfo.empty() ){
Phil Nashaef6cd52014-04-23 07:10:10 +01009718 stream << getLineOfChars<'-'>() << "\n";
Phil Nash19279252013-04-20 21:07:32 +01009719 Colour colourGuard( Colour::FileName );
9720 stream << lineInfo << "\n";
9721 }
Phil Nashaef6cd52014-04-23 07:10:10 +01009722 stream << getLineOfChars<'.'>() << "\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +00009723 }
9724
Phil Nasha04981b2013-03-08 09:30:25 +00009725 void printClosedHeader( std::string const& _name ) {
9726 printOpenHeader( _name );
Phil Nashaef6cd52014-04-23 07:10:10 +01009727 stream << getLineOfChars<'.'>() << "\n";
Phil Nasha04981b2013-03-08 09:30:25 +00009728 }
Phil Nash19279252013-04-20 21:07:32 +01009729 void printOpenHeader( std::string const& _name ) {
Phil Nashaef6cd52014-04-23 07:10:10 +01009730 stream << getLineOfChars<'-'>() << "\n";
Phil Nash5c7d3d72013-04-01 11:27:10 +01009731 {
Phil Nash12c16ff2013-04-05 20:58:01 +01009732 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +01009733 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +01009734 }
Phil Nash2e7d9662013-01-16 09:44:43 +00009735 }
9736
Phil Nash12c16ff2013-04-05 20:58:01 +01009737 // if string has a : in first line will set indent to follow it on
9738 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +01009739 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +01009740 std::size_t i = _string.find( ": " );
9741 if( i != std::string::npos )
9742 i+=2;
9743 else
9744 i = 0;
Phil Nash19279252013-04-20 21:07:32 +01009745 stream << Text( _string, TextAttributes()
9746 .setIndent( indent+i)
9747 .setInitialIndent( indent ) ) << "\n";
Phil Nash12c16ff2013-04-05 20:58:01 +01009748 }
9749
Phil Nash28c2e072014-07-09 19:22:49 +01009750 struct SummaryColumn {
9751
9752 SummaryColumn( std::string const& _label, Colour::Code _colour )
9753 : label( _label ),
9754 colour( _colour )
9755 {}
9756 SummaryColumn addRow( std::size_t count ) {
9757 std::ostringstream oss;
9758 oss << count;
9759 std::string row = oss.str();
9760 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
9761 while( it->size() < row.size() )
Phil Nashca42b2c2014-07-10 09:18:50 +01009762 *it = " " + *it;
Phil Nash28c2e072014-07-09 19:22:49 +01009763 while( it->size() > row.size() )
9764 row = " " + row;
9765 }
9766 rows.push_back( row );
9767 return *this;
9768 }
9769
9770 std::string label;
9771 Colour::Code colour;
9772 std::vector<std::string> rows;
9773
9774 };
9775
Phil Nash52e1e742014-07-03 08:11:38 +01009776 void printTotals( Totals const& totals ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00009777 if( totals.testCases.total() == 0 ) {
Phil Nash52e1e742014-07-03 08:11:38 +01009778 stream << Colour( Colour::Warning ) << "No tests ran\n";
Phil Nash2e7d9662013-01-16 09:44:43 +00009779 }
Phil Nash28c2e072014-07-09 19:22:49 +01009780 else if( totals.assertions.total() > 0 && totals.assertions.allPassed() ) {
Phil Nash52e1e742014-07-03 08:11:38 +01009781 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
9782 stream << " ("
Phil Nash2e7d9662013-01-16 09:44:43 +00009783 << pluralise( totals.assertions.passed, "assertion" ) << " in "
Phil Nash52e1e742014-07-03 08:11:38 +01009784 << pluralise( totals.testCases.passed, "test case" ) << ")"
9785 << "\n";
Phil Nashbcad0932012-12-10 08:54:57 +00009786 }
Phil Nash28c2e072014-07-09 19:22:49 +01009787 else {
Phil Nash52e1e742014-07-03 08:11:38 +01009788
Phil Nash28c2e072014-07-09 19:22:49 +01009789 std::vector<SummaryColumn> columns;
9790 columns.push_back( SummaryColumn( "", Colour::None )
9791 .addRow( totals.testCases.total() )
9792 .addRow( totals.assertions.total() ) );
9793 columns.push_back( SummaryColumn( "passed", Colour::Success )
9794 .addRow( totals.testCases.passed )
9795 .addRow( totals.assertions.passed ) );
9796 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
9797 .addRow( totals.testCases.failed )
9798 .addRow( totals.assertions.failed ) );
9799 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
9800 .addRow( totals.testCases.failedButOk )
9801 .addRow( totals.assertions.failedButOk ) );
Phil Nash52e1e742014-07-03 08:11:38 +01009802
Phil Nash28c2e072014-07-09 19:22:49 +01009803 printSummaryRow( "test cases", columns, 0 );
9804 printSummaryRow( "assertions", columns, 1 );
Phil Nashf1178122012-12-11 09:03:14 +00009805 }
Phil Nash28c2e072014-07-09 19:22:49 +01009806 }
9807 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
9808 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
9809 std::string value = it->rows[row];
9810 if( it->label.empty() ) {
9811 stream << label << ": ";
9812 if( value != "0" )
9813 stream << value;
9814 else
9815 stream << Colour( Colour::Warning ) << "- none -";
9816 }
9817 else if( value != "0" ) {
9818 stream << Colour( Colour::LightGrey ) << " | ";
9819 stream << Colour( it->colour )
9820 << value << " " << it->label;
9821 }
9822 }
9823 stream << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00009824 }
9825
Phil Nash52e1e742014-07-03 08:11:38 +01009826 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
9827 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
9828 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
9829 }
9830 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
9831 if( i > j && i > k )
9832 return i;
9833 else if( j > k )
9834 return j;
9835 else
9836 return k;
9837 }
9838
9839 void printTotalsDivider( Totals const& totals ) {
9840 if( totals.testCases.total() > 0 ) {
9841 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
9842 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
9843 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
9844 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
9845 findMax( failedRatio, failedButOkRatio, passedRatio )++;
9846 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
9847 findMax( failedRatio, failedButOkRatio, passedRatio )--;
9848
Phil Nash52e1e742014-07-03 08:11:38 +01009849 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
9850 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
Phil Nash28c2e072014-07-09 19:22:49 +01009851 if( totals.testCases.allPassed() )
9852 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
9853 else
9854 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
Phil Nash52e1e742014-07-03 08:11:38 +01009855 }
9856 else {
9857 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
9858 }
9859 stream << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00009860 }
Phil Nash2e7d9662013-01-16 09:44:43 +00009861 void printSummaryDivider() {
Phil Nashaef6cd52014-04-23 07:10:10 +01009862 stream << getLineOfChars<'-'>() << "\n";
Phil Nashff03cdf2012-12-06 08:44:51 +00009863 }
Phil Nashff03cdf2012-12-06 08:44:51 +00009864
Phil Nashcf5ced52012-12-14 07:50:08 +00009865 private:
Phil Nasha04981b2013-03-08 09:30:25 +00009866 bool m_headerPrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +00009867 };
9868
9869 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
9870
9871} // end namespace Catch
9872
Phil Nash5a2df712014-05-01 19:07:02 +01009873// #included from: ../reporters/catch_reporter_compact.hpp
9874#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
9875
9876namespace Catch {
9877
9878 struct CompactReporter : StreamingReporterBase {
9879
9880 CompactReporter( ReporterConfig const& _config )
9881 : StreamingReporterBase( _config )
9882 {}
9883
9884 virtual ~CompactReporter();
9885
9886 static std::string getDescription() {
9887 return "Reports test results on a single line, suitable for IDEs";
9888 }
9889
9890 virtual ReporterPreferences getPreferences() const {
9891 ReporterPreferences prefs;
9892 prefs.shouldRedirectStdOut = false;
9893 return prefs;
9894 }
9895
9896 virtual void noMatchingTestCases( std::string const& spec ) {
9897 stream << "No test cases matched '" << spec << "'" << std::endl;
9898 }
9899
9900 virtual void assertionStarting( AssertionInfo const& ) {
9901 }
9902
9903 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
9904 AssertionResult const& result = _assertionStats.assertionResult;
9905
9906 bool printInfoMessages = true;
9907
9908 // Drop out if result was successful and we're not printing those
9909 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
9910 if( result.getResultType() != ResultWas::Warning )
9911 return false;
9912 printInfoMessages = false;
9913 }
9914
9915 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
9916 printer.print();
9917
9918 stream << std::endl;
9919 return true;
9920 }
9921
9922 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
9923 printTotals( _testRunStats.totals );
9924 stream << "\n" << std::endl;
9925 StreamingReporterBase::testRunEnded( _testRunStats );
9926 }
9927
9928 private:
9929 class AssertionPrinter {
9930 void operator= ( AssertionPrinter const& );
9931 public:
9932 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
9933 : stream( _stream )
9934 , stats( _stats )
9935 , result( _stats.assertionResult )
9936 , messages( _stats.infoMessages )
9937 , itMessage( _stats.infoMessages.begin() )
9938 , printInfoMessages( _printInfoMessages )
9939 {}
9940
9941 void print() {
9942 printSourceInfo();
9943
9944 itMessage = messages.begin();
9945
9946 switch( result.getResultType() ) {
9947 case ResultWas::Ok:
9948 printResultType( Colour::ResultSuccess, passedString() );
9949 printOriginalExpression();
9950 printReconstructedExpression();
9951 if ( ! result.hasExpression() )
9952 printRemainingMessages( Colour::None );
9953 else
9954 printRemainingMessages();
9955 break;
9956 case ResultWas::ExpressionFailed:
9957 if( result.isOk() )
9958 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
9959 else
9960 printResultType( Colour::Error, failedString() );
9961 printOriginalExpression();
9962 printReconstructedExpression();
9963 printRemainingMessages();
9964 break;
9965 case ResultWas::ThrewException:
9966 printResultType( Colour::Error, failedString() );
9967 printIssue( "unexpected exception with message:" );
9968 printMessage();
9969 printExpressionWas();
9970 printRemainingMessages();
9971 break;
Phil Nash93b61e12014-08-22 19:35:41 +01009972 case ResultWas::FatalErrorCondition:
9973 printResultType( Colour::Error, failedString() );
9974 printIssue( "fatal error condition with message:" );
9975 printMessage();
9976 printExpressionWas();
9977 printRemainingMessages();
9978 break;
Phil Nash5a2df712014-05-01 19:07:02 +01009979 case ResultWas::DidntThrowException:
9980 printResultType( Colour::Error, failedString() );
9981 printIssue( "expected exception, got none" );
9982 printExpressionWas();
9983 printRemainingMessages();
9984 break;
9985 case ResultWas::Info:
9986 printResultType( Colour::None, "info" );
9987 printMessage();
9988 printRemainingMessages();
9989 break;
9990 case ResultWas::Warning:
9991 printResultType( Colour::None, "warning" );
9992 printMessage();
9993 printRemainingMessages();
9994 break;
9995 case ResultWas::ExplicitFailure:
9996 printResultType( Colour::Error, failedString() );
9997 printIssue( "explicitly" );
9998 printRemainingMessages( Colour::None );
9999 break;
10000 // These cases are here to prevent compiler warnings
10001 case ResultWas::Unknown:
10002 case ResultWas::FailureBit:
10003 case ResultWas::Exception:
10004 printResultType( Colour::Error, "** internal error **" );
10005 break;
10006 }
10007 }
10008
10009 private:
10010 // Colour::LightGrey
10011
Phil Nash9241e432014-05-20 18:50:59 +010010012 static Colour::Code dimColour() { return Colour::FileName; }
Phil Nash5a2df712014-05-01 19:07:02 +010010013
10014#ifdef CATCH_PLATFORM_MAC
10015 static const char* failedString() { return "FAILED"; }
10016 static const char* passedString() { return "PASSED"; }
10017#else
10018 static const char* failedString() { return "failed"; }
10019 static const char* passedString() { return "passed"; }
10020#endif
10021
10022 void printSourceInfo() const {
10023 Colour colourGuard( Colour::FileName );
10024 stream << result.getSourceInfo() << ":";
10025 }
10026
Phil Nash9241e432014-05-20 18:50:59 +010010027 void printResultType( Colour::Code colour, std::string passOrFail ) const {
Phil Nash5a2df712014-05-01 19:07:02 +010010028 if( !passOrFail.empty() ) {
10029 {
10030 Colour colourGuard( colour );
10031 stream << " " << passOrFail;
10032 }
10033 stream << ":";
10034 }
10035 }
10036
10037 void printIssue( std::string issue ) const {
10038 stream << " " << issue;
10039 }
10040
10041 void printExpressionWas() {
10042 if( result.hasExpression() ) {
10043 stream << ";";
10044 {
10045 Colour colour( dimColour() );
10046 stream << " expression was:";
10047 }
10048 printOriginalExpression();
10049 }
10050 }
10051
10052 void printOriginalExpression() const {
10053 if( result.hasExpression() ) {
10054 stream << " " << result.getExpression();
10055 }
10056 }
10057
10058 void printReconstructedExpression() const {
10059 if( result.hasExpandedExpression() ) {
10060 {
10061 Colour colour( dimColour() );
10062 stream << " for: ";
10063 }
10064 stream << result.getExpandedExpression();
10065 }
10066 }
10067
10068 void printMessage() {
10069 if ( itMessage != messages.end() ) {
10070 stream << " '" << itMessage->message << "'";
10071 ++itMessage;
10072 }
10073 }
10074
Phil Nash9241e432014-05-20 18:50:59 +010010075 void printRemainingMessages( Colour::Code colour = dimColour() ) {
Phil Nash5a2df712014-05-01 19:07:02 +010010076 if ( itMessage == messages.end() )
10077 return;
10078
10079 // using messages.end() directly yields compilation error:
10080 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
10081 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
10082
10083 {
10084 Colour colourGuard( colour );
10085 stream << " with " << pluralise( N, "message" ) << ":";
10086 }
10087
10088 for(; itMessage != itEnd; ) {
10089 // If this assertion is a warning ignore any INFO messages
10090 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
10091 stream << " '" << itMessage->message << "'";
10092 if ( ++itMessage != itEnd ) {
10093 Colour colourGuard( dimColour() );
10094 stream << " and";
10095 }
10096 }
10097 }
10098 }
10099
10100 private:
10101 std::ostream& stream;
10102 AssertionStats const& stats;
10103 AssertionResult const& result;
10104 std::vector<MessageInfo> messages;
10105 std::vector<MessageInfo>::const_iterator itMessage;
10106 bool printInfoMessages;
10107 };
10108
10109 // Colour, message variants:
10110 // - white: No tests ran.
10111 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
10112 // - white: Passed [both/all] N test cases (no assertions).
10113 // - red: Failed N tests cases, failed M assertions.
10114 // - green: Passed [both/all] N tests cases with M assertions.
10115
10116 std::string bothOrAll( std::size_t count ) const {
10117 return count == 1 ? "" : count == 2 ? "both " : "all " ;
10118 }
10119
10120 void printTotals( const Totals& totals ) const {
10121 if( totals.testCases.total() == 0 ) {
10122 stream << "No tests ran.";
10123 }
10124 else if( totals.testCases.failed == totals.testCases.total() ) {
10125 Colour colour( Colour::ResultError );
10126 const std::string qualify_assertions_failed =
10127 totals.assertions.failed == totals.assertions.total() ?
10128 bothOrAll( totals.assertions.failed ) : "";
10129 stream <<
10130 "Failed " << bothOrAll( totals.testCases.failed )
10131 << pluralise( totals.testCases.failed, "test case" ) << ", "
10132 "failed " << qualify_assertions_failed <<
10133 pluralise( totals.assertions.failed, "assertion" ) << ".";
10134 }
10135 else if( totals.assertions.total() == 0 ) {
10136 stream <<
10137 "Passed " << bothOrAll( totals.testCases.total() )
10138 << pluralise( totals.testCases.total(), "test case" )
10139 << " (no assertions).";
10140 }
10141 else if( totals.assertions.failed ) {
10142 Colour colour( Colour::ResultError );
10143 stream <<
10144 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
10145 "failed " << pluralise( totals.assertions.failed, "assertion" ) << ".";
10146 }
10147 else {
10148 Colour colour( Colour::ResultSuccess );
10149 stream <<
10150 "Passed " << bothOrAll( totals.testCases.passed )
10151 << pluralise( totals.testCases.passed, "test case" ) <<
10152 " with " << pluralise( totals.assertions.passed, "assertion" ) << ".";
10153 }
10154 }
10155 };
10156
10157 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
10158
10159} // end namespace Catch
10160
Phil Nasha695eb92012-08-13 07:46:10 +010010161namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +000010162 // These are all here to avoid warnings about not having any out of line
10163 // virtual methods
Phil Nasha695eb92012-08-13 07:46:10 +010010164 NonCopyable::~NonCopyable() {}
10165 IShared::~IShared() {}
Phil Nash7e346192015-11-03 08:00:43 +000010166 IStream::~IStream() CATCH_NOEXCEPT {}
Phil Nashece529a2015-11-03 17:37:43 +000010167 FileStream::~FileStream() CATCH_NOEXCEPT {}
10168 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
10169 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
Phil Nashd7e17902014-04-18 08:49:35 +010010170 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
Phil Nasha695eb92012-08-13 07:46:10 +010010171 IContext::~IContext() {}
10172 IResultCapture::~IResultCapture() {}
10173 ITestCase::~ITestCase() {}
10174 ITestCaseRegistry::~ITestCaseRegistry() {}
10175 IRegistryHub::~IRegistryHub() {}
10176 IMutableRegistryHub::~IMutableRegistryHub() {}
10177 IExceptionTranslator::~IExceptionTranslator() {}
10178 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
10179 IReporter::~IReporter() {}
10180 IReporterFactory::~IReporterFactory() {}
10181 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010182 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010183 AssertionStats::~AssertionStats() {}
10184 SectionStats::~SectionStats() {}
10185 TestCaseStats::~TestCaseStats() {}
10186 TestGroupStats::~TestGroupStats() {}
10187 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +010010188 CumulativeReporterBase::SectionNode::~SectionNode() {}
10189 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010190
Phil Nash2e7d9662013-01-16 09:44:43 +000010191 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +000010192 ConsoleReporter::~ConsoleReporter() {}
Phil Nash5a2df712014-05-01 19:07:02 +010010193 CompactReporter::~CompactReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +010010194 IRunner::~IRunner() {}
10195 IMutableContext::~IMutableContext() {}
10196 IConfig::~IConfig() {}
10197 XmlReporter::~XmlReporter() {}
10198 JunitReporter::~JunitReporter() {}
10199 TestRegistry::~TestRegistry() {}
10200 FreeFunctionTestCase::~FreeFunctionTestCase() {}
10201 IGeneratorInfo::~IGeneratorInfo() {}
10202 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash8342ae82015-07-13 15:03:26 +010010203 WildcardPattern::~WildcardPattern() {}
Phil Nash65cc14c2014-05-16 18:54:48 +010010204 TestSpec::Pattern::~Pattern() {}
10205 TestSpec::NamePattern::~NamePattern() {}
10206 TestSpec::TagPattern::~TagPattern() {}
10207 TestSpec::ExcludedPattern::~ExcludedPattern() {}
Phil Nasha695eb92012-08-13 07:46:10 +010010208
Phil Nash9444bbc2012-10-12 07:58:17 +010010209 Matchers::Impl::StdString::Equals::~Equals() {}
10210 Matchers::Impl::StdString::Contains::~Contains() {}
10211 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
10212 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
10213
Phil Nasha695eb92012-08-13 07:46:10 +010010214 void Config::dummy() {}
Phil Nash7e346192015-11-03 08:00:43 +000010215
10216 namespace TestCaseTracking {
10217 ITracker::~ITracker() {}
10218 TrackerBase::~TrackerBase() {}
10219 SectionTracker::~SectionTracker() {}
10220 IndexTracker::~IndexTracker() {}
10221 }
Phil Nasha695eb92012-08-13 07:46:10 +010010222}
10223
Phil Nash5bc030d2012-08-16 18:48:50 +010010224#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +010010225#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +010010226#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -040010227
Phil Nash9abb2762014-03-06 21:53:34 +000010228#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010229
Phil Nashde49ec42013-12-04 20:25:14 +000010230#ifdef CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +010010231// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +010010232#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010233
Phil Nash176eb812012-05-11 08:17:16 +010010234#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +010010235
Phil Nash176eb812012-05-11 08:17:16 +010010236// Standard C/C++ main entry point
Phil Nash981347b2015-12-09 18:11:48 +000010237int main (int argc, char * argv[]) {
Phil Nash786959d2013-06-07 19:07:50 +010010238 return Catch::Session().run( argc, argv );
Phil Nash176eb812012-05-11 08:17:16 +010010239}
10240
10241#else // __OBJC__
10242
10243// Objective-C entry point
10244int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +000010245#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010246 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +000010247#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010248
10249 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +010010250 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +010010251
Phil Nash53c990a2012-03-17 18:20:06 +000010252#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010253 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +000010254#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010255
Phil Nashdd5b9c22012-02-18 09:58:30 +000010256 return result;
Phil Nash89d1e6c2011-05-24 08:23:02 +010010257}
10258
Phil Nash176eb812012-05-11 08:17:16 +010010259#endif // __OBJC__
10260
Phil Nash9abb2762014-03-06 21:53:34 +000010261#endif
10262
10263#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
10264# undef CLARA_CONFIG_MAIN
10265#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010266
Phil Nash89d1e6c2011-05-24 08:23:02 +010010267//////
10268
Phil Nash46bcd4b2012-07-20 18:43:48 +010010269// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
10270#ifdef CATCH_CONFIG_PREFIX_ALL
10271
Phil Nash90a35942012-11-13 22:04:29 +000010272#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010010273#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "CATCH_REQUIRE_FALSE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010274
Phil Nash93a842e2015-07-13 06:36:07 +010010275#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010276#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010010277#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "CATCH_REQUIRE_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010278#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010279
Phil Nash90a35942012-11-13 22:04:29 +000010280#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010010281#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CATCH_CHECK_FALSE" )
Phil Nash90a35942012-11-13 22:04:29 +000010282#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
10283#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
10284#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CATCH_CHECK_NOFAIL" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010285
Phil Nashab036682014-06-02 07:48:03 +010010286#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010287#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010010288#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CATCH_CHECK_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010289#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010290
Phil Nash90a35942012-11-13 22:04:29 +000010291#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
10292#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010293
Phil Nasha2773812013-02-02 20:37:58 +000010294#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000010295#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010296#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000010297#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010298#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010299
Phil Nash93906752013-03-16 20:21:51 +000010300#ifdef CATCH_CONFIG_VARIADIC_MACROS
10301 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010010302 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010303 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000010304 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010305 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000010306 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000010307 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010308#else
10309 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010010310 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010311 #define CATCH_METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash7e15d9b2015-11-20 16:59:14 +000010312 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010313 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000010314 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000010315 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000010316#endif
10317#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010318
10319#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000010320#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010321
10322#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10323
Phil Nash37186a12013-03-13 12:19:30 +000010324// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000010325#ifdef CATCH_CONFIG_VARIADIC_MACROS
10326#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010010327#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000010328#else
Phil Nash37186a12013-03-13 12:19:30 +000010329#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010010330#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000010331#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010010332#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
10333#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
10334#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10335#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
10336#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000010337
Phil Nash46bcd4b2012-07-20 18:43:48 +010010338// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
10339#else
10340
Phil Nash90a35942012-11-13 22:04:29 +000010341#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010010342#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010343
Phil Nash93a842e2015-07-13 06:36:07 +010010344#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010345#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::Normal, "REQUIRE_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010010346#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010347#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010348
Phil Nash90a35942012-11-13 22:04:29 +000010349#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010010350#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
Phil Nash90a35942012-11-13 22:04:29 +000010351#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
10352#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
10353#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010354
Phil Nash93a842e2015-07-13 06:36:07 +010010355#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010356#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( expr, exceptionType, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THROWS_AS" )
Phil Nash5bbdc8f2015-07-15 23:03:11 +010010357#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010358#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010359
Phil Nash90a35942012-11-13 22:04:29 +000010360#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
10361#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +000010362
Phil Nasha2773812013-02-02 20:37:58 +000010363#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000010364#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010365#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000010366#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010367#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010368
Phil Nash93906752013-03-16 20:21:51 +000010369#ifdef CATCH_CONFIG_VARIADIC_MACROS
10370 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010010371 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010372 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000010373 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010374 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000010375 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000010376 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010377#else
10378 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010010379 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010380 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash7424b232015-12-28 15:07:32 +000010381 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010382 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000010383 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000010384 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000010385#endif
10386#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010387
10388#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000010389#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010390
10391#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10392
Phil Nash46bcd4b2012-07-20 18:43:48 +010010393#endif
10394
10395#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010396
Phil Nash37186a12013-03-13 12:19:30 +000010397// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000010398#ifdef CATCH_CONFIG_VARIADIC_MACROS
10399#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010010400#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000010401#else
Phil Nash37186a12013-03-13 12:19:30 +000010402#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010010403#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000010404#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010010405#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
10406#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
10407#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
10408#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
10409#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000010410
Phil Nash89d1e6c2011-05-24 08:23:02 +010010411using Catch::Detail::Approx;
10412
Phil Nashaec1e5e2012-05-09 19:37:51 +010010413#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010414