blob: 6a0a58edc20ffcbf9d0d43343816089219b5d1c7 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01002 * Catch v1.7.1
3 * Generated: 2017-02-07 09:44:56.263047
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 Nash8defc712013-04-24 19:10:02 +010063// #included from: catch_compiler_capabilities.h
64#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
65
Phil Nash318c9362015-05-19 18:40:00 +010066// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
67// The following features are defined:
68//
69// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
70// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
71// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
72// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
73// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
Phil Nash2f6371f2015-07-23 23:06:26 +010074// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
Phil Nashe73583d2015-08-07 17:30:34 +010075// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
Phil Nashd234ed12015-08-24 06:28:25 +010076// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010077// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
78// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
Phil Nash318c9362015-05-19 18:40:00 +010079
80// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
81
Phil Nash318c9362015-05-19 18:40:00 +010082// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
Phil Nashc984fc32016-03-15 07:24:26 +000083// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010084// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
Phil Nashd234ed12015-08-24 06:28:25 +010085// ****************
86// Note to maintainers: if new toggles are added please document them
87// in configuration.md, too
88// ****************
89
Phil Nash3b18d9e2015-06-30 18:26:09 +010090// In general each macro has a _NO_<feature name> form
91// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
92// Many features, at point of detection, define an _INTERNAL_ macro, so they
93// can be combined, en-mass, with the _NO_ forms later.
94
95// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
Phil Nash8defc712013-04-24 19:10:02 +010096
Phil Nashac220282016-06-09 08:19:23 +010097#ifdef __cplusplus
98
99# if __cplusplus >= 201103L
100# define CATCH_CPP11_OR_GREATER
101# endif
102
103# if __cplusplus >= 201402L
104# define CATCH_CPP14_OR_GREATER
105# endif
106
Phil Nashae5ee2c2016-02-29 08:17:18 +0000107#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
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100164#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
165
Phil Nash43470b22015-05-19 22:37:23 +0100166#if (_MSC_VER >= 1600)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100167# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nashd234ed12015-08-24 06:28:25 +0100168# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
Phil Nash43470b22015-05-19 22:37:23 +0100169#endif
170
Phil Nash318c9362015-05-19 18:40:00 +0100171#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
Phil Nash3b18d9e2015-06-30 18:26:09 +0100172#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
173#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3b2f2062017-01-11 16:43:56 +0000174#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100175#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
Phil Nash318c9362015-05-19 18:40:00 +0100176#endif
177
Phil Nash8defc712013-04-24 19:10:02 +0100178#endif // _MSC_VER
179
Phil Nashd234ed12015-08-24 06:28:25 +0100180////////////////////////////////////////////////////////////////////////////////
181
Phil Nash8defc712013-04-24 19:10:02 +0100182// Use variadic macros if the compiler supports them
183#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
184 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
185 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
186 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100187
Phil Nash3b18d9e2015-06-30 18:26:09 +0100188#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash786959d2013-06-07 19:07:50 +0100189
Phil Nash8defc712013-04-24 19:10:02 +0100190#endif
191
Phil Nashc984fc32016-03-15 07:24:26 +0000192// Use __COUNTER__ if the compiler supports it
193#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
194 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
195 ( defined __clang__ && __clang_major__ >= 3 )
196
197#define CATCH_INTERNAL_CONFIG_COUNTER
198
199#endif
200
Phil Nashd7e17902014-04-18 08:49:35 +0100201////////////////////////////////////////////////////////////////////////////////
202// C++ language feature support
203
Phil Nash318c9362015-05-19 18:40:00 +0100204// catch all support for C++11
Phil Nashae5ee2c2016-02-29 08:17:18 +0000205#if defined(CATCH_CPP11_OR_GREATER)
Phil Nash318c9362015-05-19 18:40:00 +0100206
Phil Nash3b18d9e2015-06-30 18:26:09 +0100207# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
208# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash318c9362015-05-19 18:40:00 +0100209# endif
210
Phil Nash3b18d9e2015-06-30 18:26:09 +0100211# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
212# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash318c9362015-05-19 18:40:00 +0100213# endif
214
Phil Nash3b18d9e2015-06-30 18:26:09 +0100215# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
216# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash318c9362015-05-19 18:40:00 +0100217# endif
218
Phil Nash3b18d9e2015-06-30 18:26:09 +0100219# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
220# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
Phil Nash318c9362015-05-19 18:40:00 +0100221# endif
222
Phil Nash3b18d9e2015-06-30 18:26:09 +0100223# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
224# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
Phil Nash318c9362015-05-19 18:40:00 +0100225# endif
226
Phil Nash3b18d9e2015-06-30 18:26:09 +0100227# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
228# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash318c9362015-05-19 18:40:00 +0100229# endif
230
Phil Nash2f6371f2015-07-23 23:06:26 +0100231# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
232# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
233# endif
234
Phil Nashe73583d2015-08-07 17:30:34 +0100235# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
236# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
237# endif
Phil Nashd234ed12015-08-24 06:28:25 +0100238# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
239# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
240# endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000241# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
242# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
243# endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100244# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
245# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
246# endif
Phil Nashe73583d2015-08-07 17:30:34 +0100247
Phil Nash318c9362015-05-19 18:40:00 +0100248#endif // __cplusplus >= 201103L
Phil Nashd7e17902014-04-18 08:49:35 +0100249
Phil Nash3b18d9e2015-06-30 18:26:09 +0100250// Now set the actual defines based on the above + anything the user has configured
251#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
252# define CATCH_CONFIG_CPP11_NULLPTR
253#endif
254#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
255# define CATCH_CONFIG_CPP11_NOEXCEPT
256#endif
257#if defined(CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CATCH_CONFIG_CPP11_GENERATED_METHODS) && !defined(CATCH_CONFIG_NO_CPP11)
258# define CATCH_CONFIG_CPP11_GENERATED_METHODS
259#endif
260#if defined(CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_NO_IS_ENUM) && !defined(CATCH_CONFIG_CPP11_IS_ENUM) && !defined(CATCH_CONFIG_NO_CPP11)
261# define CATCH_CONFIG_CPP11_IS_ENUM
262#endif
263#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
264# define CATCH_CONFIG_CPP11_TUPLE
265#endif
266#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 +0100267# define CATCH_CONFIG_VARIADIC_MACROS
268#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000269#if defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_NO_LONG_LONG) && !defined(CATCH_CONFIG_CPP11_LONG_LONG) && !defined(CATCH_CONFIG_NO_CPP11)
Phil Nash2f6371f2015-07-23 23:06:26 +0100270# define CATCH_CONFIG_CPP11_LONG_LONG
Phil Nash3b18d9e2015-06-30 18:26:09 +0100271#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000272#if defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_NO_OVERRIDE) && !defined(CATCH_CONFIG_CPP11_OVERRIDE) && !defined(CATCH_CONFIG_NO_CPP11)
Phil Nashe73583d2015-08-07 17:30:34 +0100273# define CATCH_CONFIG_CPP11_OVERRIDE
274#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000275#if defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_NO_UNIQUE_PTR) && !defined(CATCH_CONFIG_CPP11_UNIQUE_PTR) && !defined(CATCH_CONFIG_NO_CPP11)
Phil Nashd234ed12015-08-24 06:28:25 +0100276# define CATCH_CONFIG_CPP11_UNIQUE_PTR
Phil Nash3b18d9e2015-06-30 18:26:09 +0100277#endif
Martin Hořeňovský9a566092017-01-20 12:49:59 +0100278// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
279// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
280// This does not affect compilation
281#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER) && !defined(__JETBRAINS_IDE__)
Phil Nashc984fc32016-03-15 07:24:26 +0000282# define CATCH_CONFIG_COUNTER
283#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000284#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
285# define CATCH_CONFIG_CPP11_SHUFFLE
286#endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100287# if defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_NO_TYPE_TRAITS) && !defined(CATCH_CONFIG_CPP11_TYPE_TRAITS) && !defined(CATCH_CONFIG_NO_CPP11)
288# define CATCH_CONFIG_CPP11_TYPE_TRAITS
289# endif
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100290#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
291# define CATCH_CONFIG_WINDOWS_SEH
292#endif
Phil Nash3b18d9e2015-06-30 18:26:09 +0100293
Phil Nashae5ee2c2016-02-29 08:17:18 +0000294#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
295# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
296#endif
297
Phil Nashd7e17902014-04-18 08:49:35 +0100298// noexcept support:
Phil Nash17404952014-04-23 18:19:49 +0100299#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
300# define CATCH_NOEXCEPT noexcept
301# define CATCH_NOEXCEPT_IS(x) noexcept(x)
302#else
Phil Nashd7e17902014-04-18 08:49:35 +0100303# define CATCH_NOEXCEPT throw()
304# define CATCH_NOEXCEPT_IS(x)
305#endif
306
Phil Nashb971fe72015-07-02 08:21:38 +0100307// nullptr support
308#ifdef CATCH_CONFIG_CPP11_NULLPTR
309# define CATCH_NULL nullptr
310#else
311# define CATCH_NULL NULL
312#endif
313
Phil Nashe73583d2015-08-07 17:30:34 +0100314// override support
315#ifdef CATCH_CONFIG_CPP11_OVERRIDE
316# define CATCH_OVERRIDE override
317#else
318# define CATCH_OVERRIDE
319#endif
320
Phil Nashd234ed12015-08-24 06:28:25 +0100321// unique_ptr support
322#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
323# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
324#else
325# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
326#endif
327
Phil Nash3b2f2062017-01-11 16:43:56 +0000328#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
329#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
330#ifdef CATCH_CONFIG_COUNTER
331# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
332#else
333# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
334#endif
335
336#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
337#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
338
339#include <sstream>
340#include <stdexcept>
341#include <algorithm>
342
Phil Nash89d2a3f2012-05-16 15:09:17 +0100343namespace Catch {
344
Phil Nash8f66e342015-07-02 23:03:13 +0100345 struct IConfig;
346
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100347 struct CaseSensitive { enum Choice {
348 Yes,
349 No
350 }; };
351
Phil Nasha04981b2013-03-08 09:30:25 +0000352 class NonCopyable {
Phil Nash318c9362015-05-19 18:40:00 +0100353#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashe54ac702014-10-21 07:25:26 +0100354 NonCopyable( NonCopyable const& ) = delete;
355 NonCopyable( NonCopyable && ) = delete;
356 NonCopyable& operator = ( NonCopyable const& ) = delete;
357 NonCopyable& operator = ( NonCopyable && ) = delete;
358#else
359 NonCopyable( NonCopyable const& info );
360 NonCopyable& operator = ( NonCopyable const& );
361#endif
362
Phil Nasha04981b2013-03-08 09:30:25 +0000363 protected:
364 NonCopyable() {}
365 virtual ~NonCopyable();
366 };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100367
Phil Nash163088a2012-05-31 19:40:26 +0100368 class SafeBool {
369 public:
370 typedef void (SafeBool::*type)() const;
371
372 static type makeSafe( bool value ) {
373 return value ? &SafeBool::trueValue : 0;
374 }
375 private:
376 void trueValue() const {}
377 };
378
Phil Nash89d1e6c2011-05-24 08:23:02 +0100379 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100380 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100381 typename ContainerT::const_iterator it = container.begin();
382 typename ContainerT::const_iterator itEnd = container.end();
383 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100384 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100385 }
386 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100387 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100388 typename AssociativeContainerT::const_iterator it = container.begin();
389 typename AssociativeContainerT::const_iterator itEnd = container.end();
390 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100391 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100392 }
393
Phil Nash3649fdf2013-12-03 18:53:55 +0000394 bool startsWith( std::string const& s, std::string const& prefix );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100395 bool startsWith( std::string const& s, char prefix );
Phil Nash3649fdf2013-12-03 18:53:55 +0000396 bool endsWith( std::string const& s, std::string const& suffix );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100397 bool endsWith( std::string const& s, char suffix );
398 bool contains( std::string const& s, std::string const& infix );
Phil Nash3649fdf2013-12-03 18:53:55 +0000399 bool contains( std::string const& s, std::string const& infix );
400 void toLowerInPlace( std::string& s );
401 std::string toLower( std::string const& s );
402 std::string trim( std::string const& str );
Phil Nash576aff62014-12-21 00:21:23 +0000403 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
Phil Nash4c97fc52012-08-24 08:23:50 +0100404
405 struct pluralise {
Phil Nash3649fdf2013-12-03 18:53:55 +0000406 pluralise( std::size_t count, std::string const& label );
Phil Nash4c97fc52012-08-24 08:23:50 +0100407
Phil Nash3649fdf2013-12-03 18:53:55 +0000408 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
Phil Nash4c97fc52012-08-24 08:23:50 +0100409
410 std::size_t m_count;
411 std::string m_label;
412 };
Phil Nash56d5c422012-08-23 20:08:50 +0100413
Phil Nash89d2a3f2012-05-16 15:09:17 +0100414 struct SourceLineInfo {
415
Phil Nash3649fdf2013-12-03 18:53:55 +0000416 SourceLineInfo();
Phil Nashde49ec42013-12-04 20:25:14 +0000417 SourceLineInfo( char const* _file, std::size_t _line );
Phil Nash318c9362015-05-19 18:40:00 +0100418# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100419 SourceLineInfo(SourceLineInfo const& other) = default;
Phil Nashd7e17902014-04-18 08:49:35 +0100420 SourceLineInfo( SourceLineInfo && ) = default;
421 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
422 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
423# endif
Phil Nash3649fdf2013-12-03 18:53:55 +0000424 bool empty() const;
425 bool operator == ( SourceLineInfo const& other ) const;
Phil Nasha806c3e2015-03-04 08:23:40 +0000426 bool operator < ( SourceLineInfo const& other ) const;
Phil Nash3649fdf2013-12-03 18:53:55 +0000427
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100428 char const* file;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000429 std::size_t line;
430 };
431
Phil Nash3649fdf2013-12-03 18:53:55 +0000432 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
Phil Nash6e0f58d2012-02-15 18:37:21 +0000433
Phil Nash8defc712013-04-24 19:10:02 +0100434 // This is just here to avoid compiler warnings with macro constants and boolean literals
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100435 inline bool isTrue( bool value ){ return value; }
436 inline bool alwaysTrue() { return true; }
437 inline bool alwaysFalse() { return false; }
Phil Nash8defc712013-04-24 19:10:02 +0100438
Phil Nash3649fdf2013-12-03 18:53:55 +0000439 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
Phil Nash859760a2013-12-14 14:34:05 +0000440
Phil Nash8f66e342015-07-02 23:03:13 +0100441 void seedRng( IConfig const& config );
442 unsigned int rngSeed();
443
Phil Nash859760a2013-12-14 14:34:05 +0000444 // Use this in variadic streaming macros to allow
445 // >> +StreamEndStop
446 // as well as
447 // >> stuff +StreamEndStop
448 struct StreamEndStop {
449 std::string operator+() {
450 return std::string();
451 }
452 };
453 template<typename T>
454 T const& operator + ( T const& value, StreamEndStop ) {
455 return value;
456 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100457}
458
Phil Nasha695eb92012-08-13 07:46:10 +0100459#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
460#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100461
Phil Nash3b80af72012-08-09 07:47:30 +0100462#include <ostream>
463
464namespace Catch {
465
466 class NotImplementedException : public std::exception
467 {
468 public:
Phil Nash8defc712013-04-24 19:10:02 +0100469 NotImplementedException( SourceLineInfo const& lineInfo );
Phil Nash9241e432014-05-20 18:50:59 +0100470 NotImplementedException( NotImplementedException const& ) {}
Phil Nash3b80af72012-08-09 07:47:30 +0100471
Phil Nashd7e17902014-04-18 08:49:35 +0100472 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
Phil Nash3b80af72012-08-09 07:47:30 +0100473
Phil Nashd7e17902014-04-18 08:49:35 +0100474 virtual const char* what() const CATCH_NOEXCEPT;
Phil Nash3b80af72012-08-09 07:47:30 +0100475
476 private:
477 std::string m_what;
478 SourceLineInfo m_lineInfo;
479 };
480
481} // end namespace Catch
482
483///////////////////////////////////////////////////////////////////////////////
484#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
485
486// #included from: internal/catch_context.h
487#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
488
Phil Nasha70fbe32012-08-31 08:10:36 +0100489// #included from: catch_interfaces_generators.h
490#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100491
Phil Nasha70fbe32012-08-31 08:10:36 +0100492#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000493
Phil Nash89d2a3f2012-05-16 15:09:17 +0100494namespace Catch {
495
Phil Nasha70fbe32012-08-31 08:10:36 +0100496 struct IGeneratorInfo {
497 virtual ~IGeneratorInfo();
498 virtual bool moveNext() = 0;
499 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000500 };
501
Phil Nasha70fbe32012-08-31 08:10:36 +0100502 struct IGeneratorsForTest {
503 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100504
Phil Nash8defc712013-04-24 19:10:02 +0100505 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +0100506 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000507 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100508
509 IGeneratorsForTest* createGeneratorsForTest();
510
511} // end namespace Catch
512
Phil Nash49e6d532012-05-05 19:35:35 +0100513// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100514#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100515
Phil Nash37186a12013-03-13 12:19:30 +0000516#ifdef __clang__
517#pragma clang diagnostic push
518#pragma clang diagnostic ignored "-Wpadded"
519#endif
520
Phil Nash89d2a3f2012-05-16 15:09:17 +0100521namespace Catch {
522
Phil Nash49e6d532012-05-05 19:35:35 +0100523 // An intrusive reference counting smart pointer.
524 // T must implement addRef() and release() methods
525 // typically implementing the IShared interface
526 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100527 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100528 public:
Phil Nashb971fe72015-07-02 08:21:38 +0100529 Ptr() : m_p( CATCH_NULL ){}
Phil Nash49e6d532012-05-05 19:35:35 +0100530 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100531 if( m_p )
532 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100533 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000534 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100535 if( m_p )
536 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100537 }
538 ~Ptr(){
539 if( m_p )
540 m_p->release();
541 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000542 void reset() {
543 if( m_p )
544 m_p->release();
Phil Nashb971fe72015-07-02 08:21:38 +0100545 m_p = CATCH_NULL;
Phil Nashff03cdf2012-12-06 08:44:51 +0000546 }
Phil Nash49e6d532012-05-05 19:35:35 +0100547 Ptr& operator = ( T* p ){
548 Ptr temp( p );
549 swap( temp );
550 return *this;
551 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000552 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100553 Ptr temp( other );
554 swap( temp );
555 return *this;
556 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000557 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100558 T* get() const{ return m_p; }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000559 T& operator*() const { return *m_p; }
560 T* operator->() const { return m_p; }
Phil Nashb971fe72015-07-02 08:21:38 +0100561 bool operator !() const { return m_p == CATCH_NULL; }
562 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100563
564 private:
565 T* m_p;
566 };
567
568 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100569 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000570 virtual void addRef() const = 0;
571 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100572 };
573
Phil Nasha1fbfea2012-12-01 23:57:18 +0000574 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100575 struct SharedImpl : T {
576
577 SharedImpl() : m_rc( 0 ){}
578
Phil Nasha1fbfea2012-12-01 23:57:18 +0000579 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100580 ++m_rc;
581 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000582 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100583 if( --m_rc == 0 )
584 delete this;
585 }
586
Phil Nasha1fbfea2012-12-01 23:57:18 +0000587 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100588 };
589
590} // end namespace Catch
591
Phil Nash37186a12013-03-13 12:19:30 +0000592#ifdef __clang__
593#pragma clang diagnostic pop
594#endif
595
Phil Nash786959d2013-06-07 19:07:50 +0100596#include <memory>
597#include <vector>
598#include <stdlib.h>
599
600namespace Catch {
601
602 class TestCase;
603 class Stream;
604 struct IResultCapture;
605 struct IRunner;
606 struct IGeneratorsForTest;
607 struct IConfig;
608
609 struct IContext
610 {
611 virtual ~IContext();
612
Phil Nash9241e432014-05-20 18:50:59 +0100613 virtual IResultCapture* getResultCapture() = 0;
614 virtual IRunner* getRunner() = 0;
Phil Nash786959d2013-06-07 19:07:50 +0100615 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
616 virtual bool advanceGeneratorsForCurrentTest() = 0;
617 virtual Ptr<IConfig const> getConfig() const = 0;
618 };
619
620 struct IMutableContext : IContext
621 {
622 virtual ~IMutableContext();
623 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
624 virtual void setRunner( IRunner* runner ) = 0;
625 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
626 };
627
628 IContext& getCurrentContext();
629 IMutableContext& getCurrentMutableContext();
630 void cleanUpContext();
631 Stream createStream( std::string const& streamName );
632
633}
634
635// #included from: internal/catch_test_registry.hpp
636#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
637
638// #included from: catch_interfaces_testcase.h
639#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
640
Phil Nash0f9c5512012-06-02 23:12:42 +0100641#include <vector>
642
643namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100644
Phil Nash65cc14c2014-05-16 18:54:48 +0100645 class TestSpec;
Phil Nash56d5c422012-08-23 20:08:50 +0100646
Phil Nash5bc030d2012-08-16 18:48:50 +0100647 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100648 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100649 protected:
650 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100651 };
652
Phil Nasha1fbfea2012-12-01 23:57:18 +0000653 class TestCase;
Phil Nash20cad7c2014-04-15 18:44:37 +0100654 struct IConfig;
Phil Nash0f9c5512012-06-02 23:12:42 +0100655
656 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100657 virtual ~ITestCaseRegistry();
Phil Nash8defc712013-04-24 19:10:02 +0100658 virtual std::vector<TestCase> const& getAllTests() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +0100659 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100660 };
Phil Nashe73583d2015-08-07 17:30:34 +0100661
662 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
663 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
664 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
665
Phil Nash0f9c5512012-06-02 23:12:42 +0100666}
667
Phil Nash89d2a3f2012-05-16 15:09:17 +0100668namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100669
670template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100671class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100672
Phil Nash176eb812012-05-11 08:17:16 +0100673public:
674 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100675
Phil Nash176eb812012-05-11 08:17:16 +0100676 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100677 C obj;
678 (obj.*m_method)();
679 }
680
Phil Nash89d1e6c2011-05-24 08:23:02 +0100681private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100682 virtual ~MethodTestCase() {}
683
Phil Nash89d1e6c2011-05-24 08:23:02 +0100684 void (C::*m_method)();
685};
686
687typedef void(*TestFunction)();
688
Phil Nash93906752013-03-16 20:21:51 +0000689struct NameAndDesc {
690 NameAndDesc( const char* _name = "", const char* _description= "" )
691 : name( _name ), description( _description )
692 {}
693
694 const char* name;
695 const char* description;
696};
697
Phil Nash7e15d9b2015-11-20 16:59:14 +0000698void registerTestCase
699 ( ITestCase* testCase,
700 char const* className,
701 NameAndDesc const& nameAndDesc,
702 SourceLineInfo const& lineInfo );
703
Phil Nash89d2a3f2012-05-16 15:09:17 +0100704struct AutoReg {
705
Phil Nash7e15d9b2015-11-20 16:59:14 +0000706 AutoReg
707 ( TestFunction function,
708 SourceLineInfo const& lineInfo,
709 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100710
Phil Nash89d1e6c2011-05-24 08:23:02 +0100711 template<typename C>
Phil Nash7e15d9b2015-11-20 16:59:14 +0000712 AutoReg
713 ( void (C::*method)(),
714 char const* className,
715 NameAndDesc const& nameAndDesc,
716 SourceLineInfo const& lineInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100717
Phil Nash7e15d9b2015-11-20 16:59:14 +0000718 registerTestCase
719 ( new MethodTestCase<C>( method ),
720 className,
721 nameAndDesc,
722 lineInfo );
723 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100724
Phil Nash176eb812012-05-11 08:17:16 +0100725 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100726
727private:
Phil Nash8defc712013-04-24 19:10:02 +0100728 AutoReg( AutoReg const& );
729 void operator= ( AutoReg const& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100730};
731
Phil Nash7e15d9b2015-11-20 16:59:14 +0000732void registerTestCaseFunction
733 ( TestFunction function,
734 SourceLineInfo const& lineInfo,
735 NameAndDesc const& nameAndDesc );
736
Phil Nash89d1e6c2011-05-24 08:23:02 +0100737} // end namespace Catch
738
Phil Nash93906752013-03-16 20:21:51 +0000739#ifdef CATCH_CONFIG_VARIADIC_MACROS
740 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000741 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
742 static void TestName(); \
743 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); }\
744 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000745 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000746 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100747
Phil Nash93906752013-03-16 20:21:51 +0000748 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000749 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
750 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100751
Phil Nash93906752013-03-16 20:21:51 +0000752 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000753 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
Phil Nash93906752013-03-16 20:21:51 +0000754 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000755 struct TestName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000756 void test(); \
757 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000758 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000759 } \
Phil Nashc984fc32016-03-15 07:24:26 +0000760 void TestName::test()
761 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
762 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100763
Phil Nash7e15d9b2015-11-20 16:59:14 +0000764 ///////////////////////////////////////////////////////////////////////////////
765 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
766 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) );
767
Phil Nash93906752013-03-16 20:21:51 +0000768#else
769 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000770 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
771 static void TestName(); \
772 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
773 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000774 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000775 INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), Name, Desc )
Phil Nash93906752013-03-16 20:21:51 +0000776
777 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000778 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
779 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); }
780
781 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000782 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
Phil Nash93906752013-03-16 20:21:51 +0000783 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000784 struct TestCaseName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000785 void test(); \
786 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000787 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000788 } \
Phil Nashc984fc32016-03-15 07:24:26 +0000789 void TestCaseName::test()
790 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
791 INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, TestName, Desc )
Phil Nash93906752013-03-16 20:21:51 +0000792
Phil Nash7e15d9b2015-11-20 16:59:14 +0000793 ///////////////////////////////////////////////////////////////////////////////
794 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
795 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) );
Phil Nash93906752013-03-16 20:21:51 +0000796#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100797
798// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100799#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100800
Phil Nashab036682014-06-02 07:48:03 +0100801// #included from: catch_result_builder.h
802#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100803
Phil Nash89d1e6c2011-05-24 08:23:02 +0100804// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100805#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100806
Phil Nash89d2a3f2012-05-16 15:09:17 +0100807namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100808
Phil Nash90a35942012-11-13 22:04:29 +0000809 // ResultWas::OfType enum
810 struct ResultWas { enum OfType {
811 Unknown = -1,
812 Ok = 0,
813 Info = 1,
814 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100815
Phil Nash90a35942012-11-13 22:04:29 +0000816 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100817
Phil Nash90a35942012-11-13 22:04:29 +0000818 ExpressionFailed = FailureBit | 1,
819 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100820
Phil Nash90a35942012-11-13 22:04:29 +0000821 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100822
Phil Nash90a35942012-11-13 22:04:29 +0000823 ThrewException = Exception | 1,
Phil Nash93b61e12014-08-22 19:35:41 +0100824 DidntThrowException = Exception | 2,
825
826 FatalErrorCondition = 0x200 | FailureBit
Phil Nash89d1e6c2011-05-24 08:23:02 +0100827
Phil Nash90a35942012-11-13 22:04:29 +0000828 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100829
Phil Nash90a35942012-11-13 22:04:29 +0000830 inline bool isOk( ResultWas::OfType resultType ) {
831 return ( resultType & ResultWas::FailureBit ) == 0;
832 }
Phil Nasha2773812013-02-02 20:37:58 +0000833 inline bool isJustInfo( int flags ) {
834 return flags == ResultWas::Info;
835 }
Phil Nash67305122012-10-09 11:48:55 +0100836
Phil Nash90a35942012-11-13 22:04:29 +0000837 // ResultDisposition::Flags enum
838 struct ResultDisposition { enum Flags {
Phil Nash318c9362015-05-19 18:40:00 +0100839 Normal = 0x01,
Phil Nash90a35942012-11-13 22:04:29 +0000840
Phil Nash318c9362015-05-19 18:40:00 +0100841 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
842 FalseTest = 0x04, // Prefix expression with !
843 SuppressFail = 0x08 // Failures are reported but do not fail the test
Phil Nash90a35942012-11-13 22:04:29 +0000844 }; };
845
846 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
847 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
848 }
849
Phil Nash3e2e3182012-11-17 10:49:24 +0000850 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
Phil Nashab036682014-06-02 07:48:03 +0100851 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
Phil Nash3e2e3182012-11-17 10:49:24 +0000852 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000853
854} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100855
Phil Nashab036682014-06-02 07:48:03 +0100856// #included from: catch_assertionresult.h
857#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
858
859#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +0100860
Phil Nash89d2a3f2012-05-16 15:09:17 +0100861namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100862
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100863 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
864
865 struct DecomposedExpression
866 {
867 virtual ~DecomposedExpression() {}
868 virtual bool isBinaryExpression() const {
869 return false;
870 }
871 virtual void reconstructExpression( std::string& dest ) const = 0;
872
873 // Only simple binary comparisons can be decomposed.
874 // If more complex check is required then wrap sub-expressions in parentheses.
875 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
876 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
877 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
878 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
879 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
880 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
881 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
882 };
883
Phil Nashce612bf2012-11-01 08:27:09 +0000884 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100885 {
Phil Nashce612bf2012-11-01 08:27:09 +0000886 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100887 AssertionInfo( std::string const& _macroName,
888 SourceLineInfo const& _lineInfo,
889 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000890 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100891
892 std::string macroName;
893 SourceLineInfo lineInfo;
894 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000895 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000896 };
897
898 struct AssertionResultData
899 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100900 AssertionResultData() : decomposedExpression( CATCH_NULL )
901 , resultType( ResultWas::Unknown )
902 , negated( false )
903 , parenthesized( false ) {}
Phil Nashce612bf2012-11-01 08:27:09 +0000904
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100905 void negate( bool parenthesize ) {
906 negated = !negated;
907 parenthesized = parenthesize;
908 if( resultType == ResultWas::Ok )
909 resultType = ResultWas::ExpressionFailed;
910 else if( resultType == ResultWas::ExpressionFailed )
911 resultType = ResultWas::Ok;
912 }
913
914 std::string const& reconstructExpression() const {
915 if( decomposedExpression != CATCH_NULL ) {
916 decomposedExpression->reconstructExpression( reconstructedExpression );
917 if( parenthesized ) {
918 reconstructedExpression.insert( 0, 1, '(' );
919 reconstructedExpression.append( 1, ')' );
920 }
921 if( negated ) {
922 reconstructedExpression.insert( 0, 1, '!' );
923 }
924 decomposedExpression = CATCH_NULL;
925 }
926 return reconstructedExpression;
927 }
928
929 mutable DecomposedExpression const* decomposedExpression;
930 mutable std::string reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +0100931 std::string message;
932 ResultWas::OfType resultType;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100933 bool negated;
934 bool parenthesized;
Phil Nash67305122012-10-09 11:48:55 +0100935 };
936
Phil Nashce612bf2012-11-01 08:27:09 +0000937 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100938 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000939 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100940 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000941 ~AssertionResult();
Phil Nash318c9362015-05-19 18:40:00 +0100942# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +0100943 AssertionResult( AssertionResult const& ) = default;
944 AssertionResult( AssertionResult && ) = default;
945 AssertionResult& operator = ( AssertionResult const& ) = default;
946 AssertionResult& operator = ( AssertionResult && ) = default;
947# endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100948
Phil Nash90a35942012-11-13 22:04:29 +0000949 bool isOk() const;
950 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100951 ResultWas::OfType getResultType() const;
952 bool hasExpression() const;
953 bool hasMessage() const;
954 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +0100955 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100956 bool hasExpandedExpression() const;
957 std::string getExpandedExpression() const;
958 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +0000959 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +0100960 std::string getTestMacroName() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100961 void discardDecomposedExpression() const;
962 void expandDecomposedExpression() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100963
964 protected:
Phil Nashce612bf2012-11-01 08:27:09 +0000965 AssertionInfo m_info;
966 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100967 };
968
969} // end namespace Catch
970
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100971// #included from: catch_matchers.hpp
972#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
973
974namespace Catch {
975namespace Matchers {
976 namespace Impl {
977
Phil Nash08844e72015-11-05 18:52:18 +0000978 namespace Generic {
979 template<typename ExpressionT> class AllOf;
980 template<typename ExpressionT> class AnyOf;
981 template<typename ExpressionT> class Not;
982 }
983
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100984 template<typename ExpressionT>
985 struct Matcher : SharedImpl<IShared>
986 {
987 typedef ExpressionT ExpressionType;
988
989 virtual ~Matcher() {}
990 virtual Ptr<Matcher> clone() const = 0;
991 virtual bool match( ExpressionT const& expr ) const = 0;
992 virtual std::string toString() const = 0;
Phil Nash08844e72015-11-05 18:52:18 +0000993
994 Generic::AllOf<ExpressionT> operator && ( Matcher<ExpressionT> const& other ) const;
995 Generic::AnyOf<ExpressionT> operator || ( Matcher<ExpressionT> const& other ) const;
996 Generic::Not<ExpressionT> operator ! () const;
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100997 };
998
999 template<typename DerivedT, typename ExpressionT>
1000 struct MatcherImpl : Matcher<ExpressionT> {
1001
1002 virtual Ptr<Matcher<ExpressionT> > clone() const {
1003 return Ptr<Matcher<ExpressionT> >( new DerivedT( static_cast<DerivedT const&>( *this ) ) );
1004 }
1005 };
1006
1007 namespace Generic {
Phil Nashd234ed12015-08-24 06:28:25 +01001008 template<typename ExpressionT>
Phil Nash92356762015-11-06 18:06:56 +00001009 class Not : public MatcherImpl<Not<ExpressionT>, ExpressionT> {
1010 public:
Phil Nash08844e72015-11-05 18:52:18 +00001011 explicit Not( Matcher<ExpressionT> const& matcher ) : m_matcher(matcher.clone()) {}
Phil Nashd234ed12015-08-24 06:28:25 +01001012 Not( Not const& other ) : m_matcher( other.m_matcher ) {}
1013
1014 virtual bool match( ExpressionT const& expr ) const CATCH_OVERRIDE {
1015 return !m_matcher->match( expr );
1016 }
1017
1018 virtual std::string toString() const CATCH_OVERRIDE {
1019 return "not " + m_matcher->toString();
1020 }
Phil Nash92356762015-11-06 18:06:56 +00001021 private:
Phil Nashd234ed12015-08-24 06:28:25 +01001022 Ptr< Matcher<ExpressionT> > m_matcher;
1023 };
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001024
1025 template<typename ExpressionT>
1026 class AllOf : public MatcherImpl<AllOf<ExpressionT>, ExpressionT> {
1027 public:
1028
1029 AllOf() {}
1030 AllOf( AllOf const& other ) : m_matchers( other.m_matchers ) {}
1031
1032 AllOf& add( Matcher<ExpressionT> const& matcher ) {
1033 m_matchers.push_back( matcher.clone() );
1034 return *this;
1035 }
1036 virtual bool match( ExpressionT const& expr ) const
1037 {
1038 for( std::size_t i = 0; i < m_matchers.size(); ++i )
1039 if( !m_matchers[i]->match( expr ) )
1040 return false;
1041 return true;
1042 }
1043 virtual std::string toString() const {
1044 std::ostringstream oss;
1045 oss << "( ";
1046 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1047 if( i != 0 )
1048 oss << " and ";
1049 oss << m_matchers[i]->toString();
1050 }
1051 oss << " )";
1052 return oss.str();
1053 }
1054
Phil Nash08844e72015-11-05 18:52:18 +00001055 AllOf operator && ( Matcher<ExpressionT> const& other ) const {
1056 AllOf allOfExpr( *this );
1057 allOfExpr.add( other );
1058 return allOfExpr;
1059 }
1060
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001061 private:
1062 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
1063 };
1064
1065 template<typename ExpressionT>
1066 class AnyOf : public MatcherImpl<AnyOf<ExpressionT>, ExpressionT> {
1067 public:
1068
1069 AnyOf() {}
1070 AnyOf( AnyOf const& other ) : m_matchers( other.m_matchers ) {}
1071
1072 AnyOf& add( Matcher<ExpressionT> const& matcher ) {
1073 m_matchers.push_back( matcher.clone() );
1074 return *this;
1075 }
1076 virtual bool match( ExpressionT const& expr ) const
1077 {
1078 for( std::size_t i = 0; i < m_matchers.size(); ++i )
1079 if( m_matchers[i]->match( expr ) )
1080 return true;
1081 return false;
1082 }
1083 virtual std::string toString() const {
1084 std::ostringstream oss;
1085 oss << "( ";
1086 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1087 if( i != 0 )
1088 oss << " or ";
1089 oss << m_matchers[i]->toString();
1090 }
1091 oss << " )";
1092 return oss.str();
1093 }
1094
Phil Nash08844e72015-11-05 18:52:18 +00001095 AnyOf operator || ( Matcher<ExpressionT> const& other ) const {
1096 AnyOf anyOfExpr( *this );
1097 anyOfExpr.add( other );
1098 return anyOfExpr;
1099 }
1100
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001101 private:
1102 std::vector<Ptr<Matcher<ExpressionT> > > m_matchers;
1103 };
Phil Nash08844e72015-11-05 18:52:18 +00001104
1105 } // namespace Generic
1106
1107 template<typename ExpressionT>
1108 Generic::AllOf<ExpressionT> Matcher<ExpressionT>::operator && ( Matcher<ExpressionT> const& other ) const {
1109 Generic::AllOf<ExpressionT> allOfExpr;
1110 allOfExpr.add( *this );
1111 allOfExpr.add( other );
1112 return allOfExpr;
1113 }
1114
1115 template<typename ExpressionT>
1116 Generic::AnyOf<ExpressionT> Matcher<ExpressionT>::operator || ( Matcher<ExpressionT> const& other ) const {
1117 Generic::AnyOf<ExpressionT> anyOfExpr;
1118 anyOfExpr.add( *this );
1119 anyOfExpr.add( other );
1120 return anyOfExpr;
1121 }
1122
1123 template<typename ExpressionT>
1124 Generic::Not<ExpressionT> Matcher<ExpressionT>::operator ! () const {
1125 return Generic::Not<ExpressionT>( *this );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001126 }
1127
1128 namespace StdString {
1129
1130 inline std::string makeString( std::string const& str ) { return str; }
1131 inline std::string makeString( const char* str ) { return str ? std::string( str ) : std::string(); }
1132
1133 struct CasedString
1134 {
1135 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
1136 : m_caseSensitivity( caseSensitivity ),
1137 m_str( adjustString( str ) )
1138 {}
1139 std::string adjustString( std::string const& str ) const {
1140 return m_caseSensitivity == CaseSensitive::No
1141 ? toLower( str )
1142 : str;
1143
1144 }
1145 std::string toStringSuffix() const
1146 {
1147 return m_caseSensitivity == CaseSensitive::No
1148 ? " (case insensitive)"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001149 : std::string();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001150 }
1151 CaseSensitive::Choice m_caseSensitivity;
1152 std::string m_str;
1153 };
1154
1155 struct Equals : MatcherImpl<Equals, std::string> {
1156 Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1157 : m_data( str, caseSensitivity )
1158 {}
1159 Equals( Equals const& other ) : m_data( other.m_data ){}
1160
1161 virtual ~Equals();
1162
1163 virtual bool match( std::string const& expr ) const {
1164 return m_data.m_str == m_data.adjustString( expr );;
1165 }
1166 virtual std::string toString() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001167 return "equals: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001168 }
1169
1170 CasedString m_data;
1171 };
1172
1173 struct Contains : MatcherImpl<Contains, std::string> {
1174 Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1175 : m_data( substr, caseSensitivity ){}
1176 Contains( Contains const& other ) : m_data( other.m_data ){}
1177
1178 virtual ~Contains();
1179
1180 virtual bool match( std::string const& expr ) const {
1181 return m_data.adjustString( expr ).find( m_data.m_str ) != std::string::npos;
1182 }
1183 virtual std::string toString() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001184 return "contains: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001185 }
1186
1187 CasedString m_data;
1188 };
1189
1190 struct StartsWith : MatcherImpl<StartsWith, std::string> {
1191 StartsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1192 : m_data( substr, caseSensitivity ){}
1193
1194 StartsWith( StartsWith const& other ) : m_data( other.m_data ){}
1195
1196 virtual ~StartsWith();
1197
1198 virtual bool match( std::string const& expr ) const {
Phil Nashc7243562016-01-22 07:52:07 +00001199 return startsWith( m_data.adjustString( expr ), m_data.m_str );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001200 }
1201 virtual std::string toString() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001202 return "starts with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001203 }
1204
1205 CasedString m_data;
1206 };
1207
1208 struct EndsWith : MatcherImpl<EndsWith, std::string> {
1209 EndsWith( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes )
1210 : m_data( substr, caseSensitivity ){}
1211 EndsWith( EndsWith const& other ) : m_data( other.m_data ){}
1212
1213 virtual ~EndsWith();
1214
1215 virtual bool match( std::string const& expr ) const {
Phil Nashc7243562016-01-22 07:52:07 +00001216 return endsWith( m_data.adjustString( expr ), m_data.m_str );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001217 }
1218 virtual std::string toString() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001219 return "ends with: \"" + m_data.m_str + '"' + m_data.toStringSuffix();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001220 }
1221
1222 CasedString m_data;
1223 };
1224 } // namespace StdString
1225 } // namespace Impl
1226
1227 // The following functions create the actual matcher objects.
1228 // This allows the types to be inferred
1229 template<typename ExpressionT>
Phil Nashd234ed12015-08-24 06:28:25 +01001230 inline Impl::Generic::Not<ExpressionT> Not( Impl::Matcher<ExpressionT> const& m ) {
1231 return Impl::Generic::Not<ExpressionT>( m );
1232 }
1233
1234 template<typename ExpressionT>
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001235 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1236 Impl::Matcher<ExpressionT> const& m2 ) {
1237 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 );
1238 }
1239 template<typename ExpressionT>
1240 inline Impl::Generic::AllOf<ExpressionT> AllOf( Impl::Matcher<ExpressionT> const& m1,
1241 Impl::Matcher<ExpressionT> const& m2,
1242 Impl::Matcher<ExpressionT> const& m3 ) {
1243 return Impl::Generic::AllOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1244 }
1245 template<typename ExpressionT>
1246 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1247 Impl::Matcher<ExpressionT> const& m2 ) {
1248 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 );
1249 }
1250 template<typename ExpressionT>
1251 inline Impl::Generic::AnyOf<ExpressionT> AnyOf( Impl::Matcher<ExpressionT> const& m1,
1252 Impl::Matcher<ExpressionT> const& m2,
1253 Impl::Matcher<ExpressionT> const& m3 ) {
1254 return Impl::Generic::AnyOf<ExpressionT>().add( m1 ).add( m2 ).add( m3 );
1255 }
1256
1257 inline Impl::StdString::Equals Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1258 return Impl::StdString::Equals( str, caseSensitivity );
1259 }
1260 inline Impl::StdString::Equals Equals( const char* str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1261 return Impl::StdString::Equals( Impl::StdString::makeString( str ), caseSensitivity );
1262 }
1263 inline Impl::StdString::Contains Contains( std::string const& substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1264 return Impl::StdString::Contains( substr, caseSensitivity );
1265 }
1266 inline Impl::StdString::Contains Contains( const char* substr, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes ) {
1267 return Impl::StdString::Contains( Impl::StdString::makeString( substr ), caseSensitivity );
1268 }
1269 inline Impl::StdString::StartsWith StartsWith( std::string const& substr ) {
1270 return Impl::StdString::StartsWith( substr );
1271 }
1272 inline Impl::StdString::StartsWith StartsWith( const char* substr ) {
1273 return Impl::StdString::StartsWith( Impl::StdString::makeString( substr ) );
1274 }
1275 inline Impl::StdString::EndsWith EndsWith( std::string const& substr ) {
1276 return Impl::StdString::EndsWith( substr );
1277 }
1278 inline Impl::StdString::EndsWith EndsWith( const char* substr ) {
1279 return Impl::StdString::EndsWith( Impl::StdString::makeString( substr ) );
1280 }
1281
1282} // namespace Matchers
1283
1284using namespace Matchers;
1285
1286} // namespace Catch
1287
Phil Nashab036682014-06-02 07:48:03 +01001288namespace Catch {
1289
1290 struct TestFailureException{};
1291
1292 template<typename T> class ExpressionLhs;
1293
Phil Nashab036682014-06-02 07:48:03 +01001294 struct CopyableStream {
1295 CopyableStream() {}
1296 CopyableStream( CopyableStream const& other ) {
1297 oss << other.oss.str();
1298 }
1299 CopyableStream& operator=( CopyableStream const& other ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001300 oss.str(std::string());
Phil Nashab036682014-06-02 07:48:03 +01001301 oss << other.oss.str();
1302 return *this;
1303 }
1304 std::ostringstream oss;
1305 };
1306
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001307 class ResultBuilder : public DecomposedExpression {
Phil Nashab036682014-06-02 07:48:03 +01001308 public:
1309 ResultBuilder( char const* macroName,
1310 SourceLineInfo const& lineInfo,
1311 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01001312 ResultDisposition::Flags resultDisposition,
1313 char const* secondArg = "" );
Phil Nashab036682014-06-02 07:48:03 +01001314
1315 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001316 ExpressionLhs<T const&> operator <= ( T const& operand );
1317 ExpressionLhs<bool> operator <= ( bool value );
Phil Nashab036682014-06-02 07:48:03 +01001318
1319 template<typename T>
1320 ResultBuilder& operator << ( T const& value ) {
1321 m_stream.oss << value;
1322 return *this;
1323 }
1324
Phil Nashab036682014-06-02 07:48:03 +01001325 ResultBuilder& setResultType( ResultWas::OfType result );
1326 ResultBuilder& setResultType( bool result );
Phil Nashab036682014-06-02 07:48:03 +01001327
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001328 void endExpression( DecomposedExpression const& expr );
Phil Nashab036682014-06-02 07:48:03 +01001329
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001330 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
1331
Phil Nashab036682014-06-02 07:48:03 +01001332 AssertionResult build() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001333 AssertionResult build( DecomposedExpression const& expr ) const;
Phil Nashab036682014-06-02 07:48:03 +01001334
1335 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1336 void captureResult( ResultWas::OfType resultType );
1337 void captureExpression();
Phil Nash93a842e2015-07-13 06:36:07 +01001338 void captureExpectedException( std::string const& expectedMessage );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001339 void captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher );
Phil Nash93a842e2015-07-13 06:36:07 +01001340 void handleResult( AssertionResult const& result );
Phil Nashab036682014-06-02 07:48:03 +01001341 void react();
1342 bool shouldDebugBreak() const;
1343 bool allowThrows() const;
1344
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001345 template<typename ArgT, typename MatcherT>
1346 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
1347
Phil Nashab036682014-06-02 07:48:03 +01001348 private:
1349 AssertionInfo m_assertionInfo;
1350 AssertionResultData m_data;
Phil Nashab036682014-06-02 07:48:03 +01001351 CopyableStream m_stream;
1352
1353 bool m_shouldDebugBreak;
1354 bool m_shouldThrow;
1355 };
1356
1357} // namespace Catch
1358
1359// Include after due to circular dependency:
1360// #included from: catch_expression_lhs.hpp
1361#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1362
Phil Nash89d1e6c2011-05-24 08:23:02 +01001363// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001364#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001365
Phil Nashdd26e882013-03-25 09:25:31 +00001366#ifdef _MSC_VER
1367#pragma warning(push)
1368#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
1369#endif
1370
Phil Nash17404952014-04-23 18:19:49 +01001371#include <cstddef>
1372
Phil Nash89d2a3f2012-05-16 15:09:17 +01001373namespace Catch {
1374namespace Internal {
1375
1376 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001377 IsEqualTo,
1378 IsNotEqualTo,
1379 IsLessThan,
1380 IsGreaterThan,
1381 IsLessThanOrEqualTo,
1382 IsGreaterThanOrEqualTo
1383 };
1384
Phil Nash371db8b2012-05-21 18:52:09 +01001385 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1386 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1387 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1388 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1389 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1390 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1391 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +01001392
Phil Nash471eba22013-04-22 18:55:12 +01001393 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001394 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +01001395
1396// nullptr_t support based on pull request #154 from Konstantin Baumann
1397#ifdef CATCH_CONFIG_CPP11_NULLPTR
1398 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1399#endif // CATCH_CONFIG_CPP11_NULLPTR
1400
Phil Nash89d1e6c2011-05-24 08:23:02 +01001401 // So the compare overloads can be operator agnostic we convey the operator as a template
1402 // enum, which is used to specialise an Evaluator for doing the comparison.
1403 template<typename T1, typename T2, Operator Op>
1404 class Evaluator{};
1405
1406 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001407 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001408 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001409 return bool( opCast( lhs ) == opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001410 }
1411 };
1412 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001413 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001414 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001415 return bool( opCast( lhs ) != opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001416 }
1417 };
1418 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001419 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001420 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001421 return bool( opCast( lhs ) < opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001422 }
1423 };
1424 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001425 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001426 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001427 return bool( opCast( lhs ) > opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001428 }
1429 };
1430 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001431 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001432 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001433 return bool( opCast( lhs ) >= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001434 }
1435 };
1436 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001437 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001438 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001439 return bool( opCast( lhs ) <= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001440 }
1441 };
1442
1443 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001444 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001445 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1446 }
1447
Phil Nash90a35942012-11-13 22:04:29 +00001448 // This level of indirection allows us to specialise for integer types
1449 // to avoid signed/ unsigned warnings
1450
Phil Nash89d1e6c2011-05-24 08:23:02 +01001451 // "base" overload
1452 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001453 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001454 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1455 }
1456
1457 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001458 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001459 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1460 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001461 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001462 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1463 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001464 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001465 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1466 }
1467
1468 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001469 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001470 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1471 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001472 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001473 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1474 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001475 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001476 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1477 }
1478
1479 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001480 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001481 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1482 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001483 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001484 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1485 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001486 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001487 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1488 }
1489
1490 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001491 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001492 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001493 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001494 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001495 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001496 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001497 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001498 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001499 }
1500
Phil Nash06e959b2012-05-25 08:52:05 +01001501 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001502 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001503 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001504 }
Phil Nash90a35942012-11-13 22:04:29 +00001505 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001506 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001507 }
1508
Phil Nash06e959b2012-05-25 08:52:05 +01001509 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001510 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001511 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1512 }
Phil Nash90a35942012-11-13 22:04:29 +00001513 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001514 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1515 }
1516
Phil Nash2f6371f2015-07-23 23:06:26 +01001517#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1518 // long long to unsigned X
1519 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1520 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1521 }
1522 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1523 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1524 }
1525 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1526 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1527 }
1528 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1529 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1530 }
1531
1532 // unsigned long long to X
1533 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1534 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1535 }
1536 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1537 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1538 }
1539 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1540 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1541 }
1542 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1543 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1544 }
1545
1546 // pointer to long long (when comparing against NULL)
1547 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1548 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1549 }
1550 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1551 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1552 }
1553#endif // CATCH_CONFIG_CPP11_LONG_LONG
1554
Phil Nash471eba22013-04-22 18:55:12 +01001555#ifdef CATCH_CONFIG_CPP11_NULLPTR
1556 // pointer to nullptr_t (when comparing against nullptr)
1557 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001558 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
Phil Nash471eba22013-04-22 18:55:12 +01001559 }
1560 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001561 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
Phil Nash471eba22013-04-22 18:55:12 +01001562 }
1563#endif // CATCH_CONFIG_CPP11_NULLPTR
1564
Phil Nash89d1e6c2011-05-24 08:23:02 +01001565} // end of namespace Internal
1566} // end of namespace Catch
1567
Phil Nashdd26e882013-03-25 09:25:31 +00001568#ifdef _MSC_VER
1569#pragma warning(pop)
1570#endif
1571
Phil Nashab036682014-06-02 07:48:03 +01001572// #included from: catch_tostring.h
1573#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1574
Phil Nashab036682014-06-02 07:48:03 +01001575#include <sstream>
1576#include <iomanip>
1577#include <limits>
1578#include <vector>
1579#include <cstddef>
1580
1581#ifdef __OBJC__
1582// #included from: catch_objc_arc.hpp
1583#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1584
1585#import <Foundation/Foundation.h>
1586
1587#ifdef __has_feature
1588#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1589#else
1590#define CATCH_ARC_ENABLED 0
1591#endif
1592
1593void arcSafeRelease( NSObject* obj );
1594id performOptionalSelector( id obj, SEL sel );
1595
1596#if !CATCH_ARC_ENABLED
1597inline void arcSafeRelease( NSObject* obj ) {
1598 [obj release];
1599}
1600inline id performOptionalSelector( id obj, SEL sel ) {
1601 if( [obj respondsToSelector: sel] )
1602 return [obj performSelector: sel];
1603 return nil;
1604}
1605#define CATCH_UNSAFE_UNRETAINED
1606#define CATCH_ARC_STRONG
1607#else
1608inline void arcSafeRelease( NSObject* ){}
1609inline id performOptionalSelector( id obj, SEL sel ) {
1610#ifdef __clang__
1611#pragma clang diagnostic push
1612#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1613#endif
1614 if( [obj respondsToSelector: sel] )
1615 return [obj performSelector: sel];
1616#ifdef __clang__
1617#pragma clang diagnostic pop
1618#endif
1619 return nil;
1620}
1621#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1622#define CATCH_ARC_STRONG __strong
1623#endif
1624
1625#endif
1626
Phil Nash318c9362015-05-19 18:40:00 +01001627#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001628#include <tuple>
Phil Nash318c9362015-05-19 18:40:00 +01001629#endif
1630
1631#ifdef CATCH_CONFIG_CPP11_IS_ENUM
Phil Nash7f561522014-12-30 18:47:29 +00001632#include <type_traits>
1633#endif
1634
Phil Nashab036682014-06-02 07:48:03 +01001635namespace Catch {
Phil Nash4caabfa2014-09-03 19:23:22 +01001636
1637// Why we're here.
1638template<typename T>
1639std::string toString( T const& value );
1640
Phil Nash7f561522014-12-30 18:47:29 +00001641// Built in overloads
1642
1643std::string toString( std::string const& value );
1644std::string toString( std::wstring const& value );
1645std::string toString( const char* const value );
1646std::string toString( char* const value );
1647std::string toString( const wchar_t* const value );
1648std::string toString( wchar_t* const value );
1649std::string toString( int value );
1650std::string toString( unsigned long value );
1651std::string toString( unsigned int value );
1652std::string toString( const double value );
1653std::string toString( const float value );
1654std::string toString( bool value );
1655std::string toString( char value );
1656std::string toString( signed char value );
1657std::string toString( unsigned char value );
1658
Phil Nash2f6371f2015-07-23 23:06:26 +01001659#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1660std::string toString( long long value );
1661std::string toString( unsigned long long value );
1662#endif
1663
Phil Nash7f561522014-12-30 18:47:29 +00001664#ifdef CATCH_CONFIG_CPP11_NULLPTR
1665std::string toString( std::nullptr_t );
1666#endif
1667
1668#ifdef __OBJC__
1669 std::string toString( NSString const * const& nsstring );
1670 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1671 std::string toString( NSObject* const& nsObject );
1672#endif
1673
Phil Nashab036682014-06-02 07:48:03 +01001674namespace Detail {
1675
Phil Nash2f6371f2015-07-23 23:06:26 +01001676 extern const std::string unprintableString;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001677
Phil Nashab036682014-06-02 07:48:03 +01001678 struct BorgType {
1679 template<typename T> BorgType( T const& );
1680 };
1681
Phil Nash3b18d9e2015-06-30 18:26:09 +01001682 struct TrueType { char sizer[1]; };
1683 struct FalseType { char sizer[2]; };
1684
Phil Nashab036682014-06-02 07:48:03 +01001685 TrueType& testStreamable( std::ostream& );
1686 FalseType testStreamable( FalseType );
1687
1688 FalseType operator<<( std::ostream const&, BorgType const& );
1689
1690 template<typename T>
1691 struct IsStreamInsertable {
1692 static std::ostream &s;
1693 static T const&t;
1694 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1695 };
1696
Phil Nash318c9362015-05-19 18:40:00 +01001697#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001698 template<typename T,
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001699 bool IsEnum = std::is_enum<T>::value
Phil Nash4caabfa2014-09-03 19:23:22 +01001700 >
1701 struct EnumStringMaker
1702 {
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001703 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001704 };
1705
1706 template<typename T>
1707 struct EnumStringMaker<T,true>
1708 {
1709 static std::string convert( T const& v )
1710 {
1711 return ::Catch::toString(
1712 static_cast<typename std::underlying_type<T>::type>(v)
1713 );
1714 }
1715 };
1716#endif
Phil Nashab036682014-06-02 07:48:03 +01001717 template<bool C>
1718 struct StringMakerBase {
Phil Nash318c9362015-05-19 18:40:00 +01001719#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001720 template<typename T>
1721 static std::string convert( T const& v )
1722 {
1723 return EnumStringMaker<T>::convert( v );
1724 }
1725#else
Phil Nashab036682014-06-02 07:48:03 +01001726 template<typename T>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001727 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001728#endif
Phil Nashab036682014-06-02 07:48:03 +01001729 };
1730
1731 template<>
1732 struct StringMakerBase<true> {
1733 template<typename T>
1734 static std::string convert( T const& _value ) {
1735 std::ostringstream oss;
1736 oss << _value;
1737 return oss.str();
1738 }
1739 };
1740
1741 std::string rawMemoryToString( const void *object, std::size_t size );
1742
1743 template<typename T>
1744 inline std::string rawMemoryToString( const T& object ) {
1745 return rawMemoryToString( &object, sizeof(object) );
Phil Nash67305122012-10-09 11:48:55 +01001746 }
1747
Phil Nashab036682014-06-02 07:48:03 +01001748} // end namespace Detail
Phil Nashce612bf2012-11-01 08:27:09 +00001749
Phil Nashab036682014-06-02 07:48:03 +01001750template<typename T>
Phil Nashab036682014-06-02 07:48:03 +01001751struct StringMaker :
1752 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nashcd688302013-06-29 12:11:32 +01001753
Phil Nashab036682014-06-02 07:48:03 +01001754template<typename T>
1755struct StringMaker<T*> {
1756 template<typename U>
1757 static std::string convert( U* p ) {
1758 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001759 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001760 else
1761 return Detail::rawMemoryToString( p );
1762 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001763};
1764
Phil Nashab036682014-06-02 07:48:03 +01001765template<typename R, typename C>
1766struct StringMaker<R C::*> {
1767 static std::string convert( R C::* p ) {
1768 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001769 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001770 else
1771 return Detail::rawMemoryToString( p );
1772 }
1773};
1774
1775namespace Detail {
1776 template<typename InputIterator>
1777 std::string rangeToString( InputIterator first, InputIterator last );
1778}
1779
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001780//template<typename T, typename Allocator>
1781//struct StringMaker<std::vector<T, Allocator> > {
1782// static std::string convert( std::vector<T,Allocator> const& v ) {
1783// return Detail::rangeToString( v.begin(), v.end() );
1784// }
1785//};
1786
Phil Nashab036682014-06-02 07:48:03 +01001787template<typename T, typename Allocator>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001788std::string toString( std::vector<T,Allocator> const& v ) {
1789 return Detail::rangeToString( v.begin(), v.end() );
1790}
Phil Nashab036682014-06-02 07:48:03 +01001791
Phil Nash318c9362015-05-19 18:40:00 +01001792#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash572911d2015-03-04 18:33:31 +00001793
1794// toString for tuples
Phil Nash7f561522014-12-30 18:47:29 +00001795namespace TupleDetail {
1796 template<
1797 typename Tuple,
1798 std::size_t N = 0,
1799 bool = (N < std::tuple_size<Tuple>::value)
1800 >
1801 struct ElementPrinter {
1802 static void print( const Tuple& tuple, std::ostream& os )
1803 {
1804 os << ( N ? ", " : " " )
1805 << Catch::toString(std::get<N>(tuple));
1806 ElementPrinter<Tuple,N+1>::print(tuple,os);
1807 }
1808 };
1809
1810 template<
1811 typename Tuple,
1812 std::size_t N
1813 >
1814 struct ElementPrinter<Tuple,N,false> {
1815 static void print( const Tuple&, std::ostream& ) {}
1816 };
1817
1818}
1819
1820template<typename ...Types>
1821struct StringMaker<std::tuple<Types...>> {
1822
1823 static std::string convert( const std::tuple<Types...>& tuple )
1824 {
1825 std::ostringstream os;
1826 os << '{';
1827 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1828 os << " }";
1829 return os.str();
1830 }
1831};
Phil Nash318c9362015-05-19 18:40:00 +01001832#endif // CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001833
Phil Nashab036682014-06-02 07:48:03 +01001834namespace Detail {
1835 template<typename T>
1836 std::string makeString( T const& value ) {
1837 return StringMaker<T>::convert( value );
1838 }
1839} // end namespace Detail
1840
1841/// \brief converts any type to a string
1842///
1843/// The default template forwards on to ostringstream - except when an
1844/// ostringstream overload does not exist - in which case it attempts to detect
1845/// that and writes {?}.
1846/// Overload (not specialise) this template for custom typs that you don't want
1847/// to provide an ostream overload for.
1848template<typename T>
1849std::string toString( T const& value ) {
1850 return StringMaker<T>::convert( value );
1851}
1852
Phil Nashab036682014-06-02 07:48:03 +01001853 namespace Detail {
1854 template<typename InputIterator>
1855 std::string rangeToString( InputIterator first, InputIterator last ) {
1856 std::ostringstream oss;
1857 oss << "{ ";
1858 if( first != last ) {
Phil Nash13f98432014-12-12 08:11:18 +00001859 oss << Catch::toString( *first );
1860 for( ++first ; first != last ; ++first )
1861 oss << ", " << Catch::toString( *first );
Phil Nashab036682014-06-02 07:48:03 +01001862 }
1863 oss << " }";
1864 return oss.str();
1865 }
1866}
1867
Phil Nashd31737f2012-05-09 19:04:00 +01001868} // end namespace Catch
1869
Phil Nash89d2a3f2012-05-16 15:09:17 +01001870namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001871
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001872template<typename LhsT, Internal::Operator Op, typename RhsT>
1873class BinaryExpression;
Phil Nash176eb812012-05-11 08:17:16 +01001874
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001875template<typename ArgT, typename MatcherT>
1876class MatchExpression;
1877
1878// Wraps the LHS of an expression and overloads comparison operators
1879// for also capturing those and RHS (if any)
1880template<typename T>
1881class ExpressionLhs : public DecomposedExpression {
Phil Nash176eb812012-05-11 08:17:16 +01001882public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001883 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
Phil Nash176eb812012-05-11 08:17:16 +01001884
1885 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001886 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001887 operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001888 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001889 }
1890
1891 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001892 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001893 operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001894 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001895 }
1896
1897 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001898 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001899 operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001900 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001901 }
1902
1903 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001904 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001905 operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001906 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001907 }
1908
1909 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001910 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001911 operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001912 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001913 }
1914
1915 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001916 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001917 operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001918 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001919 }
1920
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001921 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001922 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001923 }
1924
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001925 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001926 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001927 }
1928
Phil Nashab036682014-06-02 07:48:03 +01001929 void endExpression() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001930 m_truthy = m_lhs ? true : false;
Phil Nashab036682014-06-02 07:48:03 +01001931 m_rb
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001932 .setResultType( m_truthy )
1933 .endExpression( *this );
Phil Nash176eb812012-05-11 08:17:16 +01001934 }
1935
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001936 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1937 dest = Catch::toString( m_truthy );
1938 }
Phil Nash176eb812012-05-11 08:17:16 +01001939
1940private:
Phil Nash9902ac92012-10-09 20:58:33 +01001941 template<Internal::Operator Op, typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001942 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1943 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1944 }
1945
1946 template<Internal::Operator Op>
1947 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1948 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
Phil Nash9902ac92012-10-09 20:58:33 +01001949 }
1950
1951private:
Phil Nashab036682014-06-02 07:48:03 +01001952 ResultBuilder& m_rb;
Phil Nash176eb812012-05-11 08:17:16 +01001953 T m_lhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001954 bool m_truthy;
1955};
1956
1957template<typename LhsT, Internal::Operator Op, typename RhsT>
1958class BinaryExpression : public DecomposedExpression {
1959public:
1960 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1961 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1962
1963 void endExpression() const {
1964 m_rb
1965 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1966 .endExpression( *this );
1967 }
1968
1969 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1970 return true;
1971 }
1972
1973 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1974 std::string lhs = Catch::toString( m_lhs );
1975 std::string rhs = Catch::toString( m_rhs );
1976 char delim = lhs.size() + rhs.size() < 40 &&
1977 lhs.find('\n') == std::string::npos &&
1978 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1979 dest.reserve( 7 + lhs.size() + rhs.size() );
1980 // 2 for spaces around operator
1981 // 2 for operator
1982 // 2 for parentheses (conditionally added later)
1983 // 1 for negation (conditionally added later)
1984 dest = lhs;
1985 dest += delim;
1986 dest += Internal::OperatorTraits<Op>::getName();
1987 dest += delim;
1988 dest += rhs;
1989 }
1990
1991private:
1992 ResultBuilder& m_rb;
1993 LhsT m_lhs;
1994 RhsT m_rhs;
1995};
1996
1997template<typename ArgT, typename MatcherT>
1998class MatchExpression : public DecomposedExpression {
1999public:
2000 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
2001 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
2002
2003 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
2004 return true;
2005 }
2006
2007 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
2008 std::string matcherAsString = m_matcher.toString();
2009 dest = Catch::toString( m_arg );
2010 dest += ' ';
2011 if( matcherAsString == Detail::unprintableString )
2012 dest += m_matcherString;
2013 else
2014 dest += matcherAsString;
2015 }
2016
2017private:
2018 ArgT m_arg;
2019 MatcherT m_matcher;
2020 char const* m_matcherString;
Phil Nash176eb812012-05-11 08:17:16 +01002021};
2022
Phil Nash176eb812012-05-11 08:17:16 +01002023} // end namespace Catch
2024
Phil Nashab036682014-06-02 07:48:03 +01002025
Phil Nash89d2a3f2012-05-16 15:09:17 +01002026namespace Catch {
2027
Phil Nash89d2a3f2012-05-16 15:09:17 +01002028 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01002029 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
Phil Nashab036682014-06-02 07:48:03 +01002030 return ExpressionLhs<T const&>( *this, operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01002031 }
2032
Phil Nash21f7ef62015-06-29 18:05:23 +01002033 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
Phil Nashab036682014-06-02 07:48:03 +01002034 return ExpressionLhs<bool>( *this, value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01002035 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002036
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002037 template<typename ArgT, typename MatcherT>
2038 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
2039 char const* matcherString ) {
2040 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
2041 setResultType( matcher.match( arg ) );
2042 endExpression( expr );
2043 }
2044
Phil Nashab036682014-06-02 07:48:03 +01002045} // namespace Catch
Phil Nash89d2a3f2012-05-16 15:09:17 +01002046
Phil Nasha2773812013-02-02 20:37:58 +00002047// #included from: catch_message.h
2048#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
2049
2050#include <string>
2051
2052namespace Catch {
2053
2054 struct MessageInfo {
2055 MessageInfo( std::string const& _macroName,
2056 SourceLineInfo const& _lineInfo,
2057 ResultWas::OfType _type );
2058
2059 std::string macroName;
2060 SourceLineInfo lineInfo;
2061 ResultWas::OfType type;
2062 std::string message;
2063 unsigned int sequence;
2064
2065 bool operator == ( MessageInfo const& other ) const {
2066 return sequence == other.sequence;
2067 }
2068 bool operator < ( MessageInfo const& other ) const {
2069 return sequence < other.sequence;
2070 }
2071 private:
2072 static unsigned int globalCount;
2073 };
2074
Phil Nashb5fd5a62013-06-28 17:09:57 +01002075 struct MessageBuilder {
2076 MessageBuilder( std::string const& macroName,
2077 SourceLineInfo const& lineInfo,
2078 ResultWas::OfType type )
2079 : m_info( macroName, lineInfo, type )
2080 {}
Phil Nasha2773812013-02-02 20:37:58 +00002081
2082 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01002083 MessageBuilder& operator << ( T const& value ) {
2084 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00002085 return *this;
2086 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01002087
2088 MessageInfo m_info;
2089 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00002090 };
2091
Phil Nashb5fd5a62013-06-28 17:09:57 +01002092 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00002093 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01002094 ScopedMessage( MessageBuilder const& builder );
Phil Nash9241e432014-05-20 18:50:59 +01002095 ScopedMessage( ScopedMessage const& other );
Phil Nashb5fd5a62013-06-28 17:09:57 +01002096 ~ScopedMessage();
2097
2098 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00002099 };
2100
2101} // end namespace Catch
2102
Phil Nashd31737f2012-05-09 19:04:00 +01002103// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01002104#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01002105
Phil Nashd31737f2012-05-09 19:04:00 +01002106#include <string>
2107
Phil Nash89d2a3f2012-05-16 15:09:17 +01002108namespace Catch {
2109
Phil Nasha1fbfea2012-12-01 23:57:18 +00002110 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00002111 class AssertionResult;
2112 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002113 struct SectionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002114 struct SectionEndInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01002115 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00002116 class ScopedMessageBuilder;
Phil Nash3649fdf2013-12-03 18:53:55 +00002117 struct Counts;
Phil Nashd31737f2012-05-09 19:04:00 +01002118
Phil Nash89d2a3f2012-05-16 15:09:17 +01002119 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01002120
Phil Nasha695eb92012-08-13 07:46:10 +01002121 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002122
Phil Nasha2773812013-02-02 20:37:58 +00002123 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002124 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01002125 Counts& assertions ) = 0;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002126 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2127 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01002128 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2129 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00002130
Phil Nash89d2a3f2012-05-16 15:09:17 +01002131 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00002132 virtual const AssertionResult* getLastResult() const = 0;
Phil Nash93b61e12014-08-22 19:35:41 +01002133
2134 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01002135 };
Phil Nashab036682014-06-02 07:48:03 +01002136
2137 IResultCapture& getResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002138}
2139
Phil Nash3649fdf2013-12-03 18:53:55 +00002140// #included from: catch_debugger.h
2141#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01002142
Phil Nash04a33642013-08-16 19:09:09 +01002143// #included from: catch_platform.h
2144#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2145
Phil Nashd31737f2012-05-09 19:04:00 +01002146#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002147# define CATCH_PLATFORM_MAC
Phil Nashd31737f2012-05-09 19:04:00 +01002148#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002149# define CATCH_PLATFORM_IPHONE
2150#elif defined(linux) || defined(__linux) || defined(__linux__)
2151# define CATCH_PLATFORM_LINUX
Phil Nash04a33642013-08-16 19:09:09 +01002152#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002153# define CATCH_PLATFORM_WINDOWS
2154# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2155# define CATCH_DEFINES_NOMINMAX
2156# endif
2157# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2158# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2159# endif
Phil Nashd31737f2012-05-09 19:04:00 +01002160#endif
2161
Phil Nash3649fdf2013-12-03 18:53:55 +00002162#include <string>
2163
2164namespace Catch{
2165
2166 bool isDebuggerActive();
2167 void writeToDebugConsole( std::string const& text );
2168}
2169
Phil Nashd31737f2012-05-09 19:04:00 +01002170#ifdef CATCH_PLATFORM_MAC
2171
Phil Nash3649fdf2013-12-03 18:53:55 +00002172 // The following code snippet based on:
Phil Nashd31737f2012-05-09 19:04:00 +01002173 // http://cocoawithlove.com/2008/03/break-into-debugger.html
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002174 #if defined(__ppc64__) || defined(__ppc__)
2175 #define CATCH_TRAP() \
2176 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2177 : : : "memory","r0","r3","r4" )
2178 #else
2179 #define CATCH_TRAP() __asm__("int $3\n" : : )
Phil Nashd31737f2012-05-09 19:04:00 +01002180 #endif
2181
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002182#elif defined(CATCH_PLATFORM_LINUX)
2183 // If we can use inline assembler, do it because this allows us to break
2184 // directly at the location of the failing check instead of breaking inside
2185 // raise() called from it, i.e. one stack frame below.
2186 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2187 #define CATCH_TRAP() asm volatile ("int $3")
2188 #else // Fall back to the generic way.
2189 #include <signal.h>
2190
2191 #define CATCH_TRAP() raise(SIGTRAP)
2192 #endif
Phil Nashd31737f2012-05-09 19:04:00 +01002193#elif defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002194 #define CATCH_TRAP() __debugbreak()
Phil Nash176eb812012-05-11 08:17:16 +01002195#elif defined(__MINGW32__)
Phil Nash176eb812012-05-11 08:17:16 +01002196 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002197 #define CATCH_TRAP() DebugBreak()
Phil Nashd31737f2012-05-09 19:04:00 +01002198#endif
2199
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002200#ifdef CATCH_TRAP
2201 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2202#else
2203 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
Phil Nash3649fdf2013-12-03 18:53:55 +00002204#endif
Phil Nashd31737f2012-05-09 19:04:00 +01002205
Phil Nashab036682014-06-02 07:48:03 +01002206// #included from: catch_interfaces_runner.h
2207#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash37186a12013-03-13 12:19:30 +00002208
Phil Nasha70fbe32012-08-31 08:10:36 +01002209namespace Catch {
Phil Nash3649fdf2013-12-03 18:53:55 +00002210 class TestCase;
Phil Nasha70fbe32012-08-31 08:10:36 +01002211
Phil Nashab036682014-06-02 07:48:03 +01002212 struct IRunner {
2213 virtual ~IRunner();
2214 virtual bool aborting() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002215 };
2216}
2217
Phil Nashce612bf2012-11-01 08:27:09 +00002218///////////////////////////////////////////////////////////////////////////////
Phil Nashab036682014-06-02 07:48:03 +01002219// In the event of a failure works out if the debugger needs to be invoked
2220// and/or an exception thrown and takes appropriate action.
2221// This needs to be done as a macro so the debugger will stop in the user
2222// source code rather than in Catch library code
2223#define INTERNAL_CATCH_REACT( resultBuilder ) \
2224 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2225 resultBuilder.react();
Phil Nashce612bf2012-11-01 08:27:09 +00002226
2227///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002228#define INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002229 do { \
Phil Nashab036682014-06-02 07:48:03 +01002230 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002231 try { \
Phil Nashae5ee2c2016-02-29 08:17:18 +00002232 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
Phil Nash21f7ef62015-06-29 18:05:23 +01002233 ( __catchResult <= expr ).endExpression(); \
Phil Nashce612bf2012-11-01 08:27:09 +00002234 } \
Phil Nashab036682014-06-02 07:48:03 +01002235 catch( ... ) { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002236 __catchResult.useActiveException( resultDisposition ); \
Phil Nashab036682014-06-02 07:48:03 +01002237 } \
2238 INTERNAL_CATCH_REACT( __catchResult ) \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002239 } 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
2240 // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
Phil Nashce612bf2012-11-01 08:27:09 +00002241
2242///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002243#define INTERNAL_CATCH_IF( expr, resultDisposition, macroName ) \
2244 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2245 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002246
2247///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002248#define INTERNAL_CATCH_ELSE( expr, resultDisposition, macroName ) \
2249 INTERNAL_CATCH_TEST( expr, resultDisposition, macroName ); \
2250 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002251
2252///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002253#define INTERNAL_CATCH_NO_THROW( expr, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002254 do { \
Phil Nashab036682014-06-02 07:48:03 +01002255 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002256 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002257 static_cast<void>(expr); \
Phil Nashab036682014-06-02 07:48:03 +01002258 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002259 } \
2260 catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002261 __catchResult.useActiveException( resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002262 } \
Phil Nashab036682014-06-02 07:48:03 +01002263 INTERNAL_CATCH_REACT( __catchResult ) \
2264 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002265
2266///////////////////////////////////////////////////////////////////////////////
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002267#define INTERNAL_CATCH_THROWS( expr, resultDisposition, matcher, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002268 do { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002270 if( __catchResult.allowThrows() ) \
2271 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002272 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002273 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2274 } \
2275 catch( ... ) { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002276 __catchResult.captureExpectedException( matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002277 } \
2278 else \
Phil Nashab036682014-06-02 07:48:03 +01002279 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002280 INTERNAL_CATCH_REACT( __catchResult ) \
2281 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002282
2283///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002284#define INTERNAL_CATCH_THROWS_AS( expr, exceptionType, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002285 do { \
Phil Nashab036682014-06-02 07:48:03 +01002286 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002287 if( __catchResult.allowThrows() ) \
2288 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002289 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002290 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2291 } \
2292 catch( exceptionType ) { \
2293 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2294 } \
2295 catch( ... ) { \
2296 __catchResult.useActiveException( resultDisposition ); \
2297 } \
2298 else \
Phil Nashab036682014-06-02 07:48:03 +01002299 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002300 INTERNAL_CATCH_REACT( __catchResult ) \
2301 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002302
2303///////////////////////////////////////////////////////////////////////////////
Phil Nash859760a2013-12-14 14:34:05 +00002304#ifdef CATCH_CONFIG_VARIADIC_MACROS
2305 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, ... ) \
2306 do { \
Phil Nashab036682014-06-02 07:48:03 +01002307 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2308 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2309 __catchResult.captureResult( messageType ); \
2310 INTERNAL_CATCH_REACT( __catchResult ) \
2311 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002312#else
2313 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2314 do { \
Phil Nashab036682014-06-02 07:48:03 +01002315 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2316 __catchResult << log + ::Catch::StreamEndStop(); \
2317 __catchResult.captureResult( messageType ); \
2318 INTERNAL_CATCH_REACT( __catchResult ) \
2319 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002320#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002321
2322///////////////////////////////////////////////////////////////////////////////
Phil Nashb5fd5a62013-06-28 17:09:57 +01002323#define INTERNAL_CATCH_INFO( log, macroName ) \
2324 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00002325
2326///////////////////////////////////////////////////////////////////////////////
Phil Nash90a35942012-11-13 22:04:29 +00002327#define INTERNAL_CHECK_THAT( arg, matcher, resultDisposition, macroName ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002328 do { \
Phil Nash7424b232015-12-28 15:07:32 +00002329 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002330 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002331 __catchResult.captureMatch( arg, matcher, #matcher ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002332 } catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002333 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002334 } \
Phil Nashab036682014-06-02 07:48:03 +01002335 INTERNAL_CATCH_REACT( __catchResult ) \
2336 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002337
Phil Nash3649fdf2013-12-03 18:53:55 +00002338// #included from: internal/catch_section.h
2339#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2340
2341// #included from: catch_section_info.h
2342#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2343
Phil Nash3649fdf2013-12-03 18:53:55 +00002344// #included from: catch_totals.hpp
2345#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2346
2347#include <cstddef>
2348
2349namespace Catch {
2350
2351 struct Counts {
Phil Nash52e1e742014-07-03 08:11:38 +01002352 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
Phil Nash3649fdf2013-12-03 18:53:55 +00002353
2354 Counts operator - ( Counts const& other ) const {
2355 Counts diff;
2356 diff.passed = passed - other.passed;
2357 diff.failed = failed - other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002358 diff.failedButOk = failedButOk - other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002359 return diff;
2360 }
2361 Counts& operator += ( Counts const& other ) {
2362 passed += other.passed;
2363 failed += other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002364 failedButOk += other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002365 return *this;
2366 }
2367
2368 std::size_t total() const {
Phil Nash52e1e742014-07-03 08:11:38 +01002369 return passed + failed + failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002370 }
Phil Nash28c2e072014-07-09 19:22:49 +01002371 bool allPassed() const {
2372 return failed == 0 && failedButOk == 0;
2373 }
Phil Nashd76e0812014-12-30 18:26:07 +00002374 bool allOk() const {
2375 return failed == 0;
2376 }
Phil Nash3649fdf2013-12-03 18:53:55 +00002377
2378 std::size_t passed;
2379 std::size_t failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002380 std::size_t failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002381 };
2382
2383 struct Totals {
2384
2385 Totals operator - ( Totals const& other ) const {
2386 Totals diff;
2387 diff.assertions = assertions - other.assertions;
2388 diff.testCases = testCases - other.testCases;
2389 return diff;
2390 }
2391
2392 Totals delta( Totals const& prevTotals ) const {
2393 Totals diff = *this - prevTotals;
2394 if( diff.assertions.failed > 0 )
2395 ++diff.testCases.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002396 else if( diff.assertions.failedButOk > 0 )
2397 ++diff.testCases.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002398 else
2399 ++diff.testCases.passed;
2400 return diff;
2401 }
2402
2403 Totals& operator += ( Totals const& other ) {
2404 assertions += other.assertions;
2405 testCases += other.testCases;
2406 return *this;
2407 }
2408
2409 Counts assertions;
2410 Counts testCases;
2411 };
2412}
Phil Nashce612bf2012-11-01 08:27:09 +00002413
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002414namespace Catch {
2415
2416 struct SectionInfo {
2417 SectionInfo
2418 ( SourceLineInfo const& _lineInfo,
2419 std::string const& _name,
2420 std::string const& _description = std::string() );
2421
2422 std::string name;
2423 std::string description;
2424 SourceLineInfo lineInfo;
2425 };
2426
2427 struct SectionEndInfo {
2428 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2429 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2430 {}
2431
2432 SectionInfo sectionInfo;
2433 Counts prevAssertions;
2434 double durationInSeconds;
2435 };
2436
2437} // end namespace Catch
2438
Phil Nashaa7123b2013-08-15 19:01:00 +01002439// #included from: catch_timer.h
2440#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2441
Phil Nash04a33642013-08-16 19:09:09 +01002442#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01002443typedef unsigned long long uint64_t;
2444#else
2445#include <stdint.h>
2446#endif
2447
2448namespace Catch {
2449
2450 class Timer {
2451 public:
2452 Timer() : m_ticks( 0 ) {}
2453 void start();
Phil Nash4caabfa2014-09-03 19:23:22 +01002454 unsigned int getElapsedMicroseconds() const;
Phil Nashaa7123b2013-08-15 19:01:00 +01002455 unsigned int getElapsedMilliseconds() const;
2456 double getElapsedSeconds() const;
2457
2458 private:
2459 uint64_t m_ticks;
2460 };
2461
2462} // namespace Catch
2463
Phil Nashce612bf2012-11-01 08:27:09 +00002464#include <string>
2465
2466namespace Catch {
2467
Phil Nashe54ac702014-10-21 07:25:26 +01002468 class Section : NonCopyable {
Phil Nashce612bf2012-11-01 08:27:09 +00002469 public:
Phil Nashce562092014-07-09 07:40:37 +01002470 Section( SectionInfo const& info );
Phil Nash3649fdf2013-12-03 18:53:55 +00002471 ~Section();
Phil Nashce612bf2012-11-01 08:27:09 +00002472
2473 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01002474 operator bool() const;
Phil Nashce612bf2012-11-01 08:27:09 +00002475
2476 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002477 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00002478
2479 std::string m_name;
2480 Counts m_assertions;
2481 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01002482 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00002483 };
2484
2485} // end namespace Catch
2486
Phil Nash93906752013-03-16 20:21:51 +00002487#ifdef CATCH_CONFIG_VARIADIC_MACROS
2488 #define INTERNAL_CATCH_SECTION( ... ) \
Phil Nashce562092014-07-09 07:40:37 +01002489 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 +00002490#else
2491 #define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashce562092014-07-09 07:40:37 +01002492 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 +00002493#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002494
2495// #included from: internal/catch_generators.hpp
2496#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2497
2498#include <iterator>
2499#include <vector>
2500#include <string>
2501#include <stdlib.h>
2502
2503namespace Catch {
2504
2505template<typename T>
2506struct IGenerator {
2507 virtual ~IGenerator() {}
2508 virtual T getValue( std::size_t index ) const = 0;
2509 virtual std::size_t size () const = 0;
2510};
2511
2512template<typename T>
2513class BetweenGenerator : public IGenerator<T> {
2514public:
2515 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2516
2517 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00002518 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00002519 }
2520
2521 virtual std::size_t size() const {
2522 return static_cast<std::size_t>( 1+m_to-m_from );
2523 }
2524
2525private:
2526
2527 T m_from;
2528 T m_to;
2529};
2530
2531template<typename T>
2532class ValuesGenerator : public IGenerator<T> {
2533public:
2534 ValuesGenerator(){}
2535
2536 void add( T value ) {
2537 m_values.push_back( value );
2538 }
2539
2540 virtual T getValue( std::size_t index ) const {
2541 return m_values[index];
2542 }
2543
2544 virtual std::size_t size() const {
2545 return m_values.size();
2546 }
2547
2548private:
2549 std::vector<T> m_values;
2550};
2551
2552template<typename T>
2553class CompositeGenerator {
2554public:
2555 CompositeGenerator() : m_totalSize( 0 ) {}
2556
Phil Nasha04981b2013-03-08 09:30:25 +00002557 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00002558 CompositeGenerator( CompositeGenerator& other )
2559 : m_fileInfo( other.m_fileInfo ),
2560 m_totalSize( 0 )
2561 {
Phil Nasha04981b2013-03-08 09:30:25 +00002562 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00002563 }
2564
2565 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2566 m_fileInfo = fileInfo;
2567 return *this;
2568 }
2569
2570 ~CompositeGenerator() {
2571 deleteAll( m_composed );
2572 }
2573
2574 operator T () const {
2575 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2576
2577 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2578 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2579 for( size_t index = 0; it != itEnd; ++it )
2580 {
2581 const IGenerator<T>* generator = *it;
2582 if( overallIndex >= index && overallIndex < index + generator->size() )
2583 {
2584 return generator->getValue( overallIndex-index );
2585 }
2586 index += generator->size();
2587 }
2588 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00002589 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 +00002590 }
2591
2592 void add( const IGenerator<T>* generator ) {
2593 m_totalSize += generator->size();
2594 m_composed.push_back( generator );
2595 }
2596
2597 CompositeGenerator& then( CompositeGenerator& other ) {
2598 move( other );
2599 return *this;
2600 }
2601
2602 CompositeGenerator& then( T value ) {
2603 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2604 valuesGen->add( value );
2605 add( valuesGen );
2606 return *this;
2607 }
2608
2609private:
2610
2611 void move( CompositeGenerator& other ) {
2612 std::copy( other.m_composed.begin(), other.m_composed.end(), std::back_inserter( m_composed ) );
2613 m_totalSize += other.m_totalSize;
2614 other.m_composed.clear();
2615 }
2616
2617 std::vector<const IGenerator<T>*> m_composed;
2618 std::string m_fileInfo;
2619 size_t m_totalSize;
2620};
2621
2622namespace Generators
2623{
2624 template<typename T>
2625 CompositeGenerator<T> between( T from, T to ) {
2626 CompositeGenerator<T> generators;
2627 generators.add( new BetweenGenerator<T>( from, to ) );
2628 return generators;
2629 }
2630
2631 template<typename T>
2632 CompositeGenerator<T> values( T val1, T val2 ) {
2633 CompositeGenerator<T> generators;
2634 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2635 valuesGen->add( val1 );
2636 valuesGen->add( val2 );
2637 generators.add( valuesGen );
2638 return generators;
2639 }
2640
2641 template<typename T>
2642 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2643 CompositeGenerator<T> generators;
2644 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2645 valuesGen->add( val1 );
2646 valuesGen->add( val2 );
2647 valuesGen->add( val3 );
2648 generators.add( valuesGen );
2649 return generators;
2650 }
2651
2652 template<typename T>
2653 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2654 CompositeGenerator<T> generators;
2655 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2656 valuesGen->add( val1 );
2657 valuesGen->add( val2 );
2658 valuesGen->add( val3 );
2659 valuesGen->add( val4 );
2660 generators.add( valuesGen );
2661 return generators;
2662 }
2663
2664} // end namespace Generators
2665
2666using namespace Generators;
2667
2668} // end namespace Catch
2669
2670#define INTERNAL_CATCH_LINESTR2( line ) #line
2671#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2672
2673#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2674
2675// #included from: internal/catch_interfaces_exception.h
2676#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2677
2678#include <string>
Phil Nashe4fa62a2015-11-18 08:39:54 +00002679#include <vector>
2680
Phil Nashab036682014-06-02 07:48:03 +01002681// #included from: catch_interfaces_registry_hub.h
2682#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2683
2684#include <string>
2685
2686namespace Catch {
2687
2688 class TestCase;
2689 struct ITestCaseRegistry;
2690 struct IExceptionTranslatorRegistry;
2691 struct IExceptionTranslator;
2692 struct IReporterRegistry;
2693 struct IReporterFactory;
2694
2695 struct IRegistryHub {
2696 virtual ~IRegistryHub();
2697
2698 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2699 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
2700 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2701 };
2702
2703 struct IMutableRegistryHub {
2704 virtual ~IMutableRegistryHub();
Phil Nashe73583d2015-08-07 17:30:34 +01002705 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2706 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
Phil Nashab036682014-06-02 07:48:03 +01002707 virtual void registerTest( TestCase const& testInfo ) = 0;
2708 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
2709 };
2710
2711 IRegistryHub& getRegistryHub();
2712 IMutableRegistryHub& getMutableRegistryHub();
2713 void cleanUp();
2714 std::string translateActiveException();
2715
2716}
2717
Phil Nash89d2a3f2012-05-16 15:09:17 +01002718namespace Catch {
2719
Phil Nash89d1e6c2011-05-24 08:23:02 +01002720 typedef std::string(*exceptionTranslateFunction)();
2721
Phil Nashe4fa62a2015-11-18 08:39:54 +00002722 struct IExceptionTranslator;
2723 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2724
Phil Nash89d2a3f2012-05-16 15:09:17 +01002725 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002726 virtual ~IExceptionTranslator();
Phil Nashe4fa62a2015-11-18 08:39:54 +00002727 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002728 };
2729
Phil Nash89d2a3f2012-05-16 15:09:17 +01002730 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002731 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002732
Phil Nash89d2a3f2012-05-16 15:09:17 +01002733 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002734 };
2735
Phil Nash89d2a3f2012-05-16 15:09:17 +01002736 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002737 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002738 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002739 public:
2740
Phil Nash89d2a3f2012-05-16 15:09:17 +01002741 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002742 : m_translateFunction( translateFunction )
2743 {}
2744
Phil Nashe4fa62a2015-11-18 08:39:54 +00002745 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002746 try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00002747 if( it == itEnd )
2748 throw;
2749 else
2750 return (*it)->translate( it+1, itEnd );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002751 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002752 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002753 return m_translateFunction( ex );
2754 }
2755 }
2756
2757 protected:
2758 std::string(*m_translateFunction)( T& );
2759 };
2760
2761 public:
2762 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002763 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002764 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002765 ( new ExceptionTranslator<T>( translateFunction ) );
2766 }
2767 };
2768}
2769
2770///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +00002771#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2772 static std::string translatorName( signature ); \
2773 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2774 static std::string translatorName( signature )
2775
2776#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002777
2778// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002779#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002780
Phil Nash89d1e6c2011-05-24 08:23:02 +01002781#include <cmath>
2782#include <limits>
2783
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002784#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2785#include <type_traits>
2786#endif
2787
Phil Nash89d2a3f2012-05-16 15:09:17 +01002788namespace Catch {
2789namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002790
Phil Nash89d2a3f2012-05-16 15:09:17 +01002791 class Approx {
2792 public:
2793 explicit Approx ( double value )
2794 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
2795 m_scale( 1.0 ),
2796 m_value( value )
2797 {}
Phil Nashf721a962011-06-07 14:13:57 +01002798
Phil Nash8defc712013-04-24 19:10:02 +01002799 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01002800 : m_epsilon( other.m_epsilon ),
2801 m_scale( other.m_scale ),
2802 m_value( other.m_value )
2803 {}
Phil Nashf721a962011-06-07 14:13:57 +01002804
Phil Nash89d2a3f2012-05-16 15:09:17 +01002805 static Approx custom() {
2806 return Approx( 0 );
2807 }
Phil Nashf721a962011-06-07 14:13:57 +01002808
Phil Nash89d2a3f2012-05-16 15:09:17 +01002809 Approx operator()( double value ) {
2810 Approx approx( value );
2811 approx.epsilon( m_epsilon );
2812 approx.scale( m_scale );
2813 return approx;
2814 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002815
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002816#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2817 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2818 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2819 // Thanks to Richard Harris for his help refining this formula
2820 auto lhs_v = double(lhs);
2821 return fabs( lhs_v - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs_v), fabs(rhs.m_value) ) );
2822 }
2823
2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2825 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2826 return operator==( rhs, lhs );
2827 }
2828
2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2830 friend bool operator != ( T lhs, Approx const& rhs ) {
2831 return !operator==( lhs, rhs );
2832 }
2833
2834 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2835 friend bool operator != ( Approx const& lhs, T rhs ) {
2836 return !operator==( rhs, lhs );
2837 }
2838
2839 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2840 friend bool operator <= ( T lhs, Approx const& rhs )
2841 {
2842 return double(lhs) < rhs.m_value || lhs == rhs;
2843 }
2844
2845 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2846 friend bool operator <= ( Approx const& lhs, T rhs )
2847 {
2848 return lhs.m_value < double(rhs) || lhs == rhs;
2849 }
2850
2851 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2852 friend bool operator >= ( T lhs, Approx const& rhs )
2853 {
2854 return double(lhs) > rhs.m_value || lhs == rhs;
2855 }
2856
2857 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2858 friend bool operator >= ( Approx const& lhs, T rhs )
2859 {
2860 return lhs.m_value > double(rhs) || lhs == rhs;
2861 }
2862#else
Phil Nash8defc712013-04-24 19:10:02 +01002863 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002864 // Thanks to Richard Harris for his help refining this formula
2865 return fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( fabs(lhs), fabs(rhs.m_value) ) );
2866 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002867
Phil Nash8defc712013-04-24 19:10:02 +01002868 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002869 return operator==( rhs, lhs );
2870 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002871
Phil Nash8defc712013-04-24 19:10:02 +01002872 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002873 return !operator==( lhs, rhs );
2874 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002875
Phil Nash8defc712013-04-24 19:10:02 +01002876 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002877 return !operator==( rhs, lhs );
2878 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002879
Phil Nash3b2f2062017-01-11 16:43:56 +00002880 friend bool operator <= ( double lhs, Approx const& rhs )
2881 {
2882 return lhs < rhs.m_value || lhs == rhs;
2883 }
2884
2885 friend bool operator <= ( Approx const& lhs, double rhs )
2886 {
2887 return lhs.m_value < rhs || lhs == rhs;
2888 }
2889
2890 friend bool operator >= ( double lhs, Approx const& rhs )
2891 {
2892 return lhs > rhs.m_value || lhs == rhs;
2893 }
2894
2895 friend bool operator >= ( Approx const& lhs, double rhs )
2896 {
2897 return lhs.m_value > rhs || lhs == rhs;
2898 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002899#endif
Phil Nash3b2f2062017-01-11 16:43:56 +00002900
Phil Nash89d2a3f2012-05-16 15:09:17 +01002901 Approx& epsilon( double newEpsilon ) {
2902 m_epsilon = newEpsilon;
2903 return *this;
2904 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002905
Phil Nash89d2a3f2012-05-16 15:09:17 +01002906 Approx& scale( double newScale ) {
2907 m_scale = newScale;
2908 return *this;
2909 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002910
Phil Nash89d2a3f2012-05-16 15:09:17 +01002911 std::string toString() const {
2912 std::ostringstream oss;
Phil Nashf385a0b2013-12-19 18:42:25 +00002913 oss << "Approx( " << Catch::toString( m_value ) << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002914 return oss.str();
2915 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002916
Phil Nash89d2a3f2012-05-16 15:09:17 +01002917 private:
2918 double m_epsilon;
2919 double m_scale;
2920 double m_value;
2921 };
2922}
2923
2924template<>
Phil Nash8defc712013-04-24 19:10:02 +01002925inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002926 return value.toString();
2927}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002928
2929} // end namespace Catch
2930
Phil Nashacdd3b52014-06-30 07:35:36 +01002931// #included from: internal/catch_interfaces_tag_alias_registry.h
2932#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
2933
2934// #included from: catch_tag_alias.h
2935#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
2936
2937#include <string>
2938
2939namespace Catch {
2940
2941 struct TagAlias {
2942 TagAlias( std::string _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
2943
2944 std::string tag;
2945 SourceLineInfo lineInfo;
2946 };
2947
2948 struct RegistrarForTagAliases {
2949 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
2950 };
2951
2952} // end namespace Catch
2953
2954#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
2955// #included from: catch_option.hpp
2956#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
2957
2958namespace Catch {
2959
2960 // An optional type
2961 template<typename T>
2962 class Option {
2963 public:
Phil Nashb971fe72015-07-02 08:21:38 +01002964 Option() : nullableValue( CATCH_NULL ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01002965 Option( T const& _value )
2966 : nullableValue( new( storage ) T( _value ) )
2967 {}
2968 Option( Option const& _other )
Phil Nashb971fe72015-07-02 08:21:38 +01002969 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
Phil Nashacdd3b52014-06-30 07:35:36 +01002970 {}
2971
2972 ~Option() {
2973 reset();
2974 }
2975
2976 Option& operator= ( Option const& _other ) {
2977 if( &_other != this ) {
2978 reset();
2979 if( _other )
2980 nullableValue = new( storage ) T( *_other );
2981 }
2982 return *this;
2983 }
2984 Option& operator = ( T const& _value ) {
2985 reset();
2986 nullableValue = new( storage ) T( _value );
2987 return *this;
2988 }
2989
2990 void reset() {
2991 if( nullableValue )
2992 nullableValue->~T();
Phil Nashb971fe72015-07-02 08:21:38 +01002993 nullableValue = CATCH_NULL;
Phil Nashacdd3b52014-06-30 07:35:36 +01002994 }
2995
2996 T& operator*() { return *nullableValue; }
2997 T const& operator*() const { return *nullableValue; }
2998 T* operator->() { return nullableValue; }
2999 const T* operator->() const { return nullableValue; }
3000
3001 T valueOr( T const& defaultValue ) const {
3002 return nullableValue ? *nullableValue : defaultValue;
3003 }
3004
Phil Nashb971fe72015-07-02 08:21:38 +01003005 bool some() const { return nullableValue != CATCH_NULL; }
3006 bool none() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003007
Phil Nashb971fe72015-07-02 08:21:38 +01003008 bool operator !() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003009 operator SafeBool::type() const {
3010 return SafeBool::makeSafe( some() );
3011 }
3012
3013 private:
3014 T* nullableValue;
3015 char storage[sizeof(T)];
3016 };
3017
3018} // end namespace Catch
3019
3020namespace Catch {
3021
3022 struct ITagAliasRegistry {
3023 virtual ~ITagAliasRegistry();
3024 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3025 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3026
3027 static ITagAliasRegistry const& get();
3028 };
3029
3030} // end namespace Catch
3031
Phil Nash0f9c5512012-06-02 23:12:42 +01003032// These files are included here so the single_include script doesn't put them
3033// in the conditionally compiled sections
Phil Nash3649fdf2013-12-03 18:53:55 +00003034// #included from: internal/catch_test_case_info.h
3035#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01003036
3037#include <string>
Phil Nash3649fdf2013-12-03 18:53:55 +00003038#include <set>
3039
3040#ifdef __clang__
3041#pragma clang diagnostic push
3042#pragma clang diagnostic ignored "-Wpadded"
3043#endif
3044
3045namespace Catch {
3046
3047 struct ITestCase;
3048
3049 struct TestCaseInfo {
Phil Nash52e1e742014-07-03 08:11:38 +01003050 enum SpecialProperties{
3051 None = 0,
3052 IsHidden = 1 << 1,
3053 ShouldFail = 1 << 2,
3054 MayFail = 1 << 3,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003055 Throws = 1 << 4,
3056 NonPortable = 1 << 5
Phil Nash52e1e742014-07-03 08:11:38 +01003057 };
3058
Phil Nash3649fdf2013-12-03 18:53:55 +00003059 TestCaseInfo( std::string const& _name,
3060 std::string const& _className,
3061 std::string const& _description,
3062 std::set<std::string> const& _tags,
Phil Nash3649fdf2013-12-03 18:53:55 +00003063 SourceLineInfo const& _lineInfo );
3064
3065 TestCaseInfo( TestCaseInfo const& other );
3066
Phil Nashb971fe72015-07-02 08:21:38 +01003067 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3068
Phil Nash52e1e742014-07-03 08:11:38 +01003069 bool isHidden() const;
3070 bool throws() const;
3071 bool okToFail() const;
3072 bool expectedToFail() const;
3073
Phil Nash3649fdf2013-12-03 18:53:55 +00003074 std::string name;
3075 std::string className;
3076 std::string description;
3077 std::set<std::string> tags;
Phil Nash9241e432014-05-20 18:50:59 +01003078 std::set<std::string> lcaseTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003079 std::string tagsAsString;
3080 SourceLineInfo lineInfo;
Phil Nash52e1e742014-07-03 08:11:38 +01003081 SpecialProperties properties;
Phil Nash3649fdf2013-12-03 18:53:55 +00003082 };
3083
Phil Nash65cc14c2014-05-16 18:54:48 +01003084 class TestCase : public TestCaseInfo {
Phil Nash3649fdf2013-12-03 18:53:55 +00003085 public:
3086
3087 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3088 TestCase( TestCase const& other );
3089
3090 TestCase withName( std::string const& _newName ) const;
3091
3092 void invoke() const;
3093
3094 TestCaseInfo const& getTestCaseInfo() const;
3095
Phil Nash3649fdf2013-12-03 18:53:55 +00003096 void swap( TestCase& other );
3097 bool operator == ( TestCase const& other ) const;
3098 bool operator < ( TestCase const& other ) const;
3099 TestCase& operator = ( TestCase const& other );
3100
3101 private:
3102 Ptr<ITestCase> test;
3103 };
3104
3105 TestCase makeTestCase( ITestCase* testCase,
3106 std::string const& className,
3107 std::string const& name,
3108 std::string const& description,
3109 SourceLineInfo const& lineInfo );
3110}
3111
3112#ifdef __clang__
3113#pragma clang diagnostic pop
3114#endif
3115
Phil Nash0f9c5512012-06-02 23:12:42 +01003116
Phil Nash371db8b2012-05-21 18:52:09 +01003117#ifdef __OBJC__
3118// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003119#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003120
Phil Nash371db8b2012-05-21 18:52:09 +01003121#import <objc/runtime.h>
3122
3123#include <string>
3124
3125// NB. Any general catch headers included here must be included
3126// in catch.hpp first to make sure they are included by the single
3127// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01003128
Phil Nash83224e62011-08-12 18:53:28 +01003129///////////////////////////////////////////////////////////////////////////////
3130// This protocol is really only here for (self) documenting purposes, since
3131// all its methods are optional.
3132@protocol OcFixture
3133
3134@optional
3135
3136-(void) setUp;
3137-(void) tearDown;
3138
3139@end
3140
Phil Nash89d2a3f2012-05-16 15:09:17 +01003141namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01003142
Phil Nash5bc030d2012-08-16 18:48:50 +01003143 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003144
3145 public:
3146 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3147
3148 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00003149 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01003150
Phil Nash53c990a2012-03-17 18:20:06 +00003151 performOptionalSelector( obj, @selector(setUp) );
3152 performOptionalSelector( obj, m_sel );
3153 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01003154
Phil Nash53c990a2012-03-17 18:20:06 +00003155 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01003156 }
Phil Nash83224e62011-08-12 18:53:28 +01003157 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003158 virtual ~OcMethod() {}
3159
Phil Nash83224e62011-08-12 18:53:28 +01003160 Class m_cls;
3161 SEL m_sel;
3162 };
3163
Phil Nash89d2a3f2012-05-16 15:09:17 +01003164 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01003165
Phil Nash89d2a3f2012-05-16 15:09:17 +01003166 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01003167 std::string const& annotationName,
3168 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01003169 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3170 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00003171 arcSafeRelease( selStr );
3172 id value = performOptionalSelector( cls, sel );
3173 if( value )
3174 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01003175 return "";
3176 }
3177 }
3178
Phil Nash89d2a3f2012-05-16 15:09:17 +01003179 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01003180 size_t noTestMethods = 0;
Phil Nashb971fe72015-07-02 08:21:38 +01003181 int noClasses = objc_getClassList( CATCH_NULL, 0 );
Phil Nash83224e62011-08-12 18:53:28 +01003182
Phil Nash861a1e72012-04-28 12:29:52 +01003183 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00003184 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01003185
Phil Nash89d2a3f2012-05-16 15:09:17 +01003186 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003187 Class cls = classes[c];
3188 {
3189 u_int count;
3190 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01003191 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003192 SEL selector = method_getName(methods[m]);
3193 std::string methodName = sel_getName(selector);
Phil Nash3649fdf2013-12-03 18:53:55 +00003194 if( startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01003195 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00003196 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3197 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00003198 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01003199
Phil Nash5bdae842013-02-19 19:47:18 +00003200 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01003201 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01003202 }
3203 }
3204 free(methods);
3205 }
3206 }
3207 return noTestMethods;
3208 }
Phil Nash78d95a02012-03-04 21:22:36 +00003209
Phil Nash89d2a3f2012-05-16 15:09:17 +01003210 namespace Matchers {
3211 namespace Impl {
3212 namespace NSStringMatchers {
3213
Phil Nasha8c65432013-02-19 08:46:09 +00003214 template<typename MatcherT>
3215 struct StringHolder : MatcherImpl<MatcherT, NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00003216 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00003217 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01003218 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00003219 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003220 }
3221
3222 NSString* m_substr;
3223 };
3224
Phil Nasha8c65432013-02-19 08:46:09 +00003225 struct Equals : StringHolder<Equals> {
Phil Nash8d18d162012-03-14 20:06:14 +00003226 Equals( NSString* substr ) : StringHolder( substr ){}
3227
Phil Nasha8c65432013-02-19 08:46:09 +00003228 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003229 return (str != nil || m_substr == nil ) &&
3230 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00003231 }
3232
Phil Nasha8c65432013-02-19 08:46:09 +00003233 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003234 return "equals string: " + Catch::toString( m_substr );
Phil Nash8d18d162012-03-14 20:06:14 +00003235 }
3236 };
3237
Phil Nasha8c65432013-02-19 08:46:09 +00003238 struct Contains : StringHolder<Contains> {
Phil Nash78d95a02012-03-04 21:22:36 +00003239 Contains( NSString* substr ) : StringHolder( substr ){}
3240
Phil Nasha8c65432013-02-19 08:46:09 +00003241 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003242 return (str != nil || m_substr == nil ) &&
3243 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00003244 }
3245
Phil Nasha8c65432013-02-19 08:46:09 +00003246 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003247 return "contains string: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003248 }
3249 };
3250
Phil Nasha8c65432013-02-19 08:46:09 +00003251 struct StartsWith : StringHolder<StartsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003252 StartsWith( NSString* substr ) : StringHolder( substr ){}
3253
Phil Nasha8c65432013-02-19 08:46:09 +00003254 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003255 return (str != nil || m_substr == nil ) &&
3256 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00003257 }
3258
Phil Nasha8c65432013-02-19 08:46:09 +00003259 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003260 return "starts with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003261 }
3262 };
Phil Nasha8c65432013-02-19 08:46:09 +00003263 struct EndsWith : StringHolder<EndsWith> {
Phil Nash78d95a02012-03-04 21:22:36 +00003264 EndsWith( NSString* substr ) : StringHolder( substr ){}
3265
Phil Nasha8c65432013-02-19 08:46:09 +00003266 virtual bool match( ExpressionType const& str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003267 return (str != nil || m_substr == nil ) &&
3268 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00003269 }
3270
Phil Nasha8c65432013-02-19 08:46:09 +00003271 virtual std::string toString() const {
Phil Nashacdd3b52014-06-30 07:35:36 +01003272 return "ends with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003273 }
3274 };
3275
3276 } // namespace NSStringMatchers
3277 } // namespace Impl
3278
Phil Nash8d18d162012-03-14 20:06:14 +00003279 inline Impl::NSStringMatchers::Equals
3280 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3281
Phil Nash78d95a02012-03-04 21:22:36 +00003282 inline Impl::NSStringMatchers::Contains
3283 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003284
Phil Nash78d95a02012-03-04 21:22:36 +00003285 inline Impl::NSStringMatchers::StartsWith
3286 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003287
Phil Nash78d95a02012-03-04 21:22:36 +00003288 inline Impl::NSStringMatchers::EndsWith
3289 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3290
3291 } // namespace Matchers
3292
3293 using namespace Matchers;
3294
3295} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003296
3297///////////////////////////////////////////////////////////////////////////////
3298#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003299+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003300{\
Phil Nash53c990a2012-03-17 18:20:06 +00003301return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003302}\
Phil Nash53c990a2012-03-17 18:20:06 +00003303+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003304{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003305return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003306} \
3307-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3308
3309#endif
3310
Phil Nash576aff62014-12-21 00:21:23 +00003311#ifdef CATCH_IMPL
Phil Nasha695eb92012-08-13 07:46:10 +01003312// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003313#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003314
3315// Collect all the implementation files together here
3316// These are the equivalent of what would usually be cpp files
3317
Phil Nash5bc030d2012-08-16 18:48:50 +01003318#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003319#pragma clang diagnostic push
3320#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003321#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003322
Phil Nashe73583d2015-08-07 17:30:34 +01003323// #included from: ../catch_session.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003324#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003325
Phil Nasha695eb92012-08-13 07:46:10 +01003326// #included from: internal/catch_commandline.hpp
3327#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3328
Phil Nash3649fdf2013-12-03 18:53:55 +00003329// #included from: catch_config.hpp
3330#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3331
Phil Nash65cc14c2014-05-16 18:54:48 +01003332// #included from: catch_test_spec_parser.hpp
3333#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003334
3335#ifdef __clang__
Phil Nash65cc14c2014-05-16 18:54:48 +01003336#pragma clang diagnostic push
Phil Nash3649fdf2013-12-03 18:53:55 +00003337#pragma clang diagnostic ignored "-Wpadded"
3338#endif
3339
Phil Nash65cc14c2014-05-16 18:54:48 +01003340// #included from: catch_test_spec.hpp
3341#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003342
Phil Nash65cc14c2014-05-16 18:54:48 +01003343#ifdef __clang__
3344#pragma clang diagnostic push
3345#pragma clang diagnostic ignored "-Wpadded"
3346#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00003347
Phil Nash8342ae82015-07-13 15:03:26 +01003348// #included from: catch_wildcard_pattern.hpp
3349#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3350
3351namespace Catch
3352{
3353 class WildcardPattern {
3354 enum WildcardPosition {
3355 NoWildcard = 0,
3356 WildcardAtStart = 1,
3357 WildcardAtEnd = 2,
3358 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3359 };
3360
3361 public:
3362
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003363 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
Phil Nash8342ae82015-07-13 15:03:26 +01003364 : m_caseSensitivity( caseSensitivity ),
3365 m_wildcard( NoWildcard ),
3366 m_pattern( adjustCase( pattern ) )
3367 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003368 if( startsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003369 m_pattern = m_pattern.substr( 1 );
3370 m_wildcard = WildcardAtStart;
3371 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003372 if( endsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003373 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3374 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3375 }
3376 }
3377 virtual ~WildcardPattern();
3378 virtual bool matches( std::string const& str ) const {
3379 switch( m_wildcard ) {
3380 case NoWildcard:
3381 return m_pattern == adjustCase( str );
3382 case WildcardAtStart:
3383 return endsWith( adjustCase( str ), m_pattern );
3384 case WildcardAtEnd:
3385 return startsWith( adjustCase( str ), m_pattern );
3386 case WildcardAtBothEnds:
3387 return contains( adjustCase( str ), m_pattern );
3388 }
3389
3390#ifdef __clang__
3391#pragma clang diagnostic push
3392#pragma clang diagnostic ignored "-Wunreachable-code"
3393#endif
3394 throw std::logic_error( "Unknown enum" );
3395#ifdef __clang__
3396#pragma clang diagnostic pop
3397#endif
3398 }
3399 private:
3400 std::string adjustCase( std::string const& str ) const {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003401 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
Phil Nash8342ae82015-07-13 15:03:26 +01003402 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003403 CaseSensitive::Choice m_caseSensitivity;
Phil Nash8342ae82015-07-13 15:03:26 +01003404 WildcardPosition m_wildcard;
3405 std::string m_pattern;
3406 };
3407}
3408
Phil Nash3649fdf2013-12-03 18:53:55 +00003409#include <string>
3410#include <vector>
3411
3412namespace Catch {
3413
Phil Nash65cc14c2014-05-16 18:54:48 +01003414 class TestSpec {
3415 struct Pattern : SharedImpl<> {
3416 virtual ~Pattern();
3417 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3418 };
3419 class NamePattern : public Pattern {
Phil Nash65cc14c2014-05-16 18:54:48 +01003420 public:
Phil Nash8342ae82015-07-13 15:03:26 +01003421 NamePattern( std::string const& name )
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003422 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
Phil Nash8342ae82015-07-13 15:03:26 +01003423 {}
Phil Nash65cc14c2014-05-16 18:54:48 +01003424 virtual ~NamePattern();
3425 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash8342ae82015-07-13 15:03:26 +01003426 return m_wildcardPattern.matches( toLower( testCase.name ) );
Phil Nash65cc14c2014-05-16 18:54:48 +01003427 }
3428 private:
Phil Nash8342ae82015-07-13 15:03:26 +01003429 WildcardPattern m_wildcardPattern;
Phil Nash65cc14c2014-05-16 18:54:48 +01003430 };
Phil Nash8342ae82015-07-13 15:03:26 +01003431
Phil Nash65cc14c2014-05-16 18:54:48 +01003432 class TagPattern : public Pattern {
3433 public:
3434 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3435 virtual ~TagPattern();
3436 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash9241e432014-05-20 18:50:59 +01003437 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
Phil Nash65cc14c2014-05-16 18:54:48 +01003438 }
3439 private:
3440 std::string m_tag;
3441 };
Phil Nash8342ae82015-07-13 15:03:26 +01003442
Phil Nash65cc14c2014-05-16 18:54:48 +01003443 class ExcludedPattern : public Pattern {
3444 public:
3445 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3446 virtual ~ExcludedPattern();
3447 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3448 private:
3449 Ptr<Pattern> m_underlyingPattern;
3450 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003451
Phil Nash65cc14c2014-05-16 18:54:48 +01003452 struct Filter {
3453 std::vector<Ptr<Pattern> > m_patterns;
3454
3455 bool matches( TestCaseInfo const& testCase ) const {
3456 // All patterns in a filter must match for the filter to be a match
Phil Nash40f60682016-09-27 10:46:22 +01003457 for( std::vector<Ptr<Pattern> >::const_iterator it = m_patterns.begin(), itEnd = m_patterns.end(); it != itEnd; ++it ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01003458 if( !(*it)->matches( testCase ) )
3459 return false;
Phil Nash40f60682016-09-27 10:46:22 +01003460 }
3461 return true;
Phil Nash65cc14c2014-05-16 18:54:48 +01003462 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003463 };
3464
3465 public:
Phil Nash65cc14c2014-05-16 18:54:48 +01003466 bool hasFilters() const {
3467 return !m_filters.empty();
3468 }
3469 bool matches( TestCaseInfo const& testCase ) const {
3470 // A TestSpec matches if any filter matches
3471 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3472 if( it->matches( testCase ) )
3473 return true;
3474 return false;
3475 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003476
3477 private:
Phil Nash65cc14c2014-05-16 18:54:48 +01003478 std::vector<Filter> m_filters;
Phil Nash3649fdf2013-12-03 18:53:55 +00003479
Phil Nash65cc14c2014-05-16 18:54:48 +01003480 friend class TestSpecParser;
Phil Nash3649fdf2013-12-03 18:53:55 +00003481 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003482}
3483
Phil Nash65cc14c2014-05-16 18:54:48 +01003484#ifdef __clang__
3485#pragma clang diagnostic pop
3486#endif
3487
3488namespace Catch {
3489
3490 class TestSpecParser {
Phil Nash3b2f2062017-01-11 16:43:56 +00003491 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Phil Nash65cc14c2014-05-16 18:54:48 +01003492 Mode m_mode;
3493 bool m_exclusion;
3494 std::size_t m_start, m_pos;
3495 std::string m_arg;
Phil Nash3b2f2062017-01-11 16:43:56 +00003496 std::vector<std::size_t> m_escapeChars;
Phil Nash65cc14c2014-05-16 18:54:48 +01003497 TestSpec::Filter m_currentFilter;
3498 TestSpec m_testSpec;
Phil Nash52e1e742014-07-03 08:11:38 +01003499 ITagAliasRegistry const* m_tagAliases;
Phil Nash65cc14c2014-05-16 18:54:48 +01003500
3501 public:
Phil Nash52e1e742014-07-03 08:11:38 +01003502 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003503
3504 TestSpecParser& parse( std::string const& arg ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01003505 m_mode = None;
3506 m_exclusion = false;
3507 m_start = std::string::npos;
Phil Nash52e1e742014-07-03 08:11:38 +01003508 m_arg = m_tagAliases->expandAliases( arg );
Phil Nash3b2f2062017-01-11 16:43:56 +00003509 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003510 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3511 visitChar( m_arg[m_pos] );
3512 if( m_mode == Name )
3513 addPattern<TestSpec::NamePattern>();
3514 return *this;
3515 }
3516 TestSpec testSpec() {
Phil Nash9241e432014-05-20 18:50:59 +01003517 addFilter();
Phil Nash65cc14c2014-05-16 18:54:48 +01003518 return m_testSpec;
3519 }
3520 private:
3521 void visitChar( char c ) {
3522 if( m_mode == None ) {
3523 switch( c ) {
3524 case ' ': return;
3525 case '~': m_exclusion = true; return;
3526 case '[': return startNewMode( Tag, ++m_pos );
3527 case '"': return startNewMode( QuotedName, ++m_pos );
Phil Nash3b2f2062017-01-11 16:43:56 +00003528 case '\\': return escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003529 default: startNewMode( Name, m_pos ); break;
3530 }
3531 }
3532 if( m_mode == Name ) {
3533 if( c == ',' ) {
3534 addPattern<TestSpec::NamePattern>();
3535 addFilter();
3536 }
3537 else if( c == '[' ) {
3538 if( subString() == "exclude:" )
3539 m_exclusion = true;
3540 else
3541 addPattern<TestSpec::NamePattern>();
3542 startNewMode( Tag, ++m_pos );
3543 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003544 else if( c == '\\' )
3545 escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003546 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003547 else if( m_mode == EscapedName )
3548 m_mode = Name;
Phil Nash65cc14c2014-05-16 18:54:48 +01003549 else if( m_mode == QuotedName && c == '"' )
3550 addPattern<TestSpec::NamePattern>();
3551 else if( m_mode == Tag && c == ']' )
3552 addPattern<TestSpec::TagPattern>();
3553 }
3554 void startNewMode( Mode mode, std::size_t start ) {
3555 m_mode = mode;
3556 m_start = start;
3557 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003558 void escape() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003559 if( m_mode == None )
3560 m_start = m_pos;
Phil Nash3b2f2062017-01-11 16:43:56 +00003561 m_mode = EscapedName;
3562 m_escapeChars.push_back( m_pos );
3563 }
Phil Nash65cc14c2014-05-16 18:54:48 +01003564 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3565 template<typename T>
3566 void addPattern() {
3567 std::string token = subString();
Phil Nash3b2f2062017-01-11 16:43:56 +00003568 for( size_t i = 0; i < m_escapeChars.size(); ++i )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003569 token = token.substr( 0, m_escapeChars[i]-i ) + token.substr( m_escapeChars[i]+1-i );
Phil Nash3b2f2062017-01-11 16:43:56 +00003570 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003571 if( startsWith( token, "exclude:" ) ) {
3572 m_exclusion = true;
3573 token = token.substr( 8 );
3574 }
3575 if( !token.empty() ) {
3576 Ptr<TestSpec::Pattern> pattern = new T( token );
3577 if( m_exclusion )
3578 pattern = new TestSpec::ExcludedPattern( pattern );
3579 m_currentFilter.m_patterns.push_back( pattern );
3580 }
3581 m_exclusion = false;
3582 m_mode = None;
3583 }
3584 void addFilter() {
3585 if( !m_currentFilter.m_patterns.empty() ) {
3586 m_testSpec.m_filters.push_back( m_currentFilter );
3587 m_currentFilter = TestSpec::Filter();
3588 }
3589 }
3590 };
3591 inline TestSpec parseTestSpec( std::string const& arg ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003592 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01003593 }
3594
3595} // namespace Catch
3596
3597#ifdef __clang__
3598#pragma clang diagnostic pop
3599#endif
3600
Phil Nashab036682014-06-02 07:48:03 +01003601// #included from: catch_interfaces_config.h
3602#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3603
3604#include <iostream>
3605#include <string>
3606#include <vector>
3607
3608namespace Catch {
3609
3610 struct Verbosity { enum Level {
3611 NoOutput = 0,
3612 Quiet,
3613 Normal
3614 }; };
3615
3616 struct WarnAbout { enum What {
3617 Nothing = 0x00,
3618 NoAssertions = 0x01
3619 }; };
3620
3621 struct ShowDurations { enum OrNot {
3622 DefaultForReporter,
3623 Always,
3624 Never
3625 }; };
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003626 struct RunTests { enum InWhatOrder {
3627 InDeclarationOrder,
3628 InLexicographicalOrder,
3629 InRandomOrder
3630 }; };
Phil Nashae5ee2c2016-02-29 08:17:18 +00003631 struct UseColour { enum YesOrNo {
3632 Auto,
3633 Yes,
3634 No
3635 }; };
Phil Nashab036682014-06-02 07:48:03 +01003636
3637 class TestSpec;
3638
3639 struct IConfig : IShared {
3640
3641 virtual ~IConfig();
3642
3643 virtual bool allowThrows() const = 0;
3644 virtual std::ostream& stream() const = 0;
3645 virtual std::string name() const = 0;
3646 virtual bool includeSuccessfulResults() const = 0;
3647 virtual bool shouldDebugBreak() const = 0;
3648 virtual bool warnAboutMissingAssertions() const = 0;
3649 virtual int abortAfter() const = 0;
3650 virtual bool showInvisibles() const = 0;
3651 virtual ShowDurations::OrNot showDurations() const = 0;
3652 virtual TestSpec const& testSpec() const = 0;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003653 virtual RunTests::InWhatOrder runOrder() const = 0;
3654 virtual unsigned int rngSeed() const = 0;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003655 virtual UseColour::YesOrNo useColour() const = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003656 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3657
Phil Nashab036682014-06-02 07:48:03 +01003658 };
3659}
3660
Phil Nash3649fdf2013-12-03 18:53:55 +00003661// #included from: catch_stream.h
3662#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3663
Phil Nash7e346192015-11-03 08:00:43 +00003664// #included from: catch_streambuf.h
3665#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003666
Phil Nash7e346192015-11-03 08:00:43 +00003667#include <streambuf>
Phil Nash3649fdf2013-12-03 18:53:55 +00003668
3669namespace Catch {
3670
Phil Nash7e346192015-11-03 08:00:43 +00003671 class StreamBufBase : public std::streambuf {
Phil Nash3649fdf2013-12-03 18:53:55 +00003672 public:
Phil Nash7e346192015-11-03 08:00:43 +00003673 virtual ~StreamBufBase() CATCH_NOEXCEPT;
Phil Nash3649fdf2013-12-03 18:53:55 +00003674 };
Phil Nash7e346192015-11-03 08:00:43 +00003675}
3676
3677#include <streambuf>
3678#include <ostream>
3679#include <fstream>
Phil Nash2be37272016-11-29 12:15:50 +00003680#include <memory>
Phil Nash7e346192015-11-03 08:00:43 +00003681
3682namespace Catch {
Phil Nash383d7c02014-10-02 19:08:19 +01003683
3684 std::ostream& cout();
3685 std::ostream& cerr();
Phil Nash7e346192015-11-03 08:00:43 +00003686
3687 struct IStream {
3688 virtual ~IStream() CATCH_NOEXCEPT;
3689 virtual std::ostream& stream() const = 0;
3690 };
3691
3692 class FileStream : public IStream {
3693 mutable std::ofstream m_ofs;
3694 public:
3695 FileStream( std::string const& filename );
Phil Nashece529a2015-11-03 17:37:43 +00003696 virtual ~FileStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003697 public: // IStream
3698 virtual std::ostream& stream() const CATCH_OVERRIDE;
3699 };
3700
3701 class CoutStream : public IStream {
3702 mutable std::ostream m_os;
3703 public:
3704 CoutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003705 virtual ~CoutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003706
3707 public: // IStream
3708 virtual std::ostream& stream() const CATCH_OVERRIDE;
3709 };
3710
3711 class DebugOutStream : public IStream {
Phil Nashac220282016-06-09 08:19:23 +01003712 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
Phil Nash7e346192015-11-03 08:00:43 +00003713 mutable std::ostream m_os;
3714 public:
3715 DebugOutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003716 virtual ~DebugOutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003717
3718 public: // IStream
3719 virtual std::ostream& stream() const CATCH_OVERRIDE;
3720 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003721}
3722
3723#include <memory>
3724#include <vector>
3725#include <string>
3726#include <iostream>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003727#include <ctime>
Phil Nash3649fdf2013-12-03 18:53:55 +00003728
3729#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3730#define CATCH_CONFIG_CONSOLE_WIDTH 80
3731#endif
3732
3733namespace Catch {
3734
3735 struct ConfigData {
3736
3737 ConfigData()
3738 : listTests( false ),
3739 listTags( false ),
3740 listReporters( false ),
3741 listTestNamesOnly( false ),
3742 showSuccessfulTests( false ),
3743 shouldDebugBreak( false ),
3744 noThrow( false ),
3745 showHelp( false ),
Phil Nashaef6cd52014-04-23 07:10:10 +01003746 showInvisibles( false ),
Phil Nashb971fe72015-07-02 08:21:38 +01003747 filenamesAsTags( false ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003748 abortAfter( -1 ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003749 rngSeed( 0 ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003750 verbosity( Verbosity::Normal ),
3751 warnings( WarnAbout::Nothing ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003752 showDurations( ShowDurations::DefaultForReporter ),
Phil Nashae5ee2c2016-02-29 08:17:18 +00003753 runOrder( RunTests::InDeclarationOrder ),
3754 useColour( UseColour::Auto )
Phil Nash3649fdf2013-12-03 18:53:55 +00003755 {}
3756
3757 bool listTests;
3758 bool listTags;
3759 bool listReporters;
3760 bool listTestNamesOnly;
3761
3762 bool showSuccessfulTests;
3763 bool shouldDebugBreak;
3764 bool noThrow;
3765 bool showHelp;
Phil Nashaef6cd52014-04-23 07:10:10 +01003766 bool showInvisibles;
Phil Nashb971fe72015-07-02 08:21:38 +01003767 bool filenamesAsTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003768
3769 int abortAfter;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003770 unsigned int rngSeed;
Phil Nash3649fdf2013-12-03 18:53:55 +00003771
3772 Verbosity::Level verbosity;
3773 WarnAbout::What warnings;
3774 ShowDurations::OrNot showDurations;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003775 RunTests::InWhatOrder runOrder;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003776 UseColour::YesOrNo useColour;
Phil Nash3649fdf2013-12-03 18:53:55 +00003777
Phil Nash3649fdf2013-12-03 18:53:55 +00003778 std::string outputFilename;
3779 std::string name;
3780 std::string processName;
3781
Phil Nashe73583d2015-08-07 17:30:34 +01003782 std::vector<std::string> reporterNames;
Phil Nash3649fdf2013-12-03 18:53:55 +00003783 std::vector<std::string> testsOrTags;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003784 std::vector<std::string> sectionsToRun;
Phil Nash3649fdf2013-12-03 18:53:55 +00003785 };
3786
3787 class Config : public SharedImpl<IConfig> {
3788 private:
3789 Config( Config const& other );
3790 Config& operator = ( Config const& other );
3791 virtual void dummy();
3792 public:
3793
3794 Config()
Phil Nash3649fdf2013-12-03 18:53:55 +00003795 {}
3796
3797 Config( ConfigData const& data )
3798 : m_data( data ),
Phil Nash7e346192015-11-03 08:00:43 +00003799 m_stream( openStream() )
Phil Nash3649fdf2013-12-03 18:53:55 +00003800 {
3801 if( !data.testsOrTags.empty() ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003802 TestSpecParser parser( ITagAliasRegistry::get() );
Phil Nash65cc14c2014-05-16 18:54:48 +01003803 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
3804 parser.parse( data.testsOrTags[i] );
3805 m_testSpec = parser.testSpec();
Phil Nash3649fdf2013-12-03 18:53:55 +00003806 }
3807 }
3808
3809 virtual ~Config() {
Phil Nash3649fdf2013-12-03 18:53:55 +00003810 }
3811
3812 std::string const& getFilename() const {
3813 return m_data.outputFilename ;
3814 }
3815
3816 bool listTests() const { return m_data.listTests; }
3817 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
3818 bool listTags() const { return m_data.listTags; }
3819 bool listReporters() const { return m_data.listReporters; }
3820
Phil Nash65cc14c2014-05-16 18:54:48 +01003821 std::string getProcessName() const { return m_data.processName; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003822
Phil Nash65cc14c2014-05-16 18:54:48 +01003823 bool shouldDebugBreak() const { return m_data.shouldDebugBreak; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003824
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003825 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
3826 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003827
Phil Nash65cc14c2014-05-16 18:54:48 +01003828 int abortAfter() const { return m_data.abortAfter; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003829
Phil Nash65cc14c2014-05-16 18:54:48 +01003830 TestSpec const& testSpec() const { return m_testSpec; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003831
3832 bool showHelp() const { return m_data.showHelp; }
Phil Nashaef6cd52014-04-23 07:10:10 +01003833 bool showInvisibles() const { return m_data.showInvisibles; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003834
3835 // IConfig interface
3836 virtual bool allowThrows() const { return !m_data.noThrow; }
Phil Nash7e346192015-11-03 08:00:43 +00003837 virtual std::ostream& stream() const { return m_stream->stream(); }
Phil Nash3649fdf2013-12-03 18:53:55 +00003838 virtual std::string name() const { return m_data.name.empty() ? m_data.processName : m_data.name; }
3839 virtual bool includeSuccessfulResults() const { return m_data.showSuccessfulTests; }
3840 virtual bool warnAboutMissingAssertions() const { return m_data.warnings & WarnAbout::NoAssertions; }
3841 virtual ShowDurations::OrNot showDurations() const { return m_data.showDurations; }
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003842 virtual RunTests::InWhatOrder runOrder() const { return m_data.runOrder; }
3843 virtual unsigned int rngSeed() const { return m_data.rngSeed; }
Phil Nashae5ee2c2016-02-29 08:17:18 +00003844 virtual UseColour::YesOrNo useColour() const { return m_data.useColour; }
Phil Nash3649fdf2013-12-03 18:53:55 +00003845
3846 private:
Phil Nash7e346192015-11-03 08:00:43 +00003847
3848 IStream const* openStream() {
3849 if( m_data.outputFilename.empty() )
3850 return new CoutStream();
3851 else if( m_data.outputFilename[0] == '%' ) {
3852 if( m_data.outputFilename == "%debug" )
3853 return new DebugOutStream();
3854 else
3855 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
3856 }
3857 else
3858 return new FileStream( m_data.outputFilename );
3859 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003860 ConfigData m_data;
3861
Phil Nashac220282016-06-09 08:19:23 +01003862 CATCH_AUTO_PTR( IStream const ) m_stream;
Phil Nash65cc14c2014-05-16 18:54:48 +01003863 TestSpec m_testSpec;
Phil Nash3649fdf2013-12-03 18:53:55 +00003864 };
3865
3866} // end namespace Catch
3867
Phil Nash1c2fbe12014-02-11 18:12:41 +00003868// #included from: catch_clara.h
3869#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
3870
Phil Nashb9fea752014-03-06 08:16:06 +00003871// Use Catch's value for console width (store Clara's off to the side, if present)
3872#ifdef CLARA_CONFIG_CONSOLE_WIDTH
3873#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
3874#undef CLARA_CONFIG_CONSOLE_WIDTH
3875#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00003876#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
3877
3878// Declare Clara inside the Catch namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003879#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
Phil Nash472dc2a2014-03-17 18:40:58 +00003880// #included from: ../external/clara.h
Phil Nasha695eb92012-08-13 07:46:10 +01003881
Phil Nash5c198d82016-05-07 23:14:04 +01003882// Version 0.0.2.4
Phil Nash3b4edd72016-02-10 19:24:48 +00003883
Phil Nash1c2fbe12014-02-11 18:12:41 +00003884// Only use header guard if we are not using an outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00003885#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
3886
3887#ifndef STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003888#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00003889#define STITCH_CLARA_OPEN_NAMESPACE
3890#define STITCH_CLARA_CLOSE_NAMESPACE
3891#else
3892#define STITCH_CLARA_CLOSE_NAMESPACE }
Phil Nash1c2fbe12014-02-11 18:12:41 +00003893#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00003894
Phil Nashb9fea752014-03-06 08:16:06 +00003895#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003896
3897// ----------- #included from tbc_text_format.h -----------
3898
Phil Nash1c2fbe12014-02-11 18:12:41 +00003899// Only use header guard if we are not using an outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003900#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
3901#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3902#define TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00003903#endif
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003904
Phil Nash38f7eef2013-03-29 13:44:33 +00003905#include <string>
3906#include <vector>
Phil Nash1c2fbe12014-02-11 18:12:41 +00003907#include <sstream>
Phil Nash3b4edd72016-02-10 19:24:48 +00003908#include <algorithm>
Phil Nash38f7eef2013-03-29 13:44:33 +00003909
Phil Nash1c2fbe12014-02-11 18:12:41 +00003910// Use optional outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00003911#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
3912namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
Phil Nash1c2fbe12014-02-11 18:12:41 +00003913#endif
3914
3915namespace Tbc {
3916
3917#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
3918 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
3919#else
3920 const unsigned int consoleWidth = 80;
3921#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01003922
Phil Nash19279252013-04-20 21:07:32 +01003923 struct TextAttributes {
3924 TextAttributes()
3925 : initialIndent( std::string::npos ),
3926 indent( 0 ),
Phil Nash1c2fbe12014-02-11 18:12:41 +00003927 width( consoleWidth-1 ),
Phil Nash19279252013-04-20 21:07:32 +01003928 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01003929 {}
Phil Nash3b80af72012-08-09 07:47:30 +01003930
Phil Nash19279252013-04-20 21:07:32 +01003931 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
3932 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
3933 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
3934 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01003935
Phil Nash19279252013-04-20 21:07:32 +01003936 std::size_t initialIndent; // indent of first line, or npos
3937 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
3938 std::size_t width; // maximum width of text, including indent. Longer text will wrap
3939 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01003940 };
3941
Phil Nash19279252013-04-20 21:07:32 +01003942 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01003943 public:
Phil Nash1c2fbe12014-02-11 18:12:41 +00003944 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
3945 : attr( _attr )
3946 {
3947 std::string wrappableChars = " [({.,/|\\-";
3948 std::size_t indent = _attr.initialIndent != std::string::npos
3949 ? _attr.initialIndent
3950 : _attr.indent;
3951 std::string remainder = _str;
3952
3953 while( !remainder.empty() ) {
3954 if( lines.size() >= 1000 ) {
3955 lines.push_back( "... message truncated due to excessive size" );
3956 return;
3957 }
3958 std::size_t tabPos = std::string::npos;
3959 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
3960 std::size_t pos = remainder.find_first_of( '\n' );
3961 if( pos <= width ) {
3962 width = pos;
3963 }
3964 pos = remainder.find_last_of( _attr.tabChar, width );
3965 if( pos != std::string::npos ) {
3966 tabPos = pos;
3967 if( remainder[width] == '\n' )
3968 width--;
3969 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
3970 }
3971
3972 if( width == remainder.size() ) {
3973 spliceLine( indent, remainder, width );
3974 }
3975 else if( remainder[width] == '\n' ) {
3976 spliceLine( indent, remainder, width );
3977 if( width <= 1 || remainder.size() != 1 )
3978 remainder = remainder.substr( 1 );
3979 indent = _attr.indent;
3980 }
3981 else {
3982 pos = remainder.find_last_of( wrappableChars, width );
3983 if( pos != std::string::npos && pos > 0 ) {
3984 spliceLine( indent, remainder, pos );
3985 if( remainder[0] == ' ' )
3986 remainder = remainder.substr( 1 );
3987 }
3988 else {
3989 spliceLine( indent, remainder, width-1 );
3990 lines.back() += "-";
3991 }
3992 if( lines.size() == 1 )
3993 indent = _attr.indent;
3994 if( tabPos != std::string::npos )
3995 indent += tabPos;
3996 }
3997 }
3998 }
3999
4000 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4001 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4002 _remainder = _remainder.substr( _pos );
4003 }
Phil Nasha695eb92012-08-13 07:46:10 +01004004
Phil Nash38f7eef2013-03-29 13:44:33 +00004005 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01004006
Phil Nash38f7eef2013-03-29 13:44:33 +00004007 const_iterator begin() const { return lines.begin(); }
4008 const_iterator end() const { return lines.end(); }
4009 std::string const& last() const { return lines.back(); }
4010 std::size_t size() const { return lines.size(); }
4011 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004012 std::string toString() const {
4013 std::ostringstream oss;
4014 oss << *this;
4015 return oss.str();
4016 }
Phil Nasha695eb92012-08-13 07:46:10 +01004017
Phil Nash1c2fbe12014-02-11 18:12:41 +00004018 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4019 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4020 it != itEnd; ++it ) {
4021 if( it != _text.begin() )
4022 _stream << "\n";
4023 _stream << *it;
4024 }
4025 return _stream;
4026 }
Phil Nasha695eb92012-08-13 07:46:10 +01004027
Phil Nasha695eb92012-08-13 07:46:10 +01004028 private:
Phil Nash19279252013-04-20 21:07:32 +01004029 std::string str;
4030 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00004031 std::vector<std::string> lines;
4032 };
4033
Phil Nash1c2fbe12014-02-11 18:12:41 +00004034} // end namespace Tbc
4035
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004036#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004037} // end outer namespace
4038#endif
4039
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004040#endif // TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00004041
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004042// ----------- end of #include from tbc_text_format.h -----------
Phil Nash3b4edd72016-02-10 19:24:48 +00004043// ........... back in clara.h
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004044
Phil Nashb9fea752014-03-06 08:16:06 +00004045#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004046
Phil Nash3b4edd72016-02-10 19:24:48 +00004047// ----------- #included from clara_compilers.h -----------
4048
4049#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4050#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4051
4052// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4053// The following features are defined:
4054//
4055// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4056// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4057// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4058// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4059// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4060
4061// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4062
4063// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4064
4065// In general each macro has a _NO_<feature name> form
4066// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4067// Many features, at point of detection, define an _INTERNAL_ macro, so they
4068// can be combined, en-mass, with the _NO_ forms later.
4069
4070// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4071
4072#ifdef __clang__
4073
4074#if __has_feature(cxx_nullptr)
4075#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4076#endif
4077
4078#if __has_feature(cxx_noexcept)
4079#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4080#endif
4081
4082#endif // __clang__
4083
4084////////////////////////////////////////////////////////////////////////////////
4085// GCC
4086#ifdef __GNUC__
4087
4088#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4089#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4090#endif
4091
4092// - otherwise more recent versions define __cplusplus >= 201103L
4093// and will get picked up below
4094
4095#endif // __GNUC__
4096
4097////////////////////////////////////////////////////////////////////////////////
4098// Visual C++
4099#ifdef _MSC_VER
4100
4101#if (_MSC_VER >= 1600)
4102#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4103#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4104#endif
4105
4106#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4107#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4108#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4109#endif
4110
4111#endif // _MSC_VER
4112
4113////////////////////////////////////////////////////////////////////////////////
4114// C++ language feature support
4115
4116// catch all support for C++11
4117#if defined(__cplusplus) && __cplusplus >= 201103L
4118
4119#define CLARA_CPP11_OR_GREATER
4120
4121#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4122#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4123#endif
4124
4125#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4126#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4127#endif
4128
4129#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4130#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4131#endif
4132
4133#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4134#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4135#endif
4136#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4137#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4138#endif
4139
4140#endif // __cplusplus >= 201103L
4141
4142// Now set the actual defines based on the above + anything the user has configured
4143#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4144#define CLARA_CONFIG_CPP11_NULLPTR
4145#endif
4146#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4147#define CLARA_CONFIG_CPP11_NOEXCEPT
4148#endif
4149#if defined(CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_NO_GENERATED_METHODS) && !defined(CLARA_CONFIG_CPP11_GENERATED_METHODS) && !defined(CLARA_CONFIG_NO_CPP11)
4150#define CLARA_CONFIG_CPP11_GENERATED_METHODS
4151#endif
4152#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4153#define CLARA_CONFIG_CPP11_OVERRIDE
4154#endif
4155#if defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_UNIQUE_PTR) && !defined(CLARA_CONFIG_CPP11_UNIQUE_PTR) && !defined(CLARA_CONFIG_NO_CPP11)
4156#define CLARA_CONFIG_CPP11_UNIQUE_PTR
4157#endif
4158
4159// noexcept support:
4160#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4161#define CLARA_NOEXCEPT noexcept
4162# define CLARA_NOEXCEPT_IS(x) noexcept(x)
4163#else
4164#define CLARA_NOEXCEPT throw()
4165# define CLARA_NOEXCEPT_IS(x)
4166#endif
4167
4168// nullptr support
4169#ifdef CLARA_CONFIG_CPP11_NULLPTR
4170#define CLARA_NULL nullptr
4171#else
4172#define CLARA_NULL NULL
4173#endif
4174
4175// override support
4176#ifdef CLARA_CONFIG_CPP11_OVERRIDE
4177#define CLARA_OVERRIDE override
4178#else
4179#define CLARA_OVERRIDE
4180#endif
4181
4182// unique_ptr support
4183#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4184# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4185#else
4186# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4187#endif
4188
4189#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4190
4191// ----------- end of #include from clara_compilers.h -----------
4192// ........... back in clara.h
4193
Phil Nash1c2fbe12014-02-11 18:12:41 +00004194#include <map>
Phil Nash1c2fbe12014-02-11 18:12:41 +00004195#include <stdexcept>
4196#include <memory>
4197
Phil Nashe5537842016-04-25 18:56:50 +01004198#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4199#define CLARA_PLATFORM_WINDOWS
4200#endif
4201
Phil Nash1c2fbe12014-02-11 18:12:41 +00004202// Use optional outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00004203#ifdef STITCH_CLARA_OPEN_NAMESPACE
4204STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004205#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00004206
Phil Nash786959d2013-06-07 19:07:50 +01004207namespace Clara {
Phil Nashb9fea752014-03-06 08:16:06 +00004208
4209 struct UnpositionalTag {};
4210
4211 extern UnpositionalTag _;
4212
4213#ifdef CLARA_CONFIG_MAIN
4214 UnpositionalTag _;
4215#endif
4216
Phil Nash786959d2013-06-07 19:07:50 +01004217 namespace Detail {
Phil Nash1c2fbe12014-02-11 18:12:41 +00004218
4219#ifdef CLARA_CONSOLE_WIDTH
4220 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4221#else
4222 const unsigned int consoleWidth = 80;
4223#endif
4224
Phil Nashb9fea752014-03-06 08:16:06 +00004225 using namespace Tbc;
4226
4227 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4228 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4229 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004230
Phil Nash786959d2013-06-07 19:07:50 +01004231 template<typename T> struct RemoveConstRef{ typedef T type; };
4232 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4233 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4234 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4235
4236 template<typename T> struct IsBool { static const bool value = false; };
4237 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01004238
4239 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01004240 void convertInto( std::string const& _source, T& _dest ) {
4241 std::stringstream ss;
4242 ss << _source;
4243 ss >> _dest;
4244 if( ss.fail() )
4245 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01004246 }
Phil Nash786959d2013-06-07 19:07:50 +01004247 inline void convertInto( std::string const& _source, std::string& _dest ) {
4248 _dest = _source;
4249 }
Phil Nash2be37272016-11-29 12:15:50 +00004250 char toLowerCh(char c) {
4251 return static_cast<char>( ::tolower( c ) );
4252 }
Phil Nash786959d2013-06-07 19:07:50 +01004253 inline void convertInto( std::string const& _source, bool& _dest ) {
4254 std::string sourceLC = _source;
Phil Nash2be37272016-11-29 12:15:50 +00004255 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
Phil Nash46118712013-08-16 19:01:32 +01004256 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01004257 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01004258 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01004259 _dest = false;
4260 else
Phil Nash46118712013-08-16 19:01:32 +01004261 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01004262 }
Phil Nasha695eb92012-08-13 07:46:10 +01004263
Phil Nash786959d2013-06-07 19:07:50 +01004264 template<typename ConfigT>
4265 struct IArgFunction {
4266 virtual ~IArgFunction() {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004267#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01004268 IArgFunction() = default;
4269 IArgFunction( IArgFunction const& ) = default;
Phil Nash3b4edd72016-02-10 19:24:48 +00004270#endif
Phil Nash786959d2013-06-07 19:07:50 +01004271 virtual void set( ConfigT& config, std::string const& value ) const = 0;
Phil Nash786959d2013-06-07 19:07:50 +01004272 virtual bool takesArg() const = 0;
4273 virtual IArgFunction* clone() const = 0;
4274 };
4275
4276 template<typename ConfigT>
4277 class BoundArgFunction {
4278 public:
Phil Nash3b4edd72016-02-10 19:24:48 +00004279 BoundArgFunction() : functionObj( CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004280 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004281 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004282 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004283 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01004284 delete functionObj;
4285 functionObj = newFunctionObj;
4286 return *this;
4287 }
4288 ~BoundArgFunction() { delete functionObj; }
4289
4290 void set( ConfigT& config, std::string const& value ) const {
4291 functionObj->set( config, value );
4292 }
Phil Nash786959d2013-06-07 19:07:50 +01004293 bool takesArg() const { return functionObj->takesArg(); }
Phil Nashaf8cd982014-03-24 18:15:04 +00004294
4295 bool isSet() const {
Phil Nash3b4edd72016-02-10 19:24:48 +00004296 return functionObj != CLARA_NULL;
Phil Nashaf8cd982014-03-24 18:15:04 +00004297 }
Phil Nash786959d2013-06-07 19:07:50 +01004298 private:
4299 IArgFunction<ConfigT>* functionObj;
4300 };
4301
4302 template<typename C>
4303 struct NullBinder : IArgFunction<C>{
4304 virtual void set( C&, std::string const& ) const {}
Phil Nash786959d2013-06-07 19:07:50 +01004305 virtual bool takesArg() const { return true; }
4306 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4307 };
4308
4309 template<typename C, typename M>
4310 struct BoundDataMember : IArgFunction<C>{
4311 BoundDataMember( M C::* _member ) : member( _member ) {}
4312 virtual void set( C& p, std::string const& stringValue ) const {
4313 convertInto( stringValue, p.*member );
4314 }
Phil Nash786959d2013-06-07 19:07:50 +01004315 virtual bool takesArg() const { return !IsBool<M>::value; }
4316 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4317 M C::* member;
4318 };
4319 template<typename C, typename M>
4320 struct BoundUnaryMethod : IArgFunction<C>{
4321 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4322 virtual void set( C& p, std::string const& stringValue ) const {
4323 typename RemoveConstRef<M>::type value;
4324 convertInto( stringValue, value );
4325 (p.*member)( value );
4326 }
Phil Nash786959d2013-06-07 19:07:50 +01004327 virtual bool takesArg() const { return !IsBool<M>::value; }
4328 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4329 void (C::*member)( M );
4330 };
4331 template<typename C>
4332 struct BoundNullaryMethod : IArgFunction<C>{
4333 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4334 virtual void set( C& p, std::string const& stringValue ) const {
4335 bool value;
4336 convertInto( stringValue, value );
4337 if( value )
4338 (p.*member)();
4339 }
Phil Nash786959d2013-06-07 19:07:50 +01004340 virtual bool takesArg() const { return false; }
4341 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4342 void (C::*member)();
4343 };
4344
4345 template<typename C>
4346 struct BoundUnaryFunction : IArgFunction<C>{
4347 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4348 virtual void set( C& obj, std::string const& stringValue ) const {
4349 bool value;
4350 convertInto( stringValue, value );
4351 if( value )
4352 function( obj );
4353 }
Phil Nash786959d2013-06-07 19:07:50 +01004354 virtual bool takesArg() const { return false; }
4355 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4356 void (*function)( C& );
4357 };
4358
4359 template<typename C, typename T>
4360 struct BoundBinaryFunction : IArgFunction<C>{
4361 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4362 virtual void set( C& obj, std::string const& stringValue ) const {
4363 typename RemoveConstRef<T>::type value;
4364 convertInto( stringValue, value );
4365 function( obj, value );
4366 }
Phil Nash786959d2013-06-07 19:07:50 +01004367 virtual bool takesArg() const { return !IsBool<T>::value; }
4368 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4369 void (*function)( C&, T );
4370 };
4371
Phil Nash786959d2013-06-07 19:07:50 +01004372 } // namespace Detail
4373
Phil Nashe5537842016-04-25 18:56:50 +01004374 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4375 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4376 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4377 args[i] = argv[i];
4378
4379 return args;
4380 }
4381
4382 class Parser {
4383 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4384 Mode mode;
4385 std::size_t from;
4386 bool inQuotes;
4387 public:
Phil Nash786959d2013-06-07 19:07:50 +01004388
4389 struct Token {
4390 enum Type { Positional, ShortOpt, LongOpt };
4391 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4392 Type type;
4393 std::string data;
4394 };
4395
Phil Nashe5537842016-04-25 18:56:50 +01004396 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4397
4398 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
Phil Nashe45e3a12013-12-23 10:24:06 +00004399 const std::string doubleDash = "--";
Phil Nashe5537842016-04-25 18:56:50 +01004400 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4401 parseIntoTokens( args[i], tokens);
Phil Nash786959d2013-06-07 19:07:50 +01004402 }
Phil Nashe5537842016-04-25 18:56:50 +01004403
4404 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
4405 for( std::size_t i = 0; i <= arg.size(); ++i ) {
4406 char c = arg[i];
4407 if( c == '"' )
4408 inQuotes = !inQuotes;
4409 mode = handleMode( i, c, arg, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004410 }
4411 }
Phil Nashe5537842016-04-25 18:56:50 +01004412 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4413 switch( mode ) {
4414 case None: return handleNone( i, c );
4415 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4416 case ShortOpt:
4417 case LongOpt:
4418 case SlashOpt: return handleOpt( i, c, arg, tokens );
4419 case Positional: return handlePositional( i, c, arg, tokens );
4420 default: throw std::logic_error( "Unknown mode" );
4421 }
4422 }
4423
4424 Mode handleNone( std::size_t i, char c ) {
4425 if( inQuotes ) {
4426 from = i;
4427 return Positional;
4428 }
4429 switch( c ) {
4430 case '-': return MaybeShortOpt;
4431#ifdef CLARA_PLATFORM_WINDOWS
4432 case '/': from = i+1; return SlashOpt;
4433#endif
4434 default: from = i; return Positional;
4435 }
4436 }
4437 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4438 switch( c ) {
4439 case '-': from = i+1; return LongOpt;
4440 default: from = i; return ShortOpt;
4441 }
4442 }
4443 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004444 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004445 return mode;
4446
4447 std::string optName = arg.substr( from, i-from );
4448 if( mode == ShortOpt )
4449 for( std::size_t j = 0; j < optName.size(); ++j )
4450 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4451 else if( mode == SlashOpt && optName.size() == 1 )
4452 tokens.push_back( Token( Token::ShortOpt, optName ) );
4453 else
4454 tokens.push_back( Token( Token::LongOpt, optName ) );
4455 return None;
4456 }
4457 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004458 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004459 return mode;
4460
4461 std::string data = arg.substr( from, i-from );
4462 tokens.push_back( Token( Token::Positional, data ) );
4463 return None;
4464 }
Phil Nasha695eb92012-08-13 07:46:10 +01004465 };
4466
Phil Nash786959d2013-06-07 19:07:50 +01004467 template<typename ConfigT>
Phil Nash472dc2a2014-03-17 18:40:58 +00004468 struct CommonArgProperties {
4469 CommonArgProperties() {}
4470 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4471
4472 Detail::BoundArgFunction<ConfigT> boundField;
4473 std::string description;
Phil Nashaf8cd982014-03-24 18:15:04 +00004474 std::string detail;
Phil Nash472dc2a2014-03-17 18:40:58 +00004475 std::string placeholder; // Only value if boundField takes an arg
4476
4477 bool takesArg() const {
4478 return !placeholder.empty();
4479 }
Phil Nashaf8cd982014-03-24 18:15:04 +00004480 void validate() const {
4481 if( !boundField.isSet() )
4482 throw std::logic_error( "option not bound" );
4483 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004484 };
4485 struct OptionArgProperties {
4486 std::vector<std::string> shortNames;
4487 std::string longName;
4488
4489 bool hasShortName( std::string const& shortName ) const {
4490 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4491 }
4492 bool hasLongName( std::string const& _longName ) const {
4493 return _longName == longName;
4494 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004495 };
4496 struct PositionalArgProperties {
4497 PositionalArgProperties() : position( -1 ) {}
4498 int position; // -1 means non-positional (floating)
4499
4500 bool isFixedPositional() const {
4501 return position != -1;
4502 }
4503 };
4504
4505 template<typename ConfigT>
Phil Nash786959d2013-06-07 19:07:50 +01004506 class CommandLine {
4507
Phil Nash472dc2a2014-03-17 18:40:58 +00004508 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4509 Arg() {}
4510 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004511
Phil Nash472dc2a2014-03-17 18:40:58 +00004512 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4513
Phil Nash786959d2013-06-07 19:07:50 +01004514 std::string dbgName() const {
4515 if( !longName.empty() )
4516 return "--" + longName;
4517 if( !shortNames.empty() )
4518 return "-" + shortNames[0];
4519 return "positional args";
4520 }
Phil Nash786959d2013-06-07 19:07:50 +01004521 std::string commands() const {
4522 std::ostringstream oss;
4523 bool first = true;
4524 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4525 for(; it != itEnd; ++it ) {
4526 if( first )
4527 first = false;
4528 else
4529 oss << ", ";
4530 oss << "-" << *it;
4531 }
4532 if( !longName.empty() ) {
4533 if( !first )
4534 oss << ", ";
4535 oss << "--" << longName;
4536 }
Phil Nashb9fea752014-03-06 08:16:06 +00004537 if( !placeholder.empty() )
4538 oss << " <" << placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004539 return oss.str();
4540 }
Phil Nash786959d2013-06-07 19:07:50 +01004541 };
4542
Phil Nash3b4edd72016-02-10 19:24:48 +00004543 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
Phil Nash5ecb72b2013-11-26 20:57:45 +00004544
Phil Nash472dc2a2014-03-17 18:40:58 +00004545 friend void addOptName( Arg& arg, std::string const& optName )
4546 {
4547 if( optName.empty() )
4548 return;
4549 if( Detail::startsWith( optName, "--" ) ) {
4550 if( !arg.longName.empty() )
4551 throw std::logic_error( "Only one long opt may be specified. '"
4552 + arg.longName
4553 + "' already specified, now attempting to add '"
4554 + optName + "'" );
4555 arg.longName = optName.substr( 2 );
4556 }
4557 else if( Detail::startsWith( optName, "-" ) )
4558 arg.shortNames.push_back( optName.substr( 1 ) );
4559 else
4560 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4561 }
4562 friend void setPositionalArg( Arg& arg, int position )
4563 {
4564 arg.position = position;
4565 }
4566
Phil Nashb9fea752014-03-06 08:16:06 +00004567 class ArgBuilder {
Phil Nash786959d2013-06-07 19:07:50 +01004568 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004569 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004570
Phil Nash472dc2a2014-03-17 18:40:58 +00004571 // Bind a non-boolean data member (requires placeholder string)
4572 template<typename C, typename M>
4573 void bind( M C::* field, std::string const& placeholder ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004574 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4575 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004576 }
4577 // Bind a boolean data member (no placeholder required)
4578 template<typename C>
4579 void bind( bool C::* field ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004580 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
Phil Nash472dc2a2014-03-17 18:40:58 +00004581 }
4582
4583 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4584 template<typename C, typename M>
Phil Nashaf8cd982014-03-24 18:15:04 +00004585 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4586 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4587 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004588 }
4589
4590 // Bind a method taking a single, boolean argument (no placeholder string required)
4591 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004592 void bind( void (C::* unaryMethod)( bool ) ) {
4593 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004594 }
4595
4596 // Bind a method that takes no arguments (will be called if opt is present)
4597 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004598 void bind( void (C::* nullaryMethod)() ) {
4599 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004600 }
4601
4602 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4603 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004604 void bind( void (* unaryFunction)( C& ) ) {
4605 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
Phil Nash472dc2a2014-03-17 18:40:58 +00004606 }
4607
4608 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4609 template<typename C, typename T>
Phil Nashaf8cd982014-03-24 18:15:04 +00004610 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4611 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4612 m_arg->placeholder = placeholder;
Phil Nash786959d2013-06-07 19:07:50 +01004613 }
Phil Nashb9fea752014-03-06 08:16:06 +00004614
4615 ArgBuilder& describe( std::string const& description ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004616 m_arg->description = description;
Phil Nash786959d2013-06-07 19:07:50 +01004617 return *this;
4618 }
Phil Nash3b4edd72016-02-10 19:24:48 +00004619 ArgBuilder& detail( std::string const& detail ) {
4620 m_arg->detail = detail;
Phil Nash786959d2013-06-07 19:07:50 +01004621 return *this;
4622 }
Phil Nashb9fea752014-03-06 08:16:06 +00004623
Phil Nash472dc2a2014-03-17 18:40:58 +00004624 protected:
Phil Nashaf8cd982014-03-24 18:15:04 +00004625 Arg* m_arg;
Phil Nash786959d2013-06-07 19:07:50 +01004626 };
Phil Nash472dc2a2014-03-17 18:40:58 +00004627
Phil Nashb9fea752014-03-06 08:16:06 +00004628 class OptBuilder : public ArgBuilder {
4629 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004630 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004631 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4632
4633 OptBuilder& operator[]( std::string const& optName ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004634 addOptName( *ArgBuilder::m_arg, optName );
Phil Nashb9fea752014-03-06 08:16:06 +00004635 return *this;
4636 }
4637 };
Phil Nash786959d2013-06-07 19:07:50 +01004638
4639 public:
4640
4641 CommandLine()
4642 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004643 m_highestSpecifiedArgPosition( 0 ),
4644 m_throwOnUnrecognisedTokens( false )
Phil Nash786959d2013-06-07 19:07:50 +01004645 {}
4646 CommandLine( CommandLine const& other )
4647 : m_boundProcessName( other.m_boundProcessName ),
4648 m_options ( other.m_options ),
4649 m_positionalArgs( other.m_positionalArgs ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004650 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4651 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
Phil Nash786959d2013-06-07 19:07:50 +01004652 {
Phil Nash472dc2a2014-03-17 18:40:58 +00004653 if( other.m_floatingArg.get() )
Phil Nash85b4e942014-10-02 18:51:05 +01004654 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
Phil Nash786959d2013-06-07 19:07:50 +01004655 }
4656
Phil Nash91ef5f72013-12-20 19:06:26 +00004657 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4658 m_throwOnUnrecognisedTokens = shouldThrow;
4659 return *this;
4660 }
4661
Phil Nashb9fea752014-03-06 08:16:06 +00004662 OptBuilder operator[]( std::string const& optName ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004663 m_options.push_back( Arg() );
4664 addOptName( m_options.back(), optName );
Phil Nashaf8cd982014-03-24 18:15:04 +00004665 OptBuilder builder( &m_options.back() );
Phil Nashb9fea752014-03-06 08:16:06 +00004666 return builder;
Phil Nash786959d2013-06-07 19:07:50 +01004667 }
Phil Nashb9fea752014-03-06 08:16:06 +00004668
4669 ArgBuilder operator[]( int position ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004670 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4671 if( position > m_highestSpecifiedArgPosition )
4672 m_highestSpecifiedArgPosition = position;
4673 setPositionalArg( m_positionalArgs[position], position );
Phil Nashaf8cd982014-03-24 18:15:04 +00004674 ArgBuilder builder( &m_positionalArgs[position] );
Phil Nashb9fea752014-03-06 08:16:06 +00004675 return builder;
4676 }
4677
4678 // Invoke this with the _ instance
4679 ArgBuilder operator[]( UnpositionalTag ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004680 if( m_floatingArg.get() )
4681 throw std::logic_error( "Only one unpositional argument can be added" );
Phil Nash85b4e942014-10-02 18:51:05 +01004682 m_floatingArg.reset( new Arg() );
Phil Nashaf8cd982014-03-24 18:15:04 +00004683 ArgBuilder builder( m_floatingArg.get() );
Phil Nashb9fea752014-03-06 08:16:06 +00004684 return builder;
4685 }
4686
Phil Nash472dc2a2014-03-17 18:40:58 +00004687 template<typename C, typename M>
4688 void bindProcessName( M C::* field ) {
4689 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4690 }
4691 template<typename C, typename M>
4692 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4693 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
Phil Nash786959d2013-06-07 19:07:50 +01004694 }
4695
Phil Nash1c2fbe12014-02-11 18:12:41 +00004696 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
Phil Nash786959d2013-06-07 19:07:50 +01004697 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4698 std::size_t maxWidth = 0;
4699 for( it = itBegin; it != itEnd; ++it )
4700 maxWidth = (std::max)( maxWidth, it->commands().size() );
4701
4702 for( it = itBegin; it != itEnd; ++it ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004703 Detail::Text usage( it->commands(), Detail::TextAttributes()
Phil Nash786959d2013-06-07 19:07:50 +01004704 .setWidth( maxWidth+indent )
4705 .setIndent( indent ) );
Phil Nash1c2fbe12014-02-11 18:12:41 +00004706 Detail::Text desc( it->description, Detail::TextAttributes()
Phil Nashaf8cd982014-03-24 18:15:04 +00004707 .setWidth( width - maxWidth - 3 ) );
Phil Nash786959d2013-06-07 19:07:50 +01004708
Phil Nash3b4edd72016-02-10 19:24:48 +00004709 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4710 std::string usageCol = i < usage.size() ? usage[i] : "";
Phil Nash786959d2013-06-07 19:07:50 +01004711 os << usageCol;
4712
4713 if( i < desc.size() && !desc[i].empty() )
4714 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4715 << desc[i];
4716 os << "\n";
4717 }
4718 }
4719 }
4720 std::string optUsage() const {
4721 std::ostringstream oss;
4722 optUsage( oss );
4723 return oss.str();
4724 }
4725
4726 void argSynopsis( std::ostream& os ) const {
4727 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4728 if( i > 1 )
4729 os << " ";
4730 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4731 if( it != m_positionalArgs.end() )
Phil Nashb9fea752014-03-06 08:16:06 +00004732 os << "<" << it->second.placeholder << ">";
Phil Nash472dc2a2014-03-17 18:40:58 +00004733 else if( m_floatingArg.get() )
4734 os << "<" << m_floatingArg->placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004735 else
4736 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4737 }
4738 // !TBD No indication of mandatory args
Phil Nash472dc2a2014-03-17 18:40:58 +00004739 if( m_floatingArg.get() ) {
Phil Nash786959d2013-06-07 19:07:50 +01004740 if( m_highestSpecifiedArgPosition > 1 )
4741 os << " ";
Phil Nash472dc2a2014-03-17 18:40:58 +00004742 os << "[<" << m_floatingArg->placeholder << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01004743 }
4744 }
4745 std::string argSynopsis() const {
4746 std::ostringstream oss;
4747 argSynopsis( oss );
4748 return oss.str();
4749 }
4750
4751 void usage( std::ostream& os, std::string const& procName ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004752 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004753 os << "usage:\n " << procName << " ";
4754 argSynopsis( os );
4755 if( !m_options.empty() ) {
4756 os << " [options]\n\nwhere options are: \n";
4757 optUsage( os, 2 );
4758 }
4759 os << "\n";
4760 }
4761 std::string usage( std::string const& procName ) const {
4762 std::ostringstream oss;
4763 usage( oss, procName );
4764 return oss.str();
4765 }
4766
Phil Nashe5537842016-04-25 18:56:50 +01004767 ConfigT parse( std::vector<std::string> const& args ) const {
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004768 ConfigT config;
Phil Nashe5537842016-04-25 18:56:50 +01004769 parseInto( args, config );
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004770 return config;
4771 }
4772
Phil Nashe5537842016-04-25 18:56:50 +01004773 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
4774 std::string processName = args[0];
Phil Nash786959d2013-06-07 19:07:50 +01004775 std::size_t lastSlash = processName.find_last_of( "/\\" );
4776 if( lastSlash != std::string::npos )
4777 processName = processName.substr( lastSlash+1 );
4778 m_boundProcessName.set( config, processName );
4779 std::vector<Parser::Token> tokens;
4780 Parser parser;
Phil Nashe5537842016-04-25 18:56:50 +01004781 parser.parseIntoTokens( args, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004782 return populate( tokens, config );
4783 }
4784
4785 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004786 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004787 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4788 unusedTokens = populateFixedArgs( unusedTokens, config );
4789 unusedTokens = populateFloatingArgs( unusedTokens, config );
4790 return unusedTokens;
4791 }
4792
4793 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4794 std::vector<Parser::Token> unusedTokens;
Phil Nash91ef5f72013-12-20 19:06:26 +00004795 std::vector<std::string> errors;
Phil Nash786959d2013-06-07 19:07:50 +01004796 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4797 Parser::Token const& token = tokens[i];
4798 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4799 for(; it != itEnd; ++it ) {
4800 Arg const& arg = *it;
4801
4802 try {
4803 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
4804 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
4805 if( arg.takesArg() ) {
4806 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
Phil Nash91ef5f72013-12-20 19:06:26 +00004807 errors.push_back( "Expected argument to option: " + token.data );
4808 else
4809 arg.boundField.set( config, tokens[++i].data );
Phil Nash786959d2013-06-07 19:07:50 +01004810 }
4811 else {
Phil Nashe5537842016-04-25 18:56:50 +01004812 arg.boundField.set( config, "true" );
Phil Nash786959d2013-06-07 19:07:50 +01004813 }
4814 break;
4815 }
4816 }
4817 catch( std::exception& ex ) {
Phil Nash91ef5f72013-12-20 19:06:26 +00004818 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01004819 }
4820 }
Phil Nash91ef5f72013-12-20 19:06:26 +00004821 if( it == itEnd ) {
4822 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
4823 unusedTokens.push_back( token );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004824 else if( errors.empty() && m_throwOnUnrecognisedTokens )
Phil Nash91ef5f72013-12-20 19:06:26 +00004825 errors.push_back( "unrecognised option: " + token.data );
4826 }
4827 }
4828 if( !errors.empty() ) {
4829 std::ostringstream oss;
4830 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
4831 it != itEnd;
4832 ++it ) {
4833 if( it != errors.begin() )
4834 oss << "\n";
4835 oss << *it;
4836 }
4837 throw std::runtime_error( oss.str() );
Phil Nash786959d2013-06-07 19:07:50 +01004838 }
4839 return unusedTokens;
4840 }
4841 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4842 std::vector<Parser::Token> unusedTokens;
4843 int position = 1;
4844 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4845 Parser::Token const& token = tokens[i];
4846 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
4847 if( it != m_positionalArgs.end() )
4848 it->second.boundField.set( config, token.data );
4849 else
4850 unusedTokens.push_back( token );
4851 if( token.type == Parser::Token::Positional )
4852 position++;
4853 }
4854 return unusedTokens;
4855 }
4856 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nash472dc2a2014-03-17 18:40:58 +00004857 if( !m_floatingArg.get() )
Phil Nash786959d2013-06-07 19:07:50 +01004858 return tokens;
4859 std::vector<Parser::Token> unusedTokens;
4860 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4861 Parser::Token const& token = tokens[i];
4862 if( token.type == Parser::Token::Positional )
Phil Nash472dc2a2014-03-17 18:40:58 +00004863 m_floatingArg->boundField.set( config, token.data );
Phil Nash786959d2013-06-07 19:07:50 +01004864 else
4865 unusedTokens.push_back( token );
4866 }
4867 return unusedTokens;
4868 }
4869
Phil Nashaf8cd982014-03-24 18:15:04 +00004870 void validate() const
4871 {
4872 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
4873 throw std::logic_error( "No options or arguments specified" );
4874
4875 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
4876 itEnd = m_options.end();
4877 it != itEnd; ++it )
4878 it->validate();
4879 }
4880
Phil Nash786959d2013-06-07 19:07:50 +01004881 private:
4882 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
4883 std::vector<Arg> m_options;
4884 std::map<int, Arg> m_positionalArgs;
Phil Nash472dc2a2014-03-17 18:40:58 +00004885 ArgAutoPtr m_floatingArg;
Phil Nash786959d2013-06-07 19:07:50 +01004886 int m_highestSpecifiedArgPosition;
Phil Nash91ef5f72013-12-20 19:06:26 +00004887 bool m_throwOnUnrecognisedTokens;
Phil Nash786959d2013-06-07 19:07:50 +01004888 };
4889
4890} // end namespace Clara
4891
Phil Nashb9fea752014-03-06 08:16:06 +00004892STITCH_CLARA_CLOSE_NAMESPACE
4893#undef STITCH_CLARA_OPEN_NAMESPACE
4894#undef STITCH_CLARA_CLOSE_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004895
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004896#endif // TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00004897#undef STITCH_CLARA_OPEN_NAMESPACE
4898
4899// Restore Clara's value for console width, if present
4900#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4901#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4902#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
4903#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00004904
Phil Nash5ecb72b2013-11-26 20:57:45 +00004905#include <fstream>
4906
Phil Nash786959d2013-06-07 19:07:50 +01004907namespace Catch {
4908
4909 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
4910 inline void abortAfterX( ConfigData& config, int x ) {
4911 if( x < 1 )
4912 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
4913 config.abortAfter = x;
4914 }
4915 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01004916 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
Phil Nashe73583d2015-08-07 17:30:34 +01004917 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
Phil Nash786959d2013-06-07 19:07:50 +01004918
4919 inline void addWarning( ConfigData& config, std::string const& _warning ) {
4920 if( _warning == "NoAssertions" )
Phil Nashce562092014-07-09 07:40:37 +01004921 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01004922 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01004923 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004924 }
4925 inline void setOrder( ConfigData& config, std::string const& order ) {
4926 if( startsWith( "declared", order ) )
4927 config.runOrder = RunTests::InDeclarationOrder;
4928 else if( startsWith( "lexical", order ) )
4929 config.runOrder = RunTests::InLexicographicalOrder;
4930 else if( startsWith( "random", order ) )
4931 config.runOrder = RunTests::InRandomOrder;
4932 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01004933 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01004934 }
4935 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
4936 if( seed == "time" ) {
4937 config.rngSeed = static_cast<unsigned int>( std::time(0) );
4938 }
4939 else {
4940 std::stringstream ss;
4941 ss << seed;
4942 ss >> config.rngSeed;
4943 if( ss.fail() )
4944 throw std::runtime_error( "Argment to --rng-seed should be the word 'time' or a number" );
4945 }
Phil Nash786959d2013-06-07 19:07:50 +01004946 }
4947 inline void setVerbosity( ConfigData& config, int level ) {
4948 // !TBD: accept strings?
Phil Nashce562092014-07-09 07:40:37 +01004949 config.verbosity = static_cast<Verbosity::Level>( level );
Phil Nashaa7123b2013-08-15 19:01:00 +01004950 }
4951 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
4952 config.showDurations = _showDurations
4953 ? ShowDurations::Always
4954 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01004955 }
Phil Nashae5ee2c2016-02-29 08:17:18 +00004956 inline void setUseColour( ConfigData& config, std::string const& value ) {
4957 std::string mode = toLower( value );
4958
4959 if( mode == "yes" )
4960 config.useColour = UseColour::Yes;
4961 else if( mode == "no" )
4962 config.useColour = UseColour::No;
4963 else if( mode == "auto" )
4964 config.useColour = UseColour::Auto;
4965 else
4966 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
4967 }
4968 inline void forceColour( ConfigData& config ) {
4969 config.useColour = UseColour::Yes;
4970 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00004971 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
4972 std::ifstream f( _filename.c_str() );
4973 if( !f.is_open() )
4974 throw std::domain_error( "Unable to load input file: " + _filename );
4975
4976 std::string line;
4977 while( std::getline( f, line ) ) {
4978 line = trim(line);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01004979 if( !line.empty() && !startsWith( line, '#' ) ) {
4980 if( !startsWith( line, '"' ) )
4981 line = '"' + line + '"';
4982 addTestOrTags( config, line + ',' );
Phil Nash40f60682016-09-27 10:46:22 +01004983 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00004984 }
4985 }
Phil Nash786959d2013-06-07 19:07:50 +01004986
4987 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
4988
Phil Nashb9fea752014-03-06 08:16:06 +00004989 using namespace Clara;
4990 CommandLine<ConfigData> cli;
Phil Nash786959d2013-06-07 19:07:50 +01004991
4992 cli.bindProcessName( &ConfigData::processName );
4993
Phil Nashb9fea752014-03-06 08:16:06 +00004994 cli["-?"]["-h"]["--help"]
Phil Nash786959d2013-06-07 19:07:50 +01004995 .describe( "display usage information" )
Phil Nash472dc2a2014-03-17 18:40:58 +00004996 .bind( &ConfigData::showHelp );
Phil Nash786959d2013-06-07 19:07:50 +01004997
Phil Nashb9fea752014-03-06 08:16:06 +00004998 cli["-l"]["--list-tests"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00004999 .describe( "list all/matching test cases" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005000 .bind( &ConfigData::listTests );
Phil Nash786959d2013-06-07 19:07:50 +01005001
Phil Nashb9fea752014-03-06 08:16:06 +00005002 cli["-t"]["--list-tags"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005003 .describe( "list all/matching tags" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005004 .bind( &ConfigData::listTags );
Phil Nash786959d2013-06-07 19:07:50 +01005005
Phil Nashb9fea752014-03-06 08:16:06 +00005006 cli["-s"]["--success"]
Phil Nash786959d2013-06-07 19:07:50 +01005007 .describe( "include successful tests in output" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005008 .bind( &ConfigData::showSuccessfulTests );
Phil Nash786959d2013-06-07 19:07:50 +01005009
Phil Nashb9fea752014-03-06 08:16:06 +00005010 cli["-b"]["--break"]
Phil Nash786959d2013-06-07 19:07:50 +01005011 .describe( "break into debugger on failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005012 .bind( &ConfigData::shouldDebugBreak );
Phil Nash786959d2013-06-07 19:07:50 +01005013
Phil Nashb9fea752014-03-06 08:16:06 +00005014 cli["-e"]["--nothrow"]
Phil Nash7d5f2712013-06-07 21:15:25 +01005015 .describe( "skip exception tests" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005016 .bind( &ConfigData::noThrow );
Phil Nash786959d2013-06-07 19:07:50 +01005017
Phil Nashaef6cd52014-04-23 07:10:10 +01005018 cli["-i"]["--invisibles"]
5019 .describe( "show invisibles (tabs, newlines)" )
5020 .bind( &ConfigData::showInvisibles );
5021
Phil Nashb9fea752014-03-06 08:16:06 +00005022 cli["-o"]["--out"]
Phil Nash786959d2013-06-07 19:07:50 +01005023 .describe( "output filename" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005024 .bind( &ConfigData::outputFilename, "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01005025
Phil Nashb9fea752014-03-06 08:16:06 +00005026 cli["-r"]["--reporter"]
5027// .placeholder( "name[:filename]" )
Phil Nash5ecb72b2013-11-26 20:57:45 +00005028 .describe( "reporter to use (defaults to console)" )
Phil Nashe73583d2015-08-07 17:30:34 +01005029 .bind( &addReporterName, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005030
Phil Nashb9fea752014-03-06 08:16:06 +00005031 cli["-n"]["--name"]
Phil Nash786959d2013-06-07 19:07:50 +01005032 .describe( "suite name" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005033 .bind( &ConfigData::name, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005034
Phil Nashb9fea752014-03-06 08:16:06 +00005035 cli["-a"]["--abort"]
Phil Nash786959d2013-06-07 19:07:50 +01005036 .describe( "abort at first failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005037 .bind( &abortAfterFirst );
Phil Nash786959d2013-06-07 19:07:50 +01005038
Phil Nashb9fea752014-03-06 08:16:06 +00005039 cli["-x"]["--abortx"]
Phil Nash786959d2013-06-07 19:07:50 +01005040 .describe( "abort after x failures" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005041 .bind( &abortAfterX, "no. failures" );
Phil Nash786959d2013-06-07 19:07:50 +01005042
Phil Nashb9fea752014-03-06 08:16:06 +00005043 cli["-w"]["--warn"]
Phil Nash786959d2013-06-07 19:07:50 +01005044 .describe( "enable warnings" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005045 .bind( &addWarning, "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01005046
Phil Nashb9fea752014-03-06 08:16:06 +00005047// - needs updating if reinstated
5048// cli.into( &setVerbosity )
Phil Nash786959d2013-06-07 19:07:50 +01005049// .describe( "level of verbosity (0=no output)" )
5050// .shortOpt( "v")
5051// .longOpt( "verbosity" )
Phil Nashb9fea752014-03-06 08:16:06 +00005052// .placeholder( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01005053
Phil Nashb9fea752014-03-06 08:16:06 +00005054 cli[_]
Phil Nash786959d2013-06-07 19:07:50 +01005055 .describe( "which test or tests to use" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005056 .bind( &addTestOrTags, "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01005057
Phil Nashb9fea752014-03-06 08:16:06 +00005058 cli["-d"]["--durations"]
Phil Nashaa7123b2013-08-15 19:01:00 +01005059 .describe( "show test durations" )
Phil Nashae5ee2c2016-02-29 08:17:18 +00005060 .bind( &setShowDurations, "yes|no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01005061
Phil Nashb9fea752014-03-06 08:16:06 +00005062 cli["-f"]["--input-file"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005063 .describe( "load test names to run from a file" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005064 .bind( &loadTestNamesFromFile, "filename" );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005065
Phil Nashe6b365d2015-07-07 08:25:15 +01005066 cli["-#"]["--filenames-as-tags"]
5067 .describe( "adds a tag for the filename" )
5068 .bind( &ConfigData::filenamesAsTags );
5069
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005070 cli["-c"]["--section"]
5071 .describe( "specify section to run" )
5072 .bind( &addSectionToRun, "section name" );
5073
Phil Nash5ecb72b2013-11-26 20:57:45 +00005074 // Less common commands which don't have a short form
Phil Nashb9fea752014-03-06 08:16:06 +00005075 cli["--list-test-names-only"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005076 .describe( "list all/matching test cases names only" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005077 .bind( &ConfigData::listTestNamesOnly );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005078
Phil Nashb9fea752014-03-06 08:16:06 +00005079 cli["--list-reporters"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005080 .describe( "list all reporters" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005081 .bind( &ConfigData::listReporters );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005082
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005083 cli["--order"]
5084 .describe( "test case order (defaults to decl)" )
5085 .bind( &setOrder, "decl|lex|rand" );
5086
5087 cli["--rng-seed"]
5088 .describe( "set a specific seed for random numbers" )
5089 .bind( &setRngSeed, "'time'|number" );
5090
Phil Nasha806c3e2015-03-04 08:23:40 +00005091 cli["--force-colour"]
Phil Nashae5ee2c2016-02-29 08:17:18 +00005092 .describe( "force colourised output (deprecated)" )
5093 .bind( &forceColour );
5094
5095 cli["--use-colour"]
5096 .describe( "should output be colourised" )
5097 .bind( &setUseColour, "yes|no" );
Phil Nasha806c3e2015-03-04 08:23:40 +00005098
Phil Nash786959d2013-06-07 19:07:50 +01005099 return cli;
5100 }
5101
Phil Nasha695eb92012-08-13 07:46:10 +01005102} // end namespace Catch
5103
5104// #included from: internal/catch_list.hpp
5105#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5106
Phil Nash1c2fbe12014-02-11 18:12:41 +00005107// #included from: catch_text.h
5108#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5109
5110#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5111
5112#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
Phil Nash472dc2a2014-03-17 18:40:58 +00005113// #included from: ../external/tbc_text_format.h
Phil Nash1c2fbe12014-02-11 18:12:41 +00005114// Only use header guard if we are not using an outer namespace
5115#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5116# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5117# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5118# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5119# endif
5120# else
5121# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5122# endif
5123#endif
5124#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5125#include <string>
5126#include <vector>
5127#include <sstream>
5128
5129// Use optional outer namespace
5130#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5131namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5132#endif
5133
5134namespace Tbc {
5135
5136#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5137 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5138#else
5139 const unsigned int consoleWidth = 80;
5140#endif
5141
5142 struct TextAttributes {
5143 TextAttributes()
5144 : initialIndent( std::string::npos ),
5145 indent( 0 ),
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005146 width( consoleWidth-1 )
Phil Nash1c2fbe12014-02-11 18:12:41 +00005147 {}
5148
5149 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
5150 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
5151 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005152
5153 std::size_t initialIndent; // indent of first line, or npos
5154 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5155 std::size_t width; // maximum width of text, including indent. Longer text will wrap
Phil Nash1c2fbe12014-02-11 18:12:41 +00005156 };
5157
5158 class Text {
5159 public:
5160 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5161 : attr( _attr )
5162 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005163 const std::string wrappableBeforeChars = "[({<\t";
5164 const std::string wrappableAfterChars = "])}>-,./|\\";
5165 const std::string wrappableInsteadOfChars = " \n\r";
5166 std::string indent = _attr.initialIndent != std::string::npos
5167 ? std::string( _attr.initialIndent, ' ' )
5168 : std::string( _attr.indent, ' ' );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005169
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005170 typedef std::string::const_iterator iterator;
5171 iterator it = _str.begin();
5172 const iterator strEnd = _str.end();
5173
5174 while( it != strEnd ) {
5175
Phil Nash1c2fbe12014-02-11 18:12:41 +00005176 if( lines.size() >= 1000 ) {
5177 lines.push_back( "... message truncated due to excessive size" );
5178 return;
5179 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005180
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005181 std::string suffix;
5182 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5183 iterator itEnd = it+width;
5184 iterator itNext = _str.end();
5185
5186 iterator itNewLine = std::find( it, itEnd, '\n' );
5187 if( itNewLine != itEnd )
5188 itEnd = itNewLine;
5189
5190 if( itEnd != strEnd ) {
5191 bool foundWrapPoint = false;
5192 iterator findIt = itEnd;
5193 do {
5194 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5195 itEnd = findIt+1;
5196 itNext = findIt+1;
5197 foundWrapPoint = true;
5198 }
5199 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5200 itEnd = findIt;
5201 itNext = findIt;
5202 foundWrapPoint = true;
5203 }
5204 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5205 itNext = findIt+1;
5206 itEnd = findIt;
5207 foundWrapPoint = true;
5208 }
5209 if( findIt == it )
5210 break;
5211 else
5212 --findIt;
5213 }
5214 while( !foundWrapPoint );
5215
5216 if( !foundWrapPoint ) {
5217 // No good wrap char, so we'll break mid word and add a hyphen
5218 --itEnd;
5219 itNext = itEnd;
5220 suffix = "-";
Phil Nash1c2fbe12014-02-11 18:12:41 +00005221 }
5222 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005223 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5224 --itEnd;
Phil Nash1c2fbe12014-02-11 18:12:41 +00005225 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005226 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005227 lines.push_back( indent + std::string( it, itEnd ) + suffix );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005228
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005229 if( indent.size() != _attr.indent )
5230 indent = std::string( _attr.indent, ' ' );
5231 it = itNext;
5232 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005233 }
5234
5235 typedef std::vector<std::string>::const_iterator const_iterator;
5236
5237 const_iterator begin() const { return lines.begin(); }
5238 const_iterator end() const { return lines.end(); }
5239 std::string const& last() const { return lines.back(); }
5240 std::size_t size() const { return lines.size(); }
5241 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
5242 std::string toString() const {
5243 std::ostringstream oss;
5244 oss << *this;
5245 return oss.str();
5246 }
5247
5248 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5249 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5250 it != itEnd; ++it ) {
5251 if( it != _text.begin() )
5252 _stream << "\n";
5253 _stream << *it;
5254 }
5255 return _stream;
5256 }
5257
5258 private:
5259 std::string str;
5260 TextAttributes attr;
5261 std::vector<std::string> lines;
5262 };
5263
5264} // end namespace Tbc
5265
5266#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5267} // end outer namespace
5268#endif
5269
5270#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5271#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5272
5273namespace Catch {
5274 using Tbc::Text;
5275 using Tbc::TextAttributes;
5276}
5277
Phil Nash5c7d3d72013-04-01 11:27:10 +01005278// #included from: catch_console_colour.hpp
5279#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005280
5281namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005282
Phil Nash12c16ff2013-04-05 20:58:01 +01005283 struct Colour {
5284 enum Code {
5285 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005286
Phil Nash12c16ff2013-04-05 20:58:01 +01005287 White,
5288 Red,
5289 Green,
5290 Blue,
5291 Cyan,
5292 Yellow,
5293 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005294
Phil Nash12c16ff2013-04-05 20:58:01 +01005295 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005296
Phil Nash12c16ff2013-04-05 20:58:01 +01005297 BrightRed = Bright | Red,
5298 BrightGreen = Bright | Green,
5299 LightGrey = Bright | Grey,
5300 BrightWhite = Bright | White,
5301
5302 // By intention
5303 FileName = LightGrey,
Phil Nash52e1e742014-07-03 08:11:38 +01005304 Warning = Yellow,
Phil Nash12c16ff2013-04-05 20:58:01 +01005305 ResultError = BrightRed,
5306 ResultSuccess = BrightGreen,
Phil Nash52e1e742014-07-03 08:11:38 +01005307 ResultExpectedFailure = Warning,
Phil Nash12c16ff2013-04-05 20:58:01 +01005308
5309 Error = BrightRed,
5310 Success = Green,
5311
5312 OriginalExpression = Cyan,
5313 ReconstructedExpression = Yellow,
5314
5315 SecondaryText = LightGrey,
5316 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01005317 };
5318
Phil Nash12c16ff2013-04-05 20:58:01 +01005319 // Use constructed object for RAII guard
5320 Colour( Code _colourCode );
Phil Nashce562092014-07-09 07:40:37 +01005321 Colour( Colour const& other );
Phil Nash12c16ff2013-04-05 20:58:01 +01005322 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01005323
Phil Nash12c16ff2013-04-05 20:58:01 +01005324 // Use static method for one-shot changes
5325 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01005326
5327 private:
Phil Nashce562092014-07-09 07:40:37 +01005328 bool m_moved;
Phil Nash5c7d3d72013-04-01 11:27:10 +01005329 };
5330
Phil Nash52e1e742014-07-03 08:11:38 +01005331 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5332
Phil Nash5c7d3d72013-04-01 11:27:10 +01005333} // end namespace Catch
5334
Phil Nash3649fdf2013-12-03 18:53:55 +00005335// #included from: catch_interfaces_reporter.h
5336#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5337
Phil Nash3649fdf2013-12-03 18:53:55 +00005338#include <string>
5339#include <ostream>
5340#include <map>
5341#include <assert.h>
5342
5343namespace Catch
5344{
5345 struct ReporterConfig {
Phil Nash7e346192015-11-03 08:00:43 +00005346 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
Phil Nash3649fdf2013-12-03 18:53:55 +00005347 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5348
Phil Nash7e346192015-11-03 08:00:43 +00005349 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
Phil Nash3649fdf2013-12-03 18:53:55 +00005350 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5351
5352 std::ostream& stream() const { return *m_stream; }
Phil Nash7e346192015-11-03 08:00:43 +00005353 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005354
5355 private:
5356 std::ostream* m_stream;
Phil Nash7e346192015-11-03 08:00:43 +00005357 Ptr<IConfig const> m_fullConfig;
Phil Nash3649fdf2013-12-03 18:53:55 +00005358 };
5359
5360 struct ReporterPreferences {
5361 ReporterPreferences()
5362 : shouldRedirectStdOut( false )
5363 {}
5364
5365 bool shouldRedirectStdOut;
5366 };
5367
5368 template<typename T>
5369 struct LazyStat : Option<T> {
5370 LazyStat() : used( false ) {}
5371 LazyStat& operator=( T const& _value ) {
5372 Option<T>::operator=( _value );
5373 used = false;
5374 return *this;
5375 }
5376 void reset() {
5377 Option<T>::reset();
5378 used = false;
5379 }
5380 bool used;
5381 };
5382
5383 struct TestRunInfo {
5384 TestRunInfo( std::string const& _name ) : name( _name ) {}
5385 std::string name;
5386 };
5387 struct GroupInfo {
5388 GroupInfo( std::string const& _name,
5389 std::size_t _groupIndex,
5390 std::size_t _groupsCount )
5391 : name( _name ),
5392 groupIndex( _groupIndex ),
5393 groupsCounts( _groupsCount )
5394 {}
5395
5396 std::string name;
5397 std::size_t groupIndex;
5398 std::size_t groupsCounts;
5399 };
5400
5401 struct AssertionStats {
5402 AssertionStats( AssertionResult const& _assertionResult,
5403 std::vector<MessageInfo> const& _infoMessages,
5404 Totals const& _totals )
5405 : assertionResult( _assertionResult ),
5406 infoMessages( _infoMessages ),
5407 totals( _totals )
5408 {
5409 if( assertionResult.hasMessage() ) {
5410 // Copy message into messages list.
5411 // !TBD This should have been done earlier, somewhere
5412 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5413 builder << assertionResult.getMessage();
5414 builder.m_info.message = builder.m_stream.str();
5415
5416 infoMessages.push_back( builder.m_info );
5417 }
5418 }
5419 virtual ~AssertionStats();
5420
Phil Nash318c9362015-05-19 18:40:00 +01005421# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005422 AssertionStats( AssertionStats const& ) = default;
5423 AssertionStats( AssertionStats && ) = default;
5424 AssertionStats& operator = ( AssertionStats const& ) = default;
5425 AssertionStats& operator = ( AssertionStats && ) = default;
5426# endif
5427
Phil Nash3649fdf2013-12-03 18:53:55 +00005428 AssertionResult assertionResult;
5429 std::vector<MessageInfo> infoMessages;
5430 Totals totals;
5431 };
5432
5433 struct SectionStats {
5434 SectionStats( SectionInfo const& _sectionInfo,
5435 Counts const& _assertions,
5436 double _durationInSeconds,
5437 bool _missingAssertions )
5438 : sectionInfo( _sectionInfo ),
5439 assertions( _assertions ),
5440 durationInSeconds( _durationInSeconds ),
5441 missingAssertions( _missingAssertions )
5442 {}
5443 virtual ~SectionStats();
Phil Nash318c9362015-05-19 18:40:00 +01005444# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005445 SectionStats( SectionStats const& ) = default;
5446 SectionStats( SectionStats && ) = default;
5447 SectionStats& operator = ( SectionStats const& ) = default;
5448 SectionStats& operator = ( SectionStats && ) = default;
5449# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005450
5451 SectionInfo sectionInfo;
5452 Counts assertions;
5453 double durationInSeconds;
5454 bool missingAssertions;
5455 };
5456
5457 struct TestCaseStats {
5458 TestCaseStats( TestCaseInfo const& _testInfo,
5459 Totals const& _totals,
5460 std::string const& _stdOut,
5461 std::string const& _stdErr,
5462 bool _aborting )
5463 : testInfo( _testInfo ),
5464 totals( _totals ),
5465 stdOut( _stdOut ),
5466 stdErr( _stdErr ),
5467 aborting( _aborting )
5468 {}
5469 virtual ~TestCaseStats();
5470
Phil Nash318c9362015-05-19 18:40:00 +01005471# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005472 TestCaseStats( TestCaseStats const& ) = default;
5473 TestCaseStats( TestCaseStats && ) = default;
5474 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5475 TestCaseStats& operator = ( TestCaseStats && ) = default;
5476# endif
5477
Phil Nash3649fdf2013-12-03 18:53:55 +00005478 TestCaseInfo testInfo;
5479 Totals totals;
5480 std::string stdOut;
5481 std::string stdErr;
5482 bool aborting;
5483 };
5484
5485 struct TestGroupStats {
5486 TestGroupStats( GroupInfo const& _groupInfo,
5487 Totals const& _totals,
5488 bool _aborting )
5489 : groupInfo( _groupInfo ),
5490 totals( _totals ),
5491 aborting( _aborting )
5492 {}
5493 TestGroupStats( GroupInfo const& _groupInfo )
5494 : groupInfo( _groupInfo ),
5495 aborting( false )
5496 {}
5497 virtual ~TestGroupStats();
5498
Phil Nash318c9362015-05-19 18:40:00 +01005499# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005500 TestGroupStats( TestGroupStats const& ) = default;
5501 TestGroupStats( TestGroupStats && ) = default;
5502 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5503 TestGroupStats& operator = ( TestGroupStats && ) = default;
5504# endif
5505
Phil Nash3649fdf2013-12-03 18:53:55 +00005506 GroupInfo groupInfo;
5507 Totals totals;
5508 bool aborting;
5509 };
5510
5511 struct TestRunStats {
5512 TestRunStats( TestRunInfo const& _runInfo,
5513 Totals const& _totals,
5514 bool _aborting )
5515 : runInfo( _runInfo ),
5516 totals( _totals ),
5517 aborting( _aborting )
5518 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005519 virtual ~TestRunStats();
5520
Phil Nash318c9362015-05-19 18:40:00 +01005521# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3649fdf2013-12-03 18:53:55 +00005522 TestRunStats( TestRunStats const& _other )
5523 : runInfo( _other.runInfo ),
5524 totals( _other.totals ),
5525 aborting( _other.aborting )
5526 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005527# else
5528 TestRunStats( TestRunStats const& ) = default;
5529 TestRunStats( TestRunStats && ) = default;
5530 TestRunStats& operator = ( TestRunStats const& ) = default;
5531 TestRunStats& operator = ( TestRunStats && ) = default;
5532# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005533
5534 TestRunInfo runInfo;
5535 Totals totals;
5536 bool aborting;
5537 };
5538
Phil Nash92b141e2016-04-28 08:13:00 +01005539 class MultipleReporters;
5540
Phil Nash3649fdf2013-12-03 18:53:55 +00005541 struct IStreamingReporter : IShared {
5542 virtual ~IStreamingReporter();
5543
5544 // Implementing class must also provide the following static method:
5545 // static std::string getDescription();
5546
5547 virtual ReporterPreferences getPreferences() const = 0;
5548
5549 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5550
5551 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5552 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5553
5554 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5555 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5556
5557 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5558
Phil Nash576aff62014-12-21 00:21:23 +00005559 // The return value indicates if the messages buffer should be cleared:
Phil Nash3649fdf2013-12-03 18:53:55 +00005560 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005561
Phil Nash3649fdf2013-12-03 18:53:55 +00005562 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5563 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5564 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5565 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nash92f08362014-12-22 20:18:05 +00005566
5567 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01005568
5569 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005570 };
5571
Phil Nashe73583d2015-08-07 17:30:34 +01005572 struct IReporterFactory : IShared {
Phil Nash3649fdf2013-12-03 18:53:55 +00005573 virtual ~IReporterFactory();
5574 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5575 virtual std::string getDescription() const = 0;
5576 };
5577
5578 struct IReporterRegistry {
Phil Nashe73583d2015-08-07 17:30:34 +01005579 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5580 typedef std::vector<Ptr<IReporterFactory> > Listeners;
Phil Nash3649fdf2013-12-03 18:53:55 +00005581
5582 virtual ~IReporterRegistry();
Phil Nash7e346192015-11-03 08:00:43 +00005583 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005584 virtual FactoryMap const& getFactories() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005585 virtual Listeners const& getListeners() const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005586 };
5587
Phil Nashe73583d2015-08-07 17:30:34 +01005588 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5589
Phil Nash3649fdf2013-12-03 18:53:55 +00005590}
5591
Phil Nasha695eb92012-08-13 07:46:10 +01005592#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00005593#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01005594
5595namespace Catch {
Phil Nasha695eb92012-08-13 07:46:10 +01005596
Phil Nash786959d2013-06-07 19:07:50 +01005597 inline std::size_t listTests( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005598
5599 TestSpec testSpec = config.testSpec();
5600 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005601 Catch::cout() << "Matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005602 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005603 Catch::cout() << "All available test cases:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005604 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005605 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005606
5607 std::size_t matchedTests = 0;
Phil Nash8d44f2d2013-11-13 08:10:45 +00005608 TextAttributes nameAttr, tagsAttr;
5609 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5610 tagsAttr.setIndent( 6 );
5611
Phil Nashe73583d2015-08-07 17:30:34 +01005612 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005613 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005614 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005615 ++it ) {
5616 matchedTests++;
5617 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Phil Nash52e1e742014-07-03 08:11:38 +01005618 Colour::Code colour = testCaseInfo.isHidden()
Phil Nash20cad7c2014-04-15 18:44:37 +01005619 ? Colour::SecondaryText
5620 : Colour::None;
5621 Colour colourGuard( colour );
Phil Nash38f7eef2013-03-29 13:44:33 +00005622
Phil Nash383d7c02014-10-02 19:08:19 +01005623 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005624 if( !testCaseInfo.tags.empty() )
Phil Nash383d7c02014-10-02 19:08:19 +01005625 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005626 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00005627
Phil Nash65cc14c2014-05-16 18:54:48 +01005628 if( !config.testSpec().hasFilters() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005629 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00005630 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005631 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005632 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00005633 }
Phil Nasha695eb92012-08-13 07:46:10 +01005634
Phil Nash5ecb72b2013-11-26 20:57:45 +00005635 inline std::size_t listTestsNamesOnly( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005636 TestSpec testSpec = config.testSpec();
5637 if( !config.testSpec().hasFilters() )
Phil Nashacdd3b52014-06-30 07:35:36 +01005638 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005639 std::size_t matchedTests = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005640 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005641 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005642 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005643 ++it ) {
5644 matchedTests++;
5645 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005646 if( startsWith( testCaseInfo.name, '#' ) )
5647 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
Phil Nash40f60682016-09-27 10:46:22 +01005648 else
5649 Catch::cout() << testCaseInfo.name << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005650 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005651 return matchedTests;
5652 }
5653
Phil Nash48fac9c2014-05-20 19:02:37 +01005654 struct TagInfo {
5655 TagInfo() : count ( 0 ) {}
5656 void add( std::string const& spelling ) {
5657 ++count;
5658 spellings.insert( spelling );
5659 }
5660 std::string all() const {
5661 std::string out;
5662 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5663 it != itEnd;
5664 ++it )
5665 out += "[" + *it + "]";
5666 return out;
5667 }
5668 std::set<std::string> spellings;
5669 std::size_t count;
5670 };
5671
Phil Nash786959d2013-06-07 19:07:50 +01005672 inline std::size_t listTags( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005673 TestSpec testSpec = config.testSpec();
5674 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005675 Catch::cout() << "Tags for matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005676 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005677 Catch::cout() << "All available tags:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005678 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005679 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005680
Phil Nash9241e432014-05-20 18:50:59 +01005681 std::map<std::string, TagInfo> tagCounts;
Phil Nash38f7eef2013-03-29 13:44:33 +00005682
Phil Nashe73583d2015-08-07 17:30:34 +01005683 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005684 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005685 it != itEnd;
5686 ++it ) {
Phil Nash20cad7c2014-04-15 18:44:37 +01005687 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5688 tagItEnd = it->getTestCaseInfo().tags.end();
5689 tagIt != tagItEnd;
5690 ++tagIt ) {
5691 std::string tagName = *tagIt;
Phil Nash9241e432014-05-20 18:50:59 +01005692 std::string lcaseTagName = toLower( tagName );
5693 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
Phil Nash20cad7c2014-04-15 18:44:37 +01005694 if( countIt == tagCounts.end() )
Phil Nash9241e432014-05-20 18:50:59 +01005695 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5696 countIt->second.add( tagName );
Phil Nash38f7eef2013-03-29 13:44:33 +00005697 }
Phil Nasha695eb92012-08-13 07:46:10 +01005698 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005699
Phil Nash9241e432014-05-20 18:50:59 +01005700 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5701 countItEnd = tagCounts.end();
Phil Nash38f7eef2013-03-29 13:44:33 +00005702 countIt != countItEnd;
5703 ++countIt ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00005704 std::ostringstream oss;
Phil Nash9241e432014-05-20 18:50:59 +01005705 oss << " " << std::setw(2) << countIt->second.count << " ";
5706 Text wrapper( countIt->second.all(), TextAttributes()
5707 .setInitialIndent( 0 )
5708 .setIndent( oss.str().size() )
5709 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005710 Catch::cout() << oss.str() << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005711 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005712 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005713 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005714 }
5715
Phil Nash786959d2013-06-07 19:07:50 +01005716 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash576aff62014-12-21 00:21:23 +00005717 Catch::cout() << "Available reporters:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005718 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01005719 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5720 std::size_t maxNameLen = 0;
5721 for(it = itBegin; it != itEnd; ++it )
5722 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5723
5724 for(it = itBegin; it != itEnd; ++it ) {
5725 Text wrapper( it->second->getDescription(), TextAttributes()
5726 .setInitialIndent( 0 )
5727 .setIndent( 7+maxNameLen )
5728 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
Phil Nash383d7c02014-10-02 19:08:19 +01005729 Catch::cout() << " "
Phil Nash786959d2013-06-07 19:07:50 +01005730 << it->first
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005731 << ':'
Phil Nash786959d2013-06-07 19:07:50 +01005732 << std::string( maxNameLen - it->first.size() + 2, ' ' )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005733 << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005734 }
Phil Nash383d7c02014-10-02 19:08:19 +01005735 Catch::cout() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005736 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005737 }
5738
Phil Nash786959d2013-06-07 19:07:50 +01005739 inline Option<std::size_t> list( Config const& config ) {
5740 Option<std::size_t> listedCount;
5741 if( config.listTests() )
5742 listedCount = listedCount.valueOr(0) + listTests( config );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005743 if( config.listTestNamesOnly() )
5744 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
Phil Nash786959d2013-06-07 19:07:50 +01005745 if( config.listTags() )
5746 listedCount = listedCount.valueOr(0) + listTags( config );
5747 if( config.listReporters() )
5748 listedCount = listedCount.valueOr(0) + listReporters( config );
5749 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01005750 }
5751
5752} // end namespace Catch
5753
Phil Nashe73583d2015-08-07 17:30:34 +01005754// #included from: internal/catch_run_context.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005755#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005756
Phil Nash8a52a392013-07-25 08:12:03 +01005757// #included from: catch_test_case_tracker.hpp
5758#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005759
5760#include <map>
5761#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01005762#include <assert.h>
Phil Nash7e346192015-11-03 08:00:43 +00005763#include <vector>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005764#include <iterator>
Phil Nasha695eb92012-08-13 07:46:10 +01005765
5766namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +00005767namespace TestCaseTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01005768
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005769 struct NameAndLocation {
5770 std::string name;
5771 SourceLineInfo location;
5772
5773 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
5774 : name( _name ),
5775 location( _location )
5776 {}
5777 };
5778
Phil Nash7e346192015-11-03 08:00:43 +00005779 struct ITracker : SharedImpl<> {
5780 virtual ~ITracker();
Phil Nash8a52a392013-07-25 08:12:03 +01005781
Phil Nash7e346192015-11-03 08:00:43 +00005782 // static queries
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005783 virtual NameAndLocation const& nameAndLocation() const = 0;
Phil Nash8a52a392013-07-25 08:12:03 +01005784
Phil Nash7e346192015-11-03 08:00:43 +00005785 // dynamic queries
5786 virtual bool isComplete() const = 0; // Successfully completed or failed
5787 virtual bool isSuccessfullyCompleted() const = 0;
5788 virtual bool isOpen() const = 0; // Started but not complete
5789 virtual bool hasChildren() const = 0;
5790
5791 virtual ITracker& parent() = 0;
5792
5793 // actions
5794 virtual void close() = 0; // Successfully complete
5795 virtual void fail() = 0;
5796 virtual void markAsNeedingAnotherRun() = 0;
5797
5798 virtual void addChild( Ptr<ITracker> const& child ) = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005799 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
Phil Nash7e346192015-11-03 08:00:43 +00005800 virtual void openChild() = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01005801
5802 // Debug/ checking
5803 virtual bool isSectionTracker() const = 0;
5804 virtual bool isIndexTracker() const = 0;
Phil Nash7e346192015-11-03 08:00:43 +00005805 };
5806
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005807 class TrackerContext {
Phil Nash7e346192015-11-03 08:00:43 +00005808
Phil Nash8a52a392013-07-25 08:12:03 +01005809 enum RunState {
5810 NotStarted,
5811 Executing,
Phil Nash7e346192015-11-03 08:00:43 +00005812 CompletedCycle
Phil Nasha695eb92012-08-13 07:46:10 +01005813 };
5814
Phil Nash7e346192015-11-03 08:00:43 +00005815 Ptr<ITracker> m_rootTracker;
5816 ITracker* m_currentTracker;
5817 RunState m_runState;
5818
5819 public:
5820
5821 static TrackerContext& instance() {
5822 static TrackerContext s_instance;
5823 return s_instance;
5824 }
5825
5826 TrackerContext()
5827 : m_currentTracker( CATCH_NULL ),
5828 m_runState( NotStarted )
Phil Nasha695eb92012-08-13 07:46:10 +01005829 {}
5830
Phil Nash7e346192015-11-03 08:00:43 +00005831 ITracker& startRun();
Phil Nasha695eb92012-08-13 07:46:10 +01005832
Phil Nash7e346192015-11-03 08:00:43 +00005833 void endRun() {
5834 m_rootTracker.reset();
5835 m_currentTracker = CATCH_NULL;
5836 m_runState = NotStarted;
Phil Nasha695eb92012-08-13 07:46:10 +01005837 }
Phil Nash3b18d9e2015-06-30 18:26:09 +01005838
Phil Nash7e346192015-11-03 08:00:43 +00005839 void startCycle() {
5840 m_currentTracker = m_rootTracker.get();
5841 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01005842 }
Phil Nash7e346192015-11-03 08:00:43 +00005843 void completeCycle() {
5844 m_runState = CompletedCycle;
5845 }
5846
5847 bool completedCycle() const {
5848 return m_runState == CompletedCycle;
5849 }
5850 ITracker& currentTracker() {
5851 return *m_currentTracker;
5852 }
5853 void setCurrentTracker( ITracker* tracker ) {
5854 m_currentTracker = tracker;
5855 }
5856 };
5857
5858 class TrackerBase : public ITracker {
5859 protected:
5860 enum CycleState {
5861 NotStarted,
5862 Executing,
5863 ExecutingChildren,
5864 NeedsAnotherRun,
5865 CompletedSuccessfully,
5866 Failed
5867 };
5868 class TrackerHasName {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005869 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00005870 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005871 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
Phil Nash7e346192015-11-03 08:00:43 +00005872 bool operator ()( Ptr<ITracker> const& tracker ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005873 return
5874 tracker->nameAndLocation().name == m_nameAndLocation.name &&
5875 tracker->nameAndLocation().location == m_nameAndLocation.location;
Phil Nash7e346192015-11-03 08:00:43 +00005876 }
5877 };
5878 typedef std::vector<Ptr<ITracker> > Children;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005879 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00005880 TrackerContext& m_ctx;
5881 ITracker* m_parent;
5882 Children m_children;
5883 CycleState m_runState;
5884 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005885 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
5886 : m_nameAndLocation( nameAndLocation ),
Phil Nash7e346192015-11-03 08:00:43 +00005887 m_ctx( ctx ),
5888 m_parent( parent ),
5889 m_runState( NotStarted )
5890 {}
5891 virtual ~TrackerBase();
5892
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005893 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
5894 return m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00005895 }
5896 virtual bool isComplete() const CATCH_OVERRIDE {
5897 return m_runState == CompletedSuccessfully || m_runState == Failed;
5898 }
5899 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
5900 return m_runState == CompletedSuccessfully;
5901 }
5902 virtual bool isOpen() const CATCH_OVERRIDE {
5903 return m_runState != NotStarted && !isComplete();
5904 }
5905 virtual bool hasChildren() const CATCH_OVERRIDE {
Phil Nash8a52a392013-07-25 08:12:03 +01005906 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00005907 }
5908
Phil Nash7e346192015-11-03 08:00:43 +00005909 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
5910 m_children.push_back( child );
5911 }
Phil Nasha695eb92012-08-13 07:46:10 +01005912
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005913 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
5914 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
Phil Nash7e346192015-11-03 08:00:43 +00005915 return( it != m_children.end() )
5916 ? it->get()
5917 : CATCH_NULL;
5918 }
5919 virtual ITracker& parent() CATCH_OVERRIDE {
5920 assert( m_parent ); // Should always be non-null except for root
5921 return *m_parent;
5922 }
5923
5924 virtual void openChild() CATCH_OVERRIDE {
5925 if( m_runState != ExecutingChildren ) {
Phil Nash3b18d9e2015-06-30 18:26:09 +01005926 m_runState = ExecutingChildren;
Phil Nash7e346192015-11-03 08:00:43 +00005927 if( m_parent )
5928 m_parent->openChild();
Phil Nash3b18d9e2015-06-30 18:26:09 +01005929 }
Phil Nasha695eb92012-08-13 07:46:10 +01005930 }
Phil Nash92b141e2016-04-28 08:13:00 +01005931
5932 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
5933 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
5934
Phil Nash7e346192015-11-03 08:00:43 +00005935 void open() {
5936 m_runState = Executing;
5937 moveToThis();
5938 if( m_parent )
5939 m_parent->openChild();
Phil Nasha695eb92012-08-13 07:46:10 +01005940 }
5941
Phil Nash7e346192015-11-03 08:00:43 +00005942 virtual void close() CATCH_OVERRIDE {
Phil Nasha695eb92012-08-13 07:46:10 +01005943
Phil Nash7e346192015-11-03 08:00:43 +00005944 // Close any still open children (e.g. generators)
5945 while( &m_ctx.currentTracker() != this )
5946 m_ctx.currentTracker().close();
5947
5948 switch( m_runState ) {
5949 case NotStarted:
5950 case CompletedSuccessfully:
5951 case Failed:
5952 throw std::logic_error( "Illogical state" );
5953
5954 case NeedsAnotherRun:
5955 break;;
5956
5957 case Executing:
5958 m_runState = CompletedSuccessfully;
5959 break;
5960 case ExecutingChildren:
5961 if( m_children.empty() || m_children.back()->isComplete() )
5962 m_runState = CompletedSuccessfully;
5963 break;
5964
5965 default:
5966 throw std::logic_error( "Unexpected state" );
Phil Nash8a52a392013-07-25 08:12:03 +01005967 }
Phil Nash7e346192015-11-03 08:00:43 +00005968 moveToParent();
5969 m_ctx.completeCycle();
5970 }
5971 virtual void fail() CATCH_OVERRIDE {
5972 m_runState = Failed;
5973 if( m_parent )
5974 m_parent->markAsNeedingAnotherRun();
5975 moveToParent();
5976 m_ctx.completeCycle();
5977 }
5978 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
5979 m_runState = NeedsAnotherRun;
5980 }
Phil Nasha695eb92012-08-13 07:46:10 +01005981 private:
Phil Nash7e346192015-11-03 08:00:43 +00005982 void moveToParent() {
5983 assert( m_parent );
5984 m_ctx.setCurrentTracker( m_parent );
Phil Nash8a52a392013-07-25 08:12:03 +01005985 }
Phil Nash7e346192015-11-03 08:00:43 +00005986 void moveToThis() {
5987 m_ctx.setCurrentTracker( this );
Phil Nash8a52a392013-07-25 08:12:03 +01005988 }
Phil Nasha695eb92012-08-13 07:46:10 +01005989 };
Phil Nash8a52a392013-07-25 08:12:03 +01005990
Phil Nash7e346192015-11-03 08:00:43 +00005991 class SectionTracker : public TrackerBase {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005992 std::vector<std::string> m_filters;
Phil Nash7e346192015-11-03 08:00:43 +00005993 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005994 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
5995 : TrackerBase( nameAndLocation, ctx, parent )
5996 {
5997 if( parent ) {
5998 while( !parent->isSectionTracker() )
5999 parent = &parent->parent();
6000
6001 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6002 addNextFilters( parentSection.m_filters );
6003 }
6004 }
Phil Nash7e346192015-11-03 08:00:43 +00006005 virtual ~SectionTracker();
Phil Nash8a52a392013-07-25 08:12:03 +01006006
Phil Nash92b141e2016-04-28 08:13:00 +01006007 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6008
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006009 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
Phil Nash7e346192015-11-03 08:00:43 +00006010 SectionTracker* section = CATCH_NULL;
6011
6012 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006013 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006014 assert( childTracker );
6015 assert( childTracker->isSectionTracker() );
6016 section = static_cast<SectionTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006017 }
6018 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006019 section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006020 currentTracker.addChild( section );
6021 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006022 if( !ctx.completedCycle() )
6023 section->tryOpen();
Phil Nash7e346192015-11-03 08:00:43 +00006024 return *section;
6025 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006026
6027 void tryOpen() {
6028 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6029 open();
6030 }
6031
6032 void addInitialFilters( std::vector<std::string> const& filters ) {
6033 if( !filters.empty() ) {
6034 m_filters.push_back(""); // Root - should never be consulted
6035 m_filters.push_back(""); // Test Case - not a section filter
6036 std::copy( filters.begin(), filters.end(), std::back_inserter( m_filters ) );
6037 }
6038 }
6039 void addNextFilters( std::vector<std::string> const& filters ) {
6040 if( filters.size() > 1 )
6041 std::copy( filters.begin()+1, filters.end(), std::back_inserter( m_filters ) );
6042 }
Phil Nash7e346192015-11-03 08:00:43 +00006043 };
6044
6045 class IndexTracker : public TrackerBase {
6046 int m_size;
6047 int m_index;
6048 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006049 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6050 : TrackerBase( nameAndLocation, ctx, parent ),
Phil Nash7e346192015-11-03 08:00:43 +00006051 m_size( size ),
6052 m_index( -1 )
6053 {}
6054 virtual ~IndexTracker();
6055
Phil Nash92b141e2016-04-28 08:13:00 +01006056 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6057
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006058 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
Phil Nash7e346192015-11-03 08:00:43 +00006059 IndexTracker* tracker = CATCH_NULL;
6060
6061 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006062 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006063 assert( childTracker );
6064 assert( childTracker->isIndexTracker() );
6065 tracker = static_cast<IndexTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006066 }
6067 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006068 tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
Phil Nash7e346192015-11-03 08:00:43 +00006069 currentTracker.addChild( tracker );
6070 }
6071
6072 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6073 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6074 tracker->moveNext();
6075 tracker->open();
6076 }
6077
6078 return *tracker;
6079 }
6080
6081 int index() const { return m_index; }
6082
6083 void moveNext() {
6084 m_index++;
6085 m_children.clear();
6086 }
6087
6088 virtual void close() CATCH_OVERRIDE {
6089 TrackerBase::close();
6090 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6091 m_runState = Executing;
6092 }
6093 };
6094
6095 inline ITracker& TrackerContext::startRun() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006096 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
Phil Nash7e346192015-11-03 08:00:43 +00006097 m_currentTracker = CATCH_NULL;
6098 m_runState = Executing;
6099 return *m_rootTracker;
6100 }
6101
6102} // namespace TestCaseTracking
6103
6104using TestCaseTracking::ITracker;
6105using TestCaseTracking::TrackerContext;
6106using TestCaseTracking::SectionTracker;
6107using TestCaseTracking::IndexTracker;
Phil Nash8a52a392013-07-25 08:12:03 +01006108
6109} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01006110
Phil Nash93b61e12014-08-22 19:35:41 +01006111// #included from: catch_fatal_condition.hpp
6112#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6113
6114namespace Catch {
6115
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006116 // Report the error condition
6117 inline void reportFatal( std::string const& message ) {
Phil Nash93b61e12014-08-22 19:35:41 +01006118 IContext& context = Catch::getCurrentContext();
6119 IResultCapture* resultCapture = context.getResultCapture();
6120 resultCapture->handleFatalErrorCondition( message );
Phil Nash93b61e12014-08-22 19:35:41 +01006121 }
6122
6123} // namespace Catch
6124
6125#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006126// #included from: catch_windows_h_proxy.h
Phil Nash93b61e12014-08-22 19:35:41 +01006127
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006128#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6129
6130#ifdef CATCH_DEFINES_NOMINMAX
6131# define NOMINMAX
6132#endif
6133#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6134# define WIN32_LEAN_AND_MEAN
6135#endif
6136
6137#ifdef __AFXDLL
6138#include <AfxWin.h>
6139#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006140#include <windows.h>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006141#endif
6142
6143#ifdef CATCH_DEFINES_NOMINMAX
6144# undef NOMINMAX
6145#endif
6146#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6147# undef WIN32_LEAN_AND_MEAN
6148#endif
6149
6150
6151# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6152
6153namespace Catch {
6154 struct FatalConditionHandler {
6155 void reset() {}
6156 };
6157}
6158
6159# else // CATCH_CONFIG_WINDOWS_SEH is defined
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006160
Phil Nash93b61e12014-08-22 19:35:41 +01006161namespace Catch {
6162
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006163 struct SignalDefs { DWORD id; const char* name; };
6164 extern SignalDefs signalDefs[];
6165 // There is no 1-1 mapping between signals and windows exceptions.
6166 // Windows can easily distinguish between SO and SigSegV,
6167 // but SigInt, SigTerm, etc are handled differently.
6168 SignalDefs signalDefs[] = {
6169 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6170 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6171 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6172 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6173 };
6174
Phil Nashe54ac702014-10-21 07:25:26 +01006175 struct FatalConditionHandler {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006176
6177 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6178 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6179 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006180 reset();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006181 reportFatal(signalDefs[i].name);
6182 }
6183 }
6184 // If its not an exception we care about, pass it along.
6185 // This stops us from eating debugger breaks etc.
6186 return EXCEPTION_CONTINUE_SEARCH;
6187 }
6188
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006189 FatalConditionHandler() {
6190 isSet = true;
6191 // 32k seems enough for Catch to handle stack overflow,
6192 // but the value was found experimentally, so there is no strong guarantee
6193 guaranteeSize = 32 * 1024;
6194 exceptionHandlerHandle = CATCH_NULL;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006195 // Register as first handler in current chain
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006196 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006197 // Pass in guarantee size to be filled
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006198 SetThreadStackGuarantee(&guaranteeSize);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006199 }
6200
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006201 static void reset() {
6202 if (isSet) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006203 // Unregister handler and restore the old guarantee
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006204 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6205 SetThreadStackGuarantee(&guaranteeSize);
6206 exceptionHandlerHandle = CATCH_NULL;
6207 isSet = false;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006208 }
6209 }
6210
6211 ~FatalConditionHandler() {
6212 reset();
6213 }
6214 private:
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006215 static bool isSet;
6216 static ULONG guaranteeSize;
6217 static PVOID exceptionHandlerHandle;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006218 };
Phil Nash93b61e12014-08-22 19:35:41 +01006219
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006220 bool FatalConditionHandler::isSet = false;
6221 ULONG FatalConditionHandler::guaranteeSize = 0;
6222 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6223
Phil Nash93b61e12014-08-22 19:35:41 +01006224} // namespace Catch
6225
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006226# endif // CATCH_CONFIG_WINDOWS_SEH
6227
Phil Nash93b61e12014-08-22 19:35:41 +01006228#else // Not Windows - assumed to be POSIX compatible //////////////////////////
6229
6230#include <signal.h>
6231
6232namespace Catch {
6233
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006234 struct SignalDefs {
6235 int id;
6236 const char* name;
6237 };
Phil Nash93b61e12014-08-22 19:35:41 +01006238 extern SignalDefs signalDefs[];
6239 SignalDefs signalDefs[] = {
6240 { SIGINT, "SIGINT - Terminal interrupt signal" },
6241 { SIGILL, "SIGILL - Illegal instruction signal" },
6242 { SIGFPE, "SIGFPE - Floating point error signal" },
6243 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6244 { SIGTERM, "SIGTERM - Termination request signal" },
6245 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006246 };
Phil Nash93b61e12014-08-22 19:35:41 +01006247
6248 struct FatalConditionHandler {
6249
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006250 static bool isSet;
6251 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6252 static stack_t oldSigStack;
6253 static char altStackMem[SIGSTKSZ];
6254
Phil Nash93b61e12014-08-22 19:35:41 +01006255 static void handleSignal( int sig ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006256 std::string name = "<unknown signal>";
6257 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6258 SignalDefs &def = signalDefs[i];
6259 if (sig == def.id) {
6260 name = def.name;
6261 break;
6262 }
6263 }
6264 reset();
6265 reportFatal(name);
6266 raise( sig );
Phil Nash93b61e12014-08-22 19:35:41 +01006267 }
6268
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006269 FatalConditionHandler() {
6270 isSet = true;
6271 stack_t sigStack;
6272 sigStack.ss_sp = altStackMem;
6273 sigStack.ss_size = SIGSTKSZ;
6274 sigStack.ss_flags = 0;
6275 sigaltstack(&sigStack, &oldSigStack);
6276 struct sigaction sa = { 0 };
6277
6278 sa.sa_handler = handleSignal;
6279 sa.sa_flags = SA_ONSTACK;
6280 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6281 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
Phil Nash85b4e942014-10-02 18:51:05 +01006282 }
6283 }
6284
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006285 ~FatalConditionHandler() {
6286 reset();
6287 }
6288 static void reset() {
6289 if( isSet ) {
6290 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6291 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6292 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6293 }
6294 // Return the old stack
6295 sigaltstack(&oldSigStack, CATCH_NULL);
6296 isSet = false;
6297 }
6298 }
Phil Nash93b61e12014-08-22 19:35:41 +01006299 };
6300
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006301 bool FatalConditionHandler::isSet = false;
6302 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6303 stack_t FatalConditionHandler::oldSigStack = {};
6304 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6305
Phil Nash93b61e12014-08-22 19:35:41 +01006306} // namespace Catch
6307
6308#endif // not Windows
6309
Phil Nasha695eb92012-08-13 07:46:10 +01006310#include <set>
6311#include <string>
6312
6313namespace Catch {
6314
6315 class StreamRedirect {
6316
6317 public:
6318 StreamRedirect( std::ostream& stream, std::string& targetString )
6319 : m_stream( stream ),
6320 m_prevBuf( stream.rdbuf() ),
6321 m_targetString( targetString )
6322 {
6323 stream.rdbuf( m_oss.rdbuf() );
6324 }
6325
6326 ~StreamRedirect() {
6327 m_targetString += m_oss.str();
6328 m_stream.rdbuf( m_prevBuf );
6329 }
6330
6331 private:
6332 std::ostream& m_stream;
6333 std::streambuf* m_prevBuf;
6334 std::ostringstream m_oss;
6335 std::string& m_targetString;
6336 };
6337
6338 ///////////////////////////////////////////////////////////////////////////
6339
Phil Nash786959d2013-06-07 19:07:50 +01006340 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01006341
Phil Nash786959d2013-06-07 19:07:50 +01006342 RunContext( RunContext const& );
6343 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01006344
6345 public:
6346
Phil Nashb971fe72015-07-02 08:21:38 +01006347 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6348 : m_runInfo( _config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00006349 m_context( getCurrentMutableContext() ),
Phil Nashb971fe72015-07-02 08:21:38 +01006350 m_activeTestCase( CATCH_NULL ),
6351 m_config( _config ),
Phil Nash7e346192015-11-03 08:00:43 +00006352 m_reporter( reporter )
Phil Nasha695eb92012-08-13 07:46:10 +01006353 {
6354 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01006355 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006356 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006357 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01006358 }
6359
Phil Nash786959d2013-06-07 19:07:50 +01006360 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00006361 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006362 }
6363
Phil Nash2e7d9662013-01-16 09:44:43 +00006364 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6365 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006366 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006367 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6368 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006369 }
Phil Nasha695eb92012-08-13 07:46:10 +01006370
Phil Nash8defc712013-04-24 19:10:02 +01006371 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006372 Totals prevTotals = m_totals;
6373
6374 std::string redirectedCout;
6375 std::string redirectedCerr;
6376
Phil Nasha1fbfea2012-12-01 23:57:18 +00006377 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01006378
Phil Nasha1fbfea2012-12-01 23:57:18 +00006379 m_reporter->testCaseStarting( testInfo );
6380
Phil Nash8a52a392013-07-25 08:12:03 +01006381 m_activeTestCase = &testCase;
Phil Nasha695eb92012-08-13 07:46:10 +01006382
6383 do {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006384 ITracker& rootTracker = m_trackerContext.startRun();
6385 dynamic_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
Phil Nasha695eb92012-08-13 07:46:10 +01006386 do {
Phil Nash7e346192015-11-03 08:00:43 +00006387 m_trackerContext.startCycle();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006388 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006389 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01006390 }
Phil Nash7e346192015-11-03 08:00:43 +00006391 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01006392 }
Phil Nash7e346192015-11-03 08:00:43 +00006393 // !TBD: deprecated - this will be replaced by indexed trackers
Phil Nasha695eb92012-08-13 07:46:10 +01006394 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6395
Phil Nash28463672012-11-21 18:06:13 +00006396 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nashc984fc32016-03-15 07:24:26 +00006397 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6398 deltaTotals.assertions.failed++;
6399 deltaTotals.testCases.passed--;
6400 deltaTotals.testCases.failed++;
6401 }
Phil Nash28463672012-11-21 18:06:13 +00006402 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00006403 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6404 deltaTotals,
6405 redirectedCout,
6406 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00006407 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00006408
Phil Nashb971fe72015-07-02 08:21:38 +01006409 m_activeTestCase = CATCH_NULL;
Phil Nash7e346192015-11-03 08:00:43 +00006410 m_testCaseTracker = CATCH_NULL;
Phil Nasha695eb92012-08-13 07:46:10 +01006411
Phil Nash5bc030d2012-08-16 18:48:50 +01006412 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01006413 }
6414
Phil Nash786959d2013-06-07 19:07:50 +01006415 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006416 return m_config;
6417 }
6418
6419 private: // IResultCapture
6420
Phil Nash8defc712013-04-24 19:10:02 +01006421 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006422 if( result.getResultType() == ResultWas::Ok ) {
6423 m_totals.assertions.passed++;
6424 }
Phil Nash90a35942012-11-13 22:04:29 +00006425 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006426 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01006427 }
6428
Phil Nashb5fd5a62013-06-28 17:09:57 +01006429 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
6430 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00006431
Phil Nasha2773812013-02-02 20:37:58 +00006432 // Reset working state
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006433 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nashab036682014-06-02 07:48:03 +01006434 m_lastResult = result;
Phil Nasha695eb92012-08-13 07:46:10 +01006435 }
6436
6437 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00006438 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01006439 Counts& assertions
6440 )
6441 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006442 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
Phil Nash7e346192015-11-03 08:00:43 +00006443 if( !sectionTracker.isOpen() )
Phil Nasha695eb92012-08-13 07:46:10 +01006444 return false;
Phil Nash7e346192015-11-03 08:00:43 +00006445 m_activeSections.push_back( &sectionTracker );
Phil Nasha695eb92012-08-13 07:46:10 +01006446
Phil Nasha1fbfea2012-12-01 23:57:18 +00006447 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00006448
Phil Nasha1fbfea2012-12-01 23:57:18 +00006449 m_reporter->sectionStarting( sectionInfo );
6450
Phil Nasha695eb92012-08-13 07:46:10 +01006451 assertions = m_totals.assertions;
6452
6453 return true;
6454 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006455 bool testForMissingAssertions( Counts& assertions ) {
Phil Nash7e346192015-11-03 08:00:43 +00006456 if( assertions.total() != 0 )
6457 return false;
Phil Nash9e421532015-11-03 17:06:54 +00006458 if( !m_config->warnAboutMissingAssertions() )
Phil Nash7e346192015-11-03 08:00:43 +00006459 return false;
6460 if( m_trackerContext.currentTracker().hasChildren() )
Phil Nashaa7123b2013-08-15 19:01:00 +01006461 return false;
6462 m_totals.assertions.failed++;
6463 assertions.failed++;
6464 return true;
6465 }
Phil Nasha695eb92012-08-13 07:46:10 +01006466
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006467 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6468 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01006469 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006470
Phil Nash7e346192015-11-03 08:00:43 +00006471 if( !m_activeSections.empty() ) {
6472 m_activeSections.back()->close();
6473 m_activeSections.pop_back();
6474 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006475
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006476 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00006477 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01006478 }
6479
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006480 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
Phil Nash7e346192015-11-03 08:00:43 +00006481 if( m_unfinishedSections.empty() )
6482 m_activeSections.back()->fail();
6483 else
6484 m_activeSections.back()->close();
6485 m_activeSections.pop_back();
6486
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006487 m_unfinishedSections.push_back( endInfo );
6488 }
6489
Phil Nashb5fd5a62013-06-28 17:09:57 +01006490 virtual void pushScopedMessage( MessageInfo const& message ) {
6491 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01006492 }
6493
Phil Nashb5fd5a62013-06-28 17:09:57 +01006494 virtual void popScopedMessage( MessageInfo const& message ) {
6495 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01006496 }
6497
Phil Nasha695eb92012-08-13 07:46:10 +01006498 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01006499 return m_activeTestCase
6500 ? m_activeTestCase->getTestCaseInfo().name
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006501 : std::string();
Phil Nasha695eb92012-08-13 07:46:10 +01006502 }
6503
Phil Nashce612bf2012-11-01 08:27:09 +00006504 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006505 return &m_lastResult;
6506 }
6507
Phil Nash93b61e12014-08-22 19:35:41 +01006508 virtual void handleFatalErrorCondition( std::string const& message ) {
6509 ResultBuilder resultBuilder = makeUnexpectedResultBuilder();
6510 resultBuilder.setResultType( ResultWas::FatalErrorCondition );
6511 resultBuilder << message;
6512 resultBuilder.captureExpression();
6513
6514 handleUnfinishedSections();
6515
6516 // Recreate section for test case (as we will lose the one that was in scope)
6517 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6518 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6519
6520 Counts assertions;
6521 assertions.failed = 1;
6522 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6523 m_reporter->sectionEnded( testCaseSectionStats );
6524
6525 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6526
6527 Totals deltaTotals;
6528 deltaTotals.testCases.failed = 1;
6529 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6530 deltaTotals,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006531 std::string(),
6532 std::string(),
Phil Nash93b61e12014-08-22 19:35:41 +01006533 false ) );
6534 m_totals.testCases.failed++;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006535 testGroupEnded( std::string(), m_totals, 1, 1 );
Phil Nash93b61e12014-08-22 19:35:41 +01006536 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6537 }
6538
Phil Nash56d5c422012-08-23 20:08:50 +01006539 public:
6540 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01006541 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01006542 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01006543 }
6544
Phil Nash56d5c422012-08-23 20:08:50 +01006545 private:
6546
Phil Nasha695eb92012-08-13 07:46:10 +01006547 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006548 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
Phil Nashce562092014-07-09 07:40:37 +01006549 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01006550 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01006551 Counts prevAssertions = m_totals.assertions;
6552 double duration = 0;
Phil Nasha695eb92012-08-13 07:46:10 +01006553 try {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006554 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
Phil Nashd768b1b2013-02-04 00:05:16 +00006555
Phil Nash8f66e342015-07-02 23:03:13 +01006556 seedRng( *m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006557
Phil Nashaa7123b2013-08-15 19:01:00 +01006558 Timer timer;
6559 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006560 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006561 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6562 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
Phil Nash93b61e12014-08-22 19:35:41 +01006563 invokeActiveTestCase();
Phil Nasha695eb92012-08-13 07:46:10 +01006564 }
6565 else {
Phil Nash93b61e12014-08-22 19:35:41 +01006566 invokeActiveTestCase();
Phil Nasha70fbe32012-08-31 08:10:36 +01006567 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006568 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01006569 }
6570 catch( TestFailureException& ) {
6571 // This just means the test was aborted due to failure
6572 }
6573 catch(...) {
Phil Nash93b61e12014-08-22 19:35:41 +01006574 makeUnexpectedResultBuilder().useActiveException();
Phil Nasha695eb92012-08-13 07:46:10 +01006575 }
Phil Nash7e346192015-11-03 08:00:43 +00006576 m_testCaseTracker->close();
Phil Nash93b61e12014-08-22 19:35:41 +01006577 handleUnfinishedSections();
Phil Nashd768b1b2013-02-04 00:05:16 +00006578 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01006579
6580 Counts assertions = m_totals.assertions - prevAssertions;
6581 bool missingAssertions = testForMissingAssertions( assertions );
6582
Phil Nash52e1e742014-07-03 08:11:38 +01006583 if( testCaseInfo.okToFail() ) {
6584 std::swap( assertions.failedButOk, assertions.failed );
6585 m_totals.assertions.failed -= assertions.failedButOk;
6586 m_totals.assertions.failedButOk += assertions.failedButOk;
6587 }
6588
Phil Nashaa7123b2013-08-15 19:01:00 +01006589 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01006590 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01006591 }
6592
Phil Nash93b61e12014-08-22 19:35:41 +01006593 void invokeActiveTestCase() {
6594 FatalConditionHandler fatalConditionHandler; // Handle signals
6595 m_activeTestCase->invoke();
Phil Nash85b4e942014-10-02 18:51:05 +01006596 fatalConditionHandler.reset();
Phil Nash93b61e12014-08-22 19:35:41 +01006597 }
6598
Phil Nasha695eb92012-08-13 07:46:10 +01006599 private:
Phil Nash93b61e12014-08-22 19:35:41 +01006600
6601 ResultBuilder makeUnexpectedResultBuilder() const {
6602 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6603 m_lastAssertionInfo.lineInfo,
6604 m_lastAssertionInfo.capturedExpression.c_str(),
6605 m_lastAssertionInfo.resultDisposition );
6606 }
6607
6608 void handleUnfinishedSections() {
6609 // If sections ended prematurely due to an exception we stored their
6610 // infos here so we can tear them down outside the unwind process.
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006611 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
Phil Nash93b61e12014-08-22 19:35:41 +01006612 itEnd = m_unfinishedSections.rend();
6613 it != itEnd;
6614 ++it )
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006615 sectionEnded( *it );
Phil Nash93b61e12014-08-22 19:35:41 +01006616 m_unfinishedSections.clear();
6617 }
6618
Phil Nasha1fbfea2012-12-01 23:57:18 +00006619 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01006620 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01006621 TestCase const* m_activeTestCase;
Phil Nash7e346192015-11-03 08:00:43 +00006622 ITracker* m_testCaseTracker;
6623 ITracker* m_currentSectionTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00006624 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01006625
Phil Nash786959d2013-06-07 19:07:50 +01006626 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01006627 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006628 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00006629 std::vector<MessageInfo> m_messages;
Phil Nash90a35942012-11-13 22:04:29 +00006630 AssertionInfo m_lastAssertionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006631 std::vector<SectionEndInfo> m_unfinishedSections;
Phil Nash7e346192015-11-03 08:00:43 +00006632 std::vector<ITracker*> m_activeSections;
6633 TrackerContext m_trackerContext;
Phil Nasha695eb92012-08-13 07:46:10 +01006634 };
6635
Phil Nashab036682014-06-02 07:48:03 +01006636 IResultCapture& getResultCapture() {
6637 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6638 return *capture;
6639 else
6640 throw std::logic_error( "No result capture instance" );
6641 }
6642
Phil Nasha695eb92012-08-13 07:46:10 +01006643} // end namespace Catch
6644
Phil Nash7673a302012-11-15 22:15:41 +00006645// #included from: internal/catch_version.h
6646#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6647
6648namespace Catch {
6649
6650 // Versioning information
6651 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006652 Version( unsigned int _majorVersion,
6653 unsigned int _minorVersion,
Phil Nash21f7ef62015-06-29 18:05:23 +01006654 unsigned int _patchNumber,
6655 std::string const& _branchName,
6656 unsigned int _buildNumber );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006657
Phil Nash9d469b62014-04-18 08:30:31 +01006658 unsigned int const majorVersion;
6659 unsigned int const minorVersion;
Phil Nash21f7ef62015-06-29 18:05:23 +01006660 unsigned int const patchNumber;
6661
6662 // buildNumber is only used if branchName is not null
6663 std::string const branchName;
Phil Nash9d469b62014-04-18 08:30:31 +01006664 unsigned int const buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01006665
6666 friend std::ostream& operator << ( std::ostream& os, Version const& version );
Phil Nashdd26e882013-03-25 09:25:31 +00006667
Phil Nash503d5d02013-07-03 08:25:11 +01006668 private:
6669 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00006670 };
6671
6672 extern Version libraryVersion;
6673}
6674
Phil Nash89d1e6c2011-05-24 08:23:02 +01006675#include <fstream>
6676#include <stdlib.h>
6677#include <limits>
6678
Phil Nash89d2a3f2012-05-16 15:09:17 +01006679namespace Catch {
6680
Phil Nashe73583d2015-08-07 17:30:34 +01006681 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006682 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6683 if( !reporter ) {
6684 std::ostringstream oss;
6685 oss << "No reporter registered with name: '" << reporterName << "'";
6686 throw std::domain_error( oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01006687 }
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006688 return reporter;
6689 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006690
Phil Nashe73583d2015-08-07 17:30:34 +01006691 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6692 std::vector<std::string> reporters = config->getReporterNames();
6693 if( reporters.empty() )
6694 reporters.push_back( "console" );
6695
6696 Ptr<IStreamingReporter> reporter;
6697 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6698 it != itEnd;
6699 ++it )
6700 reporter = addReporter( reporter, createReporter( *it, config ) );
6701 return reporter;
6702 }
Phil Nash7e346192015-11-03 08:00:43 +00006703 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
Phil Nashe73583d2015-08-07 17:30:34 +01006704 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6705 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6706 it != itEnd;
6707 ++it )
6708 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6709 return reporters;
6710 }
6711
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006712 Totals runTests( Ptr<Config> const& config ) {
6713
Phil Nash7e346192015-11-03 08:00:43 +00006714 Ptr<IConfig const> iconfig = config.get();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006715
Phil Nash7e346192015-11-03 08:00:43 +00006716 Ptr<IStreamingReporter> reporter = makeReporter( config );
6717 reporter = addListeners( iconfig, reporter );
6718
6719 RunContext context( iconfig, reporter );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006720
6721 Totals totals;
6722
6723 context.testGroupStarting( config->name(), 1, 1 );
6724
6725 TestSpec testSpec = config->testSpec();
6726 if( !testSpec.hasFilters() )
6727 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6728
Phil Nash7e346192015-11-03 08:00:43 +00006729 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
Phil Nashe73583d2015-08-07 17:30:34 +01006730 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006731 it != itEnd;
6732 ++it ) {
Phil Nash7e346192015-11-03 08:00:43 +00006733 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006734 totals += context.runTest( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006735 else
6736 reporter->skipTest( *it );
Phil Nash5bc030d2012-08-16 18:48:50 +01006737 }
Phil Nash06e959b2012-05-25 08:52:05 +01006738
Phil Nash7e346192015-11-03 08:00:43 +00006739 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006740 return totals;
6741 }
Phil Nash56d5c422012-08-23 20:08:50 +01006742
Phil Nashe73583d2015-08-07 17:30:34 +01006743 void applyFilenamesAsTags( IConfig const& config ) {
6744 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
Phil Nashb971fe72015-07-02 08:21:38 +01006745 for(std::size_t i = 0; i < tests.size(); ++i ) {
6746 TestCase& test = const_cast<TestCase&>( tests[i] );
6747 std::set<std::string> tags = test.tags;
Phil Nash786959d2013-06-07 19:07:50 +01006748
Phil Nashb971fe72015-07-02 08:21:38 +01006749 std::string filename = test.lineInfo.file;
Phil Nashc1ca0fd2015-07-03 18:30:25 +01006750 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
Phil Nashb971fe72015-07-02 08:21:38 +01006751 if( lastSlash != std::string::npos )
6752 filename = filename.substr( lastSlash+1 );
Phil Nash56d5c422012-08-23 20:08:50 +01006753
Phil Nashb971fe72015-07-02 08:21:38 +01006754 std::string::size_type lastDot = filename.find_last_of( "." );
6755 if( lastDot != std::string::npos )
6756 filename = filename.substr( 0, lastDot );
Phil Nash65cc14c2014-05-16 18:54:48 +01006757
Phil Nashe6b365d2015-07-07 08:25:15 +01006758 tags.insert( "#" + filename );
Phil Nashb971fe72015-07-02 08:21:38 +01006759 setTags( test, tags );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006760 }
Phil Nashb971fe72015-07-02 08:21:38 +01006761 }
Phil Nash56d5c422012-08-23 20:08:50 +01006762
Phil Nashe54ac702014-10-21 07:25:26 +01006763 class Session : NonCopyable {
Phil Nash786959d2013-06-07 19:07:50 +01006764 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01006765
Phil Nash786959d2013-06-07 19:07:50 +01006766 public:
Phil Nash56d5c422012-08-23 20:08:50 +01006767
Phil Nash786959d2013-06-07 19:07:50 +01006768 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6769
6770 Session()
6771 : m_cli( makeCommandLineParser() ) {
6772 if( alreadyInstantiated ) {
6773 std::string msg = "Only one instance of Catch::Session can ever be used";
Phil Nash383d7c02014-10-02 19:08:19 +01006774 Catch::cerr() << msg << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006775 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01006776 }
Phil Nash786959d2013-06-07 19:07:50 +01006777 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01006778 }
Phil Nash786959d2013-06-07 19:07:50 +01006779 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01006780 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01006781 }
6782
Phil Nash786959d2013-06-07 19:07:50 +01006783 void showHelp( std::string const& processName ) {
Phil Nash21f7ef62015-06-29 18:05:23 +01006784 Catch::cout() << "\nCatch v" << libraryVersion << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01006785
Phil Nash383d7c02014-10-02 19:08:19 +01006786 m_cli.usage( Catch::cout(), processName );
6787 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01006788 }
Phil Nash3b80af72012-08-09 07:47:30 +01006789
Phil Nashe5537842016-04-25 18:56:50 +01006790 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
Phil Nash786959d2013-06-07 19:07:50 +01006791 try {
Phil Nash91ef5f72013-12-20 19:06:26 +00006792 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
Phil Nashe5537842016-04-25 18:56:50 +01006793 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
Phil Nash786959d2013-06-07 19:07:50 +01006794 if( m_configData.showHelp )
6795 showHelp( m_configData.processName );
6796 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01006797 }
Phil Nash786959d2013-06-07 19:07:50 +01006798 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01006799 {
6800 Colour colourGuard( Colour::Red );
Phil Nash21f7ef62015-06-29 18:05:23 +01006801 Catch::cerr()
6802 << "\nError(s) in input:\n"
6803 << Text( ex.what(), TextAttributes().setIndent(2) )
6804 << "\n\n";
Phil Nash46118712013-08-16 19:01:32 +01006805 }
Phil Nash383d7c02014-10-02 19:08:19 +01006806 m_cli.usage( Catch::cout(), m_configData.processName );
Phil Nash786959d2013-06-07 19:07:50 +01006807 return (std::numeric_limits<int>::max)();
6808 }
6809 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006810 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01006811
Phil Nash786959d2013-06-07 19:07:50 +01006812 void useConfigData( ConfigData const& _configData ) {
6813 m_configData = _configData;
6814 m_config.reset();
6815 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01006816
Phil Nashe5537842016-04-25 18:56:50 +01006817 int run( int argc, char const* const* const argv ) {
Phil Nash786959d2013-06-07 19:07:50 +01006818
6819 int returnCode = applyCommandLine( argc, argv );
6820 if( returnCode == 0 )
6821 returnCode = run();
6822 return returnCode;
6823 }
6824
6825 int run() {
6826 if( m_configData.showHelp )
6827 return 0;
6828
6829 try
6830 {
6831 config(); // Force config to be constructed
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006832
Phil Nash8f66e342015-07-02 23:03:13 +01006833 seedRng( *m_config );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01006834
Phil Nashe73583d2015-08-07 17:30:34 +01006835 if( m_configData.filenamesAsTags )
6836 applyFilenamesAsTags( *m_config );
Phil Nash786959d2013-06-07 19:07:50 +01006837
6838 // Handle list request
6839 if( Option<std::size_t> listed = list( config() ) )
6840 return static_cast<int>( *listed );
6841
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006842 return static_cast<int>( runTests( m_config ).assertions.failed );
Phil Nash786959d2013-06-07 19:07:50 +01006843 }
6844 catch( std::exception& ex ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006845 Catch::cerr() << ex.what() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01006846 return (std::numeric_limits<int>::max)();
6847 }
6848 }
6849
6850 Clara::CommandLine<ConfigData> const& cli() const {
6851 return m_cli;
6852 }
6853 std::vector<Clara::Parser::Token> const& unusedTokens() const {
6854 return m_unusedTokens;
6855 }
6856 ConfigData& configData() {
6857 return m_configData;
6858 }
6859 Config& config() {
6860 if( !m_config )
6861 m_config = new Config( m_configData );
6862 return *m_config;
6863 }
Phil Nash786959d2013-06-07 19:07:50 +01006864 private:
6865 Clara::CommandLine<ConfigData> m_cli;
6866 std::vector<Clara::Parser::Token> m_unusedTokens;
6867 ConfigData m_configData;
6868 Ptr<Config> m_config;
6869 };
6870
6871 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01006872
6873} // end namespace Catch
6874
6875// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006876#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01006877
Phil Nash89d1e6c2011-05-24 08:23:02 +01006878// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04006879#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01006880
6881#include <vector>
6882#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01006883#include <sstream>
6884#include <iostream>
Phil Nash96304542014-09-15 23:32:13 +01006885#include <algorithm>
Phil Nash3b80af72012-08-09 07:47:30 +01006886
6887namespace Catch {
6888
Phil Nashe73583d2015-08-07 17:30:34 +01006889 struct RandomNumberGenerator {
Phil Nashe27c4ee2016-10-26 12:08:26 +01006890 typedef std::ptrdiff_t result_type;
Phil Nashac220282016-06-09 08:19:23 +01006891
6892 result_type operator()( result_type n ) const { return std::rand() % n; }
6893
Phil Nash3b2f2062017-01-11 16:43:56 +00006894#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nashac220282016-06-09 08:19:23 +01006895 static constexpr result_type min() { return 0; }
6896 static constexpr result_type max() { return 1000000; }
6897 result_type operator()() const { return std::rand() % max(); }
6898#endif
6899 template<typename V>
6900 static void shuffle( V& vector ) {
Phil Nash35f51052016-06-09 19:21:09 +01006901 RandomNumberGenerator rng;
Phil Nash3b2f2062017-01-11 16:43:56 +00006902#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nash35f51052016-06-09 19:21:09 +01006903 std::shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01006904#else
Phil Nash35f51052016-06-09 19:21:09 +01006905 std::random_shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01006906#endif
6907 }
Phil Nashe73583d2015-08-07 17:30:34 +01006908 };
Phil Nashee3b2652014-09-18 18:25:10 +01006909
Phil Nashe73583d2015-08-07 17:30:34 +01006910 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
6911
6912 std::vector<TestCase> sorted = unsortedTestCases;
6913
6914 switch( config.runOrder() ) {
6915 case RunTests::InLexicographicalOrder:
Phil Nashac220282016-06-09 08:19:23 +01006916 std::sort( sorted.begin(), sorted.end() );
Phil Nashe73583d2015-08-07 17:30:34 +01006917 break;
6918 case RunTests::InRandomOrder:
6919 {
6920 seedRng( config );
Phil Nashac220282016-06-09 08:19:23 +01006921 RandomNumberGenerator::shuffle( sorted );
Phil Nashe73583d2015-08-07 17:30:34 +01006922 }
6923 break;
6924 case RunTests::InDeclarationOrder:
6925 // already in declaration order
6926 break;
6927 }
6928 return sorted;
6929 }
6930 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
6931 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
6932 }
Phil Nashe73583d2015-08-07 17:30:34 +01006933
6934 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
6935 std::set<TestCase> seenFunctions;
6936 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
6937 it != itEnd;
6938 ++it ) {
6939 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
Phil Nashebf9f3b2016-05-10 19:09:59 +01006940 if( !prev.second ) {
6941 std::ostringstream ss;
6942
6943 ss << Colour( Colour::Red )
6944 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006945 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
Phil Nashebf9f3b2016-05-10 19:09:59 +01006946 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
6947
6948 throw std::runtime_error(ss.str());
Phil Nashe73583d2015-08-07 17:30:34 +01006949 }
6950 }
6951 }
6952
6953 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
6954 std::vector<TestCase> filtered;
Phil Nash8a05f462015-08-07 17:53:29 +01006955 filtered.reserve( testCases.size() );
6956 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
6957 it != itEnd;
6958 ++it )
6959 if( matchTest( *it, testSpec, config ) )
6960 filtered.push_back( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006961 return filtered;
6962 }
6963 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
6964 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
6965 }
6966
6967 class TestRegistry : public ITestCaseRegistry {
Phil Nash3b80af72012-08-09 07:47:30 +01006968 public:
Phil Nash981347b2015-12-09 18:11:48 +00006969 TestRegistry()
6970 : m_currentSortOrder( RunTests::InDeclarationOrder ),
6971 m_unnamedCount( 0 )
6972 {}
Phil Nash3b80af72012-08-09 07:47:30 +01006973 virtual ~TestRegistry();
6974
Phil Nash8defc712013-04-24 19:10:02 +01006975 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006976 std::string name = testCase.getTestCaseInfo().name;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006977 if( name.empty() ) {
Phil Nash3b80af72012-08-09 07:47:30 +01006978 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00006979 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006980 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01006981 }
Phil Nashe73583d2015-08-07 17:30:34 +01006982 m_functions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01006983 }
6984
Phil Nash8defc712013-04-24 19:10:02 +01006985 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nashe73583d2015-08-07 17:30:34 +01006986 return m_functions;
Phil Nash3b80af72012-08-09 07:47:30 +01006987 }
Phil Nashe73583d2015-08-07 17:30:34 +01006988 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
6989 if( m_sortedFunctions.empty() )
6990 enforceNoDuplicateTestCases( m_functions );
Phil Nash3b80af72012-08-09 07:47:30 +01006991
Phil Nashe73583d2015-08-07 17:30:34 +01006992 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
6993 m_sortedFunctions = sortTests( config, m_functions );
6994 m_currentSortOrder = config.runOrder();
Phil Nash3b80af72012-08-09 07:47:30 +01006995 }
Phil Nashe73583d2015-08-07 17:30:34 +01006996 return m_sortedFunctions;
Phil Nash92f08362014-12-22 20:18:05 +00006997 }
6998
6999 private:
Phil Nashe73583d2015-08-07 17:30:34 +01007000 std::vector<TestCase> m_functions;
7001 mutable RunTests::InWhatOrder m_currentSortOrder;
7002 mutable std::vector<TestCase> m_sortedFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01007003 size_t m_unnamedCount;
Phil Nash93a842e2015-07-13 06:36:07 +01007004 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
Phil Nash3b80af72012-08-09 07:47:30 +01007005 };
7006
7007 ///////////////////////////////////////////////////////////////////////////
7008
7009 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7010 public:
7011
7012 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7013
7014 virtual void invoke() const {
7015 m_fun();
7016 }
7017
7018 private:
7019 virtual ~FreeFunctionTestCase();
7020
7021 TestFunction m_fun;
7022 };
7023
Phil Nash8defc712013-04-24 19:10:02 +01007024 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00007025 std::string className = classOrQualifiedMethodName;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007026 if( startsWith( className, '&' ) )
Phil Nash90a35942012-11-13 22:04:29 +00007027 {
7028 std::size_t lastColons = className.rfind( "::" );
7029 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7030 if( penultimateColons == std::string::npos )
7031 penultimateColons = 1;
7032 className = className.substr( penultimateColons, lastColons-penultimateColons );
7033 }
7034 return className;
7035 }
7036
Phil Nash7e15d9b2015-11-20 16:59:14 +00007037 void registerTestCase
7038 ( ITestCase* testCase,
7039 char const* classOrQualifiedMethodName,
7040 NameAndDesc const& nameAndDesc,
7041 SourceLineInfo const& lineInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007042
Phil Nash7e15d9b2015-11-20 16:59:14 +00007043 getMutableRegistryHub().registerTest
7044 ( makeTestCase
7045 ( testCase,
7046 extractClassName( classOrQualifiedMethodName ),
7047 nameAndDesc.name,
7048 nameAndDesc.description,
7049 lineInfo ) );
7050 }
7051 void registerTestCaseFunction
7052 ( TestFunction function,
7053 SourceLineInfo const& lineInfo,
7054 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01007055 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01007056 }
7057
Phil Nash7e15d9b2015-11-20 16:59:14 +00007058 ///////////////////////////////////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007059
Phil Nash7e15d9b2015-11-20 16:59:14 +00007060 AutoReg::AutoReg
7061 ( TestFunction function,
7062 SourceLineInfo const& lineInfo,
7063 NameAndDesc const& nameAndDesc ) {
7064 registerTestCaseFunction( function, lineInfo, nameAndDesc );
Phil Nash3b80af72012-08-09 07:47:30 +01007065 }
7066
Phil Nash7e15d9b2015-11-20 16:59:14 +00007067 AutoReg::~AutoReg() {}
7068
Phil Nash3b80af72012-08-09 07:47:30 +01007069} // end namespace Catch
7070
7071// #included from: catch_reporter_registry.hpp
7072#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7073
7074#include <map>
7075
7076namespace Catch {
7077
7078 class ReporterRegistry : public IReporterRegistry {
7079
7080 public:
7081
Phil Nash19520152015-08-10 07:32:48 +01007082 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
Phil Nash3b80af72012-08-09 07:47:30 +01007083
Phil Nash7e346192015-11-03 08:00:43 +00007084 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007085 FactoryMap::const_iterator it = m_factories.find( name );
7086 if( it == m_factories.end() )
Phil Nashb971fe72015-07-02 08:21:38 +01007087 return CATCH_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01007088 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01007089 }
7090
Phil Nashe73583d2015-08-07 17:30:34 +01007091 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007092 m_factories.insert( std::make_pair( name, factory ) );
7093 }
Phil Nashe73583d2015-08-07 17:30:34 +01007094 void registerListener( Ptr<IReporterFactory> const& factory ) {
7095 m_listeners.push_back( factory );
7096 }
Phil Nash3b80af72012-08-09 07:47:30 +01007097
Phil Nash19520152015-08-10 07:32:48 +01007098 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007099 return m_factories;
7100 }
Phil Nash19520152015-08-10 07:32:48 +01007101 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007102 return m_listeners;
7103 }
Phil Nash3b80af72012-08-09 07:47:30 +01007104
7105 private:
7106 FactoryMap m_factories;
Phil Nashe73583d2015-08-07 17:30:34 +01007107 Listeners m_listeners;
Phil Nash3b80af72012-08-09 07:47:30 +01007108 };
7109}
7110
7111// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007112#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007113
7114#ifdef __OBJC__
7115#import "Foundation/Foundation.h"
7116#endif
7117
7118namespace Catch {
7119
7120 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7121 public:
7122 ~ExceptionTranslatorRegistry() {
7123 deleteAll( m_translators );
7124 }
7125
7126 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7127 m_translators.push_back( translator );
7128 }
7129
7130 virtual std::string translateActiveException() const {
7131 try {
7132#ifdef __OBJC__
7133 // In Objective-C try objective-c exceptions first
7134 @try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007135 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007136 }
7137 @catch (NSException *exception) {
Phil Nash13f98432014-12-12 08:11:18 +00007138 return Catch::toString( [exception description] );
Phil Nash3b80af72012-08-09 07:47:30 +01007139 }
7140#else
Phil Nashe4fa62a2015-11-18 08:39:54 +00007141 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007142#endif
7143 }
Phil Nashab036682014-06-02 07:48:03 +01007144 catch( TestFailureException& ) {
7145 throw;
7146 }
Phil Nash3b80af72012-08-09 07:47:30 +01007147 catch( std::exception& ex ) {
7148 return ex.what();
7149 }
7150 catch( std::string& msg ) {
7151 return msg;
7152 }
7153 catch( const char* msg ) {
7154 return msg;
7155 }
7156 catch(...) {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007157 return "Unknown exception";
Phil Nash3b80af72012-08-09 07:47:30 +01007158 }
7159 }
7160
Phil Nashe4fa62a2015-11-18 08:39:54 +00007161 std::string tryTranslators() const {
7162 if( m_translators.empty() )
7163 throw;
7164 else
7165 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
Phil Nash3b80af72012-08-09 07:47:30 +01007166 }
7167
7168 private:
7169 std::vector<const IExceptionTranslator*> m_translators;
7170 };
7171}
7172
7173namespace Catch {
7174
7175 namespace {
7176
7177 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7178
Phil Nash8defc712013-04-24 19:10:02 +01007179 RegistryHub( RegistryHub const& );
7180 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007181
7182 public: // IRegistryHub
7183 RegistryHub() {
7184 }
Phil Nash19520152015-08-10 07:32:48 +01007185 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007186 return m_reporterRegistry;
7187 }
Phil Nash19520152015-08-10 07:32:48 +01007188 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007189 return m_testCaseRegistry;
7190 }
Phil Nash19520152015-08-10 07:32:48 +01007191 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007192 return m_exceptionTranslatorRegistry;
7193 }
7194
7195 public: // IMutableRegistryHub
Phil Nash19520152015-08-10 07:32:48 +01007196 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007197 m_reporterRegistry.registerReporter( name, factory );
7198 }
Phil Nash19520152015-08-10 07:32:48 +01007199 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007200 m_reporterRegistry.registerListener( factory );
7201 }
Phil Nash19520152015-08-10 07:32:48 +01007202 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007203 m_testCaseRegistry.registerTest( testInfo );
7204 }
Phil Nash19520152015-08-10 07:32:48 +01007205 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007206 m_exceptionTranslatorRegistry.registerTranslator( translator );
7207 }
7208
7209 private:
7210 TestRegistry m_testCaseRegistry;
7211 ReporterRegistry m_reporterRegistry;
7212 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
7213 };
7214
7215 // Single, global, instance
7216 inline RegistryHub*& getTheRegistryHub() {
Phil Nashb971fe72015-07-02 08:21:38 +01007217 static RegistryHub* theRegistryHub = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007218 if( !theRegistryHub )
7219 theRegistryHub = new RegistryHub();
7220 return theRegistryHub;
7221 }
7222 }
7223
7224 IRegistryHub& getRegistryHub() {
7225 return *getTheRegistryHub();
7226 }
7227 IMutableRegistryHub& getMutableRegistryHub() {
7228 return *getTheRegistryHub();
7229 }
7230 void cleanUp() {
7231 delete getTheRegistryHub();
Phil Nashb971fe72015-07-02 08:21:38 +01007232 getTheRegistryHub() = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007233 cleanUpContext();
7234 }
Phil Nashce612bf2012-11-01 08:27:09 +00007235 std::string translateActiveException() {
7236 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7237 }
Phil Nash3b80af72012-08-09 07:47:30 +01007238
7239} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04007240
Phil Nash3b80af72012-08-09 07:47:30 +01007241// #included from: catch_notimplemented_exception.hpp
7242#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7243
7244#include <ostream>
7245
7246namespace Catch {
7247
Phil Nash8defc712013-04-24 19:10:02 +01007248 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01007249 : m_lineInfo( lineInfo ) {
7250 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00007251 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01007252 oss << "not implemented";
7253 m_what = oss.str();
7254 }
7255
Phil Nashd7e17902014-04-18 08:49:35 +01007256 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
Phil Nash3b80af72012-08-09 07:47:30 +01007257 return m_what.c_str();
7258 }
7259
7260} // end namespace Catch
7261
7262// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007263#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007264
Phil Nash3649fdf2013-12-03 18:53:55 +00007265// #included from: catch_stream.hpp
7266#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7267
Phil Nash3649fdf2013-12-03 18:53:55 +00007268#include <stdexcept>
7269#include <cstdio>
Phil Nash383d7c02014-10-02 19:08:19 +01007270#include <iostream>
Phil Nash3649fdf2013-12-03 18:53:55 +00007271
7272namespace Catch {
7273
7274 template<typename WriterF, size_t bufferSize=256>
7275 class StreamBufImpl : public StreamBufBase {
7276 char data[bufferSize];
7277 WriterF m_writer;
7278
7279 public:
7280 StreamBufImpl() {
7281 setp( data, data + sizeof(data) );
7282 }
7283
Phil Nashd7e17902014-04-18 08:49:35 +01007284 ~StreamBufImpl() CATCH_NOEXCEPT {
Phil Nash3649fdf2013-12-03 18:53:55 +00007285 sync();
7286 }
7287
7288 private:
7289 int overflow( int c ) {
7290 sync();
7291
7292 if( c != EOF ) {
7293 if( pbase() == epptr() )
7294 m_writer( std::string( 1, static_cast<char>( c ) ) );
7295 else
7296 sputc( static_cast<char>( c ) );
7297 }
7298 return 0;
7299 }
7300
7301 int sync() {
7302 if( pbase() != pptr() ) {
7303 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7304 setp( pbase(), epptr() );
7305 }
7306 return 0;
7307 }
7308 };
7309
7310 ///////////////////////////////////////////////////////////////////////////
7311
Phil Nash7e346192015-11-03 08:00:43 +00007312 FileStream::FileStream( std::string const& filename ) {
7313 m_ofs.open( filename.c_str() );
7314 if( m_ofs.fail() ) {
7315 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007316 oss << "Unable to open file: '" << filename << '\'';
Phil Nash7e346192015-11-03 08:00:43 +00007317 throw std::domain_error( oss.str() );
7318 }
7319 }
7320
7321 std::ostream& FileStream::stream() const {
7322 return m_ofs;
7323 }
7324
Phil Nash3649fdf2013-12-03 18:53:55 +00007325 struct OutputDebugWriter {
7326
7327 void operator()( std::string const&str ) {
7328 writeToDebugConsole( str );
7329 }
7330 };
7331
Phil Nash7e346192015-11-03 08:00:43 +00007332 DebugOutStream::DebugOutStream()
7333 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7334 m_os( m_streamBuf.get() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007335 {}
7336
Phil Nash7e346192015-11-03 08:00:43 +00007337 std::ostream& DebugOutStream::stream() const {
7338 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007339 }
Phil Nash383d7c02014-10-02 19:08:19 +01007340
Phil Nash7e346192015-11-03 08:00:43 +00007341 // Store the streambuf from cout up-front because
7342 // cout may get redirected when running tests
7343 CoutStream::CoutStream()
7344 : m_os( Catch::cout().rdbuf() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007345 {}
7346
Phil Nash7e346192015-11-03 08:00:43 +00007347 std::ostream& CoutStream::stream() const {
7348 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007349 }
Phil Nash383d7c02014-10-02 19:08:19 +01007350
Phil Nashfdc42d02015-12-04 10:19:08 +00007351#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
Phil Nash383d7c02014-10-02 19:08:19 +01007352 std::ostream& cout() {
7353 return std::cout;
7354 }
7355 std::ostream& cerr() {
7356 return std::cerr;
7357 }
7358#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00007359}
7360
Phil Nash3b80af72012-08-09 07:47:30 +01007361namespace Catch {
7362
7363 class Context : public IMutableContext {
7364
Phil Nashb971fe72015-07-02 08:21:38 +01007365 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01007366 Context( Context const& );
7367 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007368
Martin Hořeňovský9a566092017-01-20 12:49:59 +01007369 public:
7370 virtual ~Context() {
7371 deleteAllValues( m_generatorsByTestName );
7372 }
7373
Phil Nash3b80af72012-08-09 07:47:30 +01007374 public: // IContext
Phil Nash9241e432014-05-20 18:50:59 +01007375 virtual IResultCapture* getResultCapture() {
7376 return m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007377 }
Phil Nash9241e432014-05-20 18:50:59 +01007378 virtual IRunner* getRunner() {
7379 return m_runner;
Phil Nash3b80af72012-08-09 07:47:30 +01007380 }
Phil Nash8defc712013-04-24 19:10:02 +01007381 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007382 return getGeneratorsForCurrentTest()
7383 .getGeneratorInfo( fileInfo, totalSize )
7384 .getCurrentIndex();
7385 }
7386 virtual bool advanceGeneratorsForCurrentTest() {
7387 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7388 return generators && generators->moveNext();
7389 }
7390
Phil Nash786959d2013-06-07 19:07:50 +01007391 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01007392 return m_config;
7393 }
7394
7395 public: // IMutableContext
7396 virtual void setResultCapture( IResultCapture* resultCapture ) {
7397 m_resultCapture = resultCapture;
7398 }
7399 virtual void setRunner( IRunner* runner ) {
7400 m_runner = runner;
7401 }
Phil Nash786959d2013-06-07 19:07:50 +01007402 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007403 m_config = config;
7404 }
7405
7406 friend IMutableContext& getCurrentMutableContext();
7407
7408 private:
7409 IGeneratorsForTest* findGeneratorsForCurrentTest() {
Phil Nash9241e432014-05-20 18:50:59 +01007410 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007411
7412 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
Phil Nasha806c3e2015-03-04 08:23:40 +00007413 m_generatorsByTestName.find( testName );
Phil Nash3b80af72012-08-09 07:47:30 +01007414 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01007415 ? it->second
Phil Nashb971fe72015-07-02 08:21:38 +01007416 : CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007417 }
7418
7419 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7420 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7421 if( !generators ) {
Phil Nash9241e432014-05-20 18:50:59 +01007422 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007423 generators = createGeneratorsForTest();
7424 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7425 }
7426 return *generators;
7427 }
7428
7429 private:
Phil Nash93a945c2013-10-23 15:35:07 +01007430 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01007431 IRunner* m_runner;
7432 IResultCapture* m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007433 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7434 };
7435
7436 namespace {
Phil Nashb971fe72015-07-02 08:21:38 +01007437 Context* currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007438 }
7439 IMutableContext& getCurrentMutableContext() {
7440 if( !currentContext )
7441 currentContext = new Context();
7442 return *currentContext;
7443 }
7444 IContext& getCurrentContext() {
7445 return getCurrentMutableContext();
7446 }
7447
Phil Nash3b80af72012-08-09 07:47:30 +01007448 void cleanUpContext() {
7449 delete currentContext;
Phil Nashb971fe72015-07-02 08:21:38 +01007450 currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007451 }
7452}
Matt Wozniskif29c8982012-09-17 01:42:29 -04007453
Phil Nash3b80af72012-08-09 07:47:30 +01007454// #included from: catch_console_colour_impl.hpp
7455#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7456
Phil Nashe54ac702014-10-21 07:25:26 +01007457namespace Catch {
7458 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01007459
Phil Nashe54ac702014-10-21 07:25:26 +01007460 struct IColourImpl {
7461 virtual ~IColourImpl() {}
7462 virtual void use( Colour::Code _colourCode ) = 0;
7463 };
7464
7465 struct NoColourImpl : IColourImpl {
7466 void use( Colour::Code ) {}
7467
7468 static IColourImpl* instance() {
7469 static NoColourImpl s_instance;
7470 return &s_instance;
7471 }
7472 };
7473
7474 } // anon namespace
7475} // namespace Catch
7476
7477#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7478# ifdef CATCH_PLATFORM_WINDOWS
7479# define CATCH_CONFIG_COLOUR_WINDOWS
7480# else
7481# define CATCH_CONFIG_COLOUR_ANSI
7482# endif
7483#endif
7484
7485#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007486
Phil Nash3b80af72012-08-09 07:47:30 +01007487namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007488namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01007489
Phil Nashe54ac702014-10-21 07:25:26 +01007490 class Win32ColourImpl : public IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01007491 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01007492 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01007493 {
Phil Nash12c16ff2013-04-05 20:58:01 +01007494 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7495 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
Phil Nash584032d2015-07-06 06:22:28 +01007496 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7497 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
Phil Nash3b80af72012-08-09 07:47:30 +01007498 }
Phil Nash3b80af72012-08-09 07:47:30 +01007499
Phil Nash12c16ff2013-04-05 20:58:01 +01007500 virtual void use( Colour::Code _colourCode ) {
7501 switch( _colourCode ) {
Phil Nash584032d2015-07-06 06:22:28 +01007502 case Colour::None: return setTextAttribute( originalForegroundAttributes );
Phil Nash12c16ff2013-04-05 20:58:01 +01007503 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7504 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7505 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7506 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7507 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7508 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7509 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01007510
Phil Nash12c16ff2013-04-05 20:58:01 +01007511 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7512 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7513 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01007514 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01007515
Phil Nash12c16ff2013-04-05 20:58:01 +01007516 case Colour::Bright: throw std::logic_error( "not a colour" );
7517 }
Phil Nash3b80af72012-08-09 07:47:30 +01007518 }
Phil Nash3b80af72012-08-09 07:47:30 +01007519
7520 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01007521 void setTextAttribute( WORD _textAttribute ) {
Phil Nash584032d2015-07-06 06:22:28 +01007522 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
Phil Nash3b80af72012-08-09 07:47:30 +01007523 }
Phil Nash12c16ff2013-04-05 20:58:01 +01007524 HANDLE stdoutHandle;
Phil Nash584032d2015-07-06 06:22:28 +01007525 WORD originalForegroundAttributes;
7526 WORD originalBackgroundAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01007527 };
7528
Phil Nashe54ac702014-10-21 07:25:26 +01007529 IColourImpl* platformColourInstance() {
Phil Nash20cad7c2014-04-15 18:44:37 +01007530 static Win32ColourImpl s_instance;
Phil Nashae5ee2c2016-02-29 08:17:18 +00007531
7532 Ptr<IConfig const> config = getCurrentContext().getConfig();
7533 UseColour::YesOrNo colourMode = config
7534 ? config->useColour()
7535 : UseColour::Auto;
7536 if( colourMode == UseColour::Auto )
7537 colourMode = !isDebuggerActive()
7538 ? UseColour::Yes
7539 : UseColour::No;
7540 return colourMode == UseColour::Yes
7541 ? &s_instance
7542 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007543 }
Phil Nash3df6c0d2013-03-11 18:38:29 +00007544
7545} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01007546} // end namespace Catch
7547
Phil Nashe54ac702014-10-21 07:25:26 +01007548#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00007549
7550#include <unistd.h>
7551
7552namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007553namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00007554
7555 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01007556 // Thanks to Adam Strzelecki for original contribution
7557 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00007558 // https://github.com/philsquared/Catch/pull/131
Phil Nashe54ac702014-10-21 07:25:26 +01007559 class PosixColourImpl : public IColourImpl {
Phil Nash12c16ff2013-04-05 20:58:01 +01007560 public:
7561 virtual void use( Colour::Code _colourCode ) {
7562 switch( _colourCode ) {
7563 case Colour::None:
7564 case Colour::White: return setColour( "[0m" );
7565 case Colour::Red: return setColour( "[0;31m" );
7566 case Colour::Green: return setColour( "[0;32m" );
Phil Nash3b2f2062017-01-11 16:43:56 +00007567 case Colour::Blue: return setColour( "[0;34m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007568 case Colour::Cyan: return setColour( "[0;36m" );
7569 case Colour::Yellow: return setColour( "[0;33m" );
7570 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007571
Phil Nash12c16ff2013-04-05 20:58:01 +01007572 case Colour::LightGrey: return setColour( "[0;37m" );
7573 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01007574 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007575 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007576
Phil Nash12c16ff2013-04-05 20:58:01 +01007577 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00007578 }
7579 }
Phil Nashe54ac702014-10-21 07:25:26 +01007580 static IColourImpl* instance() {
7581 static PosixColourImpl s_instance;
7582 return &s_instance;
7583 }
7584
Phil Nash12c16ff2013-04-05 20:58:01 +01007585 private:
7586 void setColour( const char* _escapeCode ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007587 Catch::cout() << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00007588 }
7589 };
7590
Phil Nashe54ac702014-10-21 07:25:26 +01007591 IColourImpl* platformColourInstance() {
Phil Nasha806c3e2015-03-04 08:23:40 +00007592 Ptr<IConfig const> config = getCurrentContext().getConfig();
Phil Nashae5ee2c2016-02-29 08:17:18 +00007593 UseColour::YesOrNo colourMode = config
7594 ? config->useColour()
7595 : UseColour::Auto;
7596 if( colourMode == UseColour::Auto )
7597 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7598 ? UseColour::Yes
7599 : UseColour::No;
7600 return colourMode == UseColour::Yes
Phil Nashe54ac702014-10-21 07:25:26 +01007601 ? PosixColourImpl::instance()
7602 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007603 }
Phil Nashce612bf2012-11-01 08:27:09 +00007604
Phil Nash12c16ff2013-04-05 20:58:01 +01007605} // end anon namespace
7606} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01007607
Phil Nashe54ac702014-10-21 07:25:26 +01007608#else // not Windows or ANSI ///////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007609
7610namespace Catch {
7611
Phil Nashe54ac702014-10-21 07:25:26 +01007612 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
Phil Nash20cad7c2014-04-15 18:44:37 +01007613
Phil Nashe54ac702014-10-21 07:25:26 +01007614} // end namespace Catch
7615
7616#endif // Windows/ ANSI/ None
7617
7618namespace Catch {
Phil Nash3b80af72012-08-09 07:47:30 +01007619
Phil Nashce562092014-07-09 07:40:37 +01007620 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7621 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7622 Colour::~Colour(){ if( !m_moved ) use( None ); }
Phil Nash3b80af72012-08-09 07:47:30 +01007623
Phil Nashe54ac702014-10-21 07:25:26 +01007624 void Colour::use( Code _colourCode ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00007625 static IColourImpl* impl = platformColourInstance();
Phil Nashe54ac702014-10-21 07:25:26 +01007626 impl->use( _colourCode );
Phil Nash20cad7c2014-04-15 18:44:37 +01007627 }
Phil Nash3b80af72012-08-09 07:47:30 +01007628
7629} // end namespace Catch
7630
Phil Nash3b80af72012-08-09 07:47:30 +01007631// #included from: catch_generators_impl.hpp
7632#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7633
7634#include <vector>
7635#include <string>
7636#include <map>
7637
7638namespace Catch {
7639
7640 struct GeneratorInfo : IGeneratorInfo {
7641
7642 GeneratorInfo( std::size_t size )
7643 : m_size( size ),
7644 m_currentIndex( 0 )
7645 {}
7646
7647 bool moveNext() {
7648 if( ++m_currentIndex == m_size ) {
7649 m_currentIndex = 0;
7650 return false;
7651 }
7652 return true;
7653 }
7654
7655 std::size_t getCurrentIndex() const {
7656 return m_currentIndex;
7657 }
7658
7659 std::size_t m_size;
7660 std::size_t m_currentIndex;
7661 };
7662
7663 ///////////////////////////////////////////////////////////////////////////
7664
7665 class GeneratorsForTest : public IGeneratorsForTest {
7666
7667 public:
7668 ~GeneratorsForTest() {
7669 deleteAll( m_generatorsInOrder );
7670 }
7671
Phil Nash8defc712013-04-24 19:10:02 +01007672 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007673 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7674 if( it == m_generatorsByName.end() ) {
7675 IGeneratorInfo* info = new GeneratorInfo( size );
7676 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7677 m_generatorsInOrder.push_back( info );
7678 return *info;
7679 }
7680 return *it->second;
7681 }
7682
7683 bool moveNext() {
7684 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7685 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7686 for(; it != itEnd; ++it ) {
7687 if( (*it)->moveNext() )
7688 return true;
7689 }
7690 return false;
7691 }
7692
7693 private:
7694 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7695 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7696 };
7697
7698 IGeneratorsForTest* createGeneratorsForTest()
7699 {
7700 return new GeneratorsForTest();
7701 }
7702
7703} // end namespace Catch
7704
Phil Nashce612bf2012-11-01 08:27:09 +00007705// #included from: catch_assertionresult.hpp
7706#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007707
7708namespace Catch {
7709
Phil Nash8defc712013-04-24 19:10:02 +01007710 AssertionInfo::AssertionInfo( std::string const& _macroName,
7711 SourceLineInfo const& _lineInfo,
7712 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00007713 ResultDisposition::Flags _resultDisposition )
7714 : macroName( _macroName ),
7715 lineInfo( _lineInfo ),
7716 capturedExpression( _capturedExpression ),
7717 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01007718 {}
Phil Nash90a35942012-11-13 22:04:29 +00007719
Phil Nashce612bf2012-11-01 08:27:09 +00007720 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007721
Phil Nash8defc712013-04-24 19:10:02 +01007722 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00007723 : m_info( info ),
7724 m_resultData( data )
7725 {}
Phil Nash3b80af72012-08-09 07:47:30 +01007726
Phil Nashce612bf2012-11-01 08:27:09 +00007727 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007728
Phil Nash90a35942012-11-13 22:04:29 +00007729 // Result was a success
7730 bool AssertionResult::succeeded() const {
7731 return Catch::isOk( m_resultData.resultType );
7732 }
7733
7734 // Result was a success, or failure is suppressed
7735 bool AssertionResult::isOk() const {
7736 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01007737 }
7738
Phil Nashce612bf2012-11-01 08:27:09 +00007739 ResultWas::OfType AssertionResult::getResultType() const {
7740 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01007741 }
7742
Phil Nashce612bf2012-11-01 08:27:09 +00007743 bool AssertionResult::hasExpression() const {
7744 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007745 }
7746
Phil Nashce612bf2012-11-01 08:27:09 +00007747 bool AssertionResult::hasMessage() const {
7748 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01007749 }
7750
Phil Nashce612bf2012-11-01 08:27:09 +00007751 std::string AssertionResult::getExpression() const {
Phil Nashab036682014-06-02 07:48:03 +01007752 if( isFalseTest( m_info.resultDisposition ) )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007753 return '!' + m_info.capturedExpression;
Phil Nash786959d2013-06-07 19:07:50 +01007754 else
7755 return m_info.capturedExpression;
7756 }
7757 std::string AssertionResult::getExpressionInMacro() const {
7758 if( m_info.macroName.empty() )
7759 return m_info.capturedExpression;
7760 else
7761 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01007762 }
7763
Phil Nashce612bf2012-11-01 08:27:09 +00007764 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01007765 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01007766 }
7767
Phil Nashce612bf2012-11-01 08:27:09 +00007768 std::string AssertionResult::getExpandedExpression() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007769 return m_resultData.reconstructExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01007770 }
7771
Phil Nashce612bf2012-11-01 08:27:09 +00007772 std::string AssertionResult::getMessage() const {
7773 return m_resultData.message;
7774 }
7775 SourceLineInfo AssertionResult::getSourceInfo() const {
7776 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01007777 }
7778
Phil Nashce612bf2012-11-01 08:27:09 +00007779 std::string AssertionResult::getTestMacroName() const {
7780 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01007781 }
7782
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007783 void AssertionResult::discardDecomposedExpression() const {
7784 m_resultData.decomposedExpression = CATCH_NULL;
7785 }
7786
7787 void AssertionResult::expandDecomposedExpression() const {
7788 m_resultData.reconstructExpression();
7789 }
7790
Phil Nash3b80af72012-08-09 07:47:30 +01007791} // end namespace Catch
7792
Phil Nash5bc030d2012-08-16 18:48:50 +01007793// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007794#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01007795
7796namespace Catch {
7797
Phil Nash52e1e742014-07-03 08:11:38 +01007798 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007799 if( startsWith( tag, '.' ) ||
Phil Nash52e1e742014-07-03 08:11:38 +01007800 tag == "hide" ||
7801 tag == "!hide" )
7802 return TestCaseInfo::IsHidden;
7803 else if( tag == "!throws" )
7804 return TestCaseInfo::Throws;
7805 else if( tag == "!shouldfail" )
7806 return TestCaseInfo::ShouldFail;
7807 else if( tag == "!mayfail" )
7808 return TestCaseInfo::MayFail;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007809 else if( tag == "!nonportable" )
7810 return TestCaseInfo::NonPortable;
Phil Nash52e1e742014-07-03 08:11:38 +01007811 else
7812 return TestCaseInfo::None;
Phil Nash20cad7c2014-04-15 18:44:37 +01007813 }
7814 inline bool isReservedTag( std::string const& tag ) {
Phil Nash37e55612015-03-27 18:02:28 +00007815 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !isalnum( tag[0] );
Phil Nash20cad7c2014-04-15 18:44:37 +01007816 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007817 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
7818 if( isReservedTag( tag ) ) {
7819 {
7820 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01007821 Catch::cerr()
Phil Nash65cc14c2014-05-16 18:54:48 +01007822 << "Tag name [" << tag << "] not allowed.\n"
7823 << "Tag names starting with non alpha-numeric characters are reserved\n";
7824 }
7825 {
7826 Colour colourGuard( Colour::FileName );
Phil Nash383d7c02014-10-02 19:08:19 +01007827 Catch::cerr() << _lineInfo << std::endl;
Phil Nash65cc14c2014-05-16 18:54:48 +01007828 }
7829 exit(1);
7830 }
7831 }
Phil Nash20cad7c2014-04-15 18:44:37 +01007832
Phil Nasha1fbfea2012-12-01 23:57:18 +00007833 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01007834 std::string const& _className,
7835 std::string const& _name,
7836 std::string const& _descOrTags,
7837 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01007838 {
Phil Nash5ecb72b2013-11-26 20:57:45 +00007839 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nash65cc14c2014-05-16 18:54:48 +01007840
7841 // Parse out tags
Phil Nasha1fbfea2012-12-01 23:57:18 +00007842 std::set<std::string> tags;
Phil Nash65cc14c2014-05-16 18:54:48 +01007843 std::string desc, tag;
7844 bool inTag = false;
7845 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
7846 char c = _descOrTags[i];
7847 if( !inTag ) {
7848 if( c == '[' )
7849 inTag = true;
7850 else
7851 desc += c;
Phil Nash20cad7c2014-04-15 18:44:37 +01007852 }
Phil Nash65cc14c2014-05-16 18:54:48 +01007853 else {
7854 if( c == ']' ) {
Phil Nash91c17f32014-12-15 07:26:31 +00007855 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
7856 if( prop == TestCaseInfo::IsHidden )
Phil Nashebd48882014-05-19 18:22:59 +01007857 isHidden = true;
Phil Nash91c17f32014-12-15 07:26:31 +00007858 else if( prop == TestCaseInfo::None )
7859 enforceNotReservedTag( tag, _lineInfo );
7860
7861 tags.insert( tag );
Phil Nash65cc14c2014-05-16 18:54:48 +01007862 tag.clear();
Phil Nash91c17f32014-12-15 07:26:31 +00007863 inTag = false;
Phil Nash65cc14c2014-05-16 18:54:48 +01007864 }
7865 else
7866 tag += c;
7867 }
Phil Nashde49ec42013-12-04 20:25:14 +00007868 }
Phil Nash9241e432014-05-20 18:50:59 +01007869 if( isHidden ) {
7870 tags.insert( "hide" );
7871 tags.insert( "." );
7872 }
7873
Phil Nash52e1e742014-07-03 08:11:38 +01007874 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
Phil Nasha1fbfea2012-12-01 23:57:18 +00007875 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01007876 }
Phil Nash5bc030d2012-08-16 18:48:50 +01007877
Phil Nashb971fe72015-07-02 08:21:38 +01007878 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
7879 {
7880 testCaseInfo.tags = tags;
7881 testCaseInfo.lcaseTags.clear();
7882
7883 std::ostringstream oss;
7884 for( std::set<std::string>::const_iterator it = tags.begin(), itEnd = tags.end(); it != itEnd; ++it ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007885 oss << '[' << *it << ']';
Phil Nashb971fe72015-07-02 08:21:38 +01007886 std::string lcaseTag = toLower( *it );
7887 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
7888 testCaseInfo.lcaseTags.insert( lcaseTag );
7889 }
7890 testCaseInfo.tagsAsString = oss.str();
7891 }
7892
Phil Nash8defc712013-04-24 19:10:02 +01007893 TestCaseInfo::TestCaseInfo( std::string const& _name,
7894 std::string const& _className,
7895 std::string const& _description,
7896 std::set<std::string> const& _tags,
Phil Nash8defc712013-04-24 19:10:02 +01007897 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007898 : name( _name ),
7899 className( _className ),
7900 description( _description ),
Phil Nashff03cdf2012-12-06 08:44:51 +00007901 lineInfo( _lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01007902 properties( None )
Phil Nash38f7eef2013-03-29 13:44:33 +00007903 {
Phil Nashb971fe72015-07-02 08:21:38 +01007904 setTags( *this, _tags );
Phil Nash38f7eef2013-03-29 13:44:33 +00007905 }
Phil Nash5bc030d2012-08-16 18:48:50 +01007906
Phil Nash8defc712013-04-24 19:10:02 +01007907 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007908 : name( other.name ),
7909 className( other.className ),
7910 description( other.description ),
7911 tags( other.tags ),
Phil Nash9241e432014-05-20 18:50:59 +01007912 lcaseTags( other.lcaseTags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00007913 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00007914 lineInfo( other.lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01007915 properties( other.properties )
Phil Nash5bc030d2012-08-16 18:48:50 +01007916 {}
7917
Phil Nash52e1e742014-07-03 08:11:38 +01007918 bool TestCaseInfo::isHidden() const {
7919 return ( properties & IsHidden ) != 0;
7920 }
7921 bool TestCaseInfo::throws() const {
7922 return ( properties & Throws ) != 0;
7923 }
7924 bool TestCaseInfo::okToFail() const {
7925 return ( properties & (ShouldFail | MayFail ) ) != 0;
7926 }
7927 bool TestCaseInfo::expectedToFail() const {
7928 return ( properties & (ShouldFail ) ) != 0;
7929 }
7930
Phil Nash8defc712013-04-24 19:10:02 +01007931 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00007932
Phil Nash8defc712013-04-24 19:10:02 +01007933 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00007934 : TestCaseInfo( other ),
7935 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01007936 {}
7937
Phil Nash8defc712013-04-24 19:10:02 +01007938 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007939 TestCase other( *this );
7940 other.name = _newName;
7941 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01007942 }
7943
Phil Nash9241e432014-05-20 18:50:59 +01007944 void TestCase::swap( TestCase& other ) {
7945 test.swap( other.test );
7946 name.swap( other.name );
7947 className.swap( other.className );
7948 description.swap( other.description );
7949 tags.swap( other.tags );
7950 lcaseTags.swap( other.lcaseTags );
7951 tagsAsString.swap( other.tagsAsString );
Phil Nash52e1e742014-07-03 08:11:38 +01007952 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
Phil Nash9241e432014-05-20 18:50:59 +01007953 std::swap( lineInfo, other.lineInfo );
7954 }
7955
Phil Nasha1fbfea2012-12-01 23:57:18 +00007956 void TestCase::invoke() const {
7957 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01007958 }
7959
Phil Nash8defc712013-04-24 19:10:02 +01007960 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007961 return test.get() == other.test.get() &&
7962 name == other.name &&
7963 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01007964 }
7965
Phil Nash8defc712013-04-24 19:10:02 +01007966 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007967 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01007968 }
Phil Nash8defc712013-04-24 19:10:02 +01007969 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007970 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01007971 swap( temp );
7972 return *this;
7973 }
Phil Nash799ecf92012-09-24 08:30:13 +01007974
Phil Nash8defc712013-04-24 19:10:02 +01007975 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00007976 {
7977 return *this;
7978 }
7979
Phil Nash799ecf92012-09-24 08:30:13 +01007980} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01007981
Phil Nash7673a302012-11-15 22:15:41 +00007982// #included from: catch_version.hpp
7983#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
7984
7985namespace Catch {
7986
Phil Nash21f7ef62015-06-29 18:05:23 +01007987 Version::Version
7988 ( unsigned int _majorVersion,
7989 unsigned int _minorVersion,
7990 unsigned int _patchNumber,
7991 std::string const& _branchName,
7992 unsigned int _buildNumber )
7993 : majorVersion( _majorVersion ),
7994 minorVersion( _minorVersion ),
7995 patchNumber( _patchNumber ),
7996 branchName( _branchName ),
7997 buildNumber( _buildNumber )
7998 {}
7999
8000 std::ostream& operator << ( std::ostream& os, Version const& version ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008001 os << version.majorVersion << '.'
8002 << version.minorVersion << '.'
Phil Nash21f7ef62015-06-29 18:05:23 +01008003 << version.patchNumber;
8004
8005 if( !version.branchName.empty() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008006 os << '-' << version.branchName
8007 << '.' << version.buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01008008 }
8009 return os;
8010 }
8011
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01008012 Version libraryVersion( 1, 7, 1, "", 0 );
Phil Nash21f7ef62015-06-29 18:05:23 +01008013
Phil Nash7673a302012-11-15 22:15:41 +00008014}
8015
Phil Nasha2773812013-02-02 20:37:58 +00008016// #included from: catch_message.hpp
8017#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8018
8019namespace Catch {
8020
8021 MessageInfo::MessageInfo( std::string const& _macroName,
8022 SourceLineInfo const& _lineInfo,
8023 ResultWas::OfType _type )
8024 : macroName( _macroName ),
8025 lineInfo( _lineInfo ),
8026 type( _type ),
8027 sequence( ++globalCount )
8028 {}
8029
8030 // This may need protecting if threading support is added
8031 unsigned int MessageInfo::globalCount = 0;
8032
8033 ////////////////////////////////////////////////////////////////////////////
8034
Phil Nashb5fd5a62013-06-28 17:09:57 +01008035 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8036 : m_info( builder.m_info )
8037 {
8038 m_info.message = builder.m_stream.str();
8039 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00008040 }
Phil Nash9241e432014-05-20 18:50:59 +01008041 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8042 : m_info( other.m_info )
8043 {}
8044
Phil Nashb5fd5a62013-06-28 17:09:57 +01008045 ScopedMessage::~ScopedMessage() {
8046 getResultCapture().popScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00008047 }
8048
8049} // end namespace Catch
8050
Phil Nash243f2d22013-04-12 10:43:06 +01008051// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01008052#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8053
8054// #included from: catch_legacy_reporter_adapter.h
8055#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8056
8057namespace Catch
8058{
Phil Nash3649fdf2013-12-03 18:53:55 +00008059 // Deprecated
8060 struct IReporter : IShared {
8061 virtual ~IReporter();
8062
8063 virtual bool shouldRedirectStdout() const = 0;
8064
8065 virtual void StartTesting() = 0;
8066 virtual void EndTesting( Totals const& totals ) = 0;
8067 virtual void StartGroup( std::string const& groupName ) = 0;
8068 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8069 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8070 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8071 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8072 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8073 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8074 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8075 virtual void Aborted() = 0;
8076 virtual void Result( AssertionResult const& result ) = 0;
8077 };
8078
Phil Nash87641772013-04-08 11:50:41 +01008079 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8080 {
8081 public:
Phil Nash786959d2013-06-07 19:07:50 +01008082 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01008083 virtual ~LegacyReporterAdapter();
8084
8085 virtual ReporterPreferences getPreferences() const;
8086 virtual void noMatchingTestCases( std::string const& );
8087 virtual void testRunStarting( TestRunInfo const& );
8088 virtual void testGroupStarting( GroupInfo const& groupInfo );
8089 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8090 virtual void sectionStarting( SectionInfo const& sectionInfo );
8091 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008092 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01008093 virtual void sectionEnded( SectionStats const& sectionStats );
8094 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8095 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8096 virtual void testRunEnded( TestRunStats const& testRunStats );
Phil Nash92f08362014-12-22 20:18:05 +00008097 virtual void skipTest( TestCaseInfo const& );
Phil Nash87641772013-04-08 11:50:41 +01008098
8099 private:
8100 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01008101 };
8102}
8103
8104namespace Catch
8105{
Phil Nash786959d2013-06-07 19:07:50 +01008106 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8107 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01008108 {}
8109 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8110
8111 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8112 ReporterPreferences prefs;
8113 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8114 return prefs;
8115 }
8116
8117 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
8118 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8119 m_legacyReporter->StartTesting();
8120 }
8121 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8122 m_legacyReporter->StartGroup( groupInfo.name );
8123 }
8124 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8125 m_legacyReporter->StartTestCase( testInfo );
8126 }
8127 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8128 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8129 }
8130 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8131 // Not on legacy interface
8132 }
8133
Phil Nashb5fd5a62013-06-28 17:09:57 +01008134 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008135 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8136 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8137 it != itEnd;
8138 ++it ) {
8139 if( it->type == ResultWas::Info ) {
Phil Nashab036682014-06-02 07:48:03 +01008140 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8141 rb << it->message;
8142 rb.setResultType( ResultWas::Info );
8143 AssertionResult result = rb.build();
Phil Nash87641772013-04-08 11:50:41 +01008144 m_legacyReporter->Result( result );
8145 }
8146 }
8147 }
8148 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008149 return true;
Phil Nash87641772013-04-08 11:50:41 +01008150 }
8151 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8152 if( sectionStats.missingAssertions )
8153 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8154 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8155 }
8156 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008157 m_legacyReporter->EndTestCase
8158 ( testCaseStats.testInfo,
8159 testCaseStats.totals,
8160 testCaseStats.stdOut,
8161 testCaseStats.stdErr );
8162 }
8163 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8164 if( testGroupStats.aborting )
8165 m_legacyReporter->Aborted();
8166 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8167 }
8168 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8169 m_legacyReporter->EndTesting( testRunStats.totals );
8170 }
Phil Nash92f08362014-12-22 20:18:05 +00008171 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8172 }
Phil Nash87641772013-04-08 11:50:41 +01008173}
8174
Phil Nashaa7123b2013-08-15 19:01:00 +01008175// #included from: catch_timer.hpp
8176
8177#ifdef __clang__
8178#pragma clang diagnostic push
8179#pragma clang diagnostic ignored "-Wc++11-long-long"
8180#endif
8181
Phil Nash04a33642013-08-16 19:09:09 +01008182#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01008183#else
8184#include <sys/time.h>
8185#endif
8186
8187namespace Catch {
8188
8189 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01008190#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01008191 uint64_t getCurrentTicks() {
8192 static uint64_t hz=0, hzo=0;
8193 if (!hz) {
Phil Nash37e55612015-03-27 18:02:28 +00008194 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8195 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008196 }
8197 uint64_t t;
Phil Nash37e55612015-03-27 18:02:28 +00008198 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008199 return ((t-hzo)*1000000)/hz;
8200 }
8201#else
8202 uint64_t getCurrentTicks() {
8203 timeval t;
Phil Nashb971fe72015-07-02 08:21:38 +01008204 gettimeofday(&t,CATCH_NULL);
Phil Nashce562092014-07-09 07:40:37 +01008205 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
Phil Nashaa7123b2013-08-15 19:01:00 +01008206 }
8207#endif
8208 }
8209
8210 void Timer::start() {
8211 m_ticks = getCurrentTicks();
8212 }
Phil Nash4caabfa2014-09-03 19:23:22 +01008213 unsigned int Timer::getElapsedMicroseconds() const {
Phil Nashce562092014-07-09 07:40:37 +01008214 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
Phil Nashaa7123b2013-08-15 19:01:00 +01008215 }
8216 unsigned int Timer::getElapsedMilliseconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008217 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
Phil Nashaa7123b2013-08-15 19:01:00 +01008218 }
8219 double Timer::getElapsedSeconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008220 return getElapsedMicroseconds()/1000000.0;
Phil Nashaa7123b2013-08-15 19:01:00 +01008221 }
8222
8223} // namespace Catch
8224
8225#ifdef __clang__
8226#pragma clang diagnostic pop
8227#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00008228// #included from: catch_common.hpp
8229#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8230
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008231#include <cstring>
8232
Phil Nash3649fdf2013-12-03 18:53:55 +00008233namespace Catch {
8234
8235 bool startsWith( std::string const& s, std::string const& prefix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008236 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8237 }
8238 bool startsWith( std::string const& s, char prefix ) {
8239 return !s.empty() && s[0] == prefix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008240 }
8241 bool endsWith( std::string const& s, std::string const& suffix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008242 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8243 }
8244 bool endsWith( std::string const& s, char suffix ) {
8245 return !s.empty() && s[s.size()-1] == suffix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008246 }
8247 bool contains( std::string const& s, std::string const& infix ) {
8248 return s.find( infix ) != std::string::npos;
8249 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008250 bool contains( std::string const& s, char infix ) {
8251 return s.find(infix) != std::string::npos;
8252 }
Phil Nashe27c4ee2016-10-26 12:08:26 +01008253 char toLowerCh(char c) {
8254 return static_cast<char>( ::tolower( c ) );
8255 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008256 void toLowerInPlace( std::string& s ) {
Phil Nashe27c4ee2016-10-26 12:08:26 +01008257 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
Phil Nash3649fdf2013-12-03 18:53:55 +00008258 }
8259 std::string toLower( std::string const& s ) {
8260 std::string lc = s;
8261 toLowerInPlace( lc );
8262 return lc;
8263 }
8264 std::string trim( std::string const& str ) {
8265 static char const* whitespaceChars = "\n\r\t ";
8266 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8267 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8268
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008269 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
Phil Nash3649fdf2013-12-03 18:53:55 +00008270 }
8271
Phil Nash576aff62014-12-21 00:21:23 +00008272 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8273 bool replaced = false;
8274 std::size_t i = str.find( replaceThis );
8275 while( i != std::string::npos ) {
8276 replaced = true;
8277 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8278 if( i < str.size()-withThis.size() )
8279 i = str.find( replaceThis, i+withThis.size() );
8280 else
8281 i = std::string::npos;
8282 }
8283 return replaced;
8284 }
8285
Phil Nash3649fdf2013-12-03 18:53:55 +00008286 pluralise::pluralise( std::size_t count, std::string const& label )
8287 : m_count( count ),
8288 m_label( label )
8289 {}
8290
8291 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008292 os << pluraliser.m_count << ' ' << pluraliser.m_label;
Phil Nash3649fdf2013-12-03 18:53:55 +00008293 if( pluraliser.m_count != 1 )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008294 os << 's';
Phil Nash3649fdf2013-12-03 18:53:55 +00008295 return os;
8296 }
8297
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008298 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
Phil Nashde49ec42013-12-04 20:25:14 +00008299 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
Phil Nash3649fdf2013-12-03 18:53:55 +00008300 : file( _file ),
8301 line( _line )
8302 {}
Phil Nash3649fdf2013-12-03 18:53:55 +00008303 bool SourceLineInfo::empty() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008304 return file[0] == '\0';
Phil Nash3649fdf2013-12-03 18:53:55 +00008305 }
8306 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008307 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
Phil Nash3649fdf2013-12-03 18:53:55 +00008308 }
Phil Nasha806c3e2015-03-04 08:23:40 +00008309 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008310 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
Phil Nasha806c3e2015-03-04 08:23:40 +00008311 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008312
Phil Nash8f66e342015-07-02 23:03:13 +01008313 void seedRng( IConfig const& config ) {
8314 if( config.rngSeed() != 0 )
8315 std::srand( config.rngSeed() );
8316 }
8317 unsigned int rngSeed() {
8318 return getCurrentContext().getConfig()->rngSeed();
8319 }
8320
Phil Nash3649fdf2013-12-03 18:53:55 +00008321 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
8322#ifndef __GNUG__
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008323 os << info.file << '(' << info.line << ')';
Phil Nash3649fdf2013-12-03 18:53:55 +00008324#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008325 os << info.file << ':' << info.line;
Phil Nash3649fdf2013-12-03 18:53:55 +00008326#endif
8327 return os;
8328 }
8329
8330 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
8331 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008332 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
Phil Nashab036682014-06-02 07:48:03 +01008333 if( alwaysTrue() )
Phil Nash3649fdf2013-12-03 18:53:55 +00008334 throw std::logic_error( oss.str() );
8335 }
8336}
8337
8338// #included from: catch_section.hpp
8339#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8340
8341namespace Catch {
8342
Phil Nashce562092014-07-09 07:40:37 +01008343 SectionInfo::SectionInfo
8344 ( SourceLineInfo const& _lineInfo,
8345 std::string const& _name,
8346 std::string const& _description )
8347 : name( _name ),
8348 description( _description ),
8349 lineInfo( _lineInfo )
8350 {}
8351
8352 Section::Section( SectionInfo const& info )
8353 : m_info( info ),
Phil Nash9241e432014-05-20 18:50:59 +01008354 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nash3649fdf2013-12-03 18:53:55 +00008355 {
8356 m_timer.start();
8357 }
8358
8359 Section::~Section() {
Phil Nash0c1c9fa2015-09-27 03:28:14 -07008360 if( m_sectionIncluded ) {
8361 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8362 if( std::uncaught_exception() )
8363 getResultCapture().sectionEndedEarly( endInfo );
8364 else
8365 getResultCapture().sectionEnded( endInfo );
8366 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008367 }
8368
8369 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01008370 Section::operator bool() const {
Phil Nash3649fdf2013-12-03 18:53:55 +00008371 return m_sectionIncluded;
8372 }
8373
8374} // end namespace Catch
8375
8376// #included from: catch_debugger.hpp
8377#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8378
8379#include <iostream>
8380
8381#ifdef CATCH_PLATFORM_MAC
8382
8383 #include <assert.h>
8384 #include <stdbool.h>
8385 #include <sys/types.h>
8386 #include <unistd.h>
8387 #include <sys/sysctl.h>
8388
8389 namespace Catch{
8390
8391 // The following function is taken directly from the following technical note:
8392 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8393
8394 // Returns true if the current process is being debugged (either
8395 // running under the debugger or has a debugger attached post facto).
8396 bool isDebuggerActive(){
8397
Phil Nash3649fdf2013-12-03 18:53:55 +00008398 int mib[4];
8399 struct kinfo_proc info;
8400 size_t size;
8401
8402 // Initialize the flags so that, if sysctl fails for some bizarre
8403 // reason, we get a predictable result.
8404
8405 info.kp_proc.p_flag = 0;
8406
8407 // Initialize mib, which tells sysctl the info we want, in this case
8408 // we're looking for information about a specific process ID.
8409
8410 mib[0] = CTL_KERN;
8411 mib[1] = KERN_PROC;
8412 mib[2] = KERN_PROC_PID;
8413 mib[3] = getpid();
8414
8415 // Call sysctl.
8416
8417 size = sizeof(info);
Phil Nashb971fe72015-07-02 08:21:38 +01008418 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
Phil Nash383d7c02014-10-02 19:08:19 +01008419 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
Phil Nash7eb5acc2014-01-08 17:17:31 +00008420 return false;
8421 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008422
8423 // We're being debugged if the P_TRACED flag is set.
8424
8425 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8426 }
8427 } // namespace Catch
8428
Martin Hořeňovský9a566092017-01-20 12:49:59 +01008429#elif defined(CATCH_PLATFORM_LINUX)
8430 #include <fstream>
8431 #include <string>
8432
8433 namespace Catch{
8434 // The standard POSIX way of detecting a debugger is to attempt to
8435 // ptrace() the process, but this needs to be done from a child and not
8436 // this process itself to still allow attaching to this process later
8437 // if wanted, so is rather heavy. Under Linux we have the PID of the
8438 // "debugger" (which doesn't need to be gdb, of course, it could also
8439 // be strace, for example) in /proc/$PID/status, so just get it from
8440 // there instead.
8441 bool isDebuggerActive(){
8442 std::ifstream in("/proc/self/status");
8443 for( std::string line; std::getline(in, line); ) {
8444 static const int PREFIX_LEN = 11;
8445 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8446 // We're traced if the PID is not 0 and no other PID starts
8447 // with 0 digit, so it's enough to check for just a single
8448 // character.
8449 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8450 }
8451 }
8452
8453 return false;
8454 }
8455 } // namespace Catch
Phil Nash3649fdf2013-12-03 18:53:55 +00008456#elif defined(_MSC_VER)
8457 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8458 namespace Catch {
8459 bool isDebuggerActive() {
8460 return IsDebuggerPresent() != 0;
8461 }
8462 }
8463#elif defined(__MINGW32__)
8464 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8465 namespace Catch {
8466 bool isDebuggerActive() {
8467 return IsDebuggerPresent() != 0;
8468 }
8469 }
8470#else
8471 namespace Catch {
8472 inline bool isDebuggerActive() { return false; }
8473 }
8474#endif // Platform
8475
8476#ifdef CATCH_PLATFORM_WINDOWS
8477 extern "C" __declspec(dllimport) void __stdcall OutputDebugStringA( const char* );
8478 namespace Catch {
8479 void writeToDebugConsole( std::string const& text ) {
8480 ::OutputDebugStringA( text.c_str() );
8481 }
8482 }
8483#else
8484 namespace Catch {
8485 void writeToDebugConsole( std::string const& text ) {
8486 // !TBD: Need a version for Mac/ XCode and other IDEs
Phil Nash383d7c02014-10-02 19:08:19 +01008487 Catch::cout() << text;
Phil Nash3649fdf2013-12-03 18:53:55 +00008488 }
8489 }
8490#endif // Platform
8491
Phil Nashaef6cd52014-04-23 07:10:10 +01008492// #included from: catch_tostring.hpp
8493#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8494
8495namespace Catch {
8496
Phil Nashab036682014-06-02 07:48:03 +01008497namespace Detail {
8498
Phil Nash2f6371f2015-07-23 23:06:26 +01008499 const std::string unprintableString = "{?}";
Phil Nash6a8e8ad2014-09-15 18:40:24 +01008500
Phil Nashab036682014-06-02 07:48:03 +01008501 namespace {
Phil Nash2f6371f2015-07-23 23:06:26 +01008502 const int hexThreshold = 255;
8503
Phil Nashab036682014-06-02 07:48:03 +01008504 struct Endianness {
8505 enum Arch { Big, Little };
8506
8507 static Arch which() {
8508 union _{
8509 int asInt;
8510 char asChar[sizeof (int)];
8511 } u;
8512
8513 u.asInt = 1;
8514 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8515 }
8516 };
8517 }
8518
8519 std::string rawMemoryToString( const void *object, std::size_t size )
8520 {
8521 // Reverse order for little endian architectures
8522 int i = 0, end = static_cast<int>( size ), inc = 1;
8523 if( Endianness::which() == Endianness::Little ) {
8524 i = end-1;
8525 end = inc = -1;
8526 }
8527
8528 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8529 std::ostringstream os;
8530 os << "0x" << std::setfill('0') << std::hex;
8531 for( ; i != end; i += inc )
8532 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8533 return os.str();
8534 }
8535}
8536
Phil Nashaef6cd52014-04-23 07:10:10 +01008537std::string toString( std::string const& value ) {
8538 std::string s = value;
8539 if( getCurrentContext().getConfig()->showInvisibles() ) {
8540 for(size_t i = 0; i < s.size(); ++i ) {
8541 std::string subs;
8542 switch( s[i] ) {
8543 case '\n': subs = "\\n"; break;
8544 case '\t': subs = "\\t"; break;
8545 default: break;
8546 }
8547 if( !subs.empty() ) {
8548 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8549 ++i;
8550 }
8551 }
8552 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008553 return '"' + s + '"';
Phil Nashaef6cd52014-04-23 07:10:10 +01008554}
8555std::string toString( std::wstring const& value ) {
8556
8557 std::string s;
8558 s.reserve( value.size() );
8559 for(size_t i = 0; i < value.size(); ++i )
8560 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
Phil Nash13f98432014-12-12 08:11:18 +00008561 return Catch::toString( s );
Phil Nashaef6cd52014-04-23 07:10:10 +01008562}
8563
8564std::string toString( const char* const value ) {
8565 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8566}
8567
8568std::string toString( char* const value ) {
8569 return Catch::toString( static_cast<const char*>( value ) );
8570}
8571
Phil Nash544bf332014-08-20 08:09:32 +01008572std::string toString( const wchar_t* const value )
8573{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008574 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
Phil Nash544bf332014-08-20 08:09:32 +01008575}
8576
8577std::string toString( wchar_t* const value )
8578{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008579 return Catch::toString( static_cast<const wchar_t*>( value ) );
Phil Nash544bf332014-08-20 08:09:32 +01008580}
8581
Phil Nashaef6cd52014-04-23 07:10:10 +01008582std::string toString( int value ) {
8583 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008584 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008585 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008586 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008587 return oss.str();
8588}
8589
8590std::string toString( unsigned long value ) {
8591 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008592 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008593 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008594 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008595 return oss.str();
8596}
8597
8598std::string toString( unsigned int value ) {
Phil Nash13f98432014-12-12 08:11:18 +00008599 return Catch::toString( static_cast<unsigned long>( value ) );
Phil Nashaef6cd52014-04-23 07:10:10 +01008600}
8601
Phil Nash28c2e072014-07-09 19:22:49 +01008602template<typename T>
8603std::string fpToString( T value, int precision ) {
Phil Nashaef6cd52014-04-23 07:10:10 +01008604 std::ostringstream oss;
Phil Nash28c2e072014-07-09 19:22:49 +01008605 oss << std::setprecision( precision )
Phil Nashaef6cd52014-04-23 07:10:10 +01008606 << std::fixed
8607 << value;
8608 std::string d = oss.str();
8609 std::size_t i = d.find_last_not_of( '0' );
8610 if( i != std::string::npos && i != d.size()-1 ) {
8611 if( d[i] == '.' )
8612 i++;
8613 d = d.substr( 0, i+1 );
8614 }
8615 return d;
8616}
8617
Phil Nash28c2e072014-07-09 19:22:49 +01008618std::string toString( const double value ) {
8619 return fpToString( value, 10 );
8620}
8621std::string toString( const float value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008622 return fpToString( value, 5 ) + 'f';
Phil Nash28c2e072014-07-09 19:22:49 +01008623}
8624
Phil Nashaef6cd52014-04-23 07:10:10 +01008625std::string toString( bool value ) {
8626 return value ? "true" : "false";
8627}
8628
8629std::string toString( char value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008630 if ( value == '\r' )
8631 return "'\\r'";
8632 if ( value == '\f' )
8633 return "'\\f'";
8634 if ( value == '\n' )
8635 return "'\\n'";
8636 if ( value == '\t' )
8637 return "'\\t'";
8638 if ( '\0' <= value && value < ' ' )
8639 return toString( static_cast<unsigned int>( value ) );
8640 char chstr[] = "' '";
8641 chstr[1] = value;
8642 return chstr;
Phil Nashaef6cd52014-04-23 07:10:10 +01008643}
8644
8645std::string toString( signed char value ) {
8646 return toString( static_cast<char>( value ) );
8647}
8648
8649std::string toString( unsigned char value ) {
8650 return toString( static_cast<char>( value ) );
8651}
8652
Phil Nash2f6371f2015-07-23 23:06:26 +01008653#ifdef CATCH_CONFIG_CPP11_LONG_LONG
8654std::string toString( long long value ) {
8655 std::ostringstream oss;
8656 oss << value;
8657 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008658 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008659 return oss.str();
8660}
8661std::string toString( unsigned long long value ) {
8662 std::ostringstream oss;
8663 oss << value;
8664 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008665 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008666 return oss.str();
8667}
8668#endif
8669
Phil Nashaef6cd52014-04-23 07:10:10 +01008670#ifdef CATCH_CONFIG_CPP11_NULLPTR
8671std::string toString( std::nullptr_t ) {
8672 return "nullptr";
8673}
8674#endif
8675
8676#ifdef __OBJC__
8677 std::string toString( NSString const * const& nsstring ) {
8678 if( !nsstring )
8679 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008680 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008681 }
8682 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8683 if( !nsstring )
8684 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008685 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008686 }
8687 std::string toString( NSObject* const& nsObject ) {
8688 return toString( [nsObject description] );
8689 }
8690#endif
8691
8692} // end namespace Catch
8693
Phil Nashab036682014-06-02 07:48:03 +01008694// #included from: catch_result_builder.hpp
8695#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8696
8697namespace Catch {
8698
Phil Nash93a842e2015-07-13 06:36:07 +01008699 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008700 return secondArg.empty() || secondArg == "\"\""
Phil Nash93a842e2015-07-13 06:36:07 +01008701 ? capturedExpression
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008702 : capturedExpression + ", " + secondArg;
Phil Nash93a842e2015-07-13 06:36:07 +01008703 }
Phil Nashab036682014-06-02 07:48:03 +01008704 ResultBuilder::ResultBuilder( char const* macroName,
8705 SourceLineInfo const& lineInfo,
8706 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01008707 ResultDisposition::Flags resultDisposition,
8708 char const* secondArg )
8709 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
Phil Nashab036682014-06-02 07:48:03 +01008710 m_shouldDebugBreak( false ),
8711 m_shouldThrow( false )
8712 {}
8713
8714 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
8715 m_data.resultType = result;
8716 return *this;
8717 }
8718 ResultBuilder& ResultBuilder::setResultType( bool result ) {
8719 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
8720 return *this;
8721 }
Phil Nashab036682014-06-02 07:48:03 +01008722
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008723 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
8724 AssertionResult result = build( expr );
8725 handleResult( result );
Phil Nashab036682014-06-02 07:48:03 +01008726 }
8727
8728 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
8729 m_assertionInfo.resultDisposition = resultDisposition;
8730 m_stream.oss << Catch::translateActiveException();
8731 captureResult( ResultWas::ThrewException );
8732 }
8733
8734 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
8735 setResultType( resultType );
8736 captureExpression();
8737 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008738
Phil Nash93a842e2015-07-13 06:36:07 +01008739 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008740 if( expectedMessage.empty() )
8741 captureExpectedException( Matchers::Impl::Generic::AllOf<std::string>() );
8742 else
8743 captureExpectedException( Matchers::Equals( expectedMessage ) );
8744 }
8745
8746 void ResultBuilder::captureExpectedException( Matchers::Impl::Matcher<std::string> const& matcher ) {
8747
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008748 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
Phil Nash93a842e2015-07-13 06:36:07 +01008749 AssertionResultData data = m_data;
8750 data.resultType = ResultWas::Ok;
8751 data.reconstructedExpression = m_assertionInfo.capturedExpression;
Phil Nash93a842e2015-07-13 06:36:07 +01008752
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008753 std::string actualMessage = Catch::translateActiveException();
8754 if( !matcher.match( actualMessage ) ) {
8755 data.resultType = ResultWas::ExpressionFailed;
8756 data.reconstructedExpression = actualMessage;
Phil Nash93a842e2015-07-13 06:36:07 +01008757 }
8758 AssertionResult result( m_assertionInfo, data );
8759 handleResult( result );
8760 }
Phil Nashab036682014-06-02 07:48:03 +01008761
8762 void ResultBuilder::captureExpression() {
8763 AssertionResult result = build();
Phil Nash93a842e2015-07-13 06:36:07 +01008764 handleResult( result );
8765 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008766
Phil Nash93a842e2015-07-13 06:36:07 +01008767 void ResultBuilder::handleResult( AssertionResult const& result )
8768 {
Phil Nashab036682014-06-02 07:48:03 +01008769 getResultCapture().assertionEnded( result );
8770
8771 if( !result.isOk() ) {
8772 if( getCurrentContext().getConfig()->shouldDebugBreak() )
8773 m_shouldDebugBreak = true;
Phil Nash318c9362015-05-19 18:40:00 +01008774 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
Phil Nashab036682014-06-02 07:48:03 +01008775 m_shouldThrow = true;
8776 }
8777 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008778
Phil Nashab036682014-06-02 07:48:03 +01008779 void ResultBuilder::react() {
8780 if( m_shouldThrow )
8781 throw Catch::TestFailureException();
8782 }
8783
8784 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
8785 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
8786
8787 AssertionResult ResultBuilder::build() const
8788 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008789 return build( *this );
8790 }
Phil Nashab036682014-06-02 07:48:03 +01008791
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008792 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
8793 // a temporary DecomposedExpression, which in turn holds references to
8794 // operands, possibly temporary as well.
8795 // It should immediately be passed to handleResult; if the expression
8796 // needs to be reported, its string expansion must be composed before
8797 // the temporaries are destroyed.
8798 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
8799 {
8800 assert( m_data.resultType != ResultWas::Unknown );
Phil Nashab036682014-06-02 07:48:03 +01008801 AssertionResultData data = m_data;
8802
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008803 // Flip bool results if FalseTest flag is set
8804 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
8805 data.negate( expr.isBinaryExpression() );
Phil Nashab036682014-06-02 07:48:03 +01008806 }
8807
8808 data.message = m_stream.oss.str();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008809 data.decomposedExpression = &expr; // for lazy reconstruction
Phil Nashab036682014-06-02 07:48:03 +01008810 return AssertionResult( m_assertionInfo, data );
8811 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008812
8813 void ResultBuilder::reconstructExpression( std::string& dest ) const {
8814 dest = m_assertionInfo.capturedExpression;
Phil Nashab036682014-06-02 07:48:03 +01008815 }
8816
8817} // end namespace Catch
8818
Phil Nashacdd3b52014-06-30 07:35:36 +01008819// #included from: catch_tag_alias_registry.hpp
8820#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
8821
8822// #included from: catch_tag_alias_registry.h
8823#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
8824
8825#include <map>
8826
8827namespace Catch {
8828
8829 class TagAliasRegistry : public ITagAliasRegistry {
8830 public:
8831 virtual ~TagAliasRegistry();
8832 virtual Option<TagAlias> find( std::string const& alias ) const;
8833 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
8834 void add( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
8835 static TagAliasRegistry& get();
8836
8837 private:
8838 std::map<std::string, TagAlias> m_registry;
8839 };
8840
8841} // end namespace Catch
8842
8843#include <map>
8844#include <iostream>
8845
8846namespace Catch {
8847
8848 TagAliasRegistry::~TagAliasRegistry() {}
8849
8850 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
8851 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
8852 if( it != m_registry.end() )
8853 return it->second;
8854 else
8855 return Option<TagAlias>();
8856 }
8857
8858 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
8859 std::string expandedTestSpec = unexpandedTestSpec;
8860 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
8861 it != itEnd;
8862 ++it ) {
8863 std::size_t pos = expandedTestSpec.find( it->first );
8864 if( pos != std::string::npos ) {
8865 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
8866 it->second.tag +
8867 expandedTestSpec.substr( pos + it->first.size() );
8868 }
8869 }
8870 return expandedTestSpec;
8871 }
8872
8873 void TagAliasRegistry::add( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8874
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008875 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01008876 std::ostringstream oss;
8877 oss << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n" << lineInfo;
8878 throw std::domain_error( oss.str().c_str() );
8879 }
8880 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
8881 std::ostringstream oss;
8882 oss << "error: tag alias, \"" << alias << "\" already registered.\n"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008883 << "\tFirst seen at " << find(alias)->lineInfo << '\n'
Phil Nashacdd3b52014-06-30 07:35:36 +01008884 << "\tRedefined at " << lineInfo;
8885 throw std::domain_error( oss.str().c_str() );
8886 }
8887 }
8888
8889 TagAliasRegistry& TagAliasRegistry::get() {
8890 static TagAliasRegistry instance;
8891 return instance;
8892
8893 }
8894
8895 ITagAliasRegistry::~ITagAliasRegistry() {}
8896 ITagAliasRegistry const& ITagAliasRegistry::get() { return TagAliasRegistry::get(); }
8897
8898 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
8899 try {
8900 TagAliasRegistry::get().add( alias, tag, lineInfo );
8901 }
8902 catch( std::exception& ex ) {
8903 Colour colourGuard( Colour::Red );
Phil Nash383d7c02014-10-02 19:08:19 +01008904 Catch::cerr() << ex.what() << std::endl;
Phil Nashacdd3b52014-06-30 07:35:36 +01008905 exit(1);
8906 }
8907 }
8908
8909} // end namespace Catch
8910
Phil Nashe73583d2015-08-07 17:30:34 +01008911// #included from: ../reporters/catch_reporter_multi.hpp
8912#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
8913
8914namespace Catch {
8915
8916class MultipleReporters : public SharedImpl<IStreamingReporter> {
8917 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
8918 Reporters m_reporters;
8919
8920public:
8921 void add( Ptr<IStreamingReporter> const& reporter ) {
8922 m_reporters.push_back( reporter );
8923 }
8924
8925public: // IStreamingReporter
8926
8927 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
8928 return m_reporters[0]->getPreferences();
8929 }
8930
8931 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
8932 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8933 it != itEnd;
8934 ++it )
8935 (*it)->noMatchingTestCases( spec );
8936 }
8937
8938 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
8939 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8940 it != itEnd;
8941 ++it )
8942 (*it)->testRunStarting( testRunInfo );
8943 }
8944
8945 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
8946 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8947 it != itEnd;
8948 ++it )
8949 (*it)->testGroupStarting( groupInfo );
8950 }
8951
8952 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
8953 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8954 it != itEnd;
8955 ++it )
8956 (*it)->testCaseStarting( testInfo );
8957 }
8958
8959 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
8960 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8961 it != itEnd;
8962 ++it )
8963 (*it)->sectionStarting( sectionInfo );
8964 }
8965
8966 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
8967 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8968 it != itEnd;
8969 ++it )
8970 (*it)->assertionStarting( assertionInfo );
8971 }
8972
8973 // The return value indicates if the messages buffer should be cleared:
8974 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
8975 bool clearBuffer = false;
8976 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8977 it != itEnd;
8978 ++it )
8979 clearBuffer |= (*it)->assertionEnded( assertionStats );
8980 return clearBuffer;
8981 }
8982
8983 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
8984 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8985 it != itEnd;
8986 ++it )
8987 (*it)->sectionEnded( sectionStats );
8988 }
8989
8990 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
8991 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8992 it != itEnd;
8993 ++it )
8994 (*it)->testCaseEnded( testCaseStats );
8995 }
8996
8997 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
8998 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
8999 it != itEnd;
9000 ++it )
9001 (*it)->testGroupEnded( testGroupStats );
9002 }
9003
9004 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9005 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9006 it != itEnd;
9007 ++it )
9008 (*it)->testRunEnded( testRunStats );
9009 }
9010
9011 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9012 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9013 it != itEnd;
9014 ++it )
9015 (*it)->skipTest( testInfo );
9016 }
Phil Nash92b141e2016-04-28 08:13:00 +01009017
9018 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
9019 return this;
9020 }
9021
Phil Nashe73583d2015-08-07 17:30:34 +01009022};
9023
9024Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
9025 Ptr<IStreamingReporter> resultingReporter;
9026
9027 if( existingReporter ) {
Phil Nash92b141e2016-04-28 08:13:00 +01009028 MultipleReporters* multi = existingReporter->tryAsMulti();
Phil Nashe73583d2015-08-07 17:30:34 +01009029 if( !multi ) {
9030 multi = new MultipleReporters;
9031 resultingReporter = Ptr<IStreamingReporter>( multi );
9032 if( existingReporter )
9033 multi->add( existingReporter );
9034 }
9035 else
9036 resultingReporter = existingReporter;
9037 multi->add( additionalReporter );
9038 }
9039 else
9040 resultingReporter = additionalReporter;
9041
9042 return resultingReporter;
9043}
9044
9045} // end namespace Catch
9046
Phil Nash3faa4122013-08-15 19:09:07 +01009047// #included from: ../reporters/catch_reporter_xml.hpp
9048#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01009049
Phil Nash3649fdf2013-12-03 18:53:55 +00009050// #included from: catch_reporter_bases.hpp
9051#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
9052
Phil Nashb7713942014-12-22 07:42:57 +00009053#include <cstring>
9054
Phil Nash3649fdf2013-12-03 18:53:55 +00009055namespace Catch {
9056
9057 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
9058
9059 StreamingReporterBase( ReporterConfig const& _config )
9060 : m_config( _config.fullConfig() ),
9061 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009062 {
9063 m_reporterPrefs.shouldRedirectStdOut = false;
9064 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009065
Phil Nashe73583d2015-08-07 17:30:34 +01009066 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9067 return m_reporterPrefs;
9068 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009069
Phil Nashe73583d2015-08-07 17:30:34 +01009070 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
Phil Nash3649fdf2013-12-03 18:53:55 +00009071
Phil Nashe73583d2015-08-07 17:30:34 +01009072 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
9073
9074 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009075 currentTestRunInfo = _testRunInfo;
9076 }
Phil Nashe73583d2015-08-07 17:30:34 +01009077 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009078 currentGroupInfo = _groupInfo;
9079 }
9080
Phil Nashe73583d2015-08-07 17:30:34 +01009081 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009082 currentTestCaseInfo = _testInfo;
9083 }
Phil Nashe73583d2015-08-07 17:30:34 +01009084 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009085 m_sectionStack.push_back( _sectionInfo );
9086 }
9087
Phil Nashe73583d2015-08-07 17:30:34 +01009088 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009089 m_sectionStack.pop_back();
9090 }
Phil Nashe73583d2015-08-07 17:30:34 +01009091 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009092 currentTestCaseInfo.reset();
Phil Nash3649fdf2013-12-03 18:53:55 +00009093 }
Phil Nashe73583d2015-08-07 17:30:34 +01009094 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009095 currentGroupInfo.reset();
9096 }
Phil Nashe73583d2015-08-07 17:30:34 +01009097 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009098 currentTestCaseInfo.reset();
9099 currentGroupInfo.reset();
9100 currentTestRunInfo.reset();
9101 }
9102
Phil Nashe73583d2015-08-07 17:30:34 +01009103 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
Phil Nash92f08362014-12-22 20:18:05 +00009104 // Don't do anything with this by default.
9105 // It can optionally be overridden in the derived class.
9106 }
9107
Phil Nash7e346192015-11-03 08:00:43 +00009108 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009109 std::ostream& stream;
9110
9111 LazyStat<TestRunInfo> currentTestRunInfo;
9112 LazyStat<GroupInfo> currentGroupInfo;
9113 LazyStat<TestCaseInfo> currentTestCaseInfo;
9114
9115 std::vector<SectionInfo> m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009116 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009117 };
9118
9119 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
9120 template<typename T, typename ChildNodeT>
9121 struct Node : SharedImpl<> {
9122 explicit Node( T const& _value ) : value( _value ) {}
9123 virtual ~Node() {}
9124
9125 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
9126 T value;
9127 ChildNodes children;
9128 };
9129 struct SectionNode : SharedImpl<> {
9130 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
9131 virtual ~SectionNode();
9132
9133 bool operator == ( SectionNode const& other ) const {
9134 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
9135 }
9136 bool operator == ( Ptr<SectionNode> const& other ) const {
9137 return operator==( *other );
9138 }
9139
9140 SectionStats stats;
9141 typedef std::vector<Ptr<SectionNode> > ChildSections;
9142 typedef std::vector<AssertionStats> Assertions;
9143 ChildSections childSections;
9144 Assertions assertions;
9145 std::string stdOut;
9146 std::string stdErr;
9147 };
Phil Nasheb760f62013-12-18 08:38:33 +00009148
9149 struct BySectionInfo {
9150 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009151 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
Phil Nasheb760f62013-12-18 08:38:33 +00009152 bool operator() ( Ptr<SectionNode> const& node ) const {
9153 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
9154 }
9155 private:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009156 void operator=( BySectionInfo const& );
Phil Nasheb760f62013-12-18 08:38:33 +00009157 SectionInfo const& m_other;
9158 };
Phil Nash3649fdf2013-12-03 18:53:55 +00009159
9160 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
9161 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
9162 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
9163
9164 CumulativeReporterBase( ReporterConfig const& _config )
9165 : m_config( _config.fullConfig() ),
9166 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009167 {
9168 m_reporterPrefs.shouldRedirectStdOut = false;
9169 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009170 ~CumulativeReporterBase();
9171
Phil Nashe73583d2015-08-07 17:30:34 +01009172 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9173 return m_reporterPrefs;
9174 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009175
Phil Nashe73583d2015-08-07 17:30:34 +01009176 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
9177 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009178
Phil Nashe73583d2015-08-07 17:30:34 +01009179 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
9180
9181 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009182 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
9183 Ptr<SectionNode> node;
9184 if( m_sectionStack.empty() ) {
9185 if( !m_rootSection )
9186 m_rootSection = new SectionNode( incompleteStats );
9187 node = m_rootSection;
9188 }
9189 else {
9190 SectionNode& parentNode = *m_sectionStack.back();
9191 SectionNode::ChildSections::const_iterator it =
Phil Nasheb760f62013-12-18 08:38:33 +00009192 std::find_if( parentNode.childSections.begin(),
9193 parentNode.childSections.end(),
9194 BySectionInfo( sectionInfo ) );
Phil Nash3649fdf2013-12-03 18:53:55 +00009195 if( it == parentNode.childSections.end() ) {
9196 node = new SectionNode( incompleteStats );
9197 parentNode.childSections.push_back( node );
9198 }
9199 else
9200 node = *it;
9201 }
9202 m_sectionStack.push_back( node );
9203 m_deepestSection = node;
9204 }
9205
Phil Nashe73583d2015-08-07 17:30:34 +01009206 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009207
Phil Nashe5537842016-04-25 18:56:50 +01009208 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009209 assert( !m_sectionStack.empty() );
9210 SectionNode& sectionNode = *m_sectionStack.back();
9211 sectionNode.assertions.push_back( assertionStats );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009212 // AssertionResult holds a pointer to a temporary DecomposedExpression,
9213 // which getExpandedExpression() calls to build the expression string.
9214 // Our section stack copy of the assertionResult will likely outlive the
9215 // temporary, so it must be expanded or discarded now to avoid calling
9216 // a destroyed object later.
9217 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
Phil Nash3649fdf2013-12-03 18:53:55 +00009218 return true;
9219 }
Phil Nashe73583d2015-08-07 17:30:34 +01009220 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009221 assert( !m_sectionStack.empty() );
9222 SectionNode& node = *m_sectionStack.back();
9223 node.stats = sectionStats;
9224 m_sectionStack.pop_back();
9225 }
Phil Nashe73583d2015-08-07 17:30:34 +01009226 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009227 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
9228 assert( m_sectionStack.size() == 0 );
9229 node->children.push_back( m_rootSection );
9230 m_testCases.push_back( node );
9231 m_rootSection.reset();
9232
9233 assert( m_deepestSection );
9234 m_deepestSection->stdOut = testCaseStats.stdOut;
9235 m_deepestSection->stdErr = testCaseStats.stdErr;
9236 }
Phil Nashe73583d2015-08-07 17:30:34 +01009237 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009238 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
9239 node->children.swap( m_testCases );
9240 m_testGroups.push_back( node );
9241 }
Phil Nashe73583d2015-08-07 17:30:34 +01009242 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009243 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
9244 node->children.swap( m_testGroups );
9245 m_testRuns.push_back( node );
Phil Nasha6d74bd2013-12-11 08:28:15 +00009246 testRunEndedCumulative();
Phil Nash3649fdf2013-12-03 18:53:55 +00009247 }
Phil Nasha6d74bd2013-12-11 08:28:15 +00009248 virtual void testRunEndedCumulative() = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00009249
Phil Nashe73583d2015-08-07 17:30:34 +01009250 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
Phil Nash92f08362014-12-22 20:18:05 +00009251
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009252 virtual void prepareExpandedExpression( AssertionResult& result ) const {
9253 if( result.isOk() )
9254 result.discardDecomposedExpression();
9255 else
9256 result.expandDecomposedExpression();
9257 }
9258
Phil Nash7e346192015-11-03 08:00:43 +00009259 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009260 std::ostream& stream;
9261 std::vector<AssertionStats> m_assertions;
9262 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
9263 std::vector<Ptr<TestCaseNode> > m_testCases;
9264 std::vector<Ptr<TestGroupNode> > m_testGroups;
9265
9266 std::vector<Ptr<TestRunNode> > m_testRuns;
9267
9268 Ptr<SectionNode> m_rootSection;
9269 Ptr<SectionNode> m_deepestSection;
9270 std::vector<Ptr<SectionNode> > m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009271 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009272
9273 };
9274
Phil Nash576aff62014-12-21 00:21:23 +00009275 template<char C>
9276 char const* getLineOfChars() {
9277 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
9278 if( !*line ) {
9279 memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
9280 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
9281 }
9282 return line;
9283 }
9284
Phil Nashe73583d2015-08-07 17:30:34 +01009285 struct TestEventListenerBase : StreamingReporterBase {
9286 TestEventListenerBase( ReporterConfig const& _config )
9287 : StreamingReporterBase( _config )
9288 {}
9289
9290 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash08844e72015-11-05 18:52:18 +00009291 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01009292 return false;
9293 }
9294 };
9295
Phil Nash3649fdf2013-12-03 18:53:55 +00009296} // end namespace Catch
9297
Phil Nash56d5c422012-08-23 20:08:50 +01009298// #included from: ../internal/catch_reporter_registrars.hpp
9299#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
9300
9301namespace Catch {
9302
9303 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00009304 class LegacyReporterRegistrar {
9305
9306 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01009307 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01009308 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00009309 }
9310
9311 virtual std::string getDescription() const {
9312 return T::getDescription();
9313 }
9314 };
9315
9316 public:
9317
Phil Nash8defc712013-04-24 19:10:02 +01009318 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009319 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9320 }
9321 };
9322
9323 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01009324 class ReporterRegistrar {
9325
Phil Nashe73583d2015-08-07 17:30:34 +01009326 class ReporterFactory : public SharedImpl<IReporterFactory> {
Phil Nash56d5c422012-08-23 20:08:50 +01009327
Phil Nasha1fbfea2012-12-01 23:57:18 +00009328 // *** Please Note ***:
9329 // - If you end up here looking at a compiler error because it's trying to register
9330 // your custom reporter class be aware that the native reporter interface has changed
9331 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
9332 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
9333 // However please consider updating to the new interface as the old one is now
9334 // deprecated and will probably be removed quite soon!
9335 // Please contact me via github if you have any questions at all about this.
9336 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
9337 // no idea who is actually using custom reporters at all (possibly no-one!).
9338 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01009339 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01009340 return new T( config );
9341 }
9342
9343 virtual std::string getDescription() const {
9344 return T::getDescription();
9345 }
9346 };
9347
9348 public:
9349
Phil Nash8defc712013-04-24 19:10:02 +01009350 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009351 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9352 }
9353 };
Phil Nashe73583d2015-08-07 17:30:34 +01009354
9355 template<typename T>
9356 class ListenerRegistrar {
9357
9358 class ListenerFactory : public SharedImpl<IReporterFactory> {
9359
9360 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9361 return new T( config );
9362 }
9363 virtual std::string getDescription() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009364 return std::string();
Phil Nashe73583d2015-08-07 17:30:34 +01009365 }
9366 };
9367
9368 public:
9369
9370 ListenerRegistrar() {
9371 getMutableRegistryHub().registerListener( new ListenerFactory() );
9372 }
9373 };
Phil Nash56d5c422012-08-23 20:08:50 +01009374}
9375
Phil Nasha1fbfea2012-12-01 23:57:18 +00009376#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009377 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nashe73583d2015-08-07 17:30:34 +01009378
Phil Nash56d5c422012-08-23 20:08:50 +01009379#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009380 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01009381
Phil Nashe73583d2015-08-07 17:30:34 +01009382#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
9383 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9384
Phil Nash56d5c422012-08-23 20:08:50 +01009385// #included from: ../internal/catch_xmlwriter.hpp
9386#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
9387
9388#include <sstream>
9389#include <string>
9390#include <vector>
Phil Nash2f6371f2015-07-23 23:06:26 +01009391#include <iomanip>
Phil Nash56d5c422012-08-23 20:08:50 +01009392
9393namespace Catch {
9394
Phil Nash2f6371f2015-07-23 23:06:26 +01009395 class XmlEncode {
9396 public:
9397 enum ForWhat { ForTextNodes, ForAttributes };
9398
9399 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
9400 : m_str( str ),
9401 m_forWhat( forWhat )
9402 {}
9403
9404 void encodeTo( std::ostream& os ) const {
9405
9406 // Apostrophe escaping not necessary if we always use " to write attributes
9407 // (see: http://www.w3.org/TR/xml/#syntax)
9408
9409 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
9410 char c = m_str[i];
9411 switch( c ) {
9412 case '<': os << "&lt;"; break;
9413 case '&': os << "&amp;"; break;
9414
9415 case '>':
9416 // See: http://www.w3.org/TR/xml/#syntax
9417 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
9418 os << "&gt;";
9419 else
9420 os << c;
9421 break;
9422
9423 case '\"':
9424 if( m_forWhat == ForAttributes )
9425 os << "&quot;";
9426 else
9427 os << c;
9428 break;
9429
9430 default:
Phil Nash40f60682016-09-27 10:46:22 +01009431 // Escape control chars - based on contribution by @espenalb in PR #465 and
9432 // by @mrpi PR #588
Phil Nash3b2f2062017-01-11 16:43:56 +00009433 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' )
Phil Nash40f60682016-09-27 10:46:22 +01009434 os << "&#x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2) << static_cast<int>( c ) << ';';
Phil Nash2f6371f2015-07-23 23:06:26 +01009435 else
9436 os << c;
9437 }
9438 }
9439 }
9440
9441 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
9442 xmlEncode.encodeTo( os );
9443 return os;
9444 }
9445
9446 private:
9447 std::string m_str;
9448 ForWhat m_forWhat;
9449 };
9450
Phil Nash56d5c422012-08-23 20:08:50 +01009451 class XmlWriter {
9452 public:
9453
9454 class ScopedElement {
9455 public:
9456 ScopedElement( XmlWriter* writer )
9457 : m_writer( writer )
9458 {}
9459
Phil Nash8defc712013-04-24 19:10:02 +01009460 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01009461 : m_writer( other.m_writer ){
Phil Nashb971fe72015-07-02 08:21:38 +01009462 other.m_writer = CATCH_NULL;
Phil Nash56d5c422012-08-23 20:08:50 +01009463 }
9464
9465 ~ScopedElement() {
9466 if( m_writer )
9467 m_writer->endElement();
9468 }
9469
Phil Nash8defc712013-04-24 19:10:02 +01009470 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009471 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01009472 return *this;
9473 }
9474
9475 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009476 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009477 m_writer->writeAttribute( name, attribute );
9478 return *this;
9479 }
9480
9481 private:
9482 mutable XmlWriter* m_writer;
9483 };
9484
9485 XmlWriter()
9486 : m_tagIsOpen( false ),
9487 m_needsNewline( false ),
Phil Nash383d7c02014-10-02 19:08:19 +01009488 m_os( &Catch::cout() )
Phil Nash40f60682016-09-27 10:46:22 +01009489 {
9490 // We encode control characters, which requires
9491 // XML 1.1
9492 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
9493 *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
9494 }
Phil Nash56d5c422012-08-23 20:08:50 +01009495
9496 XmlWriter( std::ostream& os )
9497 : m_tagIsOpen( false ),
9498 m_needsNewline( false ),
9499 m_os( &os )
Phil Nash40f60682016-09-27 10:46:22 +01009500 {
9501 *m_os << "<?xml version=\"1.1\" encoding=\"UTF-8\"?>\n";
9502 }
Phil Nash56d5c422012-08-23 20:08:50 +01009503
9504 ~XmlWriter() {
9505 while( !m_tags.empty() )
9506 endElement();
9507 }
9508
Phil Nash8defc712013-04-24 19:10:02 +01009509 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009510 ensureTagClosed();
9511 newlineIfNecessary();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009512 stream() << m_indent << '<' << name;
Phil Nash56d5c422012-08-23 20:08:50 +01009513 m_tags.push_back( name );
9514 m_indent += " ";
9515 m_tagIsOpen = true;
9516 return *this;
9517 }
9518
Phil Nash8defc712013-04-24 19:10:02 +01009519 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009520 ScopedElement scoped( this );
9521 startElement( name );
9522 return scoped;
9523 }
9524
9525 XmlWriter& endElement() {
9526 newlineIfNecessary();
9527 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9528 if( m_tagIsOpen ) {
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009529 stream() << "/>";
Phil Nash56d5c422012-08-23 20:08:50 +01009530 m_tagIsOpen = false;
9531 }
9532 else {
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009533 stream() << m_indent << "</" << m_tags.back() << ">";
Phil Nash56d5c422012-08-23 20:08:50 +01009534 }
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009535 stream() << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01009536 m_tags.pop_back();
9537 return *this;
9538 }
9539
Phil Nash8defc712013-04-24 19:10:02 +01009540 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009541 if( !name.empty() && !attribute.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009542 stream() << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009543 return *this;
9544 }
9545
Phil Nash8defc712013-04-24 19:10:02 +01009546 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009547 stream() << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009548 return *this;
9549 }
9550
9551 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009552 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009553 std::ostringstream oss;
9554 oss << attribute;
9555 return writeAttribute( name, oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01009556 }
9557
Phil Nash8defc712013-04-24 19:10:02 +01009558 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009559 if( !text.empty() ){
9560 bool tagWasOpen = m_tagIsOpen;
9561 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00009562 if( tagWasOpen && indent )
Phil Nash56d5c422012-08-23 20:08:50 +01009563 stream() << m_indent;
Phil Nash2f6371f2015-07-23 23:06:26 +01009564 stream() << XmlEncode( text );
Phil Nash56d5c422012-08-23 20:08:50 +01009565 m_needsNewline = true;
9566 }
9567 return *this;
9568 }
9569
Phil Nash8defc712013-04-24 19:10:02 +01009570 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009571 ensureTagClosed();
9572 stream() << m_indent << "<!--" << text << "-->";
9573 m_needsNewline = true;
9574 return *this;
9575 }
9576
9577 XmlWriter& writeBlankLine() {
9578 ensureTagClosed();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009579 stream() << '\n';
Phil Nash56d5c422012-08-23 20:08:50 +01009580 return *this;
9581 }
9582
Phil Nash9241e432014-05-20 18:50:59 +01009583 void setStream( std::ostream& os ) {
9584 m_os = &os;
9585 }
9586
Phil Nash56d5c422012-08-23 20:08:50 +01009587 private:
Phil Nash9241e432014-05-20 18:50:59 +01009588 XmlWriter( XmlWriter const& );
9589 void operator=( XmlWriter const& );
Phil Nash56d5c422012-08-23 20:08:50 +01009590
9591 std::ostream& stream() {
9592 return *m_os;
9593 }
9594
9595 void ensureTagClosed() {
9596 if( m_tagIsOpen ) {
9597 stream() << ">\n";
9598 m_tagIsOpen = false;
9599 }
9600 }
9601
9602 void newlineIfNecessary() {
9603 if( m_needsNewline ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009604 stream() << '\n';
Phil Nash56d5c422012-08-23 20:08:50 +01009605 m_needsNewline = false;
9606 }
9607 }
9608
Phil Nash56d5c422012-08-23 20:08:50 +01009609 bool m_tagIsOpen;
9610 bool m_needsNewline;
9611 std::vector<std::string> m_tags;
9612 std::string m_indent;
9613 std::ostream* m_os;
9614 };
9615
9616}
Phil Nash2f6371f2015-07-23 23:06:26 +01009617// #included from: catch_reenable_warnings.h
9618
9619#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
9620
9621#ifdef __clang__
9622# ifdef __ICC // icpc defines the __clang__ macro
9623# pragma warning(pop)
9624# else
9625# pragma clang diagnostic pop
9626# endif
9627#elif defined __GNUC__
9628# pragma GCC diagnostic pop
9629#endif
9630
9631
Phil Nash56d5c422012-08-23 20:08:50 +01009632namespace Catch {
Phil Nashd76e0812014-12-30 18:26:07 +00009633 class XmlReporter : public StreamingReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01009634 public:
Phil Nashd76e0812014-12-30 18:26:07 +00009635 XmlReporter( ReporterConfig const& _config )
9636 : StreamingReporterBase( _config ),
Phil Nash2be37272016-11-29 12:15:50 +00009637 m_xml(_config.stream()),
Phil Nashd76e0812014-12-30 18:26:07 +00009638 m_sectionDepth( 0 )
Phil Nashe73583d2015-08-07 17:30:34 +01009639 {
9640 m_reporterPrefs.shouldRedirectStdOut = true;
9641 }
Phil Nashd76e0812014-12-30 18:26:07 +00009642
Phil Nashe73583d2015-08-07 17:30:34 +01009643 virtual ~XmlReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +01009644
9645 static std::string getDescription() {
9646 return "Reports test results as an XML document";
9647 }
Phil Nash56d5c422012-08-23 20:08:50 +01009648
Phil Nashd76e0812014-12-30 18:26:07 +00009649 public: // StreamingReporterBase
Phil Nash56d5c422012-08-23 20:08:50 +01009650
Phil Nashe73583d2015-08-07 17:30:34 +01009651 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009652 StreamingReporterBase::noMatchingTestCases( s );
9653 }
9654
Phil Nashe73583d2015-08-07 17:30:34 +01009655 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009656 StreamingReporterBase::testRunStarting( testInfo );
Phil Nash56d5c422012-08-23 20:08:50 +01009657 m_xml.startElement( "Catch" );
Phil Nashd76e0812014-12-30 18:26:07 +00009658 if( !m_config->name().empty() )
9659 m_xml.writeAttribute( "name", m_config->name() );
Phil Nash56d5c422012-08-23 20:08:50 +01009660 }
9661
Phil Nashe73583d2015-08-07 17:30:34 +01009662 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009663 StreamingReporterBase::testGroupStarting( groupInfo );
Phil Nash56d5c422012-08-23 20:08:50 +01009664 m_xml.startElement( "Group" )
Phil Nashd76e0812014-12-30 18:26:07 +00009665 .writeAttribute( "name", groupInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +01009666 }
9667
Phil Nashe73583d2015-08-07 17:30:34 +01009668 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009669 StreamingReporterBase::testCaseStarting(testInfo);
Phil Nash40f60682016-09-27 10:46:22 +01009670 m_xml.startElement( "TestCase" ).writeAttribute( "name", testInfo.name );
Phil Nashd76e0812014-12-30 18:26:07 +00009671
9672 if ( m_config->showDurations() == ShowDurations::Always )
9673 m_testCaseTimer.start();
Phil Nash56d5c422012-08-23 20:08:50 +01009674 }
9675
Phil Nashe73583d2015-08-07 17:30:34 +01009676 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009677 StreamingReporterBase::sectionStarting( sectionInfo );
Phil Nash8a52a392013-07-25 08:12:03 +01009678 if( m_sectionDepth++ > 0 ) {
9679 m_xml.startElement( "Section" )
Phil Nashd76e0812014-12-30 18:26:07 +00009680 .writeAttribute( "name", trim( sectionInfo.name ) )
9681 .writeAttribute( "description", sectionInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01009682 }
Phil Nash56d5c422012-08-23 20:08:50 +01009683 }
9684
Phil Nashe73583d2015-08-07 17:30:34 +01009685 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
Phil Nash56d5c422012-08-23 20:08:50 +01009686
Phil Nashe73583d2015-08-07 17:30:34 +01009687 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009688 const AssertionResult& assertionResult = assertionStats.assertionResult;
Phil Nash56d5c422012-08-23 20:08:50 +01009689
Phil Nashd76e0812014-12-30 18:26:07 +00009690 // Print any info messages in <Info> tags.
9691 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
9692 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
9693 it != itEnd;
9694 ++it ) {
9695 if( it->type == ResultWas::Info ) {
9696 m_xml.scopedElement( "Info" )
9697 .writeText( it->message );
9698 } else if ( it->type == ResultWas::Warning ) {
9699 m_xml.scopedElement( "Warning" )
9700 .writeText( it->message );
9701 }
9702 }
9703 }
9704
9705 // Drop out if result was successful but we're not printing them.
9706 if( !m_config->includeSuccessfulResults() && isOk(assertionResult.getResultType()) )
9707 return true;
9708
9709 // Print the expression if there is one.
Phil Nashce612bf2012-11-01 08:27:09 +00009710 if( assertionResult.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009711 m_xml.startElement( "Expression" )
Phil Nash90a35942012-11-13 22:04:29 +00009712 .writeAttribute( "success", assertionResult.succeeded() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009713 .writeAttribute( "type", assertionResult.getTestMacroName() )
Phil Nashce612bf2012-11-01 08:27:09 +00009714 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9715 .writeAttribute( "line", assertionResult.getSourceInfo().line );
Phil Nash56d5c422012-08-23 20:08:50 +01009716
9717 m_xml.scopedElement( "Original" )
Phil Nashce612bf2012-11-01 08:27:09 +00009718 .writeText( assertionResult.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009719 m_xml.scopedElement( "Expanded" )
Phil Nashce612bf2012-11-01 08:27:09 +00009720 .writeText( assertionResult.getExpandedExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +01009721 }
9722
Phil Nashd76e0812014-12-30 18:26:07 +00009723 // And... Print a result applicable to each result type.
Phil Nashce612bf2012-11-01 08:27:09 +00009724 switch( assertionResult.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009725 case ResultWas::ThrewException:
9726 m_xml.scopedElement( "Exception" )
Phil Nashce612bf2012-11-01 08:27:09 +00009727 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9728 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9729 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009730 break;
Phil Nash93b61e12014-08-22 19:35:41 +01009731 case ResultWas::FatalErrorCondition:
Phil Nashe27c4ee2016-10-26 12:08:26 +01009732 m_xml.scopedElement( "FatalErrorCondition" )
Phil Nash93b61e12014-08-22 19:35:41 +01009733 .writeAttribute( "filename", assertionResult.getSourceInfo().file )
9734 .writeAttribute( "line", assertionResult.getSourceInfo().line )
9735 .writeText( assertionResult.getMessage() );
Phil Nash93b61e12014-08-22 19:35:41 +01009736 break;
Phil Nash56d5c422012-08-23 20:08:50 +01009737 case ResultWas::Info:
9738 m_xml.scopedElement( "Info" )
Phil Nashce612bf2012-11-01 08:27:09 +00009739 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009740 break;
9741 case ResultWas::Warning:
Phil Nashd76e0812014-12-30 18:26:07 +00009742 // Warning will already have been written
Phil Nash56d5c422012-08-23 20:08:50 +01009743 break;
9744 case ResultWas::ExplicitFailure:
9745 m_xml.scopedElement( "Failure" )
Phil Nashce612bf2012-11-01 08:27:09 +00009746 .writeText( assertionResult.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +01009747 break;
Phil Nashd76e0812014-12-30 18:26:07 +00009748 default:
Phil Nash56d5c422012-08-23 20:08:50 +01009749 break;
9750 }
Phil Nashd76e0812014-12-30 18:26:07 +00009751
Phil Nashce612bf2012-11-01 08:27:09 +00009752 if( assertionResult.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +01009753 m_xml.endElement();
Phil Nashd76e0812014-12-30 18:26:07 +00009754
9755 return true;
Phil Nash56d5c422012-08-23 20:08:50 +01009756 }
9757
Phil Nashe73583d2015-08-07 17:30:34 +01009758 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009759 StreamingReporterBase::sectionEnded( sectionStats );
9760 if( --m_sectionDepth > 0 ) {
9761 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
9762 e.writeAttribute( "successes", sectionStats.assertions.passed );
9763 e.writeAttribute( "failures", sectionStats.assertions.failed );
9764 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
9765
9766 if ( m_config->showDurations() == ShowDurations::Always )
9767 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
9768
9769 m_xml.endElement();
9770 }
Phil Nash56d5c422012-08-23 20:08:50 +01009771 }
9772
Phil Nashe73583d2015-08-07 17:30:34 +01009773 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009774 StreamingReporterBase::testCaseEnded( testCaseStats );
9775 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
9776 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
9777
9778 if ( m_config->showDurations() == ShowDurations::Always )
9779 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
9780
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009781 if( !testCaseStats.stdOut.empty() )
9782 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
9783 if( !testCaseStats.stdErr.empty() )
9784 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
9785
Phil Nashd76e0812014-12-30 18:26:07 +00009786 m_xml.endElement();
9787 }
9788
Phil Nashe73583d2015-08-07 17:30:34 +01009789 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009790 StreamingReporterBase::testGroupEnded( testGroupStats );
9791 // TODO: Check testGroupStats.aborting and act accordingly.
9792 m_xml.scopedElement( "OverallResults" )
9793 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
9794 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
9795 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
9796 m_xml.endElement();
9797 }
9798
Phil Nashe73583d2015-08-07 17:30:34 +01009799 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +00009800 StreamingReporterBase::testRunEnded( testRunStats );
9801 m_xml.scopedElement( "OverallResults" )
9802 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
9803 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
9804 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
Phil Nash56d5c422012-08-23 20:08:50 +01009805 m_xml.endElement();
9806 }
9807
9808 private:
Phil Nashd76e0812014-12-30 18:26:07 +00009809 Timer m_testCaseTimer;
Phil Nash56d5c422012-08-23 20:08:50 +01009810 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +01009811 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +01009812 };
9813
Phil Nashd76e0812014-12-30 18:26:07 +00009814 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
9815
Phil Nash56d5c422012-08-23 20:08:50 +01009816} // end namespace Catch
9817
9818// #included from: ../reporters/catch_reporter_junit.hpp
9819#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
9820
Phil Nashf276a052012-12-02 00:05:51 +00009821#include <assert.h>
9822
Phil Nash56d5c422012-08-23 20:08:50 +01009823namespace Catch {
9824
Martin Hořeňovský9a566092017-01-20 12:49:59 +01009825 namespace {
9826 std::string getCurrentTimestamp() {
9827 // Beware, this is not reentrant because of backward compatibility issues
9828 // Also, UTC only, again because of backward compatibility (%z is C++11)
9829 time_t rawtime;
9830 std::time(&rawtime);
9831 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
9832
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009833#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +01009834 std::tm timeInfo = {};
9835 gmtime_s(&timeInfo, &rawtime);
9836#else
9837 std::tm* timeInfo;
9838 timeInfo = std::gmtime(&rawtime);
9839#endif
9840
9841 char timeStamp[timeStampSize];
9842 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
9843
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01009844#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +01009845 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
9846#else
9847 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
9848#endif
9849 return std::string(timeStamp);
9850 }
9851
9852 }
9853
Phil Nashaa7123b2013-08-15 19:01:00 +01009854 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +01009855 public:
Phil Nashaa7123b2013-08-15 19:01:00 +01009856 JunitReporter( ReporterConfig const& _config )
9857 : CumulativeReporterBase( _config ),
9858 xml( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009859 {
9860 m_reporterPrefs.shouldRedirectStdOut = true;
9861 }
Phil Nashaa7123b2013-08-15 19:01:00 +01009862
Phil Nashe73583d2015-08-07 17:30:34 +01009863 virtual ~JunitReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +01009864
9865 static std::string getDescription() {
9866 return "Reports test results in an XML format that looks like Ant's junitreport target";
9867 }
9868
Phil Nashe73583d2015-08-07 17:30:34 +01009869 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
Phil Nash56d5c422012-08-23 20:08:50 +01009870
Phil Nashe73583d2015-08-07 17:30:34 +01009871 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009872 CumulativeReporterBase::testRunStarting( runInfo );
9873 xml.startElement( "testsuites" );
9874 }
Phil Nash56d5c422012-08-23 20:08:50 +01009875
Phil Nashe73583d2015-08-07 17:30:34 +01009876 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009877 suiteTimer.start();
9878 stdOutForSuite.str("");
9879 stdErrForSuite.str("");
9880 unexpectedExceptions = 0;
9881 CumulativeReporterBase::testGroupStarting( groupInfo );
9882 }
9883
Phil Nashe73583d2015-08-07 17:30:34 +01009884 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009885 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException )
9886 unexpectedExceptions++;
9887 return CumulativeReporterBase::assertionEnded( assertionStats );
9888 }
9889
Phil Nashe73583d2015-08-07 17:30:34 +01009890 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009891 stdOutForSuite << testCaseStats.stdOut;
9892 stdErrForSuite << testCaseStats.stdErr;
9893 CumulativeReporterBase::testCaseEnded( testCaseStats );
9894 }
9895
Phil Nashe73583d2015-08-07 17:30:34 +01009896 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009897 double suiteTime = suiteTimer.getElapsedSeconds();
9898 CumulativeReporterBase::testGroupEnded( testGroupStats );
9899 writeGroup( *m_testGroups.back(), suiteTime );
9900 }
9901
Phil Nashe73583d2015-08-07 17:30:34 +01009902 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +01009903 xml.endElement();
9904 }
9905
9906 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
9907 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
9908 TestGroupStats const& stats = groupNode.value;
9909 xml.writeAttribute( "name", stats.groupInfo.name );
9910 xml.writeAttribute( "errors", unexpectedExceptions );
9911 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
9912 xml.writeAttribute( "tests", stats.totals.assertions.total() );
9913 xml.writeAttribute( "hostname", "tbd" ); // !TBD
9914 if( m_config->showDurations() == ShowDurations::Never )
9915 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +00009916 else
Phil Nashaa7123b2013-08-15 19:01:00 +01009917 xml.writeAttribute( "time", suiteTime );
Martin Hořeňovský9a566092017-01-20 12:49:59 +01009918 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
Phil Nashaa7123b2013-08-15 19:01:00 +01009919
9920 // Write test cases
9921 for( TestGroupNode::ChildNodes::const_iterator
9922 it = groupNode.children.begin(), itEnd = groupNode.children.end();
9923 it != itEnd;
9924 ++it )
9925 writeTestCase( **it );
9926
9927 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
9928 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +01009929 }
9930
Phil Nashaa7123b2013-08-15 19:01:00 +01009931 void writeTestCase( TestCaseNode const& testCaseNode ) {
9932 TestCaseStats const& stats = testCaseNode.value;
9933
9934 // All test cases have exactly one section - which represents the
9935 // test case itself. That section may have 0-n nested sections
9936 assert( testCaseNode.children.size() == 1 );
9937 SectionNode const& rootSection = *testCaseNode.children.front();
9938
9939 std::string className = stats.testInfo.className;
9940
9941 if( className.empty() ) {
9942 if( rootSection.childSections.empty() )
9943 className = "global";
9944 }
9945 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +01009946 }
9947
Phil Nashaa7123b2013-08-15 19:01:00 +01009948 void writeSection( std::string const& className,
9949 std::string const& rootName,
9950 SectionNode const& sectionNode ) {
9951 std::string name = trim( sectionNode.stats.sectionInfo.name );
9952 if( !rootName.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009953 name = rootName + '/' + name;
Phil Nash56d5c422012-08-23 20:08:50 +01009954
Phil Nashaa7123b2013-08-15 19:01:00 +01009955 if( !sectionNode.assertions.empty() ||
9956 !sectionNode.stdOut.empty() ||
9957 !sectionNode.stdErr.empty() ) {
9958 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
9959 if( className.empty() ) {
9960 xml.writeAttribute( "classname", name );
9961 xml.writeAttribute( "name", "root" );
9962 }
9963 else {
9964 xml.writeAttribute( "classname", className );
9965 xml.writeAttribute( "name", name );
9966 }
Phil Nash13f98432014-12-12 08:11:18 +00009967 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +01009968
Phil Nashaa7123b2013-08-15 19:01:00 +01009969 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +01009970
Phil Nashaa7123b2013-08-15 19:01:00 +01009971 if( !sectionNode.stdOut.empty() )
9972 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
9973 if( !sectionNode.stdErr.empty() )
9974 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
9975 }
9976 for( SectionNode::ChildSections::const_iterator
9977 it = sectionNode.childSections.begin(),
9978 itEnd = sectionNode.childSections.end();
9979 it != itEnd;
9980 ++it )
9981 if( className.empty() )
9982 writeSection( name, "", **it );
9983 else
9984 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +01009985 }
9986
Phil Nashaa7123b2013-08-15 19:01:00 +01009987 void writeAssertions( SectionNode const& sectionNode ) {
9988 for( SectionNode::Assertions::const_iterator
9989 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
9990 it != itEnd;
9991 ++it )
9992 writeAssertion( *it );
9993 }
9994 void writeAssertion( AssertionStats const& stats ) {
9995 AssertionResult const& result = stats.assertionResult;
9996 if( !result.isOk() ) {
9997 std::string elementName;
9998 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009999 case ResultWas::ThrewException:
Phil Nash93b61e12014-08-22 19:35:41 +010010000 case ResultWas::FatalErrorCondition:
Phil Nashaa7123b2013-08-15 19:01:00 +010010001 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +010010002 break;
10003 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +010010004 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010005 break;
10006 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +010010007 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010008 break;
Phil Nash243f2d22013-04-12 10:43:06 +010010009 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +010010010 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +010010011 break;
Phil Nashaa7123b2013-08-15 19:01:00 +010010012
10013 // We should never see these here:
10014 case ResultWas::Info:
10015 case ResultWas::Warning:
10016 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +010010017 case ResultWas::Unknown:
10018 case ResultWas::FailureBit:
10019 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +010010020 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +010010021 break;
10022 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010023
10024 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10025
10026 xml.writeAttribute( "message", result.getExpandedExpression() );
10027 xml.writeAttribute( "type", result.getTestMacroName() );
10028
10029 std::ostringstream oss;
10030 if( !result.getMessage().empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010031 oss << result.getMessage() << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010032 for( std::vector<MessageInfo>::const_iterator
10033 it = stats.infoMessages.begin(),
10034 itEnd = stats.infoMessages.end();
10035 it != itEnd;
10036 ++it )
10037 if( it->type == ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010038 oss << it->message << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010039
10040 oss << "at " << result.getSourceInfo();
10041 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +010010042 }
10043 }
10044
Phil Nashaa7123b2013-08-15 19:01:00 +010010045 XmlWriter xml;
10046 Timer suiteTimer;
10047 std::ostringstream stdOutForSuite;
10048 std::ostringstream stdErrForSuite;
10049 unsigned int unexpectedExceptions;
Phil Nash56d5c422012-08-23 20:08:50 +010010050 };
10051
Phil Nashaa7123b2013-08-15 19:01:00 +010010052 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
10053
Phil Nash56d5c422012-08-23 20:08:50 +010010054} // end namespace Catch
10055
Phil Nashff03cdf2012-12-06 08:44:51 +000010056// #included from: ../reporters/catch_reporter_console.hpp
10057#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
10058
10059namespace Catch {
10060
Phil Nash2e7d9662013-01-16 09:44:43 +000010061 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +000010062 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +000010063 : StreamingReporterBase( _config ),
Phil Nash08e52962014-07-03 19:08:44 +010010064 m_headerPrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +000010065 {}
10066
Phil Nashe73583d2015-08-07 17:30:34 +010010067 virtual ~ConsoleReporter() CATCH_OVERRIDE;
Phil Nashff03cdf2012-12-06 08:44:51 +000010068 static std::string getDescription() {
10069 return "Reports test results as plain lines of text";
10070 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010071
Phil Nashe73583d2015-08-07 17:30:34 +010010072 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010073 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash37186a12013-03-13 12:19:30 +000010074 }
10075
Phil Nashe73583d2015-08-07 17:30:34 +010010076 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
Phil Nashff03cdf2012-12-06 08:44:51 +000010077 }
Phil Nashbcad0932012-12-10 08:54:57 +000010078
Phil Nashe73583d2015-08-07 17:30:34 +010010079 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010080 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +000010081
Phil Nash8d44f2d2013-11-13 08:10:45 +000010082 bool printInfoMessages = true;
10083
Phil Nashbcad0932012-12-10 08:54:57 +000010084 // Drop out if result was successful and we're not printing those
Phil Nash8d44f2d2013-11-13 08:10:45 +000010085 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10086 if( result.getResultType() != ResultWas::Warning )
10087 return false;
10088 printInfoMessages = false;
10089 }
Phil Nashbcad0932012-12-10 08:54:57 +000010090
10091 lazyPrint();
10092
Phil Nash8d44f2d2013-11-13 08:10:45 +000010093 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
Phil Nashe4756452013-01-26 20:18:30 +000010094 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +000010095 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +010010096 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010097 }
10098
Phil Nashe73583d2015-08-07 17:30:34 +010010099 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nasha04981b2013-03-08 09:30:25 +000010100 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +000010101 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +000010102 }
Phil Nashe73583d2015-08-07 17:30:34 +010010103 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010104 if( _sectionStats.missingAssertions ) {
10105 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +010010106 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +010010107 if( m_sectionStack.size() > 1 )
10108 stream << "\nNo assertions in section";
10109 else
10110 stream << "\nNo assertions in test case";
10111 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010112 }
Phil Nash46118712013-08-16 19:01:32 +010010113 if( m_headerPrinted ) {
10114 if( m_config->showDurations() == ShowDurations::Always )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010115 stream << "Completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
Phil Nash46118712013-08-16 19:01:32 +010010116 m_headerPrinted = false;
10117 }
Phil Nashf7378ee2013-09-07 12:07:38 +010010118 else {
10119 if( m_config->showDurations() == ShowDurations::Always )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010120 stream << _sectionStats.sectionInfo.name << " completed in " << _sectionStats.durationInSeconds << 's' << std::endl;
Phil Nashf7378ee2013-09-07 12:07:38 +010010121 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010122 StreamingReporterBase::sectionEnded( _sectionStats );
10123 }
10124
Phil Nashe73583d2015-08-07 17:30:34 +010010125 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010126 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +000010127 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +000010128 }
Phil Nashe73583d2015-08-07 17:30:34 +010010129 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010130 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +000010131 printSummaryDivider();
10132 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
10133 printTotals( _testGroupStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010134 stream << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010135 }
10136 StreamingReporterBase::testGroupEnded( _testGroupStats );
10137 }
Phil Nashe73583d2015-08-07 17:30:34 +010010138 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
Phil Nash52e1e742014-07-03 08:11:38 +010010139 printTotalsDivider( _testRunStats.totals );
Phil Nash2e7d9662013-01-16 09:44:43 +000010140 printTotals( _testRunStats.totals );
Phil Nash52e1e742014-07-03 08:11:38 +010010141 stream << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010142 StreamingReporterBase::testRunEnded( _testRunStats );
10143 }
10144
10145 private:
Phil Nashe4756452013-01-26 20:18:30 +000010146
10147 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +010010148 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +000010149 public:
Phil Nash8d44f2d2013-11-13 08:10:45 +000010150 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010151 : stream( _stream ),
10152 stats( _stats ),
10153 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +010010154 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +000010155 message( result.getMessage() ),
Phil Nash8d44f2d2013-11-13 08:10:45 +000010156 messages( _stats.infoMessages ),
10157 printInfoMessages( _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010158 {
10159 switch( result.getResultType() ) {
10160 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +010010161 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010162 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +000010163 //if( result.hasMessage() )
10164 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010165 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010166 if( _stats.infoMessages.size() > 1 )
10167 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010168 break;
10169 case ResultWas::ExpressionFailed:
10170 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010171 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010172 passOrFail = "FAILED - but was ok";
10173 }
10174 else {
Phil Nash12c16ff2013-04-05 20:58:01 +010010175 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010176 passOrFail = "FAILED";
10177 }
Phil Nasha2773812013-02-02 20:37:58 +000010178 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010179 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010180 if( _stats.infoMessages.size() > 1 )
10181 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010182 break;
10183 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010184 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010185 passOrFail = "FAILED";
10186 messageLabel = "due to unexpected exception with message";
10187 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010188 case ResultWas::FatalErrorCondition:
10189 colour = Colour::Error;
10190 passOrFail = "FAILED";
10191 messageLabel = "due to a fatal error condition";
10192 break;
Phil Nashe4756452013-01-26 20:18:30 +000010193 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010194 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010195 passOrFail = "FAILED";
10196 messageLabel = "because no exception was thrown where one was expected";
10197 break;
10198 case ResultWas::Info:
10199 messageLabel = "info";
10200 break;
10201 case ResultWas::Warning:
10202 messageLabel = "warning";
10203 break;
10204 case ResultWas::ExplicitFailure:
10205 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +010010206 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +000010207 if( _stats.infoMessages.size() == 1 )
10208 messageLabel = "explicitly with message";
10209 if( _stats.infoMessages.size() > 1 )
10210 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010211 break;
Phil Nashe4756452013-01-26 20:18:30 +000010212 // These cases are here to prevent compiler warnings
10213 case ResultWas::Unknown:
10214 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +010010215 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +000010216 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +010010217 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010218 break;
10219 }
10220 }
10221
10222 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +010010223 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +000010224 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +010010225 if( result.isOk() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010226 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010227 printResultType();
10228 printOriginalExpression();
10229 printReconstructedExpression();
10230 }
Phil Nash767f1582013-03-04 12:19:15 +010010231 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010232 stream << '\n';
Phil Nash767f1582013-03-04 12:19:15 +010010233 }
Phil Nashe4756452013-01-26 20:18:30 +000010234 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +000010235 }
10236
10237 private:
10238 void printResultType() const {
10239 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010240 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +000010241 stream << passOrFail << ":\n";
10242 }
10243 }
10244 void printOriginalExpression() const {
10245 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010246 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +000010247 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +010010248 stream << result.getExpressionInMacro();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010249 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010250 }
10251 }
10252 void printReconstructedExpression() const {
10253 if( result.hasExpandedExpression() ) {
10254 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +010010255 Colour colourGuard( Colour::ReconstructedExpression );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010256 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010257 }
10258 }
10259 void printMessage() const {
10260 if( !messageLabel.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010261 stream << messageLabel << ':' << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010262 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
10263 it != itEnd;
10264 ++it ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010265 // If this assertion is a warning ignore any INFO messages
10266 if( printInfoMessages || it->type != ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010267 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010268 }
Phil Nashe4756452013-01-26 20:18:30 +000010269 }
10270 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +010010271 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +010010272 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +000010273 }
10274
Phil Nashe4756452013-01-26 20:18:30 +000010275 std::ostream& stream;
10276 AssertionStats const& stats;
10277 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +010010278 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +000010279 std::string passOrFail;
10280 std::string messageLabel;
10281 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +000010282 std::vector<MessageInfo> messages;
Phil Nash8d44f2d2013-11-13 08:10:45 +000010283 bool printInfoMessages;
Phil Nashe4756452013-01-26 20:18:30 +000010284 };
Phil Nash2e7d9662013-01-16 09:44:43 +000010285
10286 void lazyPrint() {
10287
Phil Nashaa7123b2013-08-15 19:01:00 +010010288 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010289 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +010010290 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010291 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +000010292
Phil Nasha04981b2013-03-08 09:30:25 +000010293 if( !m_headerPrinted ) {
10294 printTestCaseAndSectionHeader();
10295 m_headerPrinted = true;
10296 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010297 }
10298 void lazyPrintRunInfo() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010299 stream << '\n' << getLineOfChars<'~'>() << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010300 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +010010301 stream << currentTestRunInfo->name
Phil Nash21f7ef62015-06-29 18:05:23 +010010302 << " is a Catch v" << libraryVersion << " host application.\n"
Phil Nash2e7d9662013-01-16 09:44:43 +000010303 << "Run with -? for options\n\n";
10304
Phil Nash6a8e8ad2014-09-15 18:40:24 +010010305 if( m_config->rngSeed() != 0 )
10306 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
10307
Phil Nashaa7123b2013-08-15 19:01:00 +010010308 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010309 }
10310 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010311 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
10312 printClosedHeader( "Group: " + currentGroupInfo->name );
10313 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010314 }
10315 }
Phil Nasha04981b2013-03-08 09:30:25 +000010316 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010317 assert( !m_sectionStack.empty() );
10318 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +000010319
Phil Nashaa7123b2013-08-15 19:01:00 +010010320 if( m_sectionStack.size() > 1 ) {
10321 Colour colourGuard( Colour::Headers );
10322
10323 std::vector<SectionInfo>::const_iterator
10324 it = m_sectionStack.begin()+1, // Skip first section (test case)
10325 itEnd = m_sectionStack.end();
10326 for( ; it != itEnd; ++it )
10327 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +000010328 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010329
10330 SourceLineInfo lineInfo = m_sectionStack.front().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +010010331
10332 if( !lineInfo.empty() ){
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010333 stream << getLineOfChars<'-'>() << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010334 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010335 stream << lineInfo << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010336 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010337 stream << getLineOfChars<'.'>() << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010338 }
10339
Phil Nasha04981b2013-03-08 09:30:25 +000010340 void printClosedHeader( std::string const& _name ) {
10341 printOpenHeader( _name );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010342 stream << getLineOfChars<'.'>() << '\n';
Phil Nasha04981b2013-03-08 09:30:25 +000010343 }
Phil Nash19279252013-04-20 21:07:32 +010010344 void printOpenHeader( std::string const& _name ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010345 stream << getLineOfChars<'-'>() << '\n';
Phil Nash5c7d3d72013-04-01 11:27:10 +010010346 {
Phil Nash12c16ff2013-04-05 20:58:01 +010010347 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +010010348 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +010010349 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010350 }
10351
Phil Nash12c16ff2013-04-05 20:58:01 +010010352 // if string has a : in first line will set indent to follow it on
10353 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +010010354 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010355 std::size_t i = _string.find( ": " );
10356 if( i != std::string::npos )
10357 i+=2;
10358 else
10359 i = 0;
Phil Nash19279252013-04-20 21:07:32 +010010360 stream << Text( _string, TextAttributes()
10361 .setIndent( indent+i)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010362 .setInitialIndent( indent ) ) << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010363 }
10364
Phil Nash28c2e072014-07-09 19:22:49 +010010365 struct SummaryColumn {
10366
10367 SummaryColumn( std::string const& _label, Colour::Code _colour )
10368 : label( _label ),
10369 colour( _colour )
10370 {}
10371 SummaryColumn addRow( std::size_t count ) {
10372 std::ostringstream oss;
10373 oss << count;
10374 std::string row = oss.str();
10375 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
10376 while( it->size() < row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010377 *it = ' ' + *it;
Phil Nash28c2e072014-07-09 19:22:49 +010010378 while( it->size() > row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010379 row = ' ' + row;
Phil Nash28c2e072014-07-09 19:22:49 +010010380 }
10381 rows.push_back( row );
10382 return *this;
10383 }
10384
10385 std::string label;
10386 Colour::Code colour;
10387 std::vector<std::string> rows;
10388
10389 };
10390
Phil Nash52e1e742014-07-03 08:11:38 +010010391 void printTotals( Totals const& totals ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010392 if( totals.testCases.total() == 0 ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010393 stream << Colour( Colour::Warning ) << "No tests ran\n";
Phil Nash2e7d9662013-01-16 09:44:43 +000010394 }
Phil Nashc984fc32016-03-15 07:24:26 +000010395 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010396 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
10397 stream << " ("
Phil Nash2e7d9662013-01-16 09:44:43 +000010398 << pluralise( totals.assertions.passed, "assertion" ) << " in "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010399 << pluralise( totals.testCases.passed, "test case" ) << ')'
10400 << '\n';
Phil Nashbcad0932012-12-10 08:54:57 +000010401 }
Phil Nash28c2e072014-07-09 19:22:49 +010010402 else {
Phil Nash52e1e742014-07-03 08:11:38 +010010403
Phil Nash28c2e072014-07-09 19:22:49 +010010404 std::vector<SummaryColumn> columns;
10405 columns.push_back( SummaryColumn( "", Colour::None )
10406 .addRow( totals.testCases.total() )
10407 .addRow( totals.assertions.total() ) );
10408 columns.push_back( SummaryColumn( "passed", Colour::Success )
10409 .addRow( totals.testCases.passed )
10410 .addRow( totals.assertions.passed ) );
10411 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10412 .addRow( totals.testCases.failed )
10413 .addRow( totals.assertions.failed ) );
10414 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10415 .addRow( totals.testCases.failedButOk )
10416 .addRow( totals.assertions.failedButOk ) );
Phil Nash52e1e742014-07-03 08:11:38 +010010417
Phil Nash28c2e072014-07-09 19:22:49 +010010418 printSummaryRow( "test cases", columns, 0 );
10419 printSummaryRow( "assertions", columns, 1 );
Phil Nashf1178122012-12-11 09:03:14 +000010420 }
Phil Nash28c2e072014-07-09 19:22:49 +010010421 }
10422 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
10423 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
10424 std::string value = it->rows[row];
10425 if( it->label.empty() ) {
10426 stream << label << ": ";
10427 if( value != "0" )
10428 stream << value;
10429 else
10430 stream << Colour( Colour::Warning ) << "- none -";
10431 }
10432 else if( value != "0" ) {
10433 stream << Colour( Colour::LightGrey ) << " | ";
10434 stream << Colour( it->colour )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010435 << value << ' ' << it->label;
Phil Nash28c2e072014-07-09 19:22:49 +010010436 }
10437 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010438 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010439 }
10440
Phil Nash52e1e742014-07-03 08:11:38 +010010441 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
10442 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
10443 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
10444 }
10445 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
10446 if( i > j && i > k )
10447 return i;
10448 else if( j > k )
10449 return j;
10450 else
10451 return k;
10452 }
10453
10454 void printTotalsDivider( Totals const& totals ) {
10455 if( totals.testCases.total() > 0 ) {
10456 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
10457 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
10458 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
10459 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
10460 findMax( failedRatio, failedButOkRatio, passedRatio )++;
10461 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
10462 findMax( failedRatio, failedButOkRatio, passedRatio )--;
10463
Phil Nash52e1e742014-07-03 08:11:38 +010010464 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
10465 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
Phil Nash28c2e072014-07-09 19:22:49 +010010466 if( totals.testCases.allPassed() )
10467 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
10468 else
10469 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
Phil Nash52e1e742014-07-03 08:11:38 +010010470 }
10471 else {
10472 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
10473 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010474 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010475 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010476 void printSummaryDivider() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010477 stream << getLineOfChars<'-'>() << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010478 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010479
Phil Nashcf5ced52012-12-14 07:50:08 +000010480 private:
Phil Nasha04981b2013-03-08 09:30:25 +000010481 bool m_headerPrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +000010482 };
10483
10484 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
10485
10486} // end namespace Catch
10487
Phil Nash5a2df712014-05-01 19:07:02 +010010488// #included from: ../reporters/catch_reporter_compact.hpp
10489#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
10490
10491namespace Catch {
10492
10493 struct CompactReporter : StreamingReporterBase {
10494
10495 CompactReporter( ReporterConfig const& _config )
10496 : StreamingReporterBase( _config )
10497 {}
10498
10499 virtual ~CompactReporter();
10500
10501 static std::string getDescription() {
10502 return "Reports test results on a single line, suitable for IDEs";
10503 }
10504
10505 virtual ReporterPreferences getPreferences() const {
10506 ReporterPreferences prefs;
10507 prefs.shouldRedirectStdOut = false;
10508 return prefs;
10509 }
10510
10511 virtual void noMatchingTestCases( std::string const& spec ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010512 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010513 }
10514
10515 virtual void assertionStarting( AssertionInfo const& ) {
10516 }
10517
10518 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
10519 AssertionResult const& result = _assertionStats.assertionResult;
10520
10521 bool printInfoMessages = true;
10522
10523 // Drop out if result was successful and we're not printing those
10524 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10525 if( result.getResultType() != ResultWas::Warning )
10526 return false;
10527 printInfoMessages = false;
10528 }
10529
10530 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10531 printer.print();
10532
10533 stream << std::endl;
10534 return true;
10535 }
10536
10537 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10538 printTotals( _testRunStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010539 stream << '\n' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010540 StreamingReporterBase::testRunEnded( _testRunStats );
10541 }
10542
10543 private:
10544 class AssertionPrinter {
10545 void operator= ( AssertionPrinter const& );
10546 public:
10547 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10548 : stream( _stream )
10549 , stats( _stats )
10550 , result( _stats.assertionResult )
10551 , messages( _stats.infoMessages )
10552 , itMessage( _stats.infoMessages.begin() )
10553 , printInfoMessages( _printInfoMessages )
10554 {}
10555
10556 void print() {
10557 printSourceInfo();
10558
10559 itMessage = messages.begin();
10560
10561 switch( result.getResultType() ) {
10562 case ResultWas::Ok:
10563 printResultType( Colour::ResultSuccess, passedString() );
10564 printOriginalExpression();
10565 printReconstructedExpression();
10566 if ( ! result.hasExpression() )
10567 printRemainingMessages( Colour::None );
10568 else
10569 printRemainingMessages();
10570 break;
10571 case ResultWas::ExpressionFailed:
10572 if( result.isOk() )
10573 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
10574 else
10575 printResultType( Colour::Error, failedString() );
10576 printOriginalExpression();
10577 printReconstructedExpression();
10578 printRemainingMessages();
10579 break;
10580 case ResultWas::ThrewException:
10581 printResultType( Colour::Error, failedString() );
10582 printIssue( "unexpected exception with message:" );
10583 printMessage();
10584 printExpressionWas();
10585 printRemainingMessages();
10586 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010587 case ResultWas::FatalErrorCondition:
10588 printResultType( Colour::Error, failedString() );
10589 printIssue( "fatal error condition with message:" );
10590 printMessage();
10591 printExpressionWas();
10592 printRemainingMessages();
10593 break;
Phil Nash5a2df712014-05-01 19:07:02 +010010594 case ResultWas::DidntThrowException:
10595 printResultType( Colour::Error, failedString() );
10596 printIssue( "expected exception, got none" );
10597 printExpressionWas();
10598 printRemainingMessages();
10599 break;
10600 case ResultWas::Info:
10601 printResultType( Colour::None, "info" );
10602 printMessage();
10603 printRemainingMessages();
10604 break;
10605 case ResultWas::Warning:
10606 printResultType( Colour::None, "warning" );
10607 printMessage();
10608 printRemainingMessages();
10609 break;
10610 case ResultWas::ExplicitFailure:
10611 printResultType( Colour::Error, failedString() );
10612 printIssue( "explicitly" );
10613 printRemainingMessages( Colour::None );
10614 break;
10615 // These cases are here to prevent compiler warnings
10616 case ResultWas::Unknown:
10617 case ResultWas::FailureBit:
10618 case ResultWas::Exception:
10619 printResultType( Colour::Error, "** internal error **" );
10620 break;
10621 }
10622 }
10623
10624 private:
10625 // Colour::LightGrey
10626
Phil Nash9241e432014-05-20 18:50:59 +010010627 static Colour::Code dimColour() { return Colour::FileName; }
Phil Nash5a2df712014-05-01 19:07:02 +010010628
10629#ifdef CATCH_PLATFORM_MAC
10630 static const char* failedString() { return "FAILED"; }
10631 static const char* passedString() { return "PASSED"; }
10632#else
10633 static const char* failedString() { return "failed"; }
10634 static const char* passedString() { return "passed"; }
10635#endif
10636
10637 void printSourceInfo() const {
10638 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010639 stream << result.getSourceInfo() << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010640 }
10641
Phil Nash9241e432014-05-20 18:50:59 +010010642 void printResultType( Colour::Code colour, std::string passOrFail ) const {
Phil Nash5a2df712014-05-01 19:07:02 +010010643 if( !passOrFail.empty() ) {
10644 {
10645 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010646 stream << ' ' << passOrFail;
Phil Nash5a2df712014-05-01 19:07:02 +010010647 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010648 stream << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010649 }
10650 }
10651
10652 void printIssue( std::string issue ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010653 stream << ' ' << issue;
Phil Nash5a2df712014-05-01 19:07:02 +010010654 }
10655
10656 void printExpressionWas() {
10657 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010658 stream << ';';
Phil Nash5a2df712014-05-01 19:07:02 +010010659 {
10660 Colour colour( dimColour() );
10661 stream << " expression was:";
10662 }
10663 printOriginalExpression();
10664 }
10665 }
10666
10667 void printOriginalExpression() const {
10668 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010669 stream << ' ' << result.getExpression();
Phil Nash5a2df712014-05-01 19:07:02 +010010670 }
10671 }
10672
10673 void printReconstructedExpression() const {
10674 if( result.hasExpandedExpression() ) {
10675 {
10676 Colour colour( dimColour() );
10677 stream << " for: ";
10678 }
10679 stream << result.getExpandedExpression();
10680 }
10681 }
10682
10683 void printMessage() {
10684 if ( itMessage != messages.end() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010685 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010010686 ++itMessage;
10687 }
10688 }
10689
Phil Nash9241e432014-05-20 18:50:59 +010010690 void printRemainingMessages( Colour::Code colour = dimColour() ) {
Phil Nash5a2df712014-05-01 19:07:02 +010010691 if ( itMessage == messages.end() )
10692 return;
10693
10694 // using messages.end() directly yields compilation error:
10695 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
10696 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
10697
10698 {
10699 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010700 stream << " with " << pluralise( N, "message" ) << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010010701 }
10702
10703 for(; itMessage != itEnd; ) {
10704 // If this assertion is a warning ignore any INFO messages
10705 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010706 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010010707 if ( ++itMessage != itEnd ) {
10708 Colour colourGuard( dimColour() );
10709 stream << " and";
10710 }
10711 }
10712 }
10713 }
10714
10715 private:
10716 std::ostream& stream;
10717 AssertionStats const& stats;
10718 AssertionResult const& result;
10719 std::vector<MessageInfo> messages;
10720 std::vector<MessageInfo>::const_iterator itMessage;
10721 bool printInfoMessages;
10722 };
10723
10724 // Colour, message variants:
10725 // - white: No tests ran.
10726 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
10727 // - white: Passed [both/all] N test cases (no assertions).
10728 // - red: Failed N tests cases, failed M assertions.
10729 // - green: Passed [both/all] N tests cases with M assertions.
10730
10731 std::string bothOrAll( std::size_t count ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010732 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
Phil Nash5a2df712014-05-01 19:07:02 +010010733 }
10734
10735 void printTotals( const Totals& totals ) const {
10736 if( totals.testCases.total() == 0 ) {
10737 stream << "No tests ran.";
10738 }
10739 else if( totals.testCases.failed == totals.testCases.total() ) {
10740 Colour colour( Colour::ResultError );
10741 const std::string qualify_assertions_failed =
10742 totals.assertions.failed == totals.assertions.total() ?
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010743 bothOrAll( totals.assertions.failed ) : std::string();
Phil Nash5a2df712014-05-01 19:07:02 +010010744 stream <<
10745 "Failed " << bothOrAll( totals.testCases.failed )
10746 << pluralise( totals.testCases.failed, "test case" ) << ", "
10747 "failed " << qualify_assertions_failed <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010748 pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010010749 }
10750 else if( totals.assertions.total() == 0 ) {
10751 stream <<
10752 "Passed " << bothOrAll( totals.testCases.total() )
10753 << pluralise( totals.testCases.total(), "test case" )
10754 << " (no assertions).";
10755 }
10756 else if( totals.assertions.failed ) {
10757 Colour colour( Colour::ResultError );
10758 stream <<
10759 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010760 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010010761 }
10762 else {
10763 Colour colour( Colour::ResultSuccess );
10764 stream <<
10765 "Passed " << bothOrAll( totals.testCases.passed )
10766 << pluralise( totals.testCases.passed, "test case" ) <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010767 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010010768 }
10769 }
10770 };
10771
10772 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
10773
10774} // end namespace Catch
10775
Phil Nasha695eb92012-08-13 07:46:10 +010010776namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +000010777 // These are all here to avoid warnings about not having any out of line
10778 // virtual methods
Phil Nasha695eb92012-08-13 07:46:10 +010010779 NonCopyable::~NonCopyable() {}
10780 IShared::~IShared() {}
Phil Nash7e346192015-11-03 08:00:43 +000010781 IStream::~IStream() CATCH_NOEXCEPT {}
Phil Nashece529a2015-11-03 17:37:43 +000010782 FileStream::~FileStream() CATCH_NOEXCEPT {}
10783 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
10784 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
Phil Nashd7e17902014-04-18 08:49:35 +010010785 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
Phil Nasha695eb92012-08-13 07:46:10 +010010786 IContext::~IContext() {}
10787 IResultCapture::~IResultCapture() {}
10788 ITestCase::~ITestCase() {}
10789 ITestCaseRegistry::~ITestCaseRegistry() {}
10790 IRegistryHub::~IRegistryHub() {}
10791 IMutableRegistryHub::~IMutableRegistryHub() {}
10792 IExceptionTranslator::~IExceptionTranslator() {}
10793 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
10794 IReporter::~IReporter() {}
10795 IReporterFactory::~IReporterFactory() {}
10796 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010797 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010798 AssertionStats::~AssertionStats() {}
10799 SectionStats::~SectionStats() {}
10800 TestCaseStats::~TestCaseStats() {}
10801 TestGroupStats::~TestGroupStats() {}
10802 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +010010803 CumulativeReporterBase::SectionNode::~SectionNode() {}
10804 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000010805
Phil Nash2e7d9662013-01-16 09:44:43 +000010806 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +000010807 ConsoleReporter::~ConsoleReporter() {}
Phil Nash5a2df712014-05-01 19:07:02 +010010808 CompactReporter::~CompactReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +010010809 IRunner::~IRunner() {}
10810 IMutableContext::~IMutableContext() {}
10811 IConfig::~IConfig() {}
10812 XmlReporter::~XmlReporter() {}
10813 JunitReporter::~JunitReporter() {}
10814 TestRegistry::~TestRegistry() {}
10815 FreeFunctionTestCase::~FreeFunctionTestCase() {}
10816 IGeneratorInfo::~IGeneratorInfo() {}
10817 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash8342ae82015-07-13 15:03:26 +010010818 WildcardPattern::~WildcardPattern() {}
Phil Nash65cc14c2014-05-16 18:54:48 +010010819 TestSpec::Pattern::~Pattern() {}
10820 TestSpec::NamePattern::~NamePattern() {}
10821 TestSpec::TagPattern::~TagPattern() {}
10822 TestSpec::ExcludedPattern::~ExcludedPattern() {}
Phil Nasha695eb92012-08-13 07:46:10 +010010823
Phil Nash9444bbc2012-10-12 07:58:17 +010010824 Matchers::Impl::StdString::Equals::~Equals() {}
10825 Matchers::Impl::StdString::Contains::~Contains() {}
10826 Matchers::Impl::StdString::StartsWith::~StartsWith() {}
10827 Matchers::Impl::StdString::EndsWith::~EndsWith() {}
10828
Phil Nasha695eb92012-08-13 07:46:10 +010010829 void Config::dummy() {}
Phil Nash7e346192015-11-03 08:00:43 +000010830
10831 namespace TestCaseTracking {
10832 ITracker::~ITracker() {}
10833 TrackerBase::~TrackerBase() {}
10834 SectionTracker::~SectionTracker() {}
10835 IndexTracker::~IndexTracker() {}
10836 }
Phil Nasha695eb92012-08-13 07:46:10 +010010837}
10838
Phil Nash5bc030d2012-08-16 18:48:50 +010010839#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +010010840#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +010010841#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -040010842
Phil Nash9abb2762014-03-06 21:53:34 +000010843#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010844
Phil Nashde49ec42013-12-04 20:25:14 +000010845#ifdef CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +010010846// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +010010847#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010848
Phil Nash176eb812012-05-11 08:17:16 +010010849#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +010010850
Phil Nash176eb812012-05-11 08:17:16 +010010851// Standard C/C++ main entry point
Phil Nash981347b2015-12-09 18:11:48 +000010852int main (int argc, char * argv[]) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010853 int result = Catch::Session().run( argc, argv );
10854 return ( result < 0xff ? result : 0xff );
Phil Nash176eb812012-05-11 08:17:16 +010010855}
10856
10857#else // __OBJC__
10858
10859// Objective-C entry point
10860int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +000010861#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010862 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +000010863#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010864
10865 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +010010866 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +010010867
Phil Nash53c990a2012-03-17 18:20:06 +000010868#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010010869 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +000010870#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010871
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010872 return ( result < 0xff ? result : 0xff );
Phil Nash89d1e6c2011-05-24 08:23:02 +010010873}
10874
Phil Nash176eb812012-05-11 08:17:16 +010010875#endif // __OBJC__
10876
Phil Nash9abb2762014-03-06 21:53:34 +000010877#endif
10878
10879#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
10880# undef CLARA_CONFIG_MAIN
10881#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010010882
Phil Nash89d1e6c2011-05-24 08:23:02 +010010883//////
10884
Phil Nash46bcd4b2012-07-20 18:43:48 +010010885// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
10886#ifdef CATCH_CONFIG_PREFIX_ALL
10887
Phil Nash90a35942012-11-13 22:04:29 +000010888#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010010889#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 +010010890
Phil Nash93a842e2015-07-13 06:36:07 +010010891#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "CATCH_REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010892#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 +010010893#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 +000010894#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010895
Phil Nash90a35942012-11-13 22:04:29 +000010896#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010010897#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 +000010898#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_IF" )
10899#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECKED_ELSE" )
10900#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 +010010901
Phil Nash3b2f2062017-01-11 16:43:56 +000010902#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CATCH_CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010903#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 +010010904#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 +000010905#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_NOTHROW" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010906
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010907#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CATCH_CHECK_THAT" )
Phil Nash90a35942012-11-13 22:04:29 +000010908#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "CATCH_REQUIRE_THAT" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010909
Phil Nasha2773812013-02-02 20:37:58 +000010910#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000010911#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "CATCH_WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010912#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "CATCH_INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000010913#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010914#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CATCH_CAPTURE" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010915
Phil Nash93906752013-03-16 20:21:51 +000010916#ifdef CATCH_CONFIG_VARIADIC_MACROS
10917 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010010918 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010919 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000010920 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010921 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000010922 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000010923 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010924#else
10925 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010010926 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010927 #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 +000010928 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010929 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000010930 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000010931 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "CATCH_SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000010932#endif
10933#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010934
10935#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000010936#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +010010937
10938#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
10939
Phil Nash37186a12013-03-13 12:19:30 +000010940// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000010941#ifdef CATCH_CONFIG_VARIADIC_MACROS
10942#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010010943#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000010944#else
Phil Nash37186a12013-03-13 12:19:30 +000010945#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010010946#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000010947#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010010948#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
10949#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
10950#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
10951#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
10952#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000010953
Phil Nash46bcd4b2012-07-20 18:43:48 +010010954// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
10955#else
10956
Phil Nash90a35942012-11-13 22:04:29 +000010957#define REQUIRE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal, "REQUIRE" )
Phil Nashab036682014-06-02 07:48:03 +010010958#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, "REQUIRE_FALSE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010959
Phil Nash93a842e2015-07-13 06:36:07 +010010960#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, "", "REQUIRE_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010961#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 +010010962#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::Normal, matcher, "REQUIRE_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010963#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::Normal, "REQUIRE_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010964
Phil Nash90a35942012-11-13 22:04:29 +000010965#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
Phil Nashab036682014-06-02 07:48:03 +010010966#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, "CHECK_FALSE" )
Phil Nash90a35942012-11-13 22:04:29 +000010967#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_IF" )
10968#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECKED_ELSE" )
10969#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, "CHECK_NOFAIL" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010970
Phil Nash93a842e2015-07-13 06:36:07 +010010971#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, "", "CHECK_THROWS" )
Phil Nash90a35942012-11-13 22:04:29 +000010972#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 +010010973#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( expr, Catch::ResultDisposition::ContinueOnFailure, matcher, "CHECK_THROWS_WITH" )
Phil Nash90a35942012-11-13 22:04:29 +000010974#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK_NOTHROW" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010975
Phil Nash90a35942012-11-13 22:04:29 +000010976#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::ContinueOnFailure, "CHECK_THAT" )
10977#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( arg, matcher, Catch::ResultDisposition::Normal, "REQUIRE_THAT" )
Phil Nash78d95a02012-03-04 21:22:36 +000010978
Phil Nasha2773812013-02-02 20:37:58 +000010979#define INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nash859760a2013-12-14 14:34:05 +000010980#define WARN( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, "WARN", msg )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010981#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( msg, "INFO" )
Phil Nasha2773812013-02-02 20:37:58 +000010982#define CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nashb5fd5a62013-06-28 17:09:57 +010010983#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( #msg " := " << msg, "CAPTURE" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010010984
Phil Nash93906752013-03-16 20:21:51 +000010985#ifdef CATCH_CONFIG_VARIADIC_MACROS
10986 #define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010010987 #define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010988 #define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000010989 #define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010990 #define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000010991 #define FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", __VA_ARGS__ )
Phil Nash66d641a2013-12-14 23:16:44 +000010992 #define SUCCEED( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000010993#else
10994 #define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010010995 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010996 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash7424b232015-12-28 15:07:32 +000010997 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
Phil Nash93906752013-03-16 20:21:51 +000010998 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Phil Nash859760a2013-12-14 14:34:05 +000010999 #define FAIL( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "FAIL", msg )
Phil Nash66d641a2013-12-14 23:16:44 +000011000 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, "SUCCEED", msg )
Phil Nash93906752013-03-16 20:21:51 +000011001#endif
11002#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011003
11004#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000011005#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011006
11007#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11008
Phil Nash46bcd4b2012-07-20 18:43:48 +010011009#endif
11010
11011#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011012
Phil Nash37186a12013-03-13 12:19:30 +000011013// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000011014#ifdef CATCH_CONFIG_VARIADIC_MACROS
11015#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010011016#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000011017#else
Phil Nash37186a12013-03-13 12:19:30 +000011018#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010011019#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000011020#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010011021#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
11022#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
11023#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
11024#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
11025#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000011026
Phil Nash89d1e6c2011-05-24 08:23:02 +010011027using Catch::Detail::Approx;
11028
Phil Nashaec1e5e2012-05-09 19:37:51 +010011029#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011030