blob: f0d5e756cf42e26e30034be1b033b08a1b5ad0b4 [file] [log] [blame]
Phil Nash89d1e6c2011-05-24 08:23:02 +01001/*
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002 * Catch v1.9.2
3 * Generated: 2017-04-25 10:41:53.040184
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"
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020043# pragma GCC diagnostic ignored "-Wparentheses"
Phil Nash0952b762017-02-28 14:19:09 +000044
Phil Nasha806c3e2015-03-04 08:23:40 +000045# pragma GCC diagnostic push
46# pragma GCC diagnostic ignored "-Wpadded"
Phil Nash5bc030d2012-08-16 18:48:50 +010047#endif
Phil Nash576aff62014-12-21 00:21:23 +000048#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)
49# define CATCH_IMPL
Phil Nashf9df35b2014-03-10 18:02:18 +000050#endif
51
Phil Nash576aff62014-12-21 00:21:23 +000052#ifdef CATCH_IMPL
Phil Nash9abb2762014-03-06 21:53:34 +000053# ifndef CLARA_CONFIG_MAIN
54# define CLARA_CONFIG_MAIN_NOT_DEFINED
55# define CLARA_CONFIG_MAIN
56# endif
57#endif
58
Phil Nash3b80af72012-08-09 07:47:30 +010059// #included from: internal/catch_notimplemented_exception.h
60#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010061
Phil Nash89d1e6c2011-05-24 08:23:02 +010062// #included from: catch_common.h
Phil Nash3b80af72012-08-09 07:47:30 +010063#define TWOBLUECUBES_CATCH_COMMON_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010064
Phil Nash8defc712013-04-24 19:10:02 +010065// #included from: catch_compiler_capabilities.h
66#define TWOBLUECUBES_CATCH_COMPILER_CAPABILITIES_HPP_INCLUDED
67
Phil Nash318c9362015-05-19 18:40:00 +010068// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
69// The following features are defined:
70//
71// CATCH_CONFIG_CPP11_NULLPTR : is nullptr supported?
72// CATCH_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
73// CATCH_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
74// CATCH_CONFIG_CPP11_IS_ENUM : std::is_enum is supported?
75// CATCH_CONFIG_CPP11_TUPLE : std::tuple is supported
Phil Nash2f6371f2015-07-23 23:06:26 +010076// CATCH_CONFIG_CPP11_LONG_LONG : is long long supported?
Phil Nashe73583d2015-08-07 17:30:34 +010077// CATCH_CONFIG_CPP11_OVERRIDE : is override supported?
Phil Nashd234ed12015-08-24 06:28:25 +010078// CATCH_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010079// CATCH_CONFIG_CPP11_SHUFFLE : is std::shuffle supported?
80// CATCH_CONFIG_CPP11_TYPE_TRAITS : are type_traits and enable_if supported?
Phil Nash318c9362015-05-19 18:40:00 +010081
82// CATCH_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
83
Phil Nash318c9362015-05-19 18:40:00 +010084// CATCH_CONFIG_VARIADIC_MACROS : are variadic macros supported?
Phil Nashc984fc32016-03-15 07:24:26 +000085// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010086// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?
Phil Nash0952b762017-02-28 14:19:09 +000087// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?
Phil Nashd234ed12015-08-24 06:28:25 +010088// ****************
89// Note to maintainers: if new toggles are added please document them
90// in configuration.md, too
91// ****************
92
Phil Nash3b18d9e2015-06-30 18:26:09 +010093// In general each macro has a _NO_<feature name> form
94// (e.g. CATCH_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
95// Many features, at point of detection, define an _INTERNAL_ macro, so they
96// can be combined, en-mass, with the _NO_ forms later.
97
98// All the C++11 features can be disabled with CATCH_CONFIG_NO_CPP11
Phil Nash8defc712013-04-24 19:10:02 +010099
Phil Nashac220282016-06-09 08:19:23 +0100100#ifdef __cplusplus
101
102# if __cplusplus >= 201103L
103# define CATCH_CPP11_OR_GREATER
104# endif
105
106# if __cplusplus >= 201402L
107# define CATCH_CPP14_OR_GREATER
108# endif
109
Phil Nashae5ee2c2016-02-29 08:17:18 +0000110#endif
111
Phil Nash859760a2013-12-14 14:34:05 +0000112#ifdef __clang__
Phil Nash859760a2013-12-14 14:34:05 +0000113
Phil Nash17404952014-04-23 18:19:49 +0100114# if __has_feature(cxx_nullptr)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100115# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash17404952014-04-23 18:19:49 +0100116# endif
Phil Nash859760a2013-12-14 14:34:05 +0000117
Phil Nash17404952014-04-23 18:19:49 +0100118# if __has_feature(cxx_noexcept)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100119# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash17404952014-04-23 18:19:49 +0100120# endif
Phil Nash859760a2013-12-14 14:34:05 +0000121
Phil Nashae5ee2c2016-02-29 08:17:18 +0000122# if defined(CATCH_CPP11_OR_GREATER)
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200123# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
124 _Pragma( "clang diagnostic push" ) \
125 _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" )
126# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
127 _Pragma( "clang diagnostic pop" )
128
Phil Nash0952b762017-02-28 14:19:09 +0000129# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
130 _Pragma( "clang diagnostic push" ) \
131 _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )
132# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
133 _Pragma( "clang diagnostic pop" )
Phil Nashae5ee2c2016-02-29 08:17:18 +0000134# endif
135
Phil Nash859760a2013-12-14 14:34:05 +0000136#endif // __clang__
137
Phil Nash8defc712013-04-24 19:10:02 +0100138////////////////////////////////////////////////////////////////////////////////
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +0200139// We know some environments not to support full POSIX signals
140#if defined(__CYGWIN__) || defined(__QNX__)
Phil Nash0952b762017-02-28 14:19:09 +0000141
142# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
143# define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS
144# endif
145
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +0200146#endif
147
148////////////////////////////////////////////////////////////////////////////////
149// Cygwin
150#ifdef __CYGWIN__
151
Phil Nashc6535a02017-03-01 16:04:44 +0000152// Required for some versions of Cygwin to declare gettimeofday
153// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin
154# define _BSD_SOURCE
155
Phil Nash0952b762017-02-28 14:19:09 +0000156#endif // __CYGWIN__
157
158////////////////////////////////////////////////////////////////////////////////
Phil Nash8defc712013-04-24 19:10:02 +0100159// Borland
160#ifdef __BORLANDC__
161
Phil Nash8defc712013-04-24 19:10:02 +0100162#endif // __BORLANDC__
163
164////////////////////////////////////////////////////////////////////////////////
165// EDG
166#ifdef __EDG_VERSION__
167
Phil Nash8defc712013-04-24 19:10:02 +0100168#endif // __EDG_VERSION__
169
170////////////////////////////////////////////////////////////////////////////////
171// Digital Mars
172#ifdef __DMC__
173
Phil Nash8defc712013-04-24 19:10:02 +0100174#endif // __DMC__
175
176////////////////////////////////////////////////////////////////////////////////
177// GCC
178#ifdef __GNUC__
179
Phil Nashae5ee2c2016-02-29 08:17:18 +0000180# if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
181# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
182# endif
183
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100184// - otherwise more recent versions define __cplusplus >= 201103L
185// and will get picked up below
186
Phil Nash8defc712013-04-24 19:10:02 +0100187#endif // __GNUC__
188
189////////////////////////////////////////////////////////////////////////////////
190// Visual C++
191#ifdef _MSC_VER
192
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100193#define CATCH_INTERNAL_CONFIG_WINDOWS_SEH
194
Phil Nash43470b22015-05-19 22:37:23 +0100195#if (_MSC_VER >= 1600)
Phil Nash3b18d9e2015-06-30 18:26:09 +0100196# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nashd234ed12015-08-24 06:28:25 +0100197# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
Phil Nash43470b22015-05-19 22:37:23 +0100198#endif
199
Phil Nash318c9362015-05-19 18:40:00 +0100200#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
Phil Nash3b18d9e2015-06-30 18:26:09 +0100201#define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
202#define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3b2f2062017-01-11 16:43:56 +0000203#define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100204#define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
Phil Nash318c9362015-05-19 18:40:00 +0100205#endif
206
Phil Nash8defc712013-04-24 19:10:02 +0100207#endif // _MSC_VER
208
Phil Nashd234ed12015-08-24 06:28:25 +0100209////////////////////////////////////////////////////////////////////////////////
210
Phil Nash8defc712013-04-24 19:10:02 +0100211// Use variadic macros if the compiler supports them
212#if ( defined _MSC_VER && _MSC_VER > 1400 && !defined __EDGE__) || \
213 ( defined __WAVE__ && __WAVE_HAS_VARIADICS ) || \
214 ( defined __GNUC__ && __GNUC__ >= 3 ) || \
215 ( !defined __cplusplus && __STDC_VERSION__ >= 199901L || __cplusplus >= 201103L )
Phil Nash786959d2013-06-07 19:07:50 +0100216
Phil Nash3b18d9e2015-06-30 18:26:09 +0100217#define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash786959d2013-06-07 19:07:50 +0100218
Phil Nash8defc712013-04-24 19:10:02 +0100219#endif
220
Phil Nashc984fc32016-03-15 07:24:26 +0000221// Use __COUNTER__ if the compiler supports it
222#if ( defined _MSC_VER && _MSC_VER >= 1300 ) || \
223 ( defined __GNUC__ && __GNUC__ >= 4 && __GNUC_MINOR__ >= 3 ) || \
224 ( defined __clang__ && __clang_major__ >= 3 )
225
226#define CATCH_INTERNAL_CONFIG_COUNTER
227
228#endif
229
Phil Nashd7e17902014-04-18 08:49:35 +0100230////////////////////////////////////////////////////////////////////////////////
231// C++ language feature support
232
Phil Nash318c9362015-05-19 18:40:00 +0100233// catch all support for C++11
Phil Nashae5ee2c2016-02-29 08:17:18 +0000234#if defined(CATCH_CPP11_OR_GREATER)
Phil Nash318c9362015-05-19 18:40:00 +0100235
Phil Nash3b18d9e2015-06-30 18:26:09 +0100236# if !defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR)
237# define CATCH_INTERNAL_CONFIG_CPP11_NULLPTR
Phil Nash318c9362015-05-19 18:40:00 +0100238# endif
239
Phil Nash3b18d9e2015-06-30 18:26:09 +0100240# ifndef CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
241# define CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT
Phil Nash318c9362015-05-19 18:40:00 +0100242# endif
243
Phil Nash3b18d9e2015-06-30 18:26:09 +0100244# ifndef CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
245# define CATCH_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
Phil Nash318c9362015-05-19 18:40:00 +0100246# endif
247
Phil Nash3b18d9e2015-06-30 18:26:09 +0100248# ifndef CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
249# define CATCH_INTERNAL_CONFIG_CPP11_IS_ENUM
Phil Nash318c9362015-05-19 18:40:00 +0100250# endif
251
Phil Nash3b18d9e2015-06-30 18:26:09 +0100252# ifndef CATCH_INTERNAL_CONFIG_CPP11_TUPLE
253# define CATCH_INTERNAL_CONFIG_CPP11_TUPLE
Phil Nash318c9362015-05-19 18:40:00 +0100254# endif
255
Phil Nash3b18d9e2015-06-30 18:26:09 +0100256# ifndef CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
257# define CATCH_INTERNAL_CONFIG_VARIADIC_MACROS
Phil Nash318c9362015-05-19 18:40:00 +0100258# endif
259
Phil Nash2f6371f2015-07-23 23:06:26 +0100260# if !defined(CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG)
261# define CATCH_INTERNAL_CONFIG_CPP11_LONG_LONG
262# endif
263
Phil Nashe73583d2015-08-07 17:30:34 +0100264# if !defined(CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE)
265# define CATCH_INTERNAL_CONFIG_CPP11_OVERRIDE
266# endif
Phil Nashd234ed12015-08-24 06:28:25 +0100267# if !defined(CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
268# define CATCH_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
269# endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000270# if !defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE)
271# define CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE
272# endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100273# if !defined(CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS)
274# define CATCH_INTERNAL_CONFIG_CPP11_TYPE_TRAITS
275# endif
Phil Nashe73583d2015-08-07 17:30:34 +0100276
Phil Nash318c9362015-05-19 18:40:00 +0100277#endif // __cplusplus >= 201103L
Phil Nashd7e17902014-04-18 08:49:35 +0100278
Phil Nash3b18d9e2015-06-30 18:26:09 +0100279// Now set the actual defines based on the above + anything the user has configured
280#if defined(CATCH_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NO_NULLPTR) && !defined(CATCH_CONFIG_CPP11_NULLPTR) && !defined(CATCH_CONFIG_NO_CPP11)
281# define CATCH_CONFIG_CPP11_NULLPTR
282#endif
283#if defined(CATCH_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_CONFIG_NO_CPP11)
284# define CATCH_CONFIG_CPP11_NOEXCEPT
285#endif
286#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)
287# define CATCH_CONFIG_CPP11_GENERATED_METHODS
288#endif
289#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)
290# define CATCH_CONFIG_CPP11_IS_ENUM
291#endif
292#if defined(CATCH_INTERNAL_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_CPP11_NO_TUPLE) && !defined(CATCH_CONFIG_CPP11_TUPLE) && !defined(CATCH_CONFIG_NO_CPP11)
293# define CATCH_CONFIG_CPP11_TUPLE
294#endif
295#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 +0100296# define CATCH_CONFIG_VARIADIC_MACROS
297#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000298#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 +0100299# define CATCH_CONFIG_CPP11_LONG_LONG
Phil Nash3b18d9e2015-06-30 18:26:09 +0100300#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000301#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 +0100302# define CATCH_CONFIG_CPP11_OVERRIDE
303#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000304#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 +0100305# define CATCH_CONFIG_CPP11_UNIQUE_PTR
Phil Nash3b18d9e2015-06-30 18:26:09 +0100306#endif
Martin Hořeňovský9a566092017-01-20 12:49:59 +0100307// Use of __COUNTER__ is suppressed if __JETBRAINS_IDE__ is #defined (meaning we're being parsed by a JetBrains IDE for
308// analytics) because, at time of writing, __COUNTER__ is not properly handled by it.
309// This does not affect compilation
310#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 +0000311# define CATCH_CONFIG_COUNTER
312#endif
Phil Nash3b2f2062017-01-11 16:43:56 +0000313#if defined(CATCH_INTERNAL_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_NO_SHUFFLE) && !defined(CATCH_CONFIG_CPP11_SHUFFLE) && !defined(CATCH_CONFIG_NO_CPP11)
314# define CATCH_CONFIG_CPP11_SHUFFLE
315#endif
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100316# 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)
317# define CATCH_CONFIG_CPP11_TYPE_TRAITS
318# endif
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +0100319#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH)
320# define CATCH_CONFIG_WINDOWS_SEH
321#endif
Phil Nash0952b762017-02-28 14:19:09 +0000322// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.
323#if !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)
324# define CATCH_CONFIG_POSIX_SIGNALS
325#endif
Phil Nash3b18d9e2015-06-30 18:26:09 +0100326
Phil Nashae5ee2c2016-02-29 08:17:18 +0000327#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)
328# define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS
Phil Nash0952b762017-02-28 14:19:09 +0000329# define CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS
Phil Nashae5ee2c2016-02-29 08:17:18 +0000330#endif
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200331#if !defined(CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS)
332# define CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
333# define CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
334#endif
Phil Nashae5ee2c2016-02-29 08:17:18 +0000335
Phil Nashd7e17902014-04-18 08:49:35 +0100336// noexcept support:
Phil Nash17404952014-04-23 18:19:49 +0100337#if defined(CATCH_CONFIG_CPP11_NOEXCEPT) && !defined(CATCH_NOEXCEPT)
338# define CATCH_NOEXCEPT noexcept
339# define CATCH_NOEXCEPT_IS(x) noexcept(x)
340#else
Phil Nashd7e17902014-04-18 08:49:35 +0100341# define CATCH_NOEXCEPT throw()
342# define CATCH_NOEXCEPT_IS(x)
343#endif
344
Phil Nashb971fe72015-07-02 08:21:38 +0100345// nullptr support
346#ifdef CATCH_CONFIG_CPP11_NULLPTR
347# define CATCH_NULL nullptr
348#else
349# define CATCH_NULL NULL
350#endif
351
Phil Nashe73583d2015-08-07 17:30:34 +0100352// override support
353#ifdef CATCH_CONFIG_CPP11_OVERRIDE
354# define CATCH_OVERRIDE override
355#else
356# define CATCH_OVERRIDE
357#endif
358
Phil Nashd234ed12015-08-24 06:28:25 +0100359// unique_ptr support
360#ifdef CATCH_CONFIG_CPP11_UNIQUE_PTR
361# define CATCH_AUTO_PTR( T ) std::unique_ptr<T>
362#else
363# define CATCH_AUTO_PTR( T ) std::auto_ptr<T>
364#endif
365
Phil Nash3b2f2062017-01-11 16:43:56 +0000366#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line
367#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )
368#ifdef CATCH_CONFIG_COUNTER
369# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )
370#else
371# define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )
372#endif
373
374#define INTERNAL_CATCH_STRINGIFY2( expr ) #expr
375#define INTERNAL_CATCH_STRINGIFY( expr ) INTERNAL_CATCH_STRINGIFY2( expr )
376
377#include <sstream>
Phil Nash3b2f2062017-01-11 16:43:56 +0000378#include <algorithm>
379
Phil Nash89d2a3f2012-05-16 15:09:17 +0100380namespace Catch {
381
Phil Nash8f66e342015-07-02 23:03:13 +0100382 struct IConfig;
383
Phil Nash5bbdc8f2015-07-15 23:03:11 +0100384 struct CaseSensitive { enum Choice {
385 Yes,
386 No
387 }; };
388
Phil Nasha04981b2013-03-08 09:30:25 +0000389 class NonCopyable {
Phil Nash318c9362015-05-19 18:40:00 +0100390#ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashe54ac702014-10-21 07:25:26 +0100391 NonCopyable( NonCopyable const& ) = delete;
392 NonCopyable( NonCopyable && ) = delete;
393 NonCopyable& operator = ( NonCopyable const& ) = delete;
394 NonCopyable& operator = ( NonCopyable && ) = delete;
395#else
396 NonCopyable( NonCopyable const& info );
397 NonCopyable& operator = ( NonCopyable const& );
398#endif
399
Phil Nasha04981b2013-03-08 09:30:25 +0000400 protected:
401 NonCopyable() {}
402 virtual ~NonCopyable();
403 };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100404
Phil Nash163088a2012-05-31 19:40:26 +0100405 class SafeBool {
406 public:
407 typedef void (SafeBool::*type)() const;
408
409 static type makeSafe( bool value ) {
410 return value ? &SafeBool::trueValue : 0;
411 }
412 private:
413 void trueValue() const {}
414 };
415
Phil Nash89d1e6c2011-05-24 08:23:02 +0100416 template<typename ContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100417 inline void deleteAll( ContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100418 typename ContainerT::const_iterator it = container.begin();
419 typename ContainerT::const_iterator itEnd = container.end();
420 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100421 delete *it;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100422 }
423 template<typename AssociativeContainerT>
Phil Nashd31737f2012-05-09 19:04:00 +0100424 inline void deleteAllValues( AssociativeContainerT& container ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100425 typename AssociativeContainerT::const_iterator it = container.begin();
426 typename AssociativeContainerT::const_iterator itEnd = container.end();
427 for(; it != itEnd; ++it )
Phil Nash89d1e6c2011-05-24 08:23:02 +0100428 delete it->second;
Phil Nash89d1e6c2011-05-24 08:23:02 +0100429 }
430
Phil Nash3649fdf2013-12-03 18:53:55 +0000431 bool startsWith( std::string const& s, std::string const& prefix );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100432 bool startsWith( std::string const& s, char prefix );
Phil Nash3649fdf2013-12-03 18:53:55 +0000433 bool endsWith( std::string const& s, std::string const& suffix );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100434 bool endsWith( std::string const& s, char suffix );
435 bool contains( std::string const& s, std::string const& infix );
Phil Nash3649fdf2013-12-03 18:53:55 +0000436 void toLowerInPlace( std::string& s );
437 std::string toLower( std::string const& s );
438 std::string trim( std::string const& str );
Phil Nash576aff62014-12-21 00:21:23 +0000439 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );
Phil Nash4c97fc52012-08-24 08:23:50 +0100440
441 struct pluralise {
Phil Nash3649fdf2013-12-03 18:53:55 +0000442 pluralise( std::size_t count, std::string const& label );
Phil Nash4c97fc52012-08-24 08:23:50 +0100443
Phil Nash3649fdf2013-12-03 18:53:55 +0000444 friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );
Phil Nash4c97fc52012-08-24 08:23:50 +0100445
446 std::size_t m_count;
447 std::string m_label;
448 };
Phil Nash56d5c422012-08-23 20:08:50 +0100449
Phil Nash89d2a3f2012-05-16 15:09:17 +0100450 struct SourceLineInfo {
451
Phil Nash3649fdf2013-12-03 18:53:55 +0000452 SourceLineInfo();
Phil Nashde49ec42013-12-04 20:25:14 +0000453 SourceLineInfo( char const* _file, std::size_t _line );
Phil Nash318c9362015-05-19 18:40:00 +0100454# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100455 SourceLineInfo(SourceLineInfo const& other) = default;
Phil Nashd7e17902014-04-18 08:49:35 +0100456 SourceLineInfo( SourceLineInfo && ) = default;
457 SourceLineInfo& operator = ( SourceLineInfo const& ) = default;
458 SourceLineInfo& operator = ( SourceLineInfo && ) = default;
459# endif
Phil Nash3649fdf2013-12-03 18:53:55 +0000460 bool empty() const;
461 bool operator == ( SourceLineInfo const& other ) const;
Phil Nasha806c3e2015-03-04 08:23:40 +0000462 bool operator < ( SourceLineInfo const& other ) const;
Phil Nash3649fdf2013-12-03 18:53:55 +0000463
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100464 char const* file;
Phil Nash6e0f58d2012-02-15 18:37:21 +0000465 std::size_t line;
466 };
467
Phil Nash3649fdf2013-12-03 18:53:55 +0000468 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );
Phil Nash6e0f58d2012-02-15 18:37:21 +0000469
Phil Nash8defc712013-04-24 19:10:02 +0100470 // This is just here to avoid compiler warnings with macro constants and boolean literals
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100471 inline bool isTrue( bool value ){ return value; }
472 inline bool alwaysTrue() { return true; }
473 inline bool alwaysFalse() { return false; }
Phil Nash8defc712013-04-24 19:10:02 +0100474
Phil Nash3649fdf2013-12-03 18:53:55 +0000475 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo );
Phil Nash859760a2013-12-14 14:34:05 +0000476
Phil Nash8f66e342015-07-02 23:03:13 +0100477 void seedRng( IConfig const& config );
478 unsigned int rngSeed();
479
Phil Nash859760a2013-12-14 14:34:05 +0000480 // Use this in variadic streaming macros to allow
481 // >> +StreamEndStop
482 // as well as
483 // >> stuff +StreamEndStop
484 struct StreamEndStop {
485 std::string operator+() {
486 return std::string();
487 }
488 };
489 template<typename T>
490 T const& operator + ( T const& value, StreamEndStop ) {
491 return value;
492 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100493}
494
Phil Nasha695eb92012-08-13 07:46:10 +0100495#define CATCH_INTERNAL_LINEINFO ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )
496#define CATCH_INTERNAL_ERROR( msg ) ::Catch::throwLogicError( msg, CATCH_INTERNAL_LINEINFO );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100497
Phil Nash3b80af72012-08-09 07:47:30 +0100498namespace Catch {
499
500 class NotImplementedException : public std::exception
501 {
502 public:
Phil Nash8defc712013-04-24 19:10:02 +0100503 NotImplementedException( SourceLineInfo const& lineInfo );
Phil Nash9241e432014-05-20 18:50:59 +0100504 NotImplementedException( NotImplementedException const& ) {}
Phil Nash3b80af72012-08-09 07:47:30 +0100505
Phil Nashd7e17902014-04-18 08:49:35 +0100506 virtual ~NotImplementedException() CATCH_NOEXCEPT {}
Phil Nash3b80af72012-08-09 07:47:30 +0100507
Phil Nashd7e17902014-04-18 08:49:35 +0100508 virtual const char* what() const CATCH_NOEXCEPT;
Phil Nash3b80af72012-08-09 07:47:30 +0100509
510 private:
511 std::string m_what;
512 SourceLineInfo m_lineInfo;
513 };
514
515} // end namespace Catch
516
517///////////////////////////////////////////////////////////////////////////////
518#define CATCH_NOT_IMPLEMENTED throw Catch::NotImplementedException( CATCH_INTERNAL_LINEINFO )
519
520// #included from: internal/catch_context.h
521#define TWOBLUECUBES_CATCH_CONTEXT_H_INCLUDED
522
Phil Nasha70fbe32012-08-31 08:10:36 +0100523// #included from: catch_interfaces_generators.h
524#define TWOBLUECUBES_CATCH_INTERFACES_GENERATORS_H_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +0100525
Phil Nasha70fbe32012-08-31 08:10:36 +0100526#include <string>
Phil Nashf7299fc2012-02-25 09:39:45 +0000527
Phil Nash89d2a3f2012-05-16 15:09:17 +0100528namespace Catch {
529
Phil Nasha70fbe32012-08-31 08:10:36 +0100530 struct IGeneratorInfo {
531 virtual ~IGeneratorInfo();
532 virtual bool moveNext() = 0;
533 virtual std::size_t getCurrentIndex() const = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000534 };
535
Phil Nasha70fbe32012-08-31 08:10:36 +0100536 struct IGeneratorsForTest {
537 virtual ~IGeneratorsForTest();
Phil Nash89d2a3f2012-05-16 15:09:17 +0100538
Phil Nash8defc712013-04-24 19:10:02 +0100539 virtual IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +0100540 virtual bool moveNext() = 0;
Phil Nashf7299fc2012-02-25 09:39:45 +0000541 };
Phil Nasha70fbe32012-08-31 08:10:36 +0100542
543 IGeneratorsForTest* createGeneratorsForTest();
544
545} // end namespace Catch
546
Phil Nash49e6d532012-05-05 19:35:35 +0100547// #included from: catch_ptr.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100548#define TWOBLUECUBES_CATCH_PTR_HPP_INCLUDED
Phil Nash49e6d532012-05-05 19:35:35 +0100549
Phil Nash37186a12013-03-13 12:19:30 +0000550#ifdef __clang__
551#pragma clang diagnostic push
552#pragma clang diagnostic ignored "-Wpadded"
553#endif
554
Phil Nash89d2a3f2012-05-16 15:09:17 +0100555namespace Catch {
556
Phil Nash49e6d532012-05-05 19:35:35 +0100557 // An intrusive reference counting smart pointer.
558 // T must implement addRef() and release() methods
559 // typically implementing the IShared interface
560 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +0100561 class Ptr {
Phil Nash49e6d532012-05-05 19:35:35 +0100562 public:
Phil Nashb971fe72015-07-02 08:21:38 +0100563 Ptr() : m_p( CATCH_NULL ){}
Phil Nash49e6d532012-05-05 19:35:35 +0100564 Ptr( T* p ) : m_p( p ){
Phil Nash61756972012-07-28 20:37:07 +0100565 if( m_p )
566 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100567 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000568 Ptr( Ptr const& other ) : m_p( other.m_p ){
Phil Nash61756972012-07-28 20:37:07 +0100569 if( m_p )
570 m_p->addRef();
Phil Nash49e6d532012-05-05 19:35:35 +0100571 }
572 ~Ptr(){
573 if( m_p )
574 m_p->release();
575 }
Phil Nashff03cdf2012-12-06 08:44:51 +0000576 void reset() {
577 if( m_p )
578 m_p->release();
Phil Nashb971fe72015-07-02 08:21:38 +0100579 m_p = CATCH_NULL;
Phil Nashff03cdf2012-12-06 08:44:51 +0000580 }
Phil Nash49e6d532012-05-05 19:35:35 +0100581 Ptr& operator = ( T* p ){
582 Ptr temp( p );
583 swap( temp );
584 return *this;
585 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000586 Ptr& operator = ( Ptr const& other ){
Phil Nash49e6d532012-05-05 19:35:35 +0100587 Ptr temp( other );
588 swap( temp );
589 return *this;
590 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000591 void swap( Ptr& other ) { std::swap( m_p, other.m_p ); }
Phil Nash8b1b7cd2015-08-03 07:40:52 +0100592 T* get() const{ return m_p; }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000593 T& operator*() const { return *m_p; }
594 T* operator->() const { return m_p; }
Phil Nashb971fe72015-07-02 08:21:38 +0100595 bool operator !() const { return m_p == CATCH_NULL; }
596 operator SafeBool::type() const { return SafeBool::makeSafe( m_p != CATCH_NULL ); }
Phil Nash49e6d532012-05-05 19:35:35 +0100597
598 private:
599 T* m_p;
600 };
601
602 struct IShared : NonCopyable {
Phil Nasha695eb92012-08-13 07:46:10 +0100603 virtual ~IShared();
Phil Nasha1fbfea2012-12-01 23:57:18 +0000604 virtual void addRef() const = 0;
605 virtual void release() const = 0;
Phil Nash49e6d532012-05-05 19:35:35 +0100606 };
607
Phil Nasha1fbfea2012-12-01 23:57:18 +0000608 template<typename T = IShared>
Phil Nash49e6d532012-05-05 19:35:35 +0100609 struct SharedImpl : T {
610
611 SharedImpl() : m_rc( 0 ){}
612
Phil Nasha1fbfea2012-12-01 23:57:18 +0000613 virtual void addRef() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100614 ++m_rc;
615 }
Phil Nasha1fbfea2012-12-01 23:57:18 +0000616 virtual void release() const {
Phil Nash49e6d532012-05-05 19:35:35 +0100617 if( --m_rc == 0 )
618 delete this;
619 }
620
Phil Nasha1fbfea2012-12-01 23:57:18 +0000621 mutable unsigned int m_rc;
Phil Nash49e6d532012-05-05 19:35:35 +0100622 };
623
624} // end namespace Catch
625
Phil Nash37186a12013-03-13 12:19:30 +0000626#ifdef __clang__
627#pragma clang diagnostic pop
628#endif
629
Phil Nash786959d2013-06-07 19:07:50 +0100630namespace Catch {
631
632 class TestCase;
633 class Stream;
634 struct IResultCapture;
635 struct IRunner;
636 struct IGeneratorsForTest;
637 struct IConfig;
638
639 struct IContext
640 {
641 virtual ~IContext();
642
Phil Nash9241e432014-05-20 18:50:59 +0100643 virtual IResultCapture* getResultCapture() = 0;
644 virtual IRunner* getRunner() = 0;
Phil Nash786959d2013-06-07 19:07:50 +0100645 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) = 0;
646 virtual bool advanceGeneratorsForCurrentTest() = 0;
647 virtual Ptr<IConfig const> getConfig() const = 0;
648 };
649
650 struct IMutableContext : IContext
651 {
652 virtual ~IMutableContext();
653 virtual void setResultCapture( IResultCapture* resultCapture ) = 0;
654 virtual void setRunner( IRunner* runner ) = 0;
655 virtual void setConfig( Ptr<IConfig const> const& config ) = 0;
656 };
657
658 IContext& getCurrentContext();
659 IMutableContext& getCurrentMutableContext();
660 void cleanUpContext();
661 Stream createStream( std::string const& streamName );
662
663}
664
665// #included from: internal/catch_test_registry.hpp
666#define TWOBLUECUBES_CATCH_TEST_REGISTRY_HPP_INCLUDED
667
668// #included from: catch_interfaces_testcase.h
669#define TWOBLUECUBES_CATCH_INTERFACES_TESTCASE_H_INCLUDED
670
Phil Nash0f9c5512012-06-02 23:12:42 +0100671#include <vector>
672
673namespace Catch {
Phil Nash56d5c422012-08-23 20:08:50 +0100674
Phil Nash65cc14c2014-05-16 18:54:48 +0100675 class TestSpec;
Phil Nash56d5c422012-08-23 20:08:50 +0100676
Phil Nash5bc030d2012-08-16 18:48:50 +0100677 struct ITestCase : IShared {
Phil Nash0f9c5512012-06-02 23:12:42 +0100678 virtual void invoke () const = 0;
Phil Nash5bc030d2012-08-16 18:48:50 +0100679 protected:
680 virtual ~ITestCase();
Phil Nash0f9c5512012-06-02 23:12:42 +0100681 };
682
Phil Nasha1fbfea2012-12-01 23:57:18 +0000683 class TestCase;
Phil Nash20cad7c2014-04-15 18:44:37 +0100684 struct IConfig;
Phil Nash0f9c5512012-06-02 23:12:42 +0100685
686 struct ITestCaseRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +0100687 virtual ~ITestCaseRegistry();
Phil Nash8defc712013-04-24 19:10:02 +0100688 virtual std::vector<TestCase> const& getAllTests() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +0100689 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;
Phil Nash0f9c5512012-06-02 23:12:42 +0100690 };
Phil Nashe73583d2015-08-07 17:30:34 +0100691
692 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );
693 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );
694 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );
695
Phil Nash0f9c5512012-06-02 23:12:42 +0100696}
697
Phil Nash89d2a3f2012-05-16 15:09:17 +0100698namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100699
700template<typename C>
Phil Nash5bc030d2012-08-16 18:48:50 +0100701class MethodTestCase : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100702
Phil Nash176eb812012-05-11 08:17:16 +0100703public:
704 MethodTestCase( void (C::*method)() ) : m_method( method ) {}
Phil Nash89d1e6c2011-05-24 08:23:02 +0100705
Phil Nash176eb812012-05-11 08:17:16 +0100706 virtual void invoke() const {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100707 C obj;
708 (obj.*m_method)();
709 }
710
Phil Nash89d1e6c2011-05-24 08:23:02 +0100711private:
Phil Nash5bc030d2012-08-16 18:48:50 +0100712 virtual ~MethodTestCase() {}
713
Phil Nash89d1e6c2011-05-24 08:23:02 +0100714 void (C::*m_method)();
715};
716
717typedef void(*TestFunction)();
718
Phil Nash93906752013-03-16 20:21:51 +0000719struct NameAndDesc {
720 NameAndDesc( const char* _name = "", const char* _description= "" )
721 : name( _name ), description( _description )
722 {}
723
724 const char* name;
725 const char* description;
726};
727
Phil Nash7e15d9b2015-11-20 16:59:14 +0000728void registerTestCase
729 ( ITestCase* testCase,
730 char const* className,
731 NameAndDesc const& nameAndDesc,
732 SourceLineInfo const& lineInfo );
733
Phil Nash89d2a3f2012-05-16 15:09:17 +0100734struct AutoReg {
735
Phil Nash7e15d9b2015-11-20 16:59:14 +0000736 AutoReg
737 ( TestFunction function,
738 SourceLineInfo const& lineInfo,
739 NameAndDesc const& nameAndDesc );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100740
Phil Nash89d1e6c2011-05-24 08:23:02 +0100741 template<typename C>
Phil Nash7e15d9b2015-11-20 16:59:14 +0000742 AutoReg
743 ( void (C::*method)(),
744 char const* className,
745 NameAndDesc const& nameAndDesc,
746 SourceLineInfo const& lineInfo ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100747
Phil Nash7e15d9b2015-11-20 16:59:14 +0000748 registerTestCase
749 ( new MethodTestCase<C>( method ),
750 className,
751 nameAndDesc,
752 lineInfo );
753 }
Phil Nash89d1e6c2011-05-24 08:23:02 +0100754
Phil Nash176eb812012-05-11 08:17:16 +0100755 ~AutoReg();
Phil Nash89d1e6c2011-05-24 08:23:02 +0100756
757private:
Phil Nash8defc712013-04-24 19:10:02 +0100758 AutoReg( AutoReg const& );
759 void operator= ( AutoReg const& );
Phil Nash89d1e6c2011-05-24 08:23:02 +0100760};
761
Phil Nash7e15d9b2015-11-20 16:59:14 +0000762void registerTestCaseFunction
763 ( TestFunction function,
764 SourceLineInfo const& lineInfo,
765 NameAndDesc const& nameAndDesc );
766
Phil Nash89d1e6c2011-05-24 08:23:02 +0100767} // end namespace Catch
768
Phil Nash93906752013-03-16 20:21:51 +0000769#ifdef CATCH_CONFIG_VARIADIC_MACROS
770 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000771 #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \
772 static void TestName(); \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200773 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
774 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); } \
775 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
Phil Nashc984fc32016-03-15 07:24:26 +0000776 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000777 #define INTERNAL_CATCH_TESTCASE( ... ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000778 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 +0100779
Phil Nash93906752013-03-16 20:21:51 +0000780 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000781 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200782 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
783 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); } \
784 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
Phil Nash89d1e6c2011-05-24 08:23:02 +0100785
Phil Nash93906752013-03-16 20:21:51 +0000786 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000787 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200788 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
Phil Nash93906752013-03-16 20:21:51 +0000789 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000790 struct TestName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000791 void test(); \
792 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000793 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestName::test, #ClassName, Catch::NameAndDesc( __VA_ARGS__ ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000794 } \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200795 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
Phil Nashc984fc32016-03-15 07:24:26 +0000796 void TestName::test()
797 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \
798 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 +0100799
Phil Nash7e15d9b2015-11-20 16:59:14 +0000800 ///////////////////////////////////////////////////////////////////////////////
801 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200802 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
803 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( __VA_ARGS__ ) ); \
804 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
Phil Nash7e15d9b2015-11-20 16:59:14 +0000805
Phil Nash93906752013-03-16 20:21:51 +0000806#else
807 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000808 #define INTERNAL_CATCH_TESTCASE2( TestName, Name, Desc ) \
809 static void TestName(); \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200810 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
Phil Nashc984fc32016-03-15 07:24:26 +0000811 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &TestName, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); }\
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200812 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
Phil Nashc984fc32016-03-15 07:24:26 +0000813 static void TestName()
Phil Nash93906752013-03-16 20:21:51 +0000814 #define INTERNAL_CATCH_TESTCASE( Name, Desc ) \
Phil Nashc984fc32016-03-15 07:24:26 +0000815 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 +0000816
817 ///////////////////////////////////////////////////////////////////////////////
Phil Nash93906752013-03-16 20:21:51 +0000818 #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, Name, Desc ) \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200819 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
820 namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( &QualifiedMethod, "&" #QualifiedMethod, Catch::NameAndDesc( Name, Desc ), CATCH_INTERNAL_LINEINFO ); } \
821 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
Phil Nash93906752013-03-16 20:21:51 +0000822
823 ///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +0000824 #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestCaseName, ClassName, TestName, Desc )\
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200825 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
Phil Nash93906752013-03-16 20:21:51 +0000826 namespace{ \
Phil Nashc984fc32016-03-15 07:24:26 +0000827 struct TestCaseName : ClassName{ \
Phil Nash93906752013-03-16 20:21:51 +0000828 void test(); \
829 }; \
Phil Nashc984fc32016-03-15 07:24:26 +0000830 Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( &TestCaseName::test, #ClassName, Catch::NameAndDesc( TestName, Desc ), CATCH_INTERNAL_LINEINFO ); \
Phil Nash93906752013-03-16 20:21:51 +0000831 } \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200832 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS \
Phil Nashc984fc32016-03-15 07:24:26 +0000833 void TestCaseName::test()
834 #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, TestName, Desc )\
835 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 +0000836
Phil Nash7e15d9b2015-11-20 16:59:14 +0000837 ///////////////////////////////////////////////////////////////////////////////
838 #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, Name, Desc ) \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +0200839 CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS \
840 Catch::AutoReg( Function, CATCH_INTERNAL_LINEINFO, Catch::NameAndDesc( Name, Desc ) ); \
841 CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
842
Phil Nash93906752013-03-16 20:21:51 +0000843#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100844
845// #included from: internal/catch_capture.hpp
Phil Nash3b80af72012-08-09 07:47:30 +0100846#define TWOBLUECUBES_CATCH_CAPTURE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100847
Phil Nashab036682014-06-02 07:48:03 +0100848// #included from: catch_result_builder.h
849#define TWOBLUECUBES_CATCH_RESULT_BUILDER_H_INCLUDED
Phil Nash89d2a3f2012-05-16 15:09:17 +0100850
Phil Nash89d1e6c2011-05-24 08:23:02 +0100851// #included from: catch_result_type.h
Phil Nash3b80af72012-08-09 07:47:30 +0100852#define TWOBLUECUBES_CATCH_RESULT_TYPE_H_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +0100853
Phil Nash89d2a3f2012-05-16 15:09:17 +0100854namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100855
Phil Nash90a35942012-11-13 22:04:29 +0000856 // ResultWas::OfType enum
857 struct ResultWas { enum OfType {
858 Unknown = -1,
859 Ok = 0,
860 Info = 1,
861 Warning = 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100862
Phil Nash90a35942012-11-13 22:04:29 +0000863 FailureBit = 0x10,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100864
Phil Nash90a35942012-11-13 22:04:29 +0000865 ExpressionFailed = FailureBit | 1,
866 ExplicitFailure = FailureBit | 2,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100867
Phil Nash90a35942012-11-13 22:04:29 +0000868 Exception = 0x100 | FailureBit,
Phil Nash89d1e6c2011-05-24 08:23:02 +0100869
Phil Nash90a35942012-11-13 22:04:29 +0000870 ThrewException = Exception | 1,
Phil Nash93b61e12014-08-22 19:35:41 +0100871 DidntThrowException = Exception | 2,
872
873 FatalErrorCondition = 0x200 | FailureBit
Phil Nash89d1e6c2011-05-24 08:23:02 +0100874
Phil Nash90a35942012-11-13 22:04:29 +0000875 }; };
Phil Nash89d1e6c2011-05-24 08:23:02 +0100876
Phil Nash90a35942012-11-13 22:04:29 +0000877 inline bool isOk( ResultWas::OfType resultType ) {
878 return ( resultType & ResultWas::FailureBit ) == 0;
879 }
Phil Nasha2773812013-02-02 20:37:58 +0000880 inline bool isJustInfo( int flags ) {
881 return flags == ResultWas::Info;
882 }
Phil Nash67305122012-10-09 11:48:55 +0100883
Phil Nash90a35942012-11-13 22:04:29 +0000884 // ResultDisposition::Flags enum
885 struct ResultDisposition { enum Flags {
Phil Nash318c9362015-05-19 18:40:00 +0100886 Normal = 0x01,
Phil Nash90a35942012-11-13 22:04:29 +0000887
Phil Nash318c9362015-05-19 18:40:00 +0100888 ContinueOnFailure = 0x02, // Failures fail test, but execution continues
889 FalseTest = 0x04, // Prefix expression with !
890 SuppressFail = 0x08 // Failures are reported but do not fail the test
Phil Nash90a35942012-11-13 22:04:29 +0000891 }; };
892
893 inline ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {
894 return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );
895 }
896
Phil Nash3e2e3182012-11-17 10:49:24 +0000897 inline bool shouldContinueOnFailure( int flags ) { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }
Phil Nashab036682014-06-02 07:48:03 +0100898 inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }
Phil Nash3e2e3182012-11-17 10:49:24 +0000899 inline bool shouldSuppressFailure( int flags ) { return ( flags & ResultDisposition::SuppressFail ) != 0; }
Phil Nash90a35942012-11-13 22:04:29 +0000900
901} // end namespace Catch
Phil Nash89d1e6c2011-05-24 08:23:02 +0100902
Phil Nashab036682014-06-02 07:48:03 +0100903// #included from: catch_assertionresult.h
904#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_H_INCLUDED
905
906#include <string>
Phil Nash89d1e6c2011-05-24 08:23:02 +0100907
Phil Nash89d2a3f2012-05-16 15:09:17 +0100908namespace Catch {
Phil Nash89d1e6c2011-05-24 08:23:02 +0100909
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100910 struct STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison;
911
912 struct DecomposedExpression
913 {
914 virtual ~DecomposedExpression() {}
915 virtual bool isBinaryExpression() const {
916 return false;
917 }
918 virtual void reconstructExpression( std::string& dest ) const = 0;
919
920 // Only simple binary comparisons can be decomposed.
921 // If more complex check is required then wrap sub-expressions in parentheses.
922 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator + ( T const& );
923 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator - ( T const& );
924 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator * ( T const& );
925 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator / ( T const& );
926 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator % ( T const& );
927 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator && ( T const& );
928 template<typename T> STATIC_ASSERT_Expression_Too_Complex_Please_Rewrite_As_Binary_Comparison& operator || ( T const& );
Phil Nash0952b762017-02-28 14:19:09 +0000929
930 private:
931 DecomposedExpression& operator = (DecomposedExpression const&);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100932 };
933
Phil Nashce612bf2012-11-01 08:27:09 +0000934 struct AssertionInfo
Phil Nash67305122012-10-09 11:48:55 +0100935 {
Phil Nashce612bf2012-11-01 08:27:09 +0000936 AssertionInfo() {}
Phil Nash8defc712013-04-24 19:10:02 +0100937 AssertionInfo( std::string const& _macroName,
938 SourceLineInfo const& _lineInfo,
939 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +0000940 ResultDisposition::Flags _resultDisposition );
Phil Nash67305122012-10-09 11:48:55 +0100941
942 std::string macroName;
943 SourceLineInfo lineInfo;
944 std::string capturedExpression;
Phil Nash90a35942012-11-13 22:04:29 +0000945 ResultDisposition::Flags resultDisposition;
Phil Nashce612bf2012-11-01 08:27:09 +0000946 };
947
948 struct AssertionResultData
949 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100950 AssertionResultData() : decomposedExpression( CATCH_NULL )
951 , resultType( ResultWas::Unknown )
952 , negated( false )
953 , parenthesized( false ) {}
Phil Nashce612bf2012-11-01 08:27:09 +0000954
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100955 void negate( bool parenthesize ) {
956 negated = !negated;
957 parenthesized = parenthesize;
958 if( resultType == ResultWas::Ok )
959 resultType = ResultWas::ExpressionFailed;
960 else if( resultType == ResultWas::ExpressionFailed )
961 resultType = ResultWas::Ok;
962 }
963
964 std::string const& reconstructExpression() const {
965 if( decomposedExpression != CATCH_NULL ) {
966 decomposedExpression->reconstructExpression( reconstructedExpression );
967 if( parenthesized ) {
968 reconstructedExpression.insert( 0, 1, '(' );
969 reconstructedExpression.append( 1, ')' );
970 }
971 if( negated ) {
972 reconstructedExpression.insert( 0, 1, '!' );
973 }
974 decomposedExpression = CATCH_NULL;
975 }
976 return reconstructedExpression;
977 }
978
979 mutable DecomposedExpression const* decomposedExpression;
980 mutable std::string reconstructedExpression;
Phil Nash67305122012-10-09 11:48:55 +0100981 std::string message;
982 ResultWas::OfType resultType;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +0100983 bool negated;
984 bool parenthesized;
Phil Nash67305122012-10-09 11:48:55 +0100985 };
986
Phil Nashce612bf2012-11-01 08:27:09 +0000987 class AssertionResult {
Phil Nash89d2a3f2012-05-16 15:09:17 +0100988 public:
Phil Nashce612bf2012-11-01 08:27:09 +0000989 AssertionResult();
Phil Nash8defc712013-04-24 19:10:02 +0100990 AssertionResult( AssertionInfo const& info, AssertionResultData const& data );
Phil Nashce612bf2012-11-01 08:27:09 +0000991 ~AssertionResult();
Phil Nash318c9362015-05-19 18:40:00 +0100992# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +0100993 AssertionResult( AssertionResult const& ) = default;
994 AssertionResult( AssertionResult && ) = default;
995 AssertionResult& operator = ( AssertionResult const& ) = default;
996 AssertionResult& operator = ( AssertionResult && ) = default;
997# endif
Phil Nash89d1e6c2011-05-24 08:23:02 +0100998
Phil Nash90a35942012-11-13 22:04:29 +0000999 bool isOk() const;
1000 bool succeeded() const;
Phil Nash3b80af72012-08-09 07:47:30 +01001001 ResultWas::OfType getResultType() const;
1002 bool hasExpression() const;
1003 bool hasMessage() const;
1004 std::string getExpression() const;
Phil Nash786959d2013-06-07 19:07:50 +01001005 std::string getExpressionInMacro() const;
Phil Nash3b80af72012-08-09 07:47:30 +01001006 bool hasExpandedExpression() const;
1007 std::string getExpandedExpression() const;
1008 std::string getMessage() const;
Phil Nashce612bf2012-11-01 08:27:09 +00001009 SourceLineInfo getSourceInfo() const;
Phil Nash3b80af72012-08-09 07:47:30 +01001010 std::string getTestMacroName() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001011 void discardDecomposedExpression() const;
1012 void expandDecomposedExpression() const;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001013
1014 protected:
Phil Nashce612bf2012-11-01 08:27:09 +00001015 AssertionInfo m_info;
1016 AssertionResultData m_resultData;
Phil Nash89d1e6c2011-05-24 08:23:02 +01001017 };
1018
1019} // end namespace Catch
1020
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001021// #included from: catch_matchers.hpp
1022#define TWOBLUECUBES_CATCH_MATCHERS_HPP_INCLUDED
1023
1024namespace Catch {
1025namespace Matchers {
1026 namespace Impl {
1027
Phil Nash0952b762017-02-28 14:19:09 +00001028 template<typename ArgT> struct MatchAllOf;
1029 template<typename ArgT> struct MatchAnyOf;
1030 template<typename ArgT> struct MatchNotOf;
Phil Nash08844e72015-11-05 18:52:18 +00001031
Phil Nash0952b762017-02-28 14:19:09 +00001032 class MatcherUntypedBase {
Phil Nash92356762015-11-06 18:06:56 +00001033 public:
Phil Nash0952b762017-02-28 14:19:09 +00001034 std::string toString() const {
1035 if( m_cachedToString.empty() )
1036 m_cachedToString = describe();
1037 return m_cachedToString;
Phil Nashd234ed12015-08-24 06:28:25 +01001038 }
1039
Phil Nash0952b762017-02-28 14:19:09 +00001040 protected:
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01001041 virtual ~MatcherUntypedBase();
Phil Nash0952b762017-02-28 14:19:09 +00001042 virtual std::string describe() const = 0;
1043 mutable std::string m_cachedToString;
Phil Nash92356762015-11-06 18:06:56 +00001044 private:
Phil Nash0952b762017-02-28 14:19:09 +00001045 MatcherUntypedBase& operator = ( MatcherUntypedBase const& );
Phil Nashd234ed12015-08-24 06:28:25 +01001046 };
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001047
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01001048 template<typename ObjectT>
1049 struct MatcherMethod {
Phil Nash0952b762017-02-28 14:19:09 +00001050 virtual bool match( ObjectT const& arg ) const = 0;
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01001051 };
1052 template<typename PtrT>
1053 struct MatcherMethod<PtrT*> {
1054 virtual bool match( PtrT* arg ) const = 0;
1055 };
1056
1057 template<typename ObjectT, typename ComparatorT = ObjectT>
1058 struct MatcherBase : MatcherUntypedBase, MatcherMethod<ObjectT> {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001059
Phil Nash0952b762017-02-28 14:19:09 +00001060 MatchAllOf<ComparatorT> operator && ( MatcherBase const& other ) const;
1061 MatchAnyOf<ComparatorT> operator || ( MatcherBase const& other ) const;
1062 MatchNotOf<ComparatorT> operator ! () const;
1063 };
1064
1065 template<typename ArgT>
1066 struct MatchAllOf : MatcherBase<ArgT> {
1067 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1068 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1069 if (!m_matchers[i]->match(arg))
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001070 return false;
Phil Nash0952b762017-02-28 14:19:09 +00001071 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001072 return true;
1073 }
Phil Nash0952b762017-02-28 14:19:09 +00001074 virtual std::string describe() const CATCH_OVERRIDE {
1075 std::string description;
1076 description.reserve( 4 + m_matchers.size()*32 );
1077 description += "( ";
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001078 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1079 if( i != 0 )
Phil Nash0952b762017-02-28 14:19:09 +00001080 description += " and ";
1081 description += m_matchers[i]->toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001082 }
Phil Nash0952b762017-02-28 14:19:09 +00001083 description += " )";
1084 return description;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001085 }
1086
Phil Nash0952b762017-02-28 14:19:09 +00001087 MatchAllOf<ArgT>& operator && ( MatcherBase<ArgT> const& other ) {
1088 m_matchers.push_back( &other );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001089 return *this;
1090 }
Phil Nash0952b762017-02-28 14:19:09 +00001091
1092 std::vector<MatcherBase<ArgT> const*> m_matchers;
1093 };
1094 template<typename ArgT>
1095 struct MatchAnyOf : MatcherBase<ArgT> {
1096
1097 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1098 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1099 if (m_matchers[i]->match(arg))
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001100 return true;
Phil Nash0952b762017-02-28 14:19:09 +00001101 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001102 return false;
1103 }
Phil Nash0952b762017-02-28 14:19:09 +00001104 virtual std::string describe() const CATCH_OVERRIDE {
1105 std::string description;
1106 description.reserve( 4 + m_matchers.size()*32 );
1107 description += "( ";
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001108 for( std::size_t i = 0; i < m_matchers.size(); ++i ) {
1109 if( i != 0 )
Phil Nash0952b762017-02-28 14:19:09 +00001110 description += " or ";
1111 description += m_matchers[i]->toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001112 }
Phil Nash0952b762017-02-28 14:19:09 +00001113 description += " )";
1114 return description;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001115 }
1116
Phil Nash0952b762017-02-28 14:19:09 +00001117 MatchAnyOf<ArgT>& operator || ( MatcherBase<ArgT> const& other ) {
1118 m_matchers.push_back( &other );
1119 return *this;
Phil Nash08844e72015-11-05 18:52:18 +00001120 }
1121
Phil Nash0952b762017-02-28 14:19:09 +00001122 std::vector<MatcherBase<ArgT> const*> m_matchers;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001123 };
Phil Nash08844e72015-11-05 18:52:18 +00001124
Phil Nash0952b762017-02-28 14:19:09 +00001125 template<typename ArgT>
1126 struct MatchNotOf : MatcherBase<ArgT> {
Phil Nash08844e72015-11-05 18:52:18 +00001127
Phil Nash0952b762017-02-28 14:19:09 +00001128 MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}
Phil Nash08844e72015-11-05 18:52:18 +00001129
Phil Nash0952b762017-02-28 14:19:09 +00001130 virtual bool match( ArgT const& arg ) const CATCH_OVERRIDE {
1131 return !m_underlyingMatcher.match( arg );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001132 }
Phil Nash0952b762017-02-28 14:19:09 +00001133
1134 virtual std::string describe() const CATCH_OVERRIDE {
1135 return "not " + m_underlyingMatcher.toString();
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001136 }
Phil Nash0952b762017-02-28 14:19:09 +00001137 MatcherBase<ArgT> const& m_underlyingMatcher;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001138 };
1139
Phil Nash0952b762017-02-28 14:19:09 +00001140 template<typename ObjectT, typename ComparatorT>
1141 MatchAllOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator && ( MatcherBase const& other ) const {
1142 return MatchAllOf<ComparatorT>() && *this && other;
1143 }
1144 template<typename ObjectT, typename ComparatorT>
1145 MatchAnyOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator || ( MatcherBase const& other ) const {
1146 return MatchAnyOf<ComparatorT>() || *this || other;
1147 }
1148 template<typename ObjectT, typename ComparatorT>
1149 MatchNotOf<ComparatorT> MatcherBase<ObjectT, ComparatorT>::operator ! () const {
1150 return MatchNotOf<ComparatorT>( *this );
1151 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001152
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001153 } // namespace Impl
1154
1155 // The following functions create the actual matcher objects.
1156 // This allows the types to be inferred
Phil Nash0952b762017-02-28 14:19:09 +00001157 // - deprecated: prefer ||, && and !
1158 template<typename T>
1159 inline Impl::MatchNotOf<T> Not( Impl::MatcherBase<T> const& underlyingMatcher ) {
1160 return Impl::MatchNotOf<T>( underlyingMatcher );
Phil Nashd234ed12015-08-24 06:28:25 +01001161 }
Phil Nash0952b762017-02-28 14:19:09 +00001162 template<typename T>
1163 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1164 return Impl::MatchAllOf<T>() && m1 && m2;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001165 }
Phil Nash0952b762017-02-28 14:19:09 +00001166 template<typename T>
1167 inline Impl::MatchAllOf<T> AllOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1168 return Impl::MatchAllOf<T>() && m1 && m2 && m3;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001169 }
Phil Nash0952b762017-02-28 14:19:09 +00001170 template<typename T>
1171 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2 ) {
1172 return Impl::MatchAnyOf<T>() || m1 || m2;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001173 }
Phil Nash0952b762017-02-28 14:19:09 +00001174 template<typename T>
1175 inline Impl::MatchAnyOf<T> AnyOf( Impl::MatcherBase<T> const& m1, Impl::MatcherBase<T> const& m2, Impl::MatcherBase<T> const& m3 ) {
1176 return Impl::MatchAnyOf<T>() || m1 || m2 || m3;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001177 }
1178
1179} // namespace Matchers
1180
1181using namespace Matchers;
Phil Nash0952b762017-02-28 14:19:09 +00001182using Matchers::Impl::MatcherBase;
Phil Nash5bbdc8f2015-07-15 23:03:11 +01001183
1184} // namespace Catch
1185
Phil Nashab036682014-06-02 07:48:03 +01001186namespace Catch {
1187
1188 struct TestFailureException{};
1189
1190 template<typename T> class ExpressionLhs;
1191
Phil Nashab036682014-06-02 07:48:03 +01001192 struct CopyableStream {
1193 CopyableStream() {}
1194 CopyableStream( CopyableStream const& other ) {
1195 oss << other.oss.str();
1196 }
1197 CopyableStream& operator=( CopyableStream const& other ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001198 oss.str(std::string());
Phil Nashab036682014-06-02 07:48:03 +01001199 oss << other.oss.str();
1200 return *this;
1201 }
1202 std::ostringstream oss;
1203 };
1204
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001205 class ResultBuilder : public DecomposedExpression {
Phil Nashab036682014-06-02 07:48:03 +01001206 public:
1207 ResultBuilder( char const* macroName,
1208 SourceLineInfo const& lineInfo,
1209 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01001210 ResultDisposition::Flags resultDisposition,
1211 char const* secondArg = "" );
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02001212 ~ResultBuilder();
Phil Nashab036682014-06-02 07:48:03 +01001213
1214 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001215 ExpressionLhs<T const&> operator <= ( T const& operand );
1216 ExpressionLhs<bool> operator <= ( bool value );
Phil Nashab036682014-06-02 07:48:03 +01001217
1218 template<typename T>
1219 ResultBuilder& operator << ( T const& value ) {
1220 m_stream.oss << value;
1221 return *this;
1222 }
1223
Phil Nashab036682014-06-02 07:48:03 +01001224 ResultBuilder& setResultType( ResultWas::OfType result );
1225 ResultBuilder& setResultType( bool result );
Phil Nashab036682014-06-02 07:48:03 +01001226
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001227 void endExpression( DecomposedExpression const& expr );
Phil Nashab036682014-06-02 07:48:03 +01001228
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001229 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE;
1230
Phil Nashab036682014-06-02 07:48:03 +01001231 AssertionResult build() const;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001232 AssertionResult build( DecomposedExpression const& expr ) const;
Phil Nashab036682014-06-02 07:48:03 +01001233
1234 void useActiveException( ResultDisposition::Flags resultDisposition = ResultDisposition::Normal );
1235 void captureResult( ResultWas::OfType resultType );
1236 void captureExpression();
Phil Nash93a842e2015-07-13 06:36:07 +01001237 void captureExpectedException( std::string const& expectedMessage );
Phil Nash0952b762017-02-28 14:19:09 +00001238 void captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher );
Phil Nash93a842e2015-07-13 06:36:07 +01001239 void handleResult( AssertionResult const& result );
Phil Nashab036682014-06-02 07:48:03 +01001240 void react();
1241 bool shouldDebugBreak() const;
1242 bool allowThrows() const;
1243
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001244 template<typename ArgT, typename MatcherT>
1245 void captureMatch( ArgT const& arg, MatcherT const& matcher, char const* matcherString );
1246
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02001247 void setExceptionGuard();
1248 void unsetExceptionGuard();
1249
Phil Nashab036682014-06-02 07:48:03 +01001250 private:
1251 AssertionInfo m_assertionInfo;
1252 AssertionResultData m_data;
Phil Nashab036682014-06-02 07:48:03 +01001253 CopyableStream m_stream;
1254
1255 bool m_shouldDebugBreak;
1256 bool m_shouldThrow;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02001257 bool m_guardException;
Phil Nashab036682014-06-02 07:48:03 +01001258 };
1259
1260} // namespace Catch
1261
1262// Include after due to circular dependency:
1263// #included from: catch_expression_lhs.hpp
1264#define TWOBLUECUBES_CATCH_EXPRESSION_LHS_HPP_INCLUDED
1265
Phil Nash89d1e6c2011-05-24 08:23:02 +01001266// #included from: catch_evaluate.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01001267#define TWOBLUECUBES_CATCH_EVALUATE_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01001268
Phil Nashdd26e882013-03-25 09:25:31 +00001269#ifdef _MSC_VER
1270#pragma warning(push)
1271#pragma warning(disable:4389) // '==' : signed/unsigned mismatch
Phil Nash0952b762017-02-28 14:19:09 +00001272#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)
Phil Nashdd26e882013-03-25 09:25:31 +00001273#endif
1274
Phil Nash17404952014-04-23 18:19:49 +01001275#include <cstddef>
1276
Phil Nash89d2a3f2012-05-16 15:09:17 +01001277namespace Catch {
1278namespace Internal {
1279
1280 enum Operator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001281 IsEqualTo,
1282 IsNotEqualTo,
1283 IsLessThan,
1284 IsGreaterThan,
1285 IsLessThanOrEqualTo,
1286 IsGreaterThanOrEqualTo
1287 };
1288
Phil Nash371db8b2012-05-21 18:52:09 +01001289 template<Operator Op> struct OperatorTraits { static const char* getName(){ return "*error*"; } };
1290 template<> struct OperatorTraits<IsEqualTo> { static const char* getName(){ return "=="; } };
1291 template<> struct OperatorTraits<IsNotEqualTo> { static const char* getName(){ return "!="; } };
1292 template<> struct OperatorTraits<IsLessThan> { static const char* getName(){ return "<"; } };
1293 template<> struct OperatorTraits<IsGreaterThan> { static const char* getName(){ return ">"; } };
1294 template<> struct OperatorTraits<IsLessThanOrEqualTo> { static const char* getName(){ return "<="; } };
1295 template<> struct OperatorTraits<IsGreaterThanOrEqualTo>{ static const char* getName(){ return ">="; } };
Phil Nash89d1e6c2011-05-24 08:23:02 +01001296
Phil Nash471eba22013-04-22 18:55:12 +01001297 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01001298 inline T& opCast(T const& t) { return const_cast<T&>(t); }
Phil Nash471eba22013-04-22 18:55:12 +01001299
1300// nullptr_t support based on pull request #154 from Konstantin Baumann
1301#ifdef CATCH_CONFIG_CPP11_NULLPTR
1302 inline std::nullptr_t opCast(std::nullptr_t) { return nullptr; }
1303#endif // CATCH_CONFIG_CPP11_NULLPTR
1304
Phil Nash89d1e6c2011-05-24 08:23:02 +01001305 // So the compare overloads can be operator agnostic we convey the operator as a template
1306 // enum, which is used to specialise an Evaluator for doing the comparison.
1307 template<typename T1, typename T2, Operator Op>
1308 class Evaluator{};
1309
1310 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001311 struct Evaluator<T1, T2, IsEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001312 static bool evaluate( T1 const& lhs, T2 const& rhs) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001313 return bool( opCast( lhs ) == opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001314 }
1315 };
1316 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001317 struct Evaluator<T1, T2, IsNotEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001318 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001319 return bool( opCast( lhs ) != opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001320 }
1321 };
1322 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001323 struct Evaluator<T1, T2, IsLessThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001324 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001325 return bool( opCast( lhs ) < opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001326 }
1327 };
1328 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001329 struct Evaluator<T1, T2, IsGreaterThan> {
Phil Nash8defc712013-04-24 19:10:02 +01001330 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001331 return bool( opCast( lhs ) > opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001332 }
1333 };
1334 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001335 struct Evaluator<T1, T2, IsGreaterThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001336 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001337 return bool( opCast( lhs ) >= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001338 }
1339 };
1340 template<typename T1, typename T2>
Phil Nash89d2a3f2012-05-16 15:09:17 +01001341 struct Evaluator<T1, T2, IsLessThanOrEqualTo> {
Phil Nash8defc712013-04-24 19:10:02 +01001342 static bool evaluate( T1 const& lhs, T2 const& rhs ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00001343 return bool( opCast( lhs ) <= opCast( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001344 }
1345 };
1346
1347 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001348 bool applyEvaluator( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001349 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1350 }
1351
Phil Nash90a35942012-11-13 22:04:29 +00001352 // This level of indirection allows us to specialise for integer types
1353 // to avoid signed/ unsigned warnings
1354
Phil Nash89d1e6c2011-05-24 08:23:02 +01001355 // "base" overload
1356 template<Operator Op, typename T1, typename T2>
Phil Nash8defc712013-04-24 19:10:02 +01001357 bool compare( T1 const& lhs, T2 const& rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001358 return Evaluator<T1, T2, Op>::evaluate( lhs, rhs );
1359 }
1360
1361 // unsigned X to int
Phil Nash89d2a3f2012-05-16 15:09:17 +01001362 template<Operator Op> bool compare( unsigned int lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001363 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1364 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001365 template<Operator Op> bool compare( unsigned long lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001366 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1367 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001368 template<Operator Op> bool compare( unsigned char lhs, int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001369 return applyEvaluator<Op>( lhs, static_cast<unsigned int>( rhs ) );
1370 }
1371
1372 // unsigned X to long
Phil Nash89d2a3f2012-05-16 15:09:17 +01001373 template<Operator Op> bool compare( unsigned int lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001374 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1375 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001376 template<Operator Op> bool compare( unsigned long lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001377 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1378 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001379 template<Operator Op> bool compare( unsigned char lhs, long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001380 return applyEvaluator<Op>( lhs, static_cast<unsigned long>( rhs ) );
1381 }
1382
1383 // int to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001384 template<Operator Op> bool compare( int lhs, unsigned int rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001385 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1386 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001387 template<Operator Op> bool compare( int lhs, unsigned long rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001388 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1389 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001390 template<Operator Op> bool compare( int lhs, unsigned char rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001391 return applyEvaluator<Op>( static_cast<unsigned int>( lhs ), rhs );
1392 }
1393
1394 // long to unsigned X
Phil Nash89d2a3f2012-05-16 15:09:17 +01001395 template<Operator Op> bool compare( long lhs, unsigned int rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001396 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001397 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001398 template<Operator Op> bool compare( long lhs, unsigned long rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001399 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001400 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001401 template<Operator Op> bool compare( long lhs, unsigned char rhs ) {
Jardel Weyrich11dca662012-04-27 14:42:40 -03001402 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001403 }
1404
Phil Nash06e959b2012-05-25 08:52:05 +01001405 // pointer to long (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001406 template<Operator Op, typename T> bool compare( long lhs, T* rhs ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01001407 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
Phil Nash6f1543b2012-05-07 19:46:19 +01001408 }
Phil Nash90a35942012-11-13 22:04:29 +00001409 template<Operator Op, typename T> bool compare( T* lhs, long rhs ) {
Phil Nash6f1543b2012-05-07 19:46:19 +01001410 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
Phil Nash89d1e6c2011-05-24 08:23:02 +01001411 }
1412
Phil Nash06e959b2012-05-25 08:52:05 +01001413 // pointer to int (when comparing against NULL)
Phil Nash90a35942012-11-13 22:04:29 +00001414 template<Operator Op, typename T> bool compare( int lhs, T* rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001415 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1416 }
Phil Nash90a35942012-11-13 22:04:29 +00001417 template<Operator Op, typename T> bool compare( T* lhs, int rhs ) {
Phil Nash06e959b2012-05-25 08:52:05 +01001418 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1419 }
1420
Phil Nash2f6371f2015-07-23 23:06:26 +01001421#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1422 // long long to unsigned X
1423 template<Operator Op> bool compare( long long lhs, unsigned int rhs ) {
1424 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1425 }
1426 template<Operator Op> bool compare( long long lhs, unsigned long rhs ) {
1427 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1428 }
1429 template<Operator Op> bool compare( long long lhs, unsigned long long rhs ) {
1430 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1431 }
1432 template<Operator Op> bool compare( long long lhs, unsigned char rhs ) {
1433 return applyEvaluator<Op>( static_cast<unsigned long>( lhs ), rhs );
1434 }
1435
1436 // unsigned long long to X
1437 template<Operator Op> bool compare( unsigned long long lhs, int rhs ) {
1438 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1439 }
1440 template<Operator Op> bool compare( unsigned long long lhs, long rhs ) {
1441 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1442 }
1443 template<Operator Op> bool compare( unsigned long long lhs, long long rhs ) {
1444 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1445 }
1446 template<Operator Op> bool compare( unsigned long long lhs, char rhs ) {
1447 return applyEvaluator<Op>( static_cast<long>( lhs ), rhs );
1448 }
1449
1450 // pointer to long long (when comparing against NULL)
1451 template<Operator Op, typename T> bool compare( long long lhs, T* rhs ) {
1452 return Evaluator<T*, T*, Op>::evaluate( reinterpret_cast<T*>( lhs ), rhs );
1453 }
1454 template<Operator Op, typename T> bool compare( T* lhs, long long rhs ) {
1455 return Evaluator<T*, T*, Op>::evaluate( lhs, reinterpret_cast<T*>( rhs ) );
1456 }
1457#endif // CATCH_CONFIG_CPP11_LONG_LONG
1458
Phil Nash471eba22013-04-22 18:55:12 +01001459#ifdef CATCH_CONFIG_CPP11_NULLPTR
1460 // pointer to nullptr_t (when comparing against nullptr)
1461 template<Operator Op, typename T> bool compare( std::nullptr_t, T* rhs ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001462 return Evaluator<T*, T*, Op>::evaluate( nullptr, rhs );
Phil Nash471eba22013-04-22 18:55:12 +01001463 }
1464 template<Operator Op, typename T> bool compare( T* lhs, std::nullptr_t ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01001465 return Evaluator<T*, T*, Op>::evaluate( lhs, nullptr );
Phil Nash471eba22013-04-22 18:55:12 +01001466 }
1467#endif // CATCH_CONFIG_CPP11_NULLPTR
1468
Phil Nash89d1e6c2011-05-24 08:23:02 +01001469} // end of namespace Internal
1470} // end of namespace Catch
1471
Phil Nashdd26e882013-03-25 09:25:31 +00001472#ifdef _MSC_VER
1473#pragma warning(pop)
1474#endif
1475
Phil Nashab036682014-06-02 07:48:03 +01001476// #included from: catch_tostring.h
1477#define TWOBLUECUBES_CATCH_TOSTRING_H_INCLUDED
1478
Phil Nashab036682014-06-02 07:48:03 +01001479#include <sstream>
1480#include <iomanip>
1481#include <limits>
1482#include <vector>
1483#include <cstddef>
1484
1485#ifdef __OBJC__
1486// #included from: catch_objc_arc.hpp
1487#define TWOBLUECUBES_CATCH_OBJC_ARC_HPP_INCLUDED
1488
1489#import <Foundation/Foundation.h>
1490
1491#ifdef __has_feature
1492#define CATCH_ARC_ENABLED __has_feature(objc_arc)
1493#else
1494#define CATCH_ARC_ENABLED 0
1495#endif
1496
1497void arcSafeRelease( NSObject* obj );
1498id performOptionalSelector( id obj, SEL sel );
1499
1500#if !CATCH_ARC_ENABLED
1501inline void arcSafeRelease( NSObject* obj ) {
1502 [obj release];
1503}
1504inline id performOptionalSelector( id obj, SEL sel ) {
1505 if( [obj respondsToSelector: sel] )
1506 return [obj performSelector: sel];
1507 return nil;
1508}
1509#define CATCH_UNSAFE_UNRETAINED
1510#define CATCH_ARC_STRONG
1511#else
1512inline void arcSafeRelease( NSObject* ){}
1513inline id performOptionalSelector( id obj, SEL sel ) {
1514#ifdef __clang__
1515#pragma clang diagnostic push
1516#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
1517#endif
1518 if( [obj respondsToSelector: sel] )
1519 return [obj performSelector: sel];
1520#ifdef __clang__
1521#pragma clang diagnostic pop
1522#endif
1523 return nil;
1524}
1525#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained
1526#define CATCH_ARC_STRONG __strong
1527#endif
1528
1529#endif
1530
Phil Nash318c9362015-05-19 18:40:00 +01001531#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001532#include <tuple>
Phil Nash318c9362015-05-19 18:40:00 +01001533#endif
1534
1535#ifdef CATCH_CONFIG_CPP11_IS_ENUM
Phil Nash7f561522014-12-30 18:47:29 +00001536#include <type_traits>
1537#endif
1538
Phil Nashab036682014-06-02 07:48:03 +01001539namespace Catch {
Phil Nash4caabfa2014-09-03 19:23:22 +01001540
1541// Why we're here.
1542template<typename T>
1543std::string toString( T const& value );
1544
Phil Nash7f561522014-12-30 18:47:29 +00001545// Built in overloads
1546
1547std::string toString( std::string const& value );
1548std::string toString( std::wstring const& value );
1549std::string toString( const char* const value );
1550std::string toString( char* const value );
1551std::string toString( const wchar_t* const value );
1552std::string toString( wchar_t* const value );
1553std::string toString( int value );
1554std::string toString( unsigned long value );
1555std::string toString( unsigned int value );
1556std::string toString( const double value );
1557std::string toString( const float value );
1558std::string toString( bool value );
1559std::string toString( char value );
1560std::string toString( signed char value );
1561std::string toString( unsigned char value );
1562
Phil Nash2f6371f2015-07-23 23:06:26 +01001563#ifdef CATCH_CONFIG_CPP11_LONG_LONG
1564std::string toString( long long value );
1565std::string toString( unsigned long long value );
1566#endif
1567
Phil Nash7f561522014-12-30 18:47:29 +00001568#ifdef CATCH_CONFIG_CPP11_NULLPTR
1569std::string toString( std::nullptr_t );
1570#endif
1571
1572#ifdef __OBJC__
1573 std::string toString( NSString const * const& nsstring );
1574 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring );
1575 std::string toString( NSObject* const& nsObject );
1576#endif
1577
Phil Nashab036682014-06-02 07:48:03 +01001578namespace Detail {
1579
Phil Nash2f6371f2015-07-23 23:06:26 +01001580 extern const std::string unprintableString;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001581
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02001582 #if !defined(CATCH_CONFIG_CPP11_STREAM_INSERTABLE_CHECK)
Phil Nashab036682014-06-02 07:48:03 +01001583 struct BorgType {
1584 template<typename T> BorgType( T const& );
1585 };
1586
Phil Nash3b18d9e2015-06-30 18:26:09 +01001587 struct TrueType { char sizer[1]; };
1588 struct FalseType { char sizer[2]; };
1589
Phil Nashab036682014-06-02 07:48:03 +01001590 TrueType& testStreamable( std::ostream& );
1591 FalseType testStreamable( FalseType );
1592
1593 FalseType operator<<( std::ostream const&, BorgType const& );
1594
1595 template<typename T>
1596 struct IsStreamInsertable {
1597 static std::ostream &s;
1598 static T const&t;
1599 enum { value = sizeof( testStreamable(s << t) ) == sizeof( TrueType ) };
1600 };
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02001601#else
1602 template<typename T>
1603 class IsStreamInsertable {
1604 template<typename SS, typename TT>
1605 static auto test(int)
1606 -> decltype( std::declval<SS&>() << std::declval<TT>(), std::true_type() );
1607
1608 template<typename, typename>
1609 static auto test(...) -> std::false_type;
1610
1611 public:
1612 static const bool value = decltype(test<std::ostream,const T&>(0))::value;
1613 };
1614#endif
Phil Nashab036682014-06-02 07:48:03 +01001615
Phil Nash318c9362015-05-19 18:40:00 +01001616#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001617 template<typename T,
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001618 bool IsEnum = std::is_enum<T>::value
Phil Nash4caabfa2014-09-03 19:23:22 +01001619 >
1620 struct EnumStringMaker
1621 {
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001622 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001623 };
1624
1625 template<typename T>
1626 struct EnumStringMaker<T,true>
1627 {
1628 static std::string convert( T const& v )
1629 {
1630 return ::Catch::toString(
1631 static_cast<typename std::underlying_type<T>::type>(v)
1632 );
1633 }
1634 };
1635#endif
Phil Nashab036682014-06-02 07:48:03 +01001636 template<bool C>
1637 struct StringMakerBase {
Phil Nash318c9362015-05-19 18:40:00 +01001638#if defined(CATCH_CONFIG_CPP11_IS_ENUM)
Phil Nash4caabfa2014-09-03 19:23:22 +01001639 template<typename T>
1640 static std::string convert( T const& v )
1641 {
1642 return EnumStringMaker<T>::convert( v );
1643 }
1644#else
Phil Nashab036682014-06-02 07:48:03 +01001645 template<typename T>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001646 static std::string convert( T const& ) { return unprintableString; }
Phil Nash4caabfa2014-09-03 19:23:22 +01001647#endif
Phil Nashab036682014-06-02 07:48:03 +01001648 };
1649
1650 template<>
1651 struct StringMakerBase<true> {
1652 template<typename T>
1653 static std::string convert( T const& _value ) {
1654 std::ostringstream oss;
1655 oss << _value;
1656 return oss.str();
1657 }
1658 };
1659
1660 std::string rawMemoryToString( const void *object, std::size_t size );
1661
1662 template<typename T>
1663 inline std::string rawMemoryToString( const T& object ) {
1664 return rawMemoryToString( &object, sizeof(object) );
Phil Nash67305122012-10-09 11:48:55 +01001665 }
1666
Phil Nashab036682014-06-02 07:48:03 +01001667} // end namespace Detail
Phil Nashce612bf2012-11-01 08:27:09 +00001668
Phil Nashab036682014-06-02 07:48:03 +01001669template<typename T>
Phil Nashab036682014-06-02 07:48:03 +01001670struct StringMaker :
1671 Detail::StringMakerBase<Detail::IsStreamInsertable<T>::value> {};
Phil Nashcd688302013-06-29 12:11:32 +01001672
Phil Nashab036682014-06-02 07:48:03 +01001673template<typename T>
1674struct StringMaker<T*> {
1675 template<typename U>
1676 static std::string convert( U* p ) {
1677 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001678 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001679 else
1680 return Detail::rawMemoryToString( p );
1681 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01001682};
1683
Phil Nashab036682014-06-02 07:48:03 +01001684template<typename R, typename C>
1685struct StringMaker<R C::*> {
1686 static std::string convert( R C::* p ) {
1687 if( !p )
Phil Nashb971fe72015-07-02 08:21:38 +01001688 return "NULL";
Phil Nashab036682014-06-02 07:48:03 +01001689 else
1690 return Detail::rawMemoryToString( p );
1691 }
1692};
1693
1694namespace Detail {
1695 template<typename InputIterator>
1696 std::string rangeToString( InputIterator first, InputIterator last );
1697}
1698
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001699//template<typename T, typename Allocator>
1700//struct StringMaker<std::vector<T, Allocator> > {
1701// static std::string convert( std::vector<T,Allocator> const& v ) {
1702// return Detail::rangeToString( v.begin(), v.end() );
1703// }
1704//};
1705
Phil Nashab036682014-06-02 07:48:03 +01001706template<typename T, typename Allocator>
Phil Nash6a8e8ad2014-09-15 18:40:24 +01001707std::string toString( std::vector<T,Allocator> const& v ) {
1708 return Detail::rangeToString( v.begin(), v.end() );
1709}
Phil Nashab036682014-06-02 07:48:03 +01001710
Phil Nash318c9362015-05-19 18:40:00 +01001711#ifdef CATCH_CONFIG_CPP11_TUPLE
Phil Nash572911d2015-03-04 18:33:31 +00001712
1713// toString for tuples
Phil Nash7f561522014-12-30 18:47:29 +00001714namespace TupleDetail {
1715 template<
1716 typename Tuple,
1717 std::size_t N = 0,
1718 bool = (N < std::tuple_size<Tuple>::value)
1719 >
1720 struct ElementPrinter {
1721 static void print( const Tuple& tuple, std::ostream& os )
1722 {
1723 os << ( N ? ", " : " " )
1724 << Catch::toString(std::get<N>(tuple));
1725 ElementPrinter<Tuple,N+1>::print(tuple,os);
1726 }
1727 };
1728
1729 template<
1730 typename Tuple,
1731 std::size_t N
1732 >
1733 struct ElementPrinter<Tuple,N,false> {
1734 static void print( const Tuple&, std::ostream& ) {}
1735 };
1736
1737}
1738
1739template<typename ...Types>
1740struct StringMaker<std::tuple<Types...>> {
1741
1742 static std::string convert( const std::tuple<Types...>& tuple )
1743 {
1744 std::ostringstream os;
1745 os << '{';
1746 TupleDetail::ElementPrinter<std::tuple<Types...>>::print( tuple, os );
1747 os << " }";
1748 return os.str();
1749 }
1750};
Phil Nash318c9362015-05-19 18:40:00 +01001751#endif // CATCH_CONFIG_CPP11_TUPLE
Phil Nash7f561522014-12-30 18:47:29 +00001752
Phil Nashab036682014-06-02 07:48:03 +01001753namespace Detail {
1754 template<typename T>
1755 std::string makeString( T const& value ) {
1756 return StringMaker<T>::convert( value );
1757 }
1758} // end namespace Detail
1759
1760/// \brief converts any type to a string
1761///
1762/// The default template forwards on to ostringstream - except when an
1763/// ostringstream overload does not exist - in which case it attempts to detect
1764/// that and writes {?}.
1765/// Overload (not specialise) this template for custom typs that you don't want
1766/// to provide an ostream overload for.
1767template<typename T>
1768std::string toString( T const& value ) {
1769 return StringMaker<T>::convert( value );
1770}
1771
Phil Nashab036682014-06-02 07:48:03 +01001772 namespace Detail {
1773 template<typename InputIterator>
1774 std::string rangeToString( InputIterator first, InputIterator last ) {
1775 std::ostringstream oss;
1776 oss << "{ ";
1777 if( first != last ) {
Phil Nash13f98432014-12-12 08:11:18 +00001778 oss << Catch::toString( *first );
1779 for( ++first ; first != last ; ++first )
1780 oss << ", " << Catch::toString( *first );
Phil Nashab036682014-06-02 07:48:03 +01001781 }
1782 oss << " }";
1783 return oss.str();
1784 }
1785}
1786
Phil Nashd31737f2012-05-09 19:04:00 +01001787} // end namespace Catch
1788
Phil Nash89d2a3f2012-05-16 15:09:17 +01001789namespace Catch {
Phil Nash176eb812012-05-11 08:17:16 +01001790
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001791template<typename LhsT, Internal::Operator Op, typename RhsT>
1792class BinaryExpression;
Phil Nash176eb812012-05-11 08:17:16 +01001793
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001794template<typename ArgT, typename MatcherT>
1795class MatchExpression;
1796
1797// Wraps the LHS of an expression and overloads comparison operators
1798// for also capturing those and RHS (if any)
1799template<typename T>
1800class ExpressionLhs : public DecomposedExpression {
Phil Nash176eb812012-05-11 08:17:16 +01001801public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001802 ExpressionLhs( ResultBuilder& rb, T lhs ) : m_rb( rb ), m_lhs( lhs ), m_truthy(false) {}
Phil Nash176eb812012-05-11 08:17:16 +01001803
Phil Nash0952b762017-02-28 14:19:09 +00001804 ExpressionLhs& operator = ( const ExpressionLhs& );
1805
Phil Nash176eb812012-05-11 08:17:16 +01001806 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001807 BinaryExpression<T, Internal::IsEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001808 operator == ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001809 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001810 }
1811
1812 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001813 BinaryExpression<T, Internal::IsNotEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001814 operator != ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001815 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001816 }
1817
1818 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001819 BinaryExpression<T, Internal::IsLessThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001820 operator < ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001821 return captureExpression<Internal::IsLessThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001822 }
1823
1824 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001825 BinaryExpression<T, Internal::IsGreaterThan, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001826 operator > ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001827 return captureExpression<Internal::IsGreaterThan>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001828 }
1829
1830 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001831 BinaryExpression<T, Internal::IsLessThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001832 operator <= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001833 return captureExpression<Internal::IsLessThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001834 }
1835
1836 template<typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001837 BinaryExpression<T, Internal::IsGreaterThanOrEqualTo, RhsT const&>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001838 operator >= ( RhsT const& rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001839 return captureExpression<Internal::IsGreaterThanOrEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001840 }
1841
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001842 BinaryExpression<T, Internal::IsEqualTo, bool> operator == ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001843 return captureExpression<Internal::IsEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001844 }
1845
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01001846 BinaryExpression<T, Internal::IsNotEqualTo, bool> operator != ( bool rhs ) {
Phil Nash9902ac92012-10-09 20:58:33 +01001847 return captureExpression<Internal::IsNotEqualTo>( rhs );
Phil Nash176eb812012-05-11 08:17:16 +01001848 }
1849
Phil Nashab036682014-06-02 07:48:03 +01001850 void endExpression() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001851 m_truthy = m_lhs ? true : false;
Phil Nashab036682014-06-02 07:48:03 +01001852 m_rb
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001853 .setResultType( m_truthy )
1854 .endExpression( *this );
Phil Nash176eb812012-05-11 08:17:16 +01001855 }
1856
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001857 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1858 dest = Catch::toString( m_truthy );
1859 }
Phil Nash176eb812012-05-11 08:17:16 +01001860
1861private:
Phil Nash9902ac92012-10-09 20:58:33 +01001862 template<Internal::Operator Op, typename RhsT>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001863 BinaryExpression<T, Op, RhsT&> captureExpression( RhsT& rhs ) const {
1864 return BinaryExpression<T, Op, RhsT&>( m_rb, m_lhs, rhs );
1865 }
1866
1867 template<Internal::Operator Op>
1868 BinaryExpression<T, Op, bool> captureExpression( bool rhs ) const {
1869 return BinaryExpression<T, Op, bool>( m_rb, m_lhs, rhs );
Phil Nash9902ac92012-10-09 20:58:33 +01001870 }
1871
1872private:
Phil Nashab036682014-06-02 07:48:03 +01001873 ResultBuilder& m_rb;
Phil Nash176eb812012-05-11 08:17:16 +01001874 T m_lhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001875 bool m_truthy;
1876};
1877
1878template<typename LhsT, Internal::Operator Op, typename RhsT>
1879class BinaryExpression : public DecomposedExpression {
1880public:
1881 BinaryExpression( ResultBuilder& rb, LhsT lhs, RhsT rhs )
1882 : m_rb( rb ), m_lhs( lhs ), m_rhs( rhs ) {}
1883
Phil Nash0952b762017-02-28 14:19:09 +00001884 BinaryExpression& operator = ( BinaryExpression& );
1885
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001886 void endExpression() const {
1887 m_rb
1888 .setResultType( Internal::compare<Op>( m_lhs, m_rhs ) )
1889 .endExpression( *this );
1890 }
1891
1892 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1893 return true;
1894 }
1895
1896 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1897 std::string lhs = Catch::toString( m_lhs );
1898 std::string rhs = Catch::toString( m_rhs );
1899 char delim = lhs.size() + rhs.size() < 40 &&
1900 lhs.find('\n') == std::string::npos &&
1901 rhs.find('\n') == std::string::npos ? ' ' : '\n';
1902 dest.reserve( 7 + lhs.size() + rhs.size() );
1903 // 2 for spaces around operator
1904 // 2 for operator
1905 // 2 for parentheses (conditionally added later)
1906 // 1 for negation (conditionally added later)
1907 dest = lhs;
1908 dest += delim;
1909 dest += Internal::OperatorTraits<Op>::getName();
1910 dest += delim;
1911 dest += rhs;
1912 }
1913
1914private:
1915 ResultBuilder& m_rb;
1916 LhsT m_lhs;
1917 RhsT m_rhs;
1918};
1919
1920template<typename ArgT, typename MatcherT>
1921class MatchExpression : public DecomposedExpression {
1922public:
1923 MatchExpression( ArgT arg, MatcherT matcher, char const* matcherString )
1924 : m_arg( arg ), m_matcher( matcher ), m_matcherString( matcherString ) {}
1925
1926 virtual bool isBinaryExpression() const CATCH_OVERRIDE {
1927 return true;
1928 }
1929
1930 virtual void reconstructExpression( std::string& dest ) const CATCH_OVERRIDE {
1931 std::string matcherAsString = m_matcher.toString();
1932 dest = Catch::toString( m_arg );
1933 dest += ' ';
1934 if( matcherAsString == Detail::unprintableString )
1935 dest += m_matcherString;
1936 else
1937 dest += matcherAsString;
1938 }
1939
1940private:
1941 ArgT m_arg;
1942 MatcherT m_matcher;
1943 char const* m_matcherString;
Phil Nash176eb812012-05-11 08:17:16 +01001944};
1945
Phil Nash176eb812012-05-11 08:17:16 +01001946} // end namespace Catch
1947
Phil Nashab036682014-06-02 07:48:03 +01001948
Phil Nash89d2a3f2012-05-16 15:09:17 +01001949namespace Catch {
1950
Phil Nash89d2a3f2012-05-16 15:09:17 +01001951 template<typename T>
Phil Nash21f7ef62015-06-29 18:05:23 +01001952 inline ExpressionLhs<T const&> ResultBuilder::operator <= ( T const& operand ) {
Phil Nashab036682014-06-02 07:48:03 +01001953 return ExpressionLhs<T const&>( *this, operand );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001954 }
1955
Phil Nash21f7ef62015-06-29 18:05:23 +01001956 inline ExpressionLhs<bool> ResultBuilder::operator <= ( bool value ) {
Phil Nashab036682014-06-02 07:48:03 +01001957 return ExpressionLhs<bool>( *this, value );
Phil Nash89d2a3f2012-05-16 15:09:17 +01001958 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01001959
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01001960 template<typename ArgT, typename MatcherT>
1961 inline void ResultBuilder::captureMatch( ArgT const& arg, MatcherT const& matcher,
1962 char const* matcherString ) {
1963 MatchExpression<ArgT const&, MatcherT const&> expr( arg, matcher, matcherString );
1964 setResultType( matcher.match( arg ) );
1965 endExpression( expr );
1966 }
1967
Phil Nashab036682014-06-02 07:48:03 +01001968} // namespace Catch
Phil Nash89d2a3f2012-05-16 15:09:17 +01001969
Phil Nasha2773812013-02-02 20:37:58 +00001970// #included from: catch_message.h
1971#define TWOBLUECUBES_CATCH_MESSAGE_H_INCLUDED
1972
1973#include <string>
1974
1975namespace Catch {
1976
1977 struct MessageInfo {
1978 MessageInfo( std::string const& _macroName,
1979 SourceLineInfo const& _lineInfo,
1980 ResultWas::OfType _type );
1981
1982 std::string macroName;
1983 SourceLineInfo lineInfo;
1984 ResultWas::OfType type;
1985 std::string message;
1986 unsigned int sequence;
1987
1988 bool operator == ( MessageInfo const& other ) const {
1989 return sequence == other.sequence;
1990 }
1991 bool operator < ( MessageInfo const& other ) const {
1992 return sequence < other.sequence;
1993 }
1994 private:
1995 static unsigned int globalCount;
1996 };
1997
Phil Nashb5fd5a62013-06-28 17:09:57 +01001998 struct MessageBuilder {
1999 MessageBuilder( std::string const& macroName,
2000 SourceLineInfo const& lineInfo,
2001 ResultWas::OfType type )
2002 : m_info( macroName, lineInfo, type )
2003 {}
Phil Nasha2773812013-02-02 20:37:58 +00002004
2005 template<typename T>
Phil Nashb5fd5a62013-06-28 17:09:57 +01002006 MessageBuilder& operator << ( T const& value ) {
2007 m_stream << value;
Phil Nasha2773812013-02-02 20:37:58 +00002008 return *this;
2009 }
Phil Nashb5fd5a62013-06-28 17:09:57 +01002010
2011 MessageInfo m_info;
2012 std::ostringstream m_stream;
Phil Nasha2773812013-02-02 20:37:58 +00002013 };
2014
Phil Nashb5fd5a62013-06-28 17:09:57 +01002015 class ScopedMessage {
Phil Nasha2773812013-02-02 20:37:58 +00002016 public:
Phil Nashb5fd5a62013-06-28 17:09:57 +01002017 ScopedMessage( MessageBuilder const& builder );
Phil Nash9241e432014-05-20 18:50:59 +01002018 ScopedMessage( ScopedMessage const& other );
Phil Nashb5fd5a62013-06-28 17:09:57 +01002019 ~ScopedMessage();
2020
2021 MessageInfo m_info;
Phil Nasha2773812013-02-02 20:37:58 +00002022 };
2023
2024} // end namespace Catch
2025
Phil Nashd31737f2012-05-09 19:04:00 +01002026// #included from: catch_interfaces_capture.h
Phil Nash3b80af72012-08-09 07:47:30 +01002027#define TWOBLUECUBES_CATCH_INTERFACES_CAPTURE_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01002028
Phil Nashd31737f2012-05-09 19:04:00 +01002029#include <string>
2030
Phil Nash89d2a3f2012-05-16 15:09:17 +01002031namespace Catch {
2032
Phil Nasha1fbfea2012-12-01 23:57:18 +00002033 class TestCase;
Phil Nashce612bf2012-11-01 08:27:09 +00002034 class AssertionResult;
2035 struct AssertionInfo;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002036 struct SectionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002037 struct SectionEndInfo;
Phil Nashb5fd5a62013-06-28 17:09:57 +01002038 struct MessageInfo;
Phil Nasha2773812013-02-02 20:37:58 +00002039 class ScopedMessageBuilder;
Phil Nash3649fdf2013-12-03 18:53:55 +00002040 struct Counts;
Phil Nashd31737f2012-05-09 19:04:00 +01002041
Phil Nash89d2a3f2012-05-16 15:09:17 +01002042 struct IResultCapture {
Phil Nashd31737f2012-05-09 19:04:00 +01002043
Phil Nasha695eb92012-08-13 07:46:10 +01002044 virtual ~IResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002045
Phil Nasha2773812013-02-02 20:37:58 +00002046 virtual void assertionEnded( AssertionResult const& result ) = 0;
Phil Nasha1fbfea2012-12-01 23:57:18 +00002047 virtual bool sectionStarted( SectionInfo const& sectionInfo,
Phil Nash89d2a3f2012-05-16 15:09:17 +01002048 Counts& assertions ) = 0;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002049 virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;
2050 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;
Phil Nashb5fd5a62013-06-28 17:09:57 +01002051 virtual void pushScopedMessage( MessageInfo const& message ) = 0;
2052 virtual void popScopedMessage( MessageInfo const& message ) = 0;
Phil Nasha2773812013-02-02 20:37:58 +00002053
Phil Nash89d2a3f2012-05-16 15:09:17 +01002054 virtual std::string getCurrentTestName() const = 0;
Phil Nashce612bf2012-11-01 08:27:09 +00002055 virtual const AssertionResult* getLastResult() const = 0;
Phil Nash93b61e12014-08-22 19:35:41 +01002056
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002057 virtual void exceptionEarlyReported() = 0;
2058
Phil Nash93b61e12014-08-22 19:35:41 +01002059 virtual void handleFatalErrorCondition( std::string const& message ) = 0;
Phil Nashd31737f2012-05-09 19:04:00 +01002060 };
Phil Nashab036682014-06-02 07:48:03 +01002061
2062 IResultCapture& getResultCapture();
Phil Nashd31737f2012-05-09 19:04:00 +01002063}
2064
Phil Nash3649fdf2013-12-03 18:53:55 +00002065// #included from: catch_debugger.h
2066#define TWOBLUECUBES_CATCH_DEBUGGER_H_INCLUDED
Phil Nashd31737f2012-05-09 19:04:00 +01002067
Phil Nash04a33642013-08-16 19:09:09 +01002068// #included from: catch_platform.h
2069#define TWOBLUECUBES_CATCH_PLATFORM_H_INCLUDED
2070
Phil Nashd31737f2012-05-09 19:04:00 +01002071#if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002072# define CATCH_PLATFORM_MAC
Phil Nashd31737f2012-05-09 19:04:00 +01002073#elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002074# define CATCH_PLATFORM_IPHONE
2075#elif defined(linux) || defined(__linux) || defined(__linux__)
2076# define CATCH_PLATFORM_LINUX
Phil Nash04a33642013-08-16 19:09:09 +01002077#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002078# define CATCH_PLATFORM_WINDOWS
2079# if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)
2080# define CATCH_DEFINES_NOMINMAX
2081# endif
2082# if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)
2083# define CATCH_DEFINES_WIN32_LEAN_AND_MEAN
2084# endif
Phil Nashd31737f2012-05-09 19:04:00 +01002085#endif
2086
Phil Nash3649fdf2013-12-03 18:53:55 +00002087#include <string>
2088
2089namespace Catch{
2090
2091 bool isDebuggerActive();
2092 void writeToDebugConsole( std::string const& text );
2093}
2094
Phil Nashd31737f2012-05-09 19:04:00 +01002095#ifdef CATCH_PLATFORM_MAC
2096
Phil Nash3649fdf2013-12-03 18:53:55 +00002097 // The following code snippet based on:
Phil Nashd31737f2012-05-09 19:04:00 +01002098 // http://cocoawithlove.com/2008/03/break-into-debugger.html
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002099 #if defined(__ppc64__) || defined(__ppc__)
2100 #define CATCH_TRAP() \
2101 __asm__("li r0, 20\nsc\nnop\nli r0, 37\nli r4, 2\nsc\nnop\n" \
2102 : : : "memory","r0","r3","r4" )
2103 #else
2104 #define CATCH_TRAP() __asm__("int $3\n" : : )
Phil Nashd31737f2012-05-09 19:04:00 +01002105 #endif
2106
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002107#elif defined(CATCH_PLATFORM_LINUX)
2108 // If we can use inline assembler, do it because this allows us to break
2109 // directly at the location of the failing check instead of breaking inside
2110 // raise() called from it, i.e. one stack frame below.
2111 #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))
2112 #define CATCH_TRAP() asm volatile ("int $3")
2113 #else // Fall back to the generic way.
2114 #include <signal.h>
2115
2116 #define CATCH_TRAP() raise(SIGTRAP)
2117 #endif
Phil Nashd31737f2012-05-09 19:04:00 +01002118#elif defined(_MSC_VER)
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002119 #define CATCH_TRAP() __debugbreak()
Phil Nash176eb812012-05-11 08:17:16 +01002120#elif defined(__MINGW32__)
Phil Nash176eb812012-05-11 08:17:16 +01002121 extern "C" __declspec(dllimport) void __stdcall DebugBreak();
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002122 #define CATCH_TRAP() DebugBreak()
Phil Nashd31737f2012-05-09 19:04:00 +01002123#endif
2124
Martin Hořeňovský9a566092017-01-20 12:49:59 +01002125#ifdef CATCH_TRAP
2126 #define CATCH_BREAK_INTO_DEBUGGER() if( Catch::isDebuggerActive() ) { CATCH_TRAP(); }
2127#else
2128 #define CATCH_BREAK_INTO_DEBUGGER() Catch::alwaysTrue();
Phil Nash3649fdf2013-12-03 18:53:55 +00002129#endif
Phil Nashd31737f2012-05-09 19:04:00 +01002130
Phil Nashab036682014-06-02 07:48:03 +01002131// #included from: catch_interfaces_runner.h
2132#define TWOBLUECUBES_CATCH_INTERFACES_RUNNER_H_INCLUDED
Phil Nash37186a12013-03-13 12:19:30 +00002133
Phil Nasha70fbe32012-08-31 08:10:36 +01002134namespace Catch {
Phil Nash3649fdf2013-12-03 18:53:55 +00002135 class TestCase;
Phil Nasha70fbe32012-08-31 08:10:36 +01002136
Phil Nashab036682014-06-02 07:48:03 +01002137 struct IRunner {
2138 virtual ~IRunner();
2139 virtual bool aborting() const = 0;
Phil Nasha70fbe32012-08-31 08:10:36 +01002140 };
2141}
2142
Phil Nash0952b762017-02-28 14:19:09 +00002143#if defined(CATCH_CONFIG_FAST_COMPILE)
2144///////////////////////////////////////////////////////////////////////////////
2145// We can speedup compilation significantly by breaking into debugger lower in
2146// the callstack, because then we don't have to expand CATCH_BREAK_INTO_DEBUGGER
2147// macro in each assertion
2148#define INTERNAL_CATCH_REACT( resultBuilder ) \
2149 resultBuilder.react();
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002150
2151///////////////////////////////////////////////////////////////////////////////
2152// Another way to speed-up compilation is to omit local try-catch for REQUIRE*
2153// macros.
2154// This can potentially cause false negative, if the test code catches
2155// the exception before it propagates back up to the runner.
2156#define INTERNAL_CATCH_TEST_NO_TRY( macroName, resultDisposition, expr ) \
2157 do { \
2158 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
2159 __catchResult.setExceptionGuard(); \
2160 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
2161 ( __catchResult <= expr ).endExpression(); \
2162 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
2163 __catchResult.unsetExceptionGuard(); \
2164 INTERNAL_CATCH_REACT( __catchResult ) \
2165 } 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
2166// The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&.
2167
2168#define INTERNAL_CHECK_THAT_NO_TRY( macroName, matcher, resultDisposition, arg ) \
2169 do { \
2170 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
2171 __catchResult.setExceptionGuard(); \
2172 __catchResult.captureMatch( arg, matcher, #matcher ); \
2173 __catchResult.unsetExceptionGuard(); \
2174 INTERNAL_CATCH_REACT( __catchResult ) \
2175 } while( Catch::alwaysFalse() )
2176
Phil Nash0952b762017-02-28 14:19:09 +00002177#else
Phil Nashce612bf2012-11-01 08:27:09 +00002178///////////////////////////////////////////////////////////////////////////////
Phil Nashab036682014-06-02 07:48:03 +01002179// In the event of a failure works out if the debugger needs to be invoked
2180// and/or an exception thrown and takes appropriate action.
2181// This needs to be done as a macro so the debugger will stop in the user
2182// source code rather than in Catch library code
2183#define INTERNAL_CATCH_REACT( resultBuilder ) \
2184 if( resultBuilder.shouldDebugBreak() ) CATCH_BREAK_INTO_DEBUGGER(); \
2185 resultBuilder.react();
Phil Nash0952b762017-02-28 14:19:09 +00002186#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002187
2188///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002189#define INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002190 do { \
Phil Nashab036682014-06-02 07:48:03 +01002191 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002192 try { \
Phil Nashae5ee2c2016-02-29 08:17:18 +00002193 CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
Phil Nash21f7ef62015-06-29 18:05:23 +01002194 ( __catchResult <= expr ).endExpression(); \
Phil Nash0952b762017-02-28 14:19:09 +00002195 CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
Phil Nashce612bf2012-11-01 08:27:09 +00002196 } \
Phil Nashab036682014-06-02 07:48:03 +01002197 catch( ... ) { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002198 __catchResult.useActiveException( resultDisposition ); \
Phil Nashab036682014-06-02 07:48:03 +01002199 } \
2200 INTERNAL_CATCH_REACT( __catchResult ) \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002201 } 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
2202 // 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 +00002203
2204///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002205#define INTERNAL_CATCH_IF( macroName, resultDisposition, expr ) \
2206 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
Phil Nash90a35942012-11-13 22:04:29 +00002207 if( Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002208
2209///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002210#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, expr ) \
2211 INTERNAL_CATCH_TEST( macroName, resultDisposition, expr ); \
Phil Nash90a35942012-11-13 22:04:29 +00002212 if( !Catch::getResultCapture().getLastResult()->succeeded() )
Phil Nashce612bf2012-11-01 08:27:09 +00002213
2214///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002215#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, expr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002216 do { \
Phil Nashab036682014-06-02 07:48:03 +01002217 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002218 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002219 static_cast<void>(expr); \
Phil Nashab036682014-06-02 07:48:03 +01002220 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002221 } \
2222 catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002223 __catchResult.useActiveException( resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002224 } \
Phil Nashab036682014-06-02 07:48:03 +01002225 INTERNAL_CATCH_REACT( __catchResult ) \
2226 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002227
2228///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002229#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, matcher, expr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002230 do { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002231 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr, resultDisposition, #matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002232 if( __catchResult.allowThrows() ) \
2233 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002234 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002235 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2236 } \
2237 catch( ... ) { \
Phil Nash5bbdc8f2015-07-15 23:03:11 +01002238 __catchResult.captureExpectedException( matcher ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002239 } \
2240 else \
Phil Nashab036682014-06-02 07:48:03 +01002241 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002242 INTERNAL_CATCH_REACT( __catchResult ) \
2243 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002244
2245///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002246#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002247 do { \
Phil Nashd08cee22017-02-13 16:15:42 +00002248 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #expr ", " #exceptionType, resultDisposition ); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002249 if( __catchResult.allowThrows() ) \
2250 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002251 static_cast<void>(expr); \
Phil Nashacdd3b52014-06-30 07:35:36 +01002252 __catchResult.captureResult( Catch::ResultWas::DidntThrowException ); \
2253 } \
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002254 catch( exceptionType ) { \
Phil Nashacdd3b52014-06-30 07:35:36 +01002255 __catchResult.captureResult( Catch::ResultWas::Ok ); \
2256 } \
2257 catch( ... ) { \
2258 __catchResult.useActiveException( resultDisposition ); \
2259 } \
2260 else \
Phil Nashab036682014-06-02 07:48:03 +01002261 __catchResult.captureResult( Catch::ResultWas::Ok ); \
Phil Nashab036682014-06-02 07:48:03 +01002262 INTERNAL_CATCH_REACT( __catchResult ) \
2263 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002264
2265///////////////////////////////////////////////////////////////////////////////
Phil Nash859760a2013-12-14 14:34:05 +00002266#ifdef CATCH_CONFIG_VARIADIC_MACROS
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002267 #define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \
Phil Nash859760a2013-12-14 14:34:05 +00002268 do { \
Phil Nashab036682014-06-02 07:48:03 +01002269 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2270 __catchResult << __VA_ARGS__ + ::Catch::StreamEndStop(); \
2271 __catchResult.captureResult( messageType ); \
2272 INTERNAL_CATCH_REACT( __catchResult ) \
2273 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002274#else
2275 #define INTERNAL_CATCH_MSG( messageType, resultDisposition, macroName, log ) \
2276 do { \
Phil Nashab036682014-06-02 07:48:03 +01002277 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, "", resultDisposition ); \
2278 __catchResult << log + ::Catch::StreamEndStop(); \
2279 __catchResult.captureResult( messageType ); \
2280 INTERNAL_CATCH_REACT( __catchResult ) \
2281 } while( Catch::alwaysFalse() )
Phil Nash859760a2013-12-14 14:34:05 +00002282#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002283
2284///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002285#define INTERNAL_CATCH_INFO( macroName, log ) \
Phil Nashb5fd5a62013-06-28 17:09:57 +01002286 Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage ) = Catch::MessageBuilder( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log;
Phil Nashce612bf2012-11-01 08:27:09 +00002287
2288///////////////////////////////////////////////////////////////////////////////
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002289#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \
Phil Nashce612bf2012-11-01 08:27:09 +00002290 do { \
Phil Nash7424b232015-12-28 15:07:32 +00002291 Catch::ResultBuilder __catchResult( macroName, CATCH_INTERNAL_LINEINFO, #arg ", " #matcher, resultDisposition ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002292 try { \
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002293 __catchResult.captureMatch( arg, matcher, #matcher ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002294 } catch( ... ) { \
Phil Nashab036682014-06-02 07:48:03 +01002295 __catchResult.useActiveException( resultDisposition | Catch::ResultDisposition::ContinueOnFailure ); \
Phil Nashce612bf2012-11-01 08:27:09 +00002296 } \
Phil Nashab036682014-06-02 07:48:03 +01002297 INTERNAL_CATCH_REACT( __catchResult ) \
2298 } while( Catch::alwaysFalse() )
Phil Nashce612bf2012-11-01 08:27:09 +00002299
Phil Nash3649fdf2013-12-03 18:53:55 +00002300// #included from: internal/catch_section.h
2301#define TWOBLUECUBES_CATCH_SECTION_H_INCLUDED
2302
2303// #included from: catch_section_info.h
2304#define TWOBLUECUBES_CATCH_SECTION_INFO_H_INCLUDED
2305
Phil Nash3649fdf2013-12-03 18:53:55 +00002306// #included from: catch_totals.hpp
2307#define TWOBLUECUBES_CATCH_TOTALS_HPP_INCLUDED
2308
2309#include <cstddef>
2310
2311namespace Catch {
2312
2313 struct Counts {
Phil Nash52e1e742014-07-03 08:11:38 +01002314 Counts() : passed( 0 ), failed( 0 ), failedButOk( 0 ) {}
Phil Nash3649fdf2013-12-03 18:53:55 +00002315
2316 Counts operator - ( Counts const& other ) const {
2317 Counts diff;
2318 diff.passed = passed - other.passed;
2319 diff.failed = failed - other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002320 diff.failedButOk = failedButOk - other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002321 return diff;
2322 }
2323 Counts& operator += ( Counts const& other ) {
2324 passed += other.passed;
2325 failed += other.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002326 failedButOk += other.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002327 return *this;
2328 }
2329
2330 std::size_t total() const {
Phil Nash52e1e742014-07-03 08:11:38 +01002331 return passed + failed + failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002332 }
Phil Nash28c2e072014-07-09 19:22:49 +01002333 bool allPassed() const {
2334 return failed == 0 && failedButOk == 0;
2335 }
Phil Nashd76e0812014-12-30 18:26:07 +00002336 bool allOk() const {
2337 return failed == 0;
2338 }
Phil Nash3649fdf2013-12-03 18:53:55 +00002339
2340 std::size_t passed;
2341 std::size_t failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002342 std::size_t failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002343 };
2344
2345 struct Totals {
2346
2347 Totals operator - ( Totals const& other ) const {
2348 Totals diff;
2349 diff.assertions = assertions - other.assertions;
2350 diff.testCases = testCases - other.testCases;
2351 return diff;
2352 }
2353
2354 Totals delta( Totals const& prevTotals ) const {
2355 Totals diff = *this - prevTotals;
2356 if( diff.assertions.failed > 0 )
2357 ++diff.testCases.failed;
Phil Nash52e1e742014-07-03 08:11:38 +01002358 else if( diff.assertions.failedButOk > 0 )
2359 ++diff.testCases.failedButOk;
Phil Nash3649fdf2013-12-03 18:53:55 +00002360 else
2361 ++diff.testCases.passed;
2362 return diff;
2363 }
2364
2365 Totals& operator += ( Totals const& other ) {
2366 assertions += other.assertions;
2367 testCases += other.testCases;
2368 return *this;
2369 }
2370
2371 Counts assertions;
2372 Counts testCases;
2373 };
2374}
Phil Nashce612bf2012-11-01 08:27:09 +00002375
Phil Nashd08cee22017-02-13 16:15:42 +00002376#include <string>
2377
Phil Nash0c1c9fa2015-09-27 03:28:14 -07002378namespace Catch {
2379
2380 struct SectionInfo {
2381 SectionInfo
2382 ( SourceLineInfo const& _lineInfo,
2383 std::string const& _name,
2384 std::string const& _description = std::string() );
2385
2386 std::string name;
2387 std::string description;
2388 SourceLineInfo lineInfo;
2389 };
2390
2391 struct SectionEndInfo {
2392 SectionEndInfo( SectionInfo const& _sectionInfo, Counts const& _prevAssertions, double _durationInSeconds )
2393 : sectionInfo( _sectionInfo ), prevAssertions( _prevAssertions ), durationInSeconds( _durationInSeconds )
2394 {}
2395
2396 SectionInfo sectionInfo;
2397 Counts prevAssertions;
2398 double durationInSeconds;
2399 };
2400
2401} // end namespace Catch
2402
Phil Nashaa7123b2013-08-15 19:01:00 +01002403// #included from: catch_timer.h
2404#define TWOBLUECUBES_CATCH_TIMER_H_INCLUDED
2405
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002406#ifdef _MSC_VER
2407
2408namespace Catch {
2409 typedef unsigned long long UInt64;
2410}
Phil Nashaa7123b2013-08-15 19:01:00 +01002411#else
2412#include <stdint.h>
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002413namespace Catch {
2414 typedef uint64_t UInt64;
2415}
Phil Nashaa7123b2013-08-15 19:01:00 +01002416#endif
2417
2418namespace Catch {
Phil Nashaa7123b2013-08-15 19:01:00 +01002419 class Timer {
2420 public:
2421 Timer() : m_ticks( 0 ) {}
2422 void start();
Phil Nash4caabfa2014-09-03 19:23:22 +01002423 unsigned int getElapsedMicroseconds() const;
Phil Nashaa7123b2013-08-15 19:01:00 +01002424 unsigned int getElapsedMilliseconds() const;
2425 double getElapsedSeconds() const;
2426
2427 private:
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002428 UInt64 m_ticks;
Phil Nashaa7123b2013-08-15 19:01:00 +01002429 };
2430
2431} // namespace Catch
2432
Phil Nashce612bf2012-11-01 08:27:09 +00002433#include <string>
2434
2435namespace Catch {
2436
Phil Nashe54ac702014-10-21 07:25:26 +01002437 class Section : NonCopyable {
Phil Nashce612bf2012-11-01 08:27:09 +00002438 public:
Phil Nashce562092014-07-09 07:40:37 +01002439 Section( SectionInfo const& info );
Phil Nash3649fdf2013-12-03 18:53:55 +00002440 ~Section();
Phil Nashce612bf2012-11-01 08:27:09 +00002441
2442 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01002443 operator bool() const;
Phil Nashce612bf2012-11-01 08:27:09 +00002444
2445 private:
Phil Nasha1fbfea2012-12-01 23:57:18 +00002446 SectionInfo m_info;
Phil Nashce612bf2012-11-01 08:27:09 +00002447
2448 std::string m_name;
2449 Counts m_assertions;
2450 bool m_sectionIncluded;
Phil Nashaa7123b2013-08-15 19:01:00 +01002451 Timer m_timer;
Phil Nashce612bf2012-11-01 08:27:09 +00002452 };
2453
2454} // end namespace Catch
2455
Phil Nash93906752013-03-16 20:21:51 +00002456#ifdef CATCH_CONFIG_VARIADIC_MACROS
2457 #define INTERNAL_CATCH_SECTION( ... ) \
Phil Nashce562092014-07-09 07:40:37 +01002458 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 +00002459#else
2460 #define INTERNAL_CATCH_SECTION( name, desc ) \
Phil Nashce562092014-07-09 07:40:37 +01002461 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 +00002462#endif
Phil Nashce612bf2012-11-01 08:27:09 +00002463
2464// #included from: internal/catch_generators.hpp
2465#define TWOBLUECUBES_CATCH_GENERATORS_HPP_INCLUDED
2466
Phil Nashce612bf2012-11-01 08:27:09 +00002467#include <vector>
2468#include <string>
2469#include <stdlib.h>
2470
2471namespace Catch {
2472
2473template<typename T>
2474struct IGenerator {
2475 virtual ~IGenerator() {}
2476 virtual T getValue( std::size_t index ) const = 0;
2477 virtual std::size_t size () const = 0;
2478};
2479
2480template<typename T>
2481class BetweenGenerator : public IGenerator<T> {
2482public:
2483 BetweenGenerator( T from, T to ) : m_from( from ), m_to( to ){}
2484
2485 virtual T getValue( std::size_t index ) const {
Phil Nash2e7d9662013-01-16 09:44:43 +00002486 return m_from+static_cast<int>( index );
Phil Nashce612bf2012-11-01 08:27:09 +00002487 }
2488
2489 virtual std::size_t size() const {
2490 return static_cast<std::size_t>( 1+m_to-m_from );
2491 }
2492
2493private:
2494
2495 T m_from;
2496 T m_to;
2497};
2498
2499template<typename T>
2500class ValuesGenerator : public IGenerator<T> {
2501public:
2502 ValuesGenerator(){}
2503
2504 void add( T value ) {
2505 m_values.push_back( value );
2506 }
2507
2508 virtual T getValue( std::size_t index ) const {
2509 return m_values[index];
2510 }
2511
2512 virtual std::size_t size() const {
2513 return m_values.size();
2514 }
2515
2516private:
2517 std::vector<T> m_values;
2518};
2519
2520template<typename T>
2521class CompositeGenerator {
2522public:
2523 CompositeGenerator() : m_totalSize( 0 ) {}
2524
Phil Nasha04981b2013-03-08 09:30:25 +00002525 // *** Move semantics, similar to auto_ptr ***
Phil Nashce612bf2012-11-01 08:27:09 +00002526 CompositeGenerator( CompositeGenerator& other )
2527 : m_fileInfo( other.m_fileInfo ),
2528 m_totalSize( 0 )
2529 {
Phil Nasha04981b2013-03-08 09:30:25 +00002530 move( other );
Phil Nashce612bf2012-11-01 08:27:09 +00002531 }
2532
2533 CompositeGenerator& setFileInfo( const char* fileInfo ) {
2534 m_fileInfo = fileInfo;
2535 return *this;
2536 }
2537
2538 ~CompositeGenerator() {
2539 deleteAll( m_composed );
2540 }
2541
2542 operator T () const {
2543 size_t overallIndex = getCurrentContext().getGeneratorIndex( m_fileInfo, m_totalSize );
2544
2545 typename std::vector<const IGenerator<T>*>::const_iterator it = m_composed.begin();
2546 typename std::vector<const IGenerator<T>*>::const_iterator itEnd = m_composed.end();
2547 for( size_t index = 0; it != itEnd; ++it )
2548 {
2549 const IGenerator<T>* generator = *it;
2550 if( overallIndex >= index && overallIndex < index + generator->size() )
2551 {
2552 return generator->getValue( overallIndex-index );
2553 }
2554 index += generator->size();
2555 }
2556 CATCH_INTERNAL_ERROR( "Indexed past end of generated range" );
Phil Nasha04981b2013-03-08 09:30:25 +00002557 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 +00002558 }
2559
2560 void add( const IGenerator<T>* generator ) {
2561 m_totalSize += generator->size();
2562 m_composed.push_back( generator );
2563 }
2564
2565 CompositeGenerator& then( CompositeGenerator& other ) {
2566 move( other );
2567 return *this;
2568 }
2569
2570 CompositeGenerator& then( T value ) {
2571 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2572 valuesGen->add( value );
2573 add( valuesGen );
2574 return *this;
2575 }
2576
2577private:
2578
2579 void move( CompositeGenerator& other ) {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002580 m_composed.insert( m_composed.end(), other.m_composed.begin(), other.m_composed.end() );
Phil Nashce612bf2012-11-01 08:27:09 +00002581 m_totalSize += other.m_totalSize;
2582 other.m_composed.clear();
2583 }
2584
2585 std::vector<const IGenerator<T>*> m_composed;
2586 std::string m_fileInfo;
2587 size_t m_totalSize;
2588};
2589
2590namespace Generators
2591{
2592 template<typename T>
2593 CompositeGenerator<T> between( T from, T to ) {
2594 CompositeGenerator<T> generators;
2595 generators.add( new BetweenGenerator<T>( from, to ) );
2596 return generators;
2597 }
2598
2599 template<typename T>
2600 CompositeGenerator<T> values( T val1, T val2 ) {
2601 CompositeGenerator<T> generators;
2602 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2603 valuesGen->add( val1 );
2604 valuesGen->add( val2 );
2605 generators.add( valuesGen );
2606 return generators;
2607 }
2608
2609 template<typename T>
2610 CompositeGenerator<T> values( T val1, T val2, T val3 ){
2611 CompositeGenerator<T> generators;
2612 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2613 valuesGen->add( val1 );
2614 valuesGen->add( val2 );
2615 valuesGen->add( val3 );
2616 generators.add( valuesGen );
2617 return generators;
2618 }
2619
2620 template<typename T>
2621 CompositeGenerator<T> values( T val1, T val2, T val3, T val4 ) {
2622 CompositeGenerator<T> generators;
2623 ValuesGenerator<T>* valuesGen = new ValuesGenerator<T>();
2624 valuesGen->add( val1 );
2625 valuesGen->add( val2 );
2626 valuesGen->add( val3 );
2627 valuesGen->add( val4 );
2628 generators.add( valuesGen );
2629 return generators;
2630 }
2631
2632} // end namespace Generators
2633
2634using namespace Generators;
2635
2636} // end namespace Catch
2637
2638#define INTERNAL_CATCH_LINESTR2( line ) #line
2639#define INTERNAL_CATCH_LINESTR( line ) INTERNAL_CATCH_LINESTR2( line )
2640
2641#define INTERNAL_CATCH_GENERATE( expr ) expr.setFileInfo( __FILE__ "(" INTERNAL_CATCH_LINESTR( __LINE__ ) ")" )
2642
2643// #included from: internal/catch_interfaces_exception.h
2644#define TWOBLUECUBES_CATCH_INTERFACES_EXCEPTION_H_INCLUDED
2645
2646#include <string>
Phil Nashe4fa62a2015-11-18 08:39:54 +00002647#include <vector>
2648
Phil Nashab036682014-06-02 07:48:03 +01002649// #included from: catch_interfaces_registry_hub.h
2650#define TWOBLUECUBES_CATCH_INTERFACES_REGISTRY_HUB_H_INCLUDED
2651
2652#include <string>
2653
2654namespace Catch {
2655
2656 class TestCase;
2657 struct ITestCaseRegistry;
2658 struct IExceptionTranslatorRegistry;
2659 struct IExceptionTranslator;
2660 struct IReporterRegistry;
2661 struct IReporterFactory;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002662 struct ITagAliasRegistry;
Phil Nashab036682014-06-02 07:48:03 +01002663
2664 struct IRegistryHub {
2665 virtual ~IRegistryHub();
2666
2667 virtual IReporterRegistry const& getReporterRegistry() const = 0;
2668 virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002669 virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;
2670
Phil Nashab036682014-06-02 07:48:03 +01002671 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() = 0;
2672 };
2673
2674 struct IMutableRegistryHub {
2675 virtual ~IMutableRegistryHub();
Phil Nashe73583d2015-08-07 17:30:34 +01002676 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) = 0;
2677 virtual void registerListener( Ptr<IReporterFactory> const& factory ) = 0;
Phil Nashab036682014-06-02 07:48:03 +01002678 virtual void registerTest( TestCase const& testInfo ) = 0;
2679 virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002680 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;
Phil Nashab036682014-06-02 07:48:03 +01002681 };
2682
2683 IRegistryHub& getRegistryHub();
2684 IMutableRegistryHub& getMutableRegistryHub();
2685 void cleanUp();
2686 std::string translateActiveException();
2687
2688}
2689
Phil Nash89d2a3f2012-05-16 15:09:17 +01002690namespace Catch {
2691
Phil Nash89d1e6c2011-05-24 08:23:02 +01002692 typedef std::string(*exceptionTranslateFunction)();
2693
Phil Nashe4fa62a2015-11-18 08:39:54 +00002694 struct IExceptionTranslator;
2695 typedef std::vector<const IExceptionTranslator*> ExceptionTranslators;
2696
Phil Nash89d2a3f2012-05-16 15:09:17 +01002697 struct IExceptionTranslator {
Phil Nasha695eb92012-08-13 07:46:10 +01002698 virtual ~IExceptionTranslator();
Phil Nashe4fa62a2015-11-18 08:39:54 +00002699 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002700 };
2701
Phil Nash89d2a3f2012-05-16 15:09:17 +01002702 struct IExceptionTranslatorRegistry {
Phil Nasha695eb92012-08-13 07:46:10 +01002703 virtual ~IExceptionTranslatorRegistry();
Phil Nash89d1e6c2011-05-24 08:23:02 +01002704
Phil Nash89d2a3f2012-05-16 15:09:17 +01002705 virtual std::string translateActiveException() const = 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01002706 };
2707
Phil Nash89d2a3f2012-05-16 15:09:17 +01002708 class ExceptionTranslatorRegistrar {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002709 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002710 class ExceptionTranslator : public IExceptionTranslator {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002711 public:
2712
Phil Nash89d2a3f2012-05-16 15:09:17 +01002713 ExceptionTranslator( std::string(*translateFunction)( T& ) )
Phil Nash89d1e6c2011-05-24 08:23:02 +01002714 : m_translateFunction( translateFunction )
2715 {}
2716
Phil Nashe4fa62a2015-11-18 08:39:54 +00002717 virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const CATCH_OVERRIDE {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002718 try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00002719 if( it == itEnd )
2720 throw;
2721 else
2722 return (*it)->translate( it+1, itEnd );
Phil Nash89d1e6c2011-05-24 08:23:02 +01002723 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01002724 catch( T& ex ) {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002725 return m_translateFunction( ex );
2726 }
2727 }
2728
2729 protected:
2730 std::string(*m_translateFunction)( T& );
2731 };
2732
2733 public:
2734 template<typename T>
Phil Nash89d2a3f2012-05-16 15:09:17 +01002735 ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {
Phil Nash3b80af72012-08-09 07:47:30 +01002736 getMutableRegistryHub().registerTranslator
Phil Nash89d1e6c2011-05-24 08:23:02 +01002737 ( new ExceptionTranslator<T>( translateFunction ) );
2738 }
2739 };
2740}
2741
2742///////////////////////////////////////////////////////////////////////////////
Phil Nashc984fc32016-03-15 07:24:26 +00002743#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \
2744 static std::string translatorName( signature ); \
2745 namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); }\
2746 static std::string translatorName( signature )
2747
2748#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 +01002749
2750// #included from: internal/catch_approx.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01002751#define TWOBLUECUBES_CATCH_APPROX_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01002752
Phil Nash89d1e6c2011-05-24 08:23:02 +01002753#include <cmath>
2754#include <limits>
2755
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002756#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2757#include <type_traits>
2758#endif
2759
Phil Nash89d2a3f2012-05-16 15:09:17 +01002760namespace Catch {
2761namespace Detail {
Phil Nash89d1e6c2011-05-24 08:23:02 +01002762
Phil Nash89d2a3f2012-05-16 15:09:17 +01002763 class Approx {
2764 public:
2765 explicit Approx ( double value )
2766 : m_epsilon( std::numeric_limits<float>::epsilon()*100 ),
Phil Nash0952b762017-02-28 14:19:09 +00002767 m_margin( 0.0 ),
Phil Nash89d2a3f2012-05-16 15:09:17 +01002768 m_scale( 1.0 ),
2769 m_value( value )
2770 {}
Phil Nashf721a962011-06-07 14:13:57 +01002771
Phil Nash8defc712013-04-24 19:10:02 +01002772 Approx( Approx const& other )
Phil Nash89d2a3f2012-05-16 15:09:17 +01002773 : m_epsilon( other.m_epsilon ),
Phil Nash0952b762017-02-28 14:19:09 +00002774 m_margin( other.m_margin ),
Phil Nash89d2a3f2012-05-16 15:09:17 +01002775 m_scale( other.m_scale ),
2776 m_value( other.m_value )
2777 {}
Phil Nashf721a962011-06-07 14:13:57 +01002778
Phil Nash89d2a3f2012-05-16 15:09:17 +01002779 static Approx custom() {
2780 return Approx( 0 );
2781 }
Phil Nashf721a962011-06-07 14:13:57 +01002782
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002783#if defined(CATCH_CONFIG_CPP11_TYPE_TRAITS)
2784
2785 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2786 Approx operator()( T value ) {
2787 Approx approx( static_cast<double>(value) );
Phil Nash89d2a3f2012-05-16 15:09:17 +01002788 approx.epsilon( m_epsilon );
Phil Nash0952b762017-02-28 14:19:09 +00002789 approx.margin( m_margin );
Phil Nash89d2a3f2012-05-16 15:09:17 +01002790 approx.scale( m_scale );
2791 return approx;
2792 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002793
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002794 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2795 explicit Approx( T value ): Approx(static_cast<double>(value))
2796 {}
2797
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002798 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2799 friend bool operator == ( const T& lhs, Approx const& rhs ) {
2800 // Thanks to Richard Harris for his help refining this formula
2801 auto lhs_v = double(lhs);
Phil Nash0952b762017-02-28 14:19:09 +00002802 bool relativeOK = std::fabs(lhs_v - rhs.m_value) < rhs.m_epsilon * (rhs.m_scale + (std::max)(std::fabs(lhs_v), std::fabs(rhs.m_value)));
2803 if (relativeOK) {
2804 return true;
2805 }
2806 return std::fabs(lhs_v - rhs.m_value) < rhs.m_margin;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002807 }
2808
2809 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2810 friend bool operator == ( Approx const& lhs, const T& rhs ) {
2811 return operator==( rhs, lhs );
2812 }
2813
2814 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2815 friend bool operator != ( T lhs, Approx const& rhs ) {
2816 return !operator==( lhs, rhs );
2817 }
2818
2819 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2820 friend bool operator != ( Approx const& lhs, T rhs ) {
2821 return !operator==( rhs, lhs );
2822 }
2823
2824 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002825 friend bool operator <= ( T lhs, Approx const& rhs ) {
2826 return double(lhs) < rhs.m_value || lhs == rhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002827 }
2828
2829 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002830 friend bool operator <= ( Approx const& lhs, T rhs ) {
2831 return lhs.m_value < double(rhs) || lhs == rhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002832 }
2833
2834 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002835 friend bool operator >= ( T lhs, Approx const& rhs ) {
2836 return double(lhs) > rhs.m_value || lhs == rhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002837 }
2838
2839 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002840 friend bool operator >= ( Approx const& lhs, T rhs ) {
2841 return lhs.m_value > double(rhs) || lhs == rhs;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002842 }
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002843
2844 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2845 Approx& epsilon( T newEpsilon ) {
2846 m_epsilon = double(newEpsilon);
2847 return *this;
2848 }
2849
2850 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2851 Approx& margin( T newMargin ) {
2852 m_margin = double(newMargin);
2853 return *this;
2854 }
2855
2856 template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>
2857 Approx& scale( T newScale ) {
2858 m_scale = double(newScale);
2859 return *this;
2860 }
2861
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01002862#else
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002863
2864 Approx operator()( double value ) {
2865 Approx approx( value );
2866 approx.epsilon( m_epsilon );
2867 approx.margin( m_margin );
2868 approx.scale( m_scale );
2869 return approx;
2870 }
2871
Phil Nash8defc712013-04-24 19:10:02 +01002872 friend bool operator == ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002873 // Thanks to Richard Harris for his help refining this formula
Phil Nash0952b762017-02-28 14:19:09 +00002874 bool relativeOK = std::fabs( lhs - rhs.m_value ) < rhs.m_epsilon * (rhs.m_scale + (std::max)( std::fabs(lhs), std::fabs(rhs.m_value) ) );
2875 if (relativeOK) {
2876 return true;
2877 }
2878 return std::fabs(lhs - rhs.m_value) < rhs.m_margin;
Phil Nash89d2a3f2012-05-16 15:09:17 +01002879 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002880
Phil Nash8defc712013-04-24 19:10:02 +01002881 friend bool operator == ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002882 return operator==( rhs, lhs );
2883 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002884
Phil Nash8defc712013-04-24 19:10:02 +01002885 friend bool operator != ( double lhs, Approx const& rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002886 return !operator==( lhs, rhs );
2887 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002888
Phil Nash8defc712013-04-24 19:10:02 +01002889 friend bool operator != ( Approx const& lhs, double rhs ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002890 return !operator==( rhs, lhs );
2891 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002892
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002893 friend bool operator <= ( double lhs, Approx const& rhs ) {
2894 return lhs < rhs.m_value || lhs == rhs;
Phil Nash3b2f2062017-01-11 16:43:56 +00002895 }
2896
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002897 friend bool operator <= ( Approx const& lhs, double rhs ) {
2898 return lhs.m_value < rhs || lhs == rhs;
Phil Nash3b2f2062017-01-11 16:43:56 +00002899 }
2900
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002901 friend bool operator >= ( double lhs, Approx const& rhs ) {
2902 return lhs > rhs.m_value || lhs == rhs;
Phil Nash3b2f2062017-01-11 16:43:56 +00002903 }
2904
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02002905 friend bool operator >= ( Approx const& lhs, double rhs ) {
2906 return lhs.m_value > rhs || lhs == rhs;
Phil Nash3b2f2062017-01-11 16:43:56 +00002907 }
2908
Phil Nash89d2a3f2012-05-16 15:09:17 +01002909 Approx& epsilon( double newEpsilon ) {
2910 m_epsilon = newEpsilon;
2911 return *this;
2912 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002913
Phil Nash0952b762017-02-28 14:19:09 +00002914 Approx& margin( double newMargin ) {
2915 m_margin = newMargin;
2916 return *this;
2917 }
2918
Phil Nash89d2a3f2012-05-16 15:09:17 +01002919 Approx& scale( double newScale ) {
2920 m_scale = newScale;
2921 return *this;
2922 }
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02002923#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01002924
Phil Nash89d2a3f2012-05-16 15:09:17 +01002925 std::string toString() const {
2926 std::ostringstream oss;
Phil Nashf385a0b2013-12-19 18:42:25 +00002927 oss << "Approx( " << Catch::toString( m_value ) << " )";
Phil Nash89d2a3f2012-05-16 15:09:17 +01002928 return oss.str();
2929 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01002930
Phil Nash89d2a3f2012-05-16 15:09:17 +01002931 private:
2932 double m_epsilon;
Phil Nash0952b762017-02-28 14:19:09 +00002933 double m_margin;
Phil Nash89d2a3f2012-05-16 15:09:17 +01002934 double m_scale;
2935 double m_value;
2936 };
2937}
2938
2939template<>
Phil Nash8defc712013-04-24 19:10:02 +01002940inline std::string toString<Detail::Approx>( Detail::Approx const& value ) {
Phil Nash89d2a3f2012-05-16 15:09:17 +01002941 return value.toString();
2942}
Phil Nash89d1e6c2011-05-24 08:23:02 +01002943
2944} // end namespace Catch
2945
Phil Nash0952b762017-02-28 14:19:09 +00002946// #included from: internal/catch_matchers_string.h
2947#define TWOBLUECUBES_CATCH_MATCHERS_STRING_H_INCLUDED
2948
2949namespace Catch {
2950namespace Matchers {
2951
2952 namespace StdString {
2953
2954 struct CasedString
2955 {
2956 CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );
2957 std::string adjustString( std::string const& str ) const;
2958 std::string caseSensitivitySuffix() const;
2959
2960 CaseSensitive::Choice m_caseSensitivity;
2961 std::string m_str;
2962 };
2963
2964 struct StringMatcherBase : MatcherBase<std::string> {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01002965 StringMatcherBase( std::string const& operation, CasedString const& comparator );
Phil Nash0952b762017-02-28 14:19:09 +00002966 virtual std::string describe() const CATCH_OVERRIDE;
2967
2968 CasedString m_comparator;
2969 std::string m_operation;
2970 };
2971
2972 struct EqualsMatcher : StringMatcherBase {
2973 EqualsMatcher( CasedString const& comparator );
2974 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2975 };
2976 struct ContainsMatcher : StringMatcherBase {
2977 ContainsMatcher( CasedString const& comparator );
2978 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2979 };
2980 struct StartsWithMatcher : StringMatcherBase {
2981 StartsWithMatcher( CasedString const& comparator );
2982 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2983 };
2984 struct EndsWithMatcher : StringMatcherBase {
2985 EndsWithMatcher( CasedString const& comparator );
2986 virtual bool match( std::string const& source ) const CATCH_OVERRIDE;
2987 };
2988
2989 } // namespace StdString
2990
2991 // The following functions create the actual matcher objects.
2992 // This allows the types to be inferred
2993
2994 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2995 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2996 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2997 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );
2998
2999} // namespace Matchers
3000} // namespace Catch
3001
3002// #included from: internal/catch_matchers_vector.h
3003#define TWOBLUECUBES_CATCH_MATCHERS_VECTOR_H_INCLUDED
3004
3005namespace Catch {
3006namespace Matchers {
3007
3008 namespace Vector {
3009
3010 template<typename T>
3011 struct ContainsElementMatcher : MatcherBase<std::vector<T>, T> {
3012
3013 ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}
3014
3015 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3016 return std::find(v.begin(), v.end(), m_comparator) != v.end();
3017 }
3018
3019 virtual std::string describe() const CATCH_OVERRIDE {
3020 return "Contains: " + Catch::toString( m_comparator );
3021 }
3022
3023 T const& m_comparator;
3024 };
3025
3026 template<typename T>
3027 struct ContainsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3028
3029 ContainsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3030
3031 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3032 // !TBD: see note in EqualsMatcher
3033 if (m_comparator.size() > v.size())
3034 return false;
3035 for (size_t i = 0; i < m_comparator.size(); ++i)
3036 if (std::find(v.begin(), v.end(), m_comparator[i]) == v.end())
3037 return false;
3038 return true;
3039 }
3040 virtual std::string describe() const CATCH_OVERRIDE {
3041 return "Contains: " + Catch::toString( m_comparator );
3042 }
3043
3044 std::vector<T> const& m_comparator;
3045 };
3046
3047 template<typename T>
3048 struct EqualsMatcher : MatcherBase<std::vector<T>, std::vector<T> > {
3049
3050 EqualsMatcher(std::vector<T> const &comparator) : m_comparator( comparator ) {}
3051
3052 bool match(std::vector<T> const &v) const CATCH_OVERRIDE {
3053 // !TBD: This currently works if all elements can be compared using !=
3054 // - a more general approach would be via a compare template that defaults
3055 // to using !=. but could be specialised for, e.g. std::vector<T> etc
3056 // - then just call that directly
3057 if (m_comparator.size() != v.size())
3058 return false;
3059 for (size_t i = 0; i < v.size(); ++i)
3060 if (m_comparator[i] != v[i])
3061 return false;
3062 return true;
3063 }
3064 virtual std::string describe() const CATCH_OVERRIDE {
3065 return "Equals: " + Catch::toString( m_comparator );
3066 }
3067 std::vector<T> const& m_comparator;
3068 };
3069
3070 } // namespace Vector
3071
3072 // The following functions create the actual matcher objects.
3073 // This allows the types to be inferred
3074
3075 template<typename T>
3076 Vector::ContainsMatcher<T> Contains( std::vector<T> const& comparator ) {
3077 return Vector::ContainsMatcher<T>( comparator );
3078 }
3079
3080 template<typename T>
3081 Vector::ContainsElementMatcher<T> VectorContains( T const& comparator ) {
3082 return Vector::ContainsElementMatcher<T>( comparator );
3083 }
3084
3085 template<typename T>
3086 Vector::EqualsMatcher<T> Equals( std::vector<T> const& comparator ) {
3087 return Vector::EqualsMatcher<T>( comparator );
3088 }
3089
3090} // namespace Matchers
3091} // namespace Catch
3092
Phil Nashacdd3b52014-06-30 07:35:36 +01003093// #included from: internal/catch_interfaces_tag_alias_registry.h
3094#define TWOBLUECUBES_CATCH_INTERFACES_TAG_ALIAS_REGISTRY_H_INCLUDED
3095
3096// #included from: catch_tag_alias.h
3097#define TWOBLUECUBES_CATCH_TAG_ALIAS_H_INCLUDED
3098
3099#include <string>
3100
3101namespace Catch {
3102
3103 struct TagAlias {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003104 TagAlias( std::string const& _tag, SourceLineInfo _lineInfo ) : tag( _tag ), lineInfo( _lineInfo ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003105
3106 std::string tag;
3107 SourceLineInfo lineInfo;
3108 };
3109
3110 struct RegistrarForTagAliases {
3111 RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );
3112 };
3113
3114} // end namespace Catch
3115
3116#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); }
3117// #included from: catch_option.hpp
3118#define TWOBLUECUBES_CATCH_OPTION_HPP_INCLUDED
3119
3120namespace Catch {
3121
3122 // An optional type
3123 template<typename T>
3124 class Option {
3125 public:
Phil Nashb971fe72015-07-02 08:21:38 +01003126 Option() : nullableValue( CATCH_NULL ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003127 Option( T const& _value )
3128 : nullableValue( new( storage ) T( _value ) )
3129 {}
3130 Option( Option const& _other )
Phil Nashb971fe72015-07-02 08:21:38 +01003131 : nullableValue( _other ? new( storage ) T( *_other ) : CATCH_NULL )
Phil Nashacdd3b52014-06-30 07:35:36 +01003132 {}
3133
3134 ~Option() {
3135 reset();
3136 }
3137
3138 Option& operator= ( Option const& _other ) {
3139 if( &_other != this ) {
3140 reset();
3141 if( _other )
3142 nullableValue = new( storage ) T( *_other );
3143 }
3144 return *this;
3145 }
3146 Option& operator = ( T const& _value ) {
3147 reset();
3148 nullableValue = new( storage ) T( _value );
3149 return *this;
3150 }
3151
3152 void reset() {
3153 if( nullableValue )
3154 nullableValue->~T();
Phil Nashb971fe72015-07-02 08:21:38 +01003155 nullableValue = CATCH_NULL;
Phil Nashacdd3b52014-06-30 07:35:36 +01003156 }
3157
3158 T& operator*() { return *nullableValue; }
3159 T const& operator*() const { return *nullableValue; }
3160 T* operator->() { return nullableValue; }
3161 const T* operator->() const { return nullableValue; }
3162
3163 T valueOr( T const& defaultValue ) const {
3164 return nullableValue ? *nullableValue : defaultValue;
3165 }
3166
Phil Nashb971fe72015-07-02 08:21:38 +01003167 bool some() const { return nullableValue != CATCH_NULL; }
3168 bool none() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003169
Phil Nashb971fe72015-07-02 08:21:38 +01003170 bool operator !() const { return nullableValue == CATCH_NULL; }
Phil Nashacdd3b52014-06-30 07:35:36 +01003171 operator SafeBool::type() const {
3172 return SafeBool::makeSafe( some() );
3173 }
3174
3175 private:
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02003176 T *nullableValue;
3177 union {
3178 char storage[sizeof(T)];
3179
3180 // These are here to force alignment for the storage
3181 long double dummy1;
3182 void (*dummy2)();
3183 long double dummy3;
3184#ifdef CATCH_CONFIG_CPP11_LONG_LONG
3185 long long dummy4;
3186#endif
3187 };
Phil Nashacdd3b52014-06-30 07:35:36 +01003188 };
3189
3190} // end namespace Catch
3191
3192namespace Catch {
3193
3194 struct ITagAliasRegistry {
3195 virtual ~ITagAliasRegistry();
3196 virtual Option<TagAlias> find( std::string const& alias ) const = 0;
3197 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;
3198
3199 static ITagAliasRegistry const& get();
3200 };
3201
3202} // end namespace Catch
3203
Phil Nash0f9c5512012-06-02 23:12:42 +01003204// These files are included here so the single_include script doesn't put them
3205// in the conditionally compiled sections
Phil Nash3649fdf2013-12-03 18:53:55 +00003206// #included from: internal/catch_test_case_info.h
3207#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_H_INCLUDED
Phil Nash0f9c5512012-06-02 23:12:42 +01003208
3209#include <string>
Phil Nash3649fdf2013-12-03 18:53:55 +00003210#include <set>
3211
3212#ifdef __clang__
3213#pragma clang diagnostic push
3214#pragma clang diagnostic ignored "-Wpadded"
3215#endif
3216
3217namespace Catch {
3218
3219 struct ITestCase;
3220
3221 struct TestCaseInfo {
Phil Nash52e1e742014-07-03 08:11:38 +01003222 enum SpecialProperties{
3223 None = 0,
3224 IsHidden = 1 << 1,
3225 ShouldFail = 1 << 2,
3226 MayFail = 1 << 3,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003227 Throws = 1 << 4,
3228 NonPortable = 1 << 5
Phil Nash52e1e742014-07-03 08:11:38 +01003229 };
3230
Phil Nash3649fdf2013-12-03 18:53:55 +00003231 TestCaseInfo( std::string const& _name,
3232 std::string const& _className,
3233 std::string const& _description,
3234 std::set<std::string> const& _tags,
Phil Nash3649fdf2013-12-03 18:53:55 +00003235 SourceLineInfo const& _lineInfo );
3236
3237 TestCaseInfo( TestCaseInfo const& other );
3238
Phil Nashb971fe72015-07-02 08:21:38 +01003239 friend void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags );
3240
Phil Nash52e1e742014-07-03 08:11:38 +01003241 bool isHidden() const;
3242 bool throws() const;
3243 bool okToFail() const;
3244 bool expectedToFail() const;
3245
Phil Nash3649fdf2013-12-03 18:53:55 +00003246 std::string name;
3247 std::string className;
3248 std::string description;
3249 std::set<std::string> tags;
Phil Nash9241e432014-05-20 18:50:59 +01003250 std::set<std::string> lcaseTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003251 std::string tagsAsString;
3252 SourceLineInfo lineInfo;
Phil Nash52e1e742014-07-03 08:11:38 +01003253 SpecialProperties properties;
Phil Nash3649fdf2013-12-03 18:53:55 +00003254 };
3255
Phil Nash65cc14c2014-05-16 18:54:48 +01003256 class TestCase : public TestCaseInfo {
Phil Nash3649fdf2013-12-03 18:53:55 +00003257 public:
3258
3259 TestCase( ITestCase* testCase, TestCaseInfo const& info );
3260 TestCase( TestCase const& other );
3261
3262 TestCase withName( std::string const& _newName ) const;
3263
3264 void invoke() const;
3265
3266 TestCaseInfo const& getTestCaseInfo() const;
3267
Phil Nash3649fdf2013-12-03 18:53:55 +00003268 void swap( TestCase& other );
3269 bool operator == ( TestCase const& other ) const;
3270 bool operator < ( TestCase const& other ) const;
3271 TestCase& operator = ( TestCase const& other );
3272
3273 private:
3274 Ptr<ITestCase> test;
3275 };
3276
3277 TestCase makeTestCase( ITestCase* testCase,
3278 std::string const& className,
3279 std::string const& name,
3280 std::string const& description,
3281 SourceLineInfo const& lineInfo );
3282}
3283
3284#ifdef __clang__
3285#pragma clang diagnostic pop
3286#endif
3287
Phil Nash0f9c5512012-06-02 23:12:42 +01003288
Phil Nash371db8b2012-05-21 18:52:09 +01003289#ifdef __OBJC__
3290// #included from: internal/catch_objc.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003291#define TWOBLUECUBES_CATCH_OBJC_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01003292
Phil Nash371db8b2012-05-21 18:52:09 +01003293#import <objc/runtime.h>
3294
3295#include <string>
3296
3297// NB. Any general catch headers included here must be included
3298// in catch.hpp first to make sure they are included by the single
3299// header for non obj-usage
Phil Nash81528252011-08-15 09:06:31 +01003300
Phil Nash83224e62011-08-12 18:53:28 +01003301///////////////////////////////////////////////////////////////////////////////
3302// This protocol is really only here for (self) documenting purposes, since
3303// all its methods are optional.
3304@protocol OcFixture
3305
3306@optional
3307
3308-(void) setUp;
3309-(void) tearDown;
3310
3311@end
3312
Phil Nash89d2a3f2012-05-16 15:09:17 +01003313namespace Catch {
Phil Nash83224e62011-08-12 18:53:28 +01003314
Phil Nash5bc030d2012-08-16 18:48:50 +01003315 class OcMethod : public SharedImpl<ITestCase> {
Phil Nash89d2a3f2012-05-16 15:09:17 +01003316
3317 public:
3318 OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}
3319
3320 virtual void invoke() const {
Phil Nash53c990a2012-03-17 18:20:06 +00003321 id obj = [[m_cls alloc] init];
Phil Nash83224e62011-08-12 18:53:28 +01003322
Phil Nash53c990a2012-03-17 18:20:06 +00003323 performOptionalSelector( obj, @selector(setUp) );
3324 performOptionalSelector( obj, m_sel );
3325 performOptionalSelector( obj, @selector(tearDown) );
Phil Nash83224e62011-08-12 18:53:28 +01003326
Phil Nash53c990a2012-03-17 18:20:06 +00003327 arcSafeRelease( obj );
Phil Nash83224e62011-08-12 18:53:28 +01003328 }
Phil Nash83224e62011-08-12 18:53:28 +01003329 private:
Phil Nash5bc030d2012-08-16 18:48:50 +01003330 virtual ~OcMethod() {}
3331
Phil Nash83224e62011-08-12 18:53:28 +01003332 Class m_cls;
3333 SEL m_sel;
3334 };
3335
Phil Nash89d2a3f2012-05-16 15:09:17 +01003336 namespace Detail{
Phil Nash83224e62011-08-12 18:53:28 +01003337
Phil Nash89d2a3f2012-05-16 15:09:17 +01003338 inline std::string getAnnotation( Class cls,
Phil Nash8defc712013-04-24 19:10:02 +01003339 std::string const& annotationName,
3340 std::string const& testCaseName ) {
Phil Nash83224e62011-08-12 18:53:28 +01003341 NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];
3342 SEL sel = NSSelectorFromString( selStr );
Phil Nash53c990a2012-03-17 18:20:06 +00003343 arcSafeRelease( selStr );
3344 id value = performOptionalSelector( cls, sel );
3345 if( value )
3346 return [(NSString*)value UTF8String];
Phil Nash83224e62011-08-12 18:53:28 +01003347 return "";
3348 }
3349 }
3350
Phil Nash89d2a3f2012-05-16 15:09:17 +01003351 inline size_t registerTestMethods() {
Phil Nash83224e62011-08-12 18:53:28 +01003352 size_t noTestMethods = 0;
Phil Nashb971fe72015-07-02 08:21:38 +01003353 int noClasses = objc_getClassList( CATCH_NULL, 0 );
Phil Nash83224e62011-08-12 18:53:28 +01003354
Phil Nash861a1e72012-04-28 12:29:52 +01003355 Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);
Phil Nash53c990a2012-03-17 18:20:06 +00003356 objc_getClassList( classes, noClasses );
Phil Nash83224e62011-08-12 18:53:28 +01003357
Phil Nash89d2a3f2012-05-16 15:09:17 +01003358 for( int c = 0; c < noClasses; c++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003359 Class cls = classes[c];
3360 {
3361 u_int count;
3362 Method* methods = class_copyMethodList( cls, &count );
Phil Nash7004f4a2012-05-22 08:56:59 +01003363 for( u_int m = 0; m < count ; m++ ) {
Phil Nash83224e62011-08-12 18:53:28 +01003364 SEL selector = method_getName(methods[m]);
3365 std::string methodName = sel_getName(selector);
Phil Nash3649fdf2013-12-03 18:53:55 +00003366 if( startsWith( methodName, "Catch_TestCase_" ) ) {
Phil Nash83224e62011-08-12 18:53:28 +01003367 std::string testCaseName = methodName.substr( 15 );
Phil Nash53c990a2012-03-17 18:20:06 +00003368 std::string name = Detail::getAnnotation( cls, "Name", testCaseName );
3369 std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );
Phil Nasha8c65432013-02-19 08:46:09 +00003370 const char* className = class_getName( cls );
Phil Nash83224e62011-08-12 18:53:28 +01003371
Phil Nash5bdae842013-02-19 19:47:18 +00003372 getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, name.c_str(), desc.c_str(), SourceLineInfo() ) );
Phil Nash83224e62011-08-12 18:53:28 +01003373 noTestMethods++;
Phil Nash83224e62011-08-12 18:53:28 +01003374 }
3375 }
3376 free(methods);
3377 }
3378 }
3379 return noTestMethods;
3380 }
Phil Nash78d95a02012-03-04 21:22:36 +00003381
Phil Nash89d2a3f2012-05-16 15:09:17 +01003382 namespace Matchers {
3383 namespace Impl {
3384 namespace NSStringMatchers {
3385
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003386 struct StringHolder : MatcherBase<NSString*>{
Phil Nash78d95a02012-03-04 21:22:36 +00003387 StringHolder( NSString* substr ) : m_substr( [substr copy] ){}
Phil Nasha8c65432013-02-19 08:46:09 +00003388 StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}
Phil Nash89d2a3f2012-05-16 15:09:17 +01003389 StringHolder() {
Phil Nash53c990a2012-03-17 18:20:06 +00003390 arcSafeRelease( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003391 }
3392
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003393 virtual bool match( NSString* arg ) const CATCH_OVERRIDE {
3394 return false;
3395 }
3396
Phil Nash78d95a02012-03-04 21:22:36 +00003397 NSString* m_substr;
3398 };
3399
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003400 struct Equals : StringHolder {
Phil Nash8d18d162012-03-14 20:06:14 +00003401 Equals( NSString* substr ) : StringHolder( substr ){}
3402
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003403 virtual bool match( NSString* str ) const CATCH_OVERRIDE {
Phil Nash372a6c62013-07-23 08:15:34 +01003404 return (str != nil || m_substr == nil ) &&
3405 [str isEqualToString:m_substr];
Phil Nash8d18d162012-03-14 20:06:14 +00003406 }
3407
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003408 virtual std::string describe() const CATCH_OVERRIDE {
Phil Nashacdd3b52014-06-30 07:35:36 +01003409 return "equals string: " + Catch::toString( m_substr );
Phil Nash8d18d162012-03-14 20:06:14 +00003410 }
3411 };
3412
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003413 struct Contains : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00003414 Contains( NSString* substr ) : StringHolder( substr ){}
3415
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003416 virtual bool match( NSString* str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003417 return (str != nil || m_substr == nil ) &&
3418 [str rangeOfString:m_substr].location != NSNotFound;
Phil Nash78d95a02012-03-04 21:22:36 +00003419 }
3420
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003421 virtual std::string describe() const CATCH_OVERRIDE {
Phil Nashacdd3b52014-06-30 07:35:36 +01003422 return "contains string: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003423 }
3424 };
3425
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003426 struct StartsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00003427 StartsWith( NSString* substr ) : StringHolder( substr ){}
3428
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003429 virtual bool match( NSString* str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003430 return (str != nil || m_substr == nil ) &&
3431 [str rangeOfString:m_substr].location == 0;
Phil Nash78d95a02012-03-04 21:22:36 +00003432 }
3433
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003434 virtual std::string describe() const CATCH_OVERRIDE {
Phil Nashacdd3b52014-06-30 07:35:36 +01003435 return "starts with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003436 }
3437 };
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003438 struct EndsWith : StringHolder {
Phil Nash78d95a02012-03-04 21:22:36 +00003439 EndsWith( NSString* substr ) : StringHolder( substr ){}
3440
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003441 virtual bool match( NSString* str ) const {
Phil Nash372a6c62013-07-23 08:15:34 +01003442 return (str != nil || m_substr == nil ) &&
3443 [str rangeOfString:m_substr].location == [str length] - [m_substr length];
Phil Nash78d95a02012-03-04 21:22:36 +00003444 }
3445
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01003446 virtual std::string describe() const CATCH_OVERRIDE {
Phil Nashacdd3b52014-06-30 07:35:36 +01003447 return "ends with: " + Catch::toString( m_substr );
Phil Nash78d95a02012-03-04 21:22:36 +00003448 }
3449 };
3450
3451 } // namespace NSStringMatchers
3452 } // namespace Impl
3453
Phil Nash8d18d162012-03-14 20:06:14 +00003454 inline Impl::NSStringMatchers::Equals
3455 Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }
3456
Phil Nash78d95a02012-03-04 21:22:36 +00003457 inline Impl::NSStringMatchers::Contains
3458 Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003459
Phil Nash78d95a02012-03-04 21:22:36 +00003460 inline Impl::NSStringMatchers::StartsWith
3461 StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }
Phil Nash8d18d162012-03-14 20:06:14 +00003462
Phil Nash78d95a02012-03-04 21:22:36 +00003463 inline Impl::NSStringMatchers::EndsWith
3464 EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }
3465
3466 } // namespace Matchers
3467
3468 using namespace Matchers;
3469
3470} // namespace Catch
Phil Nash83224e62011-08-12 18:53:28 +01003471
3472///////////////////////////////////////////////////////////////////////////////
3473#define OC_TEST_CASE( name, desc )\
Phil Nash53c990a2012-03-17 18:20:06 +00003474+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Name_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003475{\
Phil Nash53c990a2012-03-17 18:20:06 +00003476return @ name; \
Phil Nash83224e62011-08-12 18:53:28 +01003477}\
Phil Nash53c990a2012-03-17 18:20:06 +00003478+(NSString*) INTERNAL_CATCH_UNIQUE_NAME( Catch_Description_test ) \
Phil Nash83224e62011-08-12 18:53:28 +01003479{ \
Phil Nash53c990a2012-03-17 18:20:06 +00003480return @ desc; \
Phil Nash83224e62011-08-12 18:53:28 +01003481} \
3482-(void) INTERNAL_CATCH_UNIQUE_NAME( Catch_TestCase_test )
3483
3484#endif
3485
Phil Nash576aff62014-12-21 00:21:23 +00003486#ifdef CATCH_IMPL
Phil Nash0952b762017-02-28 14:19:09 +00003487
3488// !TBD: Move the leak detector code into a separate header
3489#ifdef CATCH_CONFIG_WINDOWS_CRTDBG
3490#include <crtdbg.h>
3491class LeakDetector {
3492public:
3493 LeakDetector() {
3494 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);
3495 flag |= _CRTDBG_LEAK_CHECK_DF;
3496 flag |= _CRTDBG_ALLOC_MEM_DF;
3497 _CrtSetDbgFlag(flag);
3498 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
3499 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
3500 // Change this to leaking allocation's number to break there
3501 _CrtSetBreakAlloc(-1);
3502 }
3503};
3504#else
3505class LeakDetector {};
3506#endif
3507
3508LeakDetector leakDetector;
3509
Phil Nasha695eb92012-08-13 07:46:10 +01003510// #included from: internal/catch_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04003511#define TWOBLUECUBES_CATCH_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01003512
3513// Collect all the implementation files together here
3514// These are the equivalent of what would usually be cpp files
3515
Phil Nash5bc030d2012-08-16 18:48:50 +01003516#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +01003517#pragma clang diagnostic push
3518#pragma clang diagnostic ignored "-Wweak-vtables"
Phil Nash5bc030d2012-08-16 18:48:50 +01003519#endif
Phil Nasha695eb92012-08-13 07:46:10 +01003520
Phil Nashe73583d2015-08-07 17:30:34 +01003521// #included from: ../catch_session.hpp
Phil Nash3b80af72012-08-09 07:47:30 +01003522#define TWOBLUECUBES_CATCH_RUNNER_HPP_INCLUDED
Phil Nash83224e62011-08-12 18:53:28 +01003523
Phil Nasha695eb92012-08-13 07:46:10 +01003524// #included from: internal/catch_commandline.hpp
3525#define TWOBLUECUBES_CATCH_COMMANDLINE_HPP_INCLUDED
3526
Phil Nash3649fdf2013-12-03 18:53:55 +00003527// #included from: catch_config.hpp
3528#define TWOBLUECUBES_CATCH_CONFIG_HPP_INCLUDED
3529
Phil Nash65cc14c2014-05-16 18:54:48 +01003530// #included from: catch_test_spec_parser.hpp
3531#define TWOBLUECUBES_CATCH_TEST_SPEC_PARSER_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003532
3533#ifdef __clang__
Phil Nash65cc14c2014-05-16 18:54:48 +01003534#pragma clang diagnostic push
Phil Nash3649fdf2013-12-03 18:53:55 +00003535#pragma clang diagnostic ignored "-Wpadded"
3536#endif
3537
Phil Nash65cc14c2014-05-16 18:54:48 +01003538// #included from: catch_test_spec.hpp
3539#define TWOBLUECUBES_CATCH_TEST_SPEC_HPP_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003540
Phil Nash65cc14c2014-05-16 18:54:48 +01003541#ifdef __clang__
3542#pragma clang diagnostic push
3543#pragma clang diagnostic ignored "-Wpadded"
3544#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00003545
Phil Nash8342ae82015-07-13 15:03:26 +01003546// #included from: catch_wildcard_pattern.hpp
3547#define TWOBLUECUBES_CATCH_WILDCARD_PATTERN_HPP_INCLUDED
3548
Phil Nashd08cee22017-02-13 16:15:42 +00003549#include <stdexcept>
3550
Phil Nash8342ae82015-07-13 15:03:26 +01003551namespace Catch
3552{
3553 class WildcardPattern {
3554 enum WildcardPosition {
3555 NoWildcard = 0,
3556 WildcardAtStart = 1,
3557 WildcardAtEnd = 2,
3558 WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd
3559 };
3560
3561 public:
3562
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003563 WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity )
Phil Nash8342ae82015-07-13 15:03:26 +01003564 : m_caseSensitivity( caseSensitivity ),
3565 m_wildcard( NoWildcard ),
3566 m_pattern( adjustCase( pattern ) )
3567 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003568 if( startsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003569 m_pattern = m_pattern.substr( 1 );
3570 m_wildcard = WildcardAtStart;
3571 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003572 if( endsWith( m_pattern, '*' ) ) {
Phil Nash8342ae82015-07-13 15:03:26 +01003573 m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );
3574 m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );
3575 }
3576 }
3577 virtual ~WildcardPattern();
3578 virtual bool matches( std::string const& str ) const {
3579 switch( m_wildcard ) {
3580 case NoWildcard:
3581 return m_pattern == adjustCase( str );
3582 case WildcardAtStart:
3583 return endsWith( adjustCase( str ), m_pattern );
3584 case WildcardAtEnd:
3585 return startsWith( adjustCase( str ), m_pattern );
3586 case WildcardAtBothEnds:
3587 return contains( adjustCase( str ), m_pattern );
3588 }
3589
3590#ifdef __clang__
3591#pragma clang diagnostic push
3592#pragma clang diagnostic ignored "-Wunreachable-code"
3593#endif
3594 throw std::logic_error( "Unknown enum" );
3595#ifdef __clang__
3596#pragma clang diagnostic pop
3597#endif
3598 }
3599 private:
3600 std::string adjustCase( std::string const& str ) const {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003601 return m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str;
Phil Nash8342ae82015-07-13 15:03:26 +01003602 }
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003603 CaseSensitive::Choice m_caseSensitivity;
Phil Nash8342ae82015-07-13 15:03:26 +01003604 WildcardPosition m_wildcard;
3605 std::string m_pattern;
3606 };
3607}
3608
Phil Nash3649fdf2013-12-03 18:53:55 +00003609#include <string>
3610#include <vector>
3611
3612namespace Catch {
3613
Phil Nash65cc14c2014-05-16 18:54:48 +01003614 class TestSpec {
3615 struct Pattern : SharedImpl<> {
3616 virtual ~Pattern();
3617 virtual bool matches( TestCaseInfo const& testCase ) const = 0;
3618 };
3619 class NamePattern : public Pattern {
Phil Nash65cc14c2014-05-16 18:54:48 +01003620 public:
Phil Nash8342ae82015-07-13 15:03:26 +01003621 NamePattern( std::string const& name )
Phil Nash5bbdc8f2015-07-15 23:03:11 +01003622 : m_wildcardPattern( toLower( name ), CaseSensitive::No )
Phil Nash8342ae82015-07-13 15:03:26 +01003623 {}
Phil Nash65cc14c2014-05-16 18:54:48 +01003624 virtual ~NamePattern();
3625 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash8342ae82015-07-13 15:03:26 +01003626 return m_wildcardPattern.matches( toLower( testCase.name ) );
Phil Nash65cc14c2014-05-16 18:54:48 +01003627 }
3628 private:
Phil Nash8342ae82015-07-13 15:03:26 +01003629 WildcardPattern m_wildcardPattern;
Phil Nash65cc14c2014-05-16 18:54:48 +01003630 };
Phil Nash8342ae82015-07-13 15:03:26 +01003631
Phil Nash65cc14c2014-05-16 18:54:48 +01003632 class TagPattern : public Pattern {
3633 public:
3634 TagPattern( std::string const& tag ) : m_tag( toLower( tag ) ) {}
3635 virtual ~TagPattern();
3636 virtual bool matches( TestCaseInfo const& testCase ) const {
Phil Nash9241e432014-05-20 18:50:59 +01003637 return testCase.lcaseTags.find( m_tag ) != testCase.lcaseTags.end();
Phil Nash65cc14c2014-05-16 18:54:48 +01003638 }
3639 private:
3640 std::string m_tag;
3641 };
Phil Nash8342ae82015-07-13 15:03:26 +01003642
Phil Nash65cc14c2014-05-16 18:54:48 +01003643 class ExcludedPattern : public Pattern {
3644 public:
3645 ExcludedPattern( Ptr<Pattern> const& underlyingPattern ) : m_underlyingPattern( underlyingPattern ) {}
3646 virtual ~ExcludedPattern();
3647 virtual bool matches( TestCaseInfo const& testCase ) const { return !m_underlyingPattern->matches( testCase ); }
3648 private:
3649 Ptr<Pattern> m_underlyingPattern;
3650 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003651
Phil Nash65cc14c2014-05-16 18:54:48 +01003652 struct Filter {
3653 std::vector<Ptr<Pattern> > m_patterns;
3654
3655 bool matches( TestCaseInfo const& testCase ) const {
3656 // All patterns in a filter must match for the filter to be a match
Phil Nash40f60682016-09-27 10:46:22 +01003657 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 +01003658 if( !(*it)->matches( testCase ) )
3659 return false;
Phil Nash40f60682016-09-27 10:46:22 +01003660 }
3661 return true;
Phil Nash65cc14c2014-05-16 18:54:48 +01003662 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003663 };
3664
3665 public:
Phil Nash65cc14c2014-05-16 18:54:48 +01003666 bool hasFilters() const {
3667 return !m_filters.empty();
3668 }
3669 bool matches( TestCaseInfo const& testCase ) const {
3670 // A TestSpec matches if any filter matches
3671 for( std::vector<Filter>::const_iterator it = m_filters.begin(), itEnd = m_filters.end(); it != itEnd; ++it )
3672 if( it->matches( testCase ) )
3673 return true;
3674 return false;
3675 }
Phil Nash3649fdf2013-12-03 18:53:55 +00003676
3677 private:
Phil Nash65cc14c2014-05-16 18:54:48 +01003678 std::vector<Filter> m_filters;
Phil Nash3649fdf2013-12-03 18:53:55 +00003679
Phil Nash65cc14c2014-05-16 18:54:48 +01003680 friend class TestSpecParser;
Phil Nash3649fdf2013-12-03 18:53:55 +00003681 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003682}
3683
Phil Nash65cc14c2014-05-16 18:54:48 +01003684#ifdef __clang__
3685#pragma clang diagnostic pop
3686#endif
3687
3688namespace Catch {
3689
3690 class TestSpecParser {
Phil Nash3b2f2062017-01-11 16:43:56 +00003691 enum Mode{ None, Name, QuotedName, Tag, EscapedName };
Phil Nash65cc14c2014-05-16 18:54:48 +01003692 Mode m_mode;
3693 bool m_exclusion;
3694 std::size_t m_start, m_pos;
3695 std::string m_arg;
Phil Nash3b2f2062017-01-11 16:43:56 +00003696 std::vector<std::size_t> m_escapeChars;
Phil Nash65cc14c2014-05-16 18:54:48 +01003697 TestSpec::Filter m_currentFilter;
3698 TestSpec m_testSpec;
Phil Nash52e1e742014-07-03 08:11:38 +01003699 ITagAliasRegistry const* m_tagAliases;
Phil Nash65cc14c2014-05-16 18:54:48 +01003700
3701 public:
Phil Nash52e1e742014-07-03 08:11:38 +01003702 TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}
Phil Nashacdd3b52014-06-30 07:35:36 +01003703
3704 TestSpecParser& parse( std::string const& arg ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01003705 m_mode = None;
3706 m_exclusion = false;
3707 m_start = std::string::npos;
Phil Nash52e1e742014-07-03 08:11:38 +01003708 m_arg = m_tagAliases->expandAliases( arg );
Phil Nash3b2f2062017-01-11 16:43:56 +00003709 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003710 for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )
3711 visitChar( m_arg[m_pos] );
3712 if( m_mode == Name )
3713 addPattern<TestSpec::NamePattern>();
3714 return *this;
3715 }
3716 TestSpec testSpec() {
Phil Nash9241e432014-05-20 18:50:59 +01003717 addFilter();
Phil Nash65cc14c2014-05-16 18:54:48 +01003718 return m_testSpec;
3719 }
3720 private:
3721 void visitChar( char c ) {
3722 if( m_mode == None ) {
3723 switch( c ) {
3724 case ' ': return;
3725 case '~': m_exclusion = true; return;
3726 case '[': return startNewMode( Tag, ++m_pos );
3727 case '"': return startNewMode( QuotedName, ++m_pos );
Phil Nash3b2f2062017-01-11 16:43:56 +00003728 case '\\': return escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003729 default: startNewMode( Name, m_pos ); break;
3730 }
3731 }
3732 if( m_mode == Name ) {
3733 if( c == ',' ) {
3734 addPattern<TestSpec::NamePattern>();
3735 addFilter();
3736 }
3737 else if( c == '[' ) {
3738 if( subString() == "exclude:" )
3739 m_exclusion = true;
3740 else
3741 addPattern<TestSpec::NamePattern>();
3742 startNewMode( Tag, ++m_pos );
3743 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003744 else if( c == '\\' )
3745 escape();
Phil Nash65cc14c2014-05-16 18:54:48 +01003746 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003747 else if( m_mode == EscapedName )
3748 m_mode = Name;
Phil Nash65cc14c2014-05-16 18:54:48 +01003749 else if( m_mode == QuotedName && c == '"' )
3750 addPattern<TestSpec::NamePattern>();
3751 else if( m_mode == Tag && c == ']' )
3752 addPattern<TestSpec::TagPattern>();
3753 }
3754 void startNewMode( Mode mode, std::size_t start ) {
3755 m_mode = mode;
3756 m_start = start;
3757 }
Phil Nash3b2f2062017-01-11 16:43:56 +00003758 void escape() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003759 if( m_mode == None )
3760 m_start = m_pos;
Phil Nash3b2f2062017-01-11 16:43:56 +00003761 m_mode = EscapedName;
3762 m_escapeChars.push_back( m_pos );
3763 }
Phil Nash65cc14c2014-05-16 18:54:48 +01003764 std::string subString() const { return m_arg.substr( m_start, m_pos - m_start ); }
3765 template<typename T>
3766 void addPattern() {
3767 std::string token = subString();
Phil Nash3b2f2062017-01-11 16:43:56 +00003768 for( size_t i = 0; i < m_escapeChars.size(); ++i )
Phil Nash0952b762017-02-28 14:19:09 +00003769 token = token.substr( 0, m_escapeChars[i]-m_start-i ) + token.substr( m_escapeChars[i]-m_start-i+1 );
Phil Nash3b2f2062017-01-11 16:43:56 +00003770 m_escapeChars.clear();
Phil Nash65cc14c2014-05-16 18:54:48 +01003771 if( startsWith( token, "exclude:" ) ) {
3772 m_exclusion = true;
3773 token = token.substr( 8 );
3774 }
3775 if( !token.empty() ) {
3776 Ptr<TestSpec::Pattern> pattern = new T( token );
3777 if( m_exclusion )
3778 pattern = new TestSpec::ExcludedPattern( pattern );
3779 m_currentFilter.m_patterns.push_back( pattern );
3780 }
3781 m_exclusion = false;
3782 m_mode = None;
3783 }
3784 void addFilter() {
3785 if( !m_currentFilter.m_patterns.empty() ) {
3786 m_testSpec.m_filters.push_back( m_currentFilter );
3787 m_currentFilter = TestSpec::Filter();
3788 }
3789 }
3790 };
3791 inline TestSpec parseTestSpec( std::string const& arg ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01003792 return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01003793 }
3794
3795} // namespace Catch
3796
3797#ifdef __clang__
3798#pragma clang diagnostic pop
3799#endif
3800
Phil Nashab036682014-06-02 07:48:03 +01003801// #included from: catch_interfaces_config.h
3802#define TWOBLUECUBES_CATCH_INTERFACES_CONFIG_H_INCLUDED
3803
Phil Nashd08cee22017-02-13 16:15:42 +00003804#include <iosfwd>
Phil Nashab036682014-06-02 07:48:03 +01003805#include <string>
3806#include <vector>
3807
3808namespace Catch {
3809
3810 struct Verbosity { enum Level {
3811 NoOutput = 0,
3812 Quiet,
3813 Normal
3814 }; };
3815
3816 struct WarnAbout { enum What {
3817 Nothing = 0x00,
3818 NoAssertions = 0x01
3819 }; };
3820
3821 struct ShowDurations { enum OrNot {
3822 DefaultForReporter,
3823 Always,
3824 Never
3825 }; };
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003826 struct RunTests { enum InWhatOrder {
3827 InDeclarationOrder,
3828 InLexicographicalOrder,
3829 InRandomOrder
3830 }; };
Phil Nashae5ee2c2016-02-29 08:17:18 +00003831 struct UseColour { enum YesOrNo {
3832 Auto,
3833 Yes,
3834 No
3835 }; };
Phil Nashab036682014-06-02 07:48:03 +01003836
3837 class TestSpec;
3838
3839 struct IConfig : IShared {
3840
3841 virtual ~IConfig();
3842
3843 virtual bool allowThrows() const = 0;
3844 virtual std::ostream& stream() const = 0;
3845 virtual std::string name() const = 0;
3846 virtual bool includeSuccessfulResults() const = 0;
3847 virtual bool shouldDebugBreak() const = 0;
3848 virtual bool warnAboutMissingAssertions() const = 0;
3849 virtual int abortAfter() const = 0;
3850 virtual bool showInvisibles() const = 0;
3851 virtual ShowDurations::OrNot showDurations() const = 0;
3852 virtual TestSpec const& testSpec() const = 0;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003853 virtual RunTests::InWhatOrder runOrder() const = 0;
3854 virtual unsigned int rngSeed() const = 0;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003855 virtual UseColour::YesOrNo useColour() const = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003856 virtual std::vector<std::string> const& getSectionsToRun() const = 0;
3857
Phil Nashab036682014-06-02 07:48:03 +01003858 };
3859}
3860
Phil Nash3649fdf2013-12-03 18:53:55 +00003861// #included from: catch_stream.h
3862#define TWOBLUECUBES_CATCH_STREAM_H_INCLUDED
3863
Phil Nash7e346192015-11-03 08:00:43 +00003864// #included from: catch_streambuf.h
3865#define TWOBLUECUBES_CATCH_STREAMBUF_H_INCLUDED
Phil Nash3649fdf2013-12-03 18:53:55 +00003866
Phil Nash7e346192015-11-03 08:00:43 +00003867#include <streambuf>
Phil Nash3649fdf2013-12-03 18:53:55 +00003868
3869namespace Catch {
3870
Phil Nash7e346192015-11-03 08:00:43 +00003871 class StreamBufBase : public std::streambuf {
Phil Nash3649fdf2013-12-03 18:53:55 +00003872 public:
Phil Nash7e346192015-11-03 08:00:43 +00003873 virtual ~StreamBufBase() CATCH_NOEXCEPT;
Phil Nash3649fdf2013-12-03 18:53:55 +00003874 };
Phil Nash7e346192015-11-03 08:00:43 +00003875}
3876
3877#include <streambuf>
3878#include <ostream>
3879#include <fstream>
Phil Nash2be37272016-11-29 12:15:50 +00003880#include <memory>
Phil Nash7e346192015-11-03 08:00:43 +00003881
3882namespace Catch {
Phil Nash383d7c02014-10-02 19:08:19 +01003883
3884 std::ostream& cout();
3885 std::ostream& cerr();
Phil Nash7e346192015-11-03 08:00:43 +00003886
3887 struct IStream {
3888 virtual ~IStream() CATCH_NOEXCEPT;
3889 virtual std::ostream& stream() const = 0;
3890 };
3891
3892 class FileStream : public IStream {
3893 mutable std::ofstream m_ofs;
3894 public:
3895 FileStream( std::string const& filename );
Phil Nashece529a2015-11-03 17:37:43 +00003896 virtual ~FileStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003897 public: // IStream
3898 virtual std::ostream& stream() const CATCH_OVERRIDE;
3899 };
3900
3901 class CoutStream : public IStream {
3902 mutable std::ostream m_os;
3903 public:
3904 CoutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003905 virtual ~CoutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003906
3907 public: // IStream
3908 virtual std::ostream& stream() const CATCH_OVERRIDE;
3909 };
3910
3911 class DebugOutStream : public IStream {
Phil Nashac220282016-06-09 08:19:23 +01003912 CATCH_AUTO_PTR( StreamBufBase ) m_streamBuf;
Phil Nash7e346192015-11-03 08:00:43 +00003913 mutable std::ostream m_os;
3914 public:
3915 DebugOutStream();
Phil Nashece529a2015-11-03 17:37:43 +00003916 virtual ~DebugOutStream() CATCH_NOEXCEPT;
Phil Nash7e346192015-11-03 08:00:43 +00003917
3918 public: // IStream
3919 virtual std::ostream& stream() const CATCH_OVERRIDE;
3920 };
Phil Nash3649fdf2013-12-03 18:53:55 +00003921}
3922
3923#include <memory>
3924#include <vector>
3925#include <string>
Phil Nashd08cee22017-02-13 16:15:42 +00003926#include <stdexcept>
Phil Nash3649fdf2013-12-03 18:53:55 +00003927
3928#ifndef CATCH_CONFIG_CONSOLE_WIDTH
3929#define CATCH_CONFIG_CONSOLE_WIDTH 80
3930#endif
3931
3932namespace Catch {
3933
3934 struct ConfigData {
3935
3936 ConfigData()
3937 : listTests( false ),
3938 listTags( false ),
3939 listReporters( false ),
3940 listTestNamesOnly( false ),
3941 showSuccessfulTests( false ),
3942 shouldDebugBreak( false ),
3943 noThrow( false ),
3944 showHelp( false ),
Phil Nashaef6cd52014-04-23 07:10:10 +01003945 showInvisibles( false ),
Phil Nashb971fe72015-07-02 08:21:38 +01003946 filenamesAsTags( false ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003947 abortAfter( -1 ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003948 rngSeed( 0 ),
Phil Nash3649fdf2013-12-03 18:53:55 +00003949 verbosity( Verbosity::Normal ),
3950 warnings( WarnAbout::Nothing ),
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003951 showDurations( ShowDurations::DefaultForReporter ),
Phil Nashae5ee2c2016-02-29 08:17:18 +00003952 runOrder( RunTests::InDeclarationOrder ),
3953 useColour( UseColour::Auto )
Phil Nash3649fdf2013-12-03 18:53:55 +00003954 {}
3955
3956 bool listTests;
3957 bool listTags;
3958 bool listReporters;
3959 bool listTestNamesOnly;
3960
3961 bool showSuccessfulTests;
3962 bool shouldDebugBreak;
3963 bool noThrow;
3964 bool showHelp;
Phil Nashaef6cd52014-04-23 07:10:10 +01003965 bool showInvisibles;
Phil Nashb971fe72015-07-02 08:21:38 +01003966 bool filenamesAsTags;
Phil Nash3649fdf2013-12-03 18:53:55 +00003967
3968 int abortAfter;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003969 unsigned int rngSeed;
Phil Nash3649fdf2013-12-03 18:53:55 +00003970
3971 Verbosity::Level verbosity;
3972 WarnAbout::What warnings;
3973 ShowDurations::OrNot showDurations;
Phil Nash6a8e8ad2014-09-15 18:40:24 +01003974 RunTests::InWhatOrder runOrder;
Phil Nashae5ee2c2016-02-29 08:17:18 +00003975 UseColour::YesOrNo useColour;
Phil Nash3649fdf2013-12-03 18:53:55 +00003976
Phil Nash3649fdf2013-12-03 18:53:55 +00003977 std::string outputFilename;
3978 std::string name;
3979 std::string processName;
3980
Phil Nashe73583d2015-08-07 17:30:34 +01003981 std::vector<std::string> reporterNames;
Phil Nash3649fdf2013-12-03 18:53:55 +00003982 std::vector<std::string> testsOrTags;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01003983 std::vector<std::string> sectionsToRun;
Phil Nash3649fdf2013-12-03 18:53:55 +00003984 };
3985
3986 class Config : public SharedImpl<IConfig> {
3987 private:
3988 Config( Config const& other );
3989 Config& operator = ( Config const& other );
3990 virtual void dummy();
3991 public:
3992
3993 Config()
Phil Nash3649fdf2013-12-03 18:53:55 +00003994 {}
3995
3996 Config( ConfigData const& data )
3997 : m_data( data ),
Phil Nash7e346192015-11-03 08:00:43 +00003998 m_stream( openStream() )
Phil Nash3649fdf2013-12-03 18:53:55 +00003999 {
4000 if( !data.testsOrTags.empty() ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01004001 TestSpecParser parser( ITagAliasRegistry::get() );
Phil Nash65cc14c2014-05-16 18:54:48 +01004002 for( std::size_t i = 0; i < data.testsOrTags.size(); ++i )
4003 parser.parse( data.testsOrTags[i] );
4004 m_testSpec = parser.testSpec();
Phil Nash3649fdf2013-12-03 18:53:55 +00004005 }
4006 }
4007
Phil Nashd08cee22017-02-13 16:15:42 +00004008 virtual ~Config() {}
Phil Nash3649fdf2013-12-03 18:53:55 +00004009
4010 std::string const& getFilename() const {
4011 return m_data.outputFilename ;
4012 }
4013
4014 bool listTests() const { return m_data.listTests; }
4015 bool listTestNamesOnly() const { return m_data.listTestNamesOnly; }
4016 bool listTags() const { return m_data.listTags; }
4017 bool listReporters() const { return m_data.listReporters; }
4018
Phil Nash65cc14c2014-05-16 18:54:48 +01004019 std::string getProcessName() const { return m_data.processName; }
Phil Nash3649fdf2013-12-03 18:53:55 +00004020
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01004021 std::vector<std::string> const& getReporterNames() const { return m_data.reporterNames; }
4022 std::vector<std::string> const& getSectionsToRun() const CATCH_OVERRIDE { return m_data.sectionsToRun; }
Phil Nash3649fdf2013-12-03 18:53:55 +00004023
Phil Nashd08cee22017-02-13 16:15:42 +00004024 virtual TestSpec const& testSpec() const CATCH_OVERRIDE { return m_testSpec; }
Phil Nash3649fdf2013-12-03 18:53:55 +00004025
4026 bool showHelp() const { return m_data.showHelp; }
4027
4028 // IConfig interface
Phil Nashd08cee22017-02-13 16:15:42 +00004029 virtual bool allowThrows() const CATCH_OVERRIDE { return !m_data.noThrow; }
4030 virtual std::ostream& stream() const CATCH_OVERRIDE { return m_stream->stream(); }
4031 virtual std::string name() const CATCH_OVERRIDE { return m_data.name.empty() ? m_data.processName : m_data.name; }
4032 virtual bool includeSuccessfulResults() const CATCH_OVERRIDE { return m_data.showSuccessfulTests; }
4033 virtual bool warnAboutMissingAssertions() const CATCH_OVERRIDE { return m_data.warnings & WarnAbout::NoAssertions; }
4034 virtual ShowDurations::OrNot showDurations() const CATCH_OVERRIDE { return m_data.showDurations; }
4035 virtual RunTests::InWhatOrder runOrder() const CATCH_OVERRIDE { return m_data.runOrder; }
4036 virtual unsigned int rngSeed() const CATCH_OVERRIDE { return m_data.rngSeed; }
4037 virtual UseColour::YesOrNo useColour() const CATCH_OVERRIDE { return m_data.useColour; }
4038 virtual bool shouldDebugBreak() const CATCH_OVERRIDE { return m_data.shouldDebugBreak; }
4039 virtual int abortAfter() const CATCH_OVERRIDE { return m_data.abortAfter; }
4040 virtual bool showInvisibles() const CATCH_OVERRIDE { return m_data.showInvisibles; }
Phil Nash3649fdf2013-12-03 18:53:55 +00004041
4042 private:
Phil Nash7e346192015-11-03 08:00:43 +00004043
4044 IStream const* openStream() {
4045 if( m_data.outputFilename.empty() )
4046 return new CoutStream();
4047 else if( m_data.outputFilename[0] == '%' ) {
4048 if( m_data.outputFilename == "%debug" )
4049 return new DebugOutStream();
4050 else
4051 throw std::domain_error( "Unrecognised stream: " + m_data.outputFilename );
4052 }
4053 else
4054 return new FileStream( m_data.outputFilename );
4055 }
Phil Nash3649fdf2013-12-03 18:53:55 +00004056 ConfigData m_data;
4057
Phil Nashac220282016-06-09 08:19:23 +01004058 CATCH_AUTO_PTR( IStream const ) m_stream;
Phil Nash65cc14c2014-05-16 18:54:48 +01004059 TestSpec m_testSpec;
Phil Nash3649fdf2013-12-03 18:53:55 +00004060 };
4061
4062} // end namespace Catch
4063
Phil Nash1c2fbe12014-02-11 18:12:41 +00004064// #included from: catch_clara.h
4065#define TWOBLUECUBES_CATCH_CLARA_H_INCLUDED
4066
Phil Nashb9fea752014-03-06 08:16:06 +00004067// Use Catch's value for console width (store Clara's off to the side, if present)
4068#ifdef CLARA_CONFIG_CONSOLE_WIDTH
4069#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CLARA_CONFIG_CONSOLE_WIDTH
4070#undef CLARA_CONFIG_CONSOLE_WIDTH
4071#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00004072#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
4073
4074// Declare Clara inside the Catch namespace
Phil Nashb9fea752014-03-06 08:16:06 +00004075#define STITCH_CLARA_OPEN_NAMESPACE namespace Catch {
Phil Nash472dc2a2014-03-17 18:40:58 +00004076// #included from: ../external/clara.h
Phil Nasha695eb92012-08-13 07:46:10 +01004077
Phil Nash5c198d82016-05-07 23:14:04 +01004078// Version 0.0.2.4
Phil Nash3b4edd72016-02-10 19:24:48 +00004079
Phil Nash1c2fbe12014-02-11 18:12:41 +00004080// Only use header guard if we are not using an outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00004081#if !defined(TWOBLUECUBES_CLARA_H_INCLUDED) || defined(STITCH_CLARA_OPEN_NAMESPACE)
4082
4083#ifndef STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004084#define TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00004085#define STITCH_CLARA_OPEN_NAMESPACE
4086#define STITCH_CLARA_CLOSE_NAMESPACE
4087#else
4088#define STITCH_CLARA_CLOSE_NAMESPACE }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004089#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00004090
Phil Nashb9fea752014-03-06 08:16:06 +00004091#define STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004092
4093// ----------- #included from tbc_text_format.h -----------
4094
Phil Nash1c2fbe12014-02-11 18:12:41 +00004095// Only use header guard if we are not using an outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004096#if !defined(TBC_TEXT_FORMAT_H_INCLUDED) || defined(STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE)
4097#ifndef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4098#define TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00004099#endif
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004100
Phil Nash38f7eef2013-03-29 13:44:33 +00004101#include <string>
4102#include <vector>
Phil Nash1c2fbe12014-02-11 18:12:41 +00004103#include <sstream>
Phil Nash3b4edd72016-02-10 19:24:48 +00004104#include <algorithm>
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004105#include <cctype>
Phil Nash38f7eef2013-03-29 13:44:33 +00004106
Phil Nash1c2fbe12014-02-11 18:12:41 +00004107// Use optional outer namespace
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004108#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
4109namespace STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
Phil Nash1c2fbe12014-02-11 18:12:41 +00004110#endif
4111
4112namespace Tbc {
4113
4114#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
4115 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
4116#else
4117 const unsigned int consoleWidth = 80;
4118#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +01004119
Phil Nash19279252013-04-20 21:07:32 +01004120 struct TextAttributes {
4121 TextAttributes()
4122 : initialIndent( std::string::npos ),
4123 indent( 0 ),
Phil Nash1c2fbe12014-02-11 18:12:41 +00004124 width( consoleWidth-1 ),
Phil Nash19279252013-04-20 21:07:32 +01004125 tabChar( '\t' )
Phil Nash89d1e6c2011-05-24 08:23:02 +01004126 {}
Phil Nash3b80af72012-08-09 07:47:30 +01004127
Phil Nash19279252013-04-20 21:07:32 +01004128 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
4129 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
4130 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
4131 TextAttributes& setTabChar( char _value ) { tabChar = _value; return *this; }
Phil Nash89d2a3f2012-05-16 15:09:17 +01004132
Phil Nash19279252013-04-20 21:07:32 +01004133 std::size_t initialIndent; // indent of first line, or npos
4134 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
4135 std::size_t width; // maximum width of text, including indent. Longer text will wrap
4136 char tabChar; // If this char is seen the indent is changed to current pos
Phil Nash89d1e6c2011-05-24 08:23:02 +01004137 };
4138
Phil Nash19279252013-04-20 21:07:32 +01004139 class Text {
Phil Nasha695eb92012-08-13 07:46:10 +01004140 public:
Phil Nash1c2fbe12014-02-11 18:12:41 +00004141 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
4142 : attr( _attr )
4143 {
4144 std::string wrappableChars = " [({.,/|\\-";
4145 std::size_t indent = _attr.initialIndent != std::string::npos
4146 ? _attr.initialIndent
4147 : _attr.indent;
4148 std::string remainder = _str;
4149
4150 while( !remainder.empty() ) {
4151 if( lines.size() >= 1000 ) {
4152 lines.push_back( "... message truncated due to excessive size" );
4153 return;
4154 }
4155 std::size_t tabPos = std::string::npos;
4156 std::size_t width = (std::min)( remainder.size(), _attr.width - indent );
4157 std::size_t pos = remainder.find_first_of( '\n' );
4158 if( pos <= width ) {
4159 width = pos;
4160 }
4161 pos = remainder.find_last_of( _attr.tabChar, width );
4162 if( pos != std::string::npos ) {
4163 tabPos = pos;
4164 if( remainder[width] == '\n' )
4165 width--;
4166 remainder = remainder.substr( 0, tabPos ) + remainder.substr( tabPos+1 );
4167 }
4168
4169 if( width == remainder.size() ) {
4170 spliceLine( indent, remainder, width );
4171 }
4172 else if( remainder[width] == '\n' ) {
4173 spliceLine( indent, remainder, width );
4174 if( width <= 1 || remainder.size() != 1 )
4175 remainder = remainder.substr( 1 );
4176 indent = _attr.indent;
4177 }
4178 else {
4179 pos = remainder.find_last_of( wrappableChars, width );
4180 if( pos != std::string::npos && pos > 0 ) {
4181 spliceLine( indent, remainder, pos );
4182 if( remainder[0] == ' ' )
4183 remainder = remainder.substr( 1 );
4184 }
4185 else {
4186 spliceLine( indent, remainder, width-1 );
4187 lines.back() += "-";
4188 }
4189 if( lines.size() == 1 )
4190 indent = _attr.indent;
4191 if( tabPos != std::string::npos )
4192 indent += tabPos;
4193 }
4194 }
4195 }
4196
4197 void spliceLine( std::size_t _indent, std::string& _remainder, std::size_t _pos ) {
4198 lines.push_back( std::string( _indent, ' ' ) + _remainder.substr( 0, _pos ) );
4199 _remainder = _remainder.substr( _pos );
4200 }
Phil Nasha695eb92012-08-13 07:46:10 +01004201
Phil Nash38f7eef2013-03-29 13:44:33 +00004202 typedef std::vector<std::string>::const_iterator const_iterator;
Phil Nasha695eb92012-08-13 07:46:10 +01004203
Phil Nash38f7eef2013-03-29 13:44:33 +00004204 const_iterator begin() const { return lines.begin(); }
4205 const_iterator end() const { return lines.end(); }
4206 std::string const& last() const { return lines.back(); }
4207 std::size_t size() const { return lines.size(); }
4208 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004209 std::string toString() const {
4210 std::ostringstream oss;
4211 oss << *this;
4212 return oss.str();
4213 }
Phil Nasha695eb92012-08-13 07:46:10 +01004214
Phil Nash1c2fbe12014-02-11 18:12:41 +00004215 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
4216 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
4217 it != itEnd; ++it ) {
4218 if( it != _text.begin() )
4219 _stream << "\n";
4220 _stream << *it;
4221 }
4222 return _stream;
4223 }
Phil Nasha695eb92012-08-13 07:46:10 +01004224
Phil Nasha695eb92012-08-13 07:46:10 +01004225 private:
Phil Nash19279252013-04-20 21:07:32 +01004226 std::string str;
4227 TextAttributes attr;
Phil Nash38f7eef2013-03-29 13:44:33 +00004228 std::vector<std::string> lines;
4229 };
4230
Phil Nash1c2fbe12014-02-11 18:12:41 +00004231} // end namespace Tbc
4232
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004233#ifdef STITCH_TBC_TEXT_FORMAT_OUTER_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004234} // end outer namespace
4235#endif
4236
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004237#endif // TBC_TEXT_FORMAT_H_INCLUDED
Phil Nash1c2fbe12014-02-11 18:12:41 +00004238
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004239// ----------- end of #include from tbc_text_format.h -----------
Phil Nash3b4edd72016-02-10 19:24:48 +00004240// ........... back in clara.h
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004241
Phil Nashb9fea752014-03-06 08:16:06 +00004242#undef STITCH_TBC_TEXT_FORMAT_OPEN_NAMESPACE
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004243
Phil Nash3b4edd72016-02-10 19:24:48 +00004244// ----------- #included from clara_compilers.h -----------
4245
4246#ifndef TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4247#define TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4248
4249// Detect a number of compiler features - mostly C++11/14 conformance - by compiler
4250// The following features are defined:
4251//
4252// CLARA_CONFIG_CPP11_NULLPTR : is nullptr supported?
4253// CLARA_CONFIG_CPP11_NOEXCEPT : is noexcept supported?
4254// CLARA_CONFIG_CPP11_GENERATED_METHODS : The delete and default keywords for compiler generated methods
4255// CLARA_CONFIG_CPP11_OVERRIDE : is override supported?
4256// CLARA_CONFIG_CPP11_UNIQUE_PTR : is unique_ptr supported (otherwise use auto_ptr)
4257
4258// CLARA_CONFIG_CPP11_OR_GREATER : Is C++11 supported?
4259
4260// CLARA_CONFIG_VARIADIC_MACROS : are variadic macros supported?
4261
4262// In general each macro has a _NO_<feature name> form
4263// (e.g. CLARA_CONFIG_CPP11_NO_NULLPTR) which disables the feature.
4264// Many features, at point of detection, define an _INTERNAL_ macro, so they
4265// can be combined, en-mass, with the _NO_ forms later.
4266
4267// All the C++11 features can be disabled with CLARA_CONFIG_NO_CPP11
4268
4269#ifdef __clang__
4270
4271#if __has_feature(cxx_nullptr)
4272#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4273#endif
4274
4275#if __has_feature(cxx_noexcept)
4276#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4277#endif
4278
4279#endif // __clang__
4280
4281////////////////////////////////////////////////////////////////////////////////
4282// GCC
4283#ifdef __GNUC__
4284
4285#if __GNUC__ == 4 && __GNUC_MINOR__ >= 6 && defined(__GXX_EXPERIMENTAL_CXX0X__)
4286#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4287#endif
4288
4289// - otherwise more recent versions define __cplusplus >= 201103L
4290// and will get picked up below
4291
4292#endif // __GNUC__
4293
4294////////////////////////////////////////////////////////////////////////////////
4295// Visual C++
4296#ifdef _MSC_VER
4297
4298#if (_MSC_VER >= 1600)
4299#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4300#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4301#endif
4302
4303#if (_MSC_VER >= 1900 ) // (VC++ 13 (VS2015))
4304#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4305#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4306#endif
4307
4308#endif // _MSC_VER
4309
4310////////////////////////////////////////////////////////////////////////////////
4311// C++ language feature support
4312
4313// catch all support for C++11
4314#if defined(__cplusplus) && __cplusplus >= 201103L
4315
4316#define CLARA_CPP11_OR_GREATER
4317
4318#if !defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR)
4319#define CLARA_INTERNAL_CONFIG_CPP11_NULLPTR
4320#endif
4321
4322#ifndef CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4323#define CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT
4324#endif
4325
4326#ifndef CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4327#define CLARA_INTERNAL_CONFIG_CPP11_GENERATED_METHODS
4328#endif
4329
4330#if !defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE)
4331#define CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE
4332#endif
4333#if !defined(CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR)
4334#define CLARA_INTERNAL_CONFIG_CPP11_UNIQUE_PTR
4335#endif
4336
4337#endif // __cplusplus >= 201103L
4338
4339// Now set the actual defines based on the above + anything the user has configured
4340#if defined(CLARA_INTERNAL_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NO_NULLPTR) && !defined(CLARA_CONFIG_CPP11_NULLPTR) && !defined(CLARA_CONFIG_NO_CPP11)
4341#define CLARA_CONFIG_CPP11_NULLPTR
4342#endif
4343#if defined(CLARA_INTERNAL_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NO_NOEXCEPT) && !defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_CONFIG_NO_CPP11)
4344#define CLARA_CONFIG_CPP11_NOEXCEPT
4345#endif
4346#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)
4347#define CLARA_CONFIG_CPP11_GENERATED_METHODS
4348#endif
4349#if defined(CLARA_INTERNAL_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_OVERRIDE) && !defined(CLARA_CONFIG_CPP11_OVERRIDE) && !defined(CLARA_CONFIG_NO_CPP11)
4350#define CLARA_CONFIG_CPP11_OVERRIDE
4351#endif
4352#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)
4353#define CLARA_CONFIG_CPP11_UNIQUE_PTR
4354#endif
4355
4356// noexcept support:
4357#if defined(CLARA_CONFIG_CPP11_NOEXCEPT) && !defined(CLARA_NOEXCEPT)
4358#define CLARA_NOEXCEPT noexcept
4359# define CLARA_NOEXCEPT_IS(x) noexcept(x)
4360#else
4361#define CLARA_NOEXCEPT throw()
4362# define CLARA_NOEXCEPT_IS(x)
4363#endif
4364
4365// nullptr support
4366#ifdef CLARA_CONFIG_CPP11_NULLPTR
4367#define CLARA_NULL nullptr
4368#else
4369#define CLARA_NULL NULL
4370#endif
4371
4372// override support
4373#ifdef CLARA_CONFIG_CPP11_OVERRIDE
4374#define CLARA_OVERRIDE override
4375#else
4376#define CLARA_OVERRIDE
4377#endif
4378
4379// unique_ptr support
4380#ifdef CLARA_CONFIG_CPP11_UNIQUE_PTR
4381# define CLARA_AUTO_PTR( T ) std::unique_ptr<T>
4382#else
4383# define CLARA_AUTO_PTR( T ) std::auto_ptr<T>
4384#endif
4385
4386#endif // TWOBLUECUBES_CLARA_COMPILERS_H_INCLUDED
4387
4388// ----------- end of #include from clara_compilers.h -----------
4389// ........... back in clara.h
4390
Phil Nash1c2fbe12014-02-11 18:12:41 +00004391#include <map>
Phil Nash1c2fbe12014-02-11 18:12:41 +00004392#include <stdexcept>
4393#include <memory>
4394
Phil Nashe5537842016-04-25 18:56:50 +01004395#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
4396#define CLARA_PLATFORM_WINDOWS
4397#endif
4398
Phil Nash1c2fbe12014-02-11 18:12:41 +00004399// Use optional outer namespace
Phil Nashb9fea752014-03-06 08:16:06 +00004400#ifdef STITCH_CLARA_OPEN_NAMESPACE
4401STITCH_CLARA_OPEN_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00004402#endif
Phil Nash38f7eef2013-03-29 13:44:33 +00004403
Phil Nash786959d2013-06-07 19:07:50 +01004404namespace Clara {
Phil Nashb9fea752014-03-06 08:16:06 +00004405
4406 struct UnpositionalTag {};
4407
4408 extern UnpositionalTag _;
4409
4410#ifdef CLARA_CONFIG_MAIN
4411 UnpositionalTag _;
4412#endif
4413
Phil Nash786959d2013-06-07 19:07:50 +01004414 namespace Detail {
Phil Nash1c2fbe12014-02-11 18:12:41 +00004415
4416#ifdef CLARA_CONSOLE_WIDTH
4417 const unsigned int consoleWidth = CLARA_CONFIG_CONSOLE_WIDTH;
4418#else
4419 const unsigned int consoleWidth = 80;
4420#endif
4421
Phil Nashb9fea752014-03-06 08:16:06 +00004422 using namespace Tbc;
4423
4424 inline bool startsWith( std::string const& str, std::string const& prefix ) {
4425 return str.size() >= prefix.size() && str.substr( 0, prefix.size() ) == prefix;
4426 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00004427
Phil Nash786959d2013-06-07 19:07:50 +01004428 template<typename T> struct RemoveConstRef{ typedef T type; };
4429 template<typename T> struct RemoveConstRef<T&>{ typedef T type; };
4430 template<typename T> struct RemoveConstRef<T const&>{ typedef T type; };
4431 template<typename T> struct RemoveConstRef<T const>{ typedef T type; };
4432
4433 template<typename T> struct IsBool { static const bool value = false; };
4434 template<> struct IsBool<bool> { static const bool value = true; };
Phil Nasha695eb92012-08-13 07:46:10 +01004435
4436 template<typename T>
Phil Nash786959d2013-06-07 19:07:50 +01004437 void convertInto( std::string const& _source, T& _dest ) {
4438 std::stringstream ss;
4439 ss << _source;
4440 ss >> _dest;
4441 if( ss.fail() )
4442 throw std::runtime_error( "Unable to convert " + _source + " to destination type" );
Phil Nasha695eb92012-08-13 07:46:10 +01004443 }
Phil Nash786959d2013-06-07 19:07:50 +01004444 inline void convertInto( std::string const& _source, std::string& _dest ) {
4445 _dest = _source;
4446 }
Phil Nash2be37272016-11-29 12:15:50 +00004447 char toLowerCh(char c) {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004448 return static_cast<char>( std::tolower( c ) );
Phil Nash2be37272016-11-29 12:15:50 +00004449 }
Phil Nash786959d2013-06-07 19:07:50 +01004450 inline void convertInto( std::string const& _source, bool& _dest ) {
4451 std::string sourceLC = _source;
Phil Nash2be37272016-11-29 12:15:50 +00004452 std::transform( sourceLC.begin(), sourceLC.end(), sourceLC.begin(), toLowerCh );
Phil Nash46118712013-08-16 19:01:32 +01004453 if( sourceLC == "y" || sourceLC == "1" || sourceLC == "true" || sourceLC == "yes" || sourceLC == "on" )
Phil Nash786959d2013-06-07 19:07:50 +01004454 _dest = true;
Phil Nash46118712013-08-16 19:01:32 +01004455 else if( sourceLC == "n" || sourceLC == "0" || sourceLC == "false" || sourceLC == "no" || sourceLC == "off" )
Phil Nash786959d2013-06-07 19:07:50 +01004456 _dest = false;
4457 else
Phil Nash46118712013-08-16 19:01:32 +01004458 throw std::runtime_error( "Expected a boolean value but did not recognise:\n '" + _source + "'" );
Phil Nash786959d2013-06-07 19:07:50 +01004459 }
Phil Nasha695eb92012-08-13 07:46:10 +01004460
Phil Nash786959d2013-06-07 19:07:50 +01004461 template<typename ConfigT>
4462 struct IArgFunction {
4463 virtual ~IArgFunction() {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004464#ifdef CLARA_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01004465 IArgFunction() = default;
4466 IArgFunction( IArgFunction const& ) = default;
Phil Nash3b4edd72016-02-10 19:24:48 +00004467#endif
Phil Nash786959d2013-06-07 19:07:50 +01004468 virtual void set( ConfigT& config, std::string const& value ) const = 0;
Phil Nash786959d2013-06-07 19:07:50 +01004469 virtual bool takesArg() const = 0;
4470 virtual IArgFunction* clone() const = 0;
4471 };
4472
4473 template<typename ConfigT>
4474 class BoundArgFunction {
4475 public:
Phil Nash3b4edd72016-02-10 19:24:48 +00004476 BoundArgFunction() : functionObj( CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004477 BoundArgFunction( IArgFunction<ConfigT>* _functionObj ) : functionObj( _functionObj ) {}
Phil Nash3b4edd72016-02-10 19:24:48 +00004478 BoundArgFunction( BoundArgFunction const& other ) : functionObj( other.functionObj ? other.functionObj->clone() : CLARA_NULL ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004479 BoundArgFunction& operator = ( BoundArgFunction const& other ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004480 IArgFunction<ConfigT>* newFunctionObj = other.functionObj ? other.functionObj->clone() : CLARA_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01004481 delete functionObj;
4482 functionObj = newFunctionObj;
4483 return *this;
4484 }
4485 ~BoundArgFunction() { delete functionObj; }
4486
4487 void set( ConfigT& config, std::string const& value ) const {
4488 functionObj->set( config, value );
4489 }
Phil Nash786959d2013-06-07 19:07:50 +01004490 bool takesArg() const { return functionObj->takesArg(); }
Phil Nashaf8cd982014-03-24 18:15:04 +00004491
4492 bool isSet() const {
Phil Nash3b4edd72016-02-10 19:24:48 +00004493 return functionObj != CLARA_NULL;
Phil Nashaf8cd982014-03-24 18:15:04 +00004494 }
Phil Nash786959d2013-06-07 19:07:50 +01004495 private:
4496 IArgFunction<ConfigT>* functionObj;
4497 };
4498
4499 template<typename C>
4500 struct NullBinder : IArgFunction<C>{
4501 virtual void set( C&, std::string const& ) const {}
Phil Nash786959d2013-06-07 19:07:50 +01004502 virtual bool takesArg() const { return true; }
4503 virtual IArgFunction<C>* clone() const { return new NullBinder( *this ); }
4504 };
4505
4506 template<typename C, typename M>
4507 struct BoundDataMember : IArgFunction<C>{
4508 BoundDataMember( M C::* _member ) : member( _member ) {}
4509 virtual void set( C& p, std::string const& stringValue ) const {
4510 convertInto( stringValue, p.*member );
4511 }
Phil Nash786959d2013-06-07 19:07:50 +01004512 virtual bool takesArg() const { return !IsBool<M>::value; }
4513 virtual IArgFunction<C>* clone() const { return new BoundDataMember( *this ); }
4514 M C::* member;
4515 };
4516 template<typename C, typename M>
4517 struct BoundUnaryMethod : IArgFunction<C>{
4518 BoundUnaryMethod( void (C::*_member)( M ) ) : member( _member ) {}
4519 virtual void set( C& p, std::string const& stringValue ) const {
4520 typename RemoveConstRef<M>::type value;
4521 convertInto( stringValue, value );
4522 (p.*member)( value );
4523 }
Phil Nash786959d2013-06-07 19:07:50 +01004524 virtual bool takesArg() const { return !IsBool<M>::value; }
4525 virtual IArgFunction<C>* clone() const { return new BoundUnaryMethod( *this ); }
4526 void (C::*member)( M );
4527 };
4528 template<typename C>
4529 struct BoundNullaryMethod : IArgFunction<C>{
4530 BoundNullaryMethod( void (C::*_member)() ) : member( _member ) {}
4531 virtual void set( C& p, std::string const& stringValue ) const {
4532 bool value;
4533 convertInto( stringValue, value );
4534 if( value )
4535 (p.*member)();
4536 }
Phil Nash786959d2013-06-07 19:07:50 +01004537 virtual bool takesArg() const { return false; }
4538 virtual IArgFunction<C>* clone() const { return new BoundNullaryMethod( *this ); }
4539 void (C::*member)();
4540 };
4541
4542 template<typename C>
4543 struct BoundUnaryFunction : IArgFunction<C>{
4544 BoundUnaryFunction( void (*_function)( C& ) ) : function( _function ) {}
4545 virtual void set( C& obj, std::string const& stringValue ) const {
4546 bool value;
4547 convertInto( stringValue, value );
4548 if( value )
4549 function( obj );
4550 }
Phil Nash786959d2013-06-07 19:07:50 +01004551 virtual bool takesArg() const { return false; }
4552 virtual IArgFunction<C>* clone() const { return new BoundUnaryFunction( *this ); }
4553 void (*function)( C& );
4554 };
4555
4556 template<typename C, typename T>
4557 struct BoundBinaryFunction : IArgFunction<C>{
4558 BoundBinaryFunction( void (*_function)( C&, T ) ) : function( _function ) {}
4559 virtual void set( C& obj, std::string const& stringValue ) const {
4560 typename RemoveConstRef<T>::type value;
4561 convertInto( stringValue, value );
4562 function( obj, value );
4563 }
Phil Nash786959d2013-06-07 19:07:50 +01004564 virtual bool takesArg() const { return !IsBool<T>::value; }
4565 virtual IArgFunction<C>* clone() const { return new BoundBinaryFunction( *this ); }
4566 void (*function)( C&, T );
4567 };
4568
Phil Nash786959d2013-06-07 19:07:50 +01004569 } // namespace Detail
4570
Phil Nashe5537842016-04-25 18:56:50 +01004571 inline std::vector<std::string> argsToVector( int argc, char const* const* const argv ) {
4572 std::vector<std::string> args( static_cast<std::size_t>( argc ) );
4573 for( std::size_t i = 0; i < static_cast<std::size_t>( argc ); ++i )
4574 args[i] = argv[i];
4575
4576 return args;
4577 }
4578
4579 class Parser {
4580 enum Mode { None, MaybeShortOpt, SlashOpt, ShortOpt, LongOpt, Positional };
4581 Mode mode;
4582 std::size_t from;
4583 bool inQuotes;
4584 public:
Phil Nash786959d2013-06-07 19:07:50 +01004585
4586 struct Token {
4587 enum Type { Positional, ShortOpt, LongOpt };
4588 Token( Type _type, std::string const& _data ) : type( _type ), data( _data ) {}
4589 Type type;
4590 std::string data;
4591 };
4592
Phil Nashe5537842016-04-25 18:56:50 +01004593 Parser() : mode( None ), from( 0 ), inQuotes( false ){}
4594
4595 void parseIntoTokens( std::vector<std::string> const& args, std::vector<Token>& tokens ) {
Phil Nashe45e3a12013-12-23 10:24:06 +00004596 const std::string doubleDash = "--";
Phil Nashe5537842016-04-25 18:56:50 +01004597 for( std::size_t i = 1; i < args.size() && args[i] != doubleDash; ++i )
4598 parseIntoTokens( args[i], tokens);
Phil Nash786959d2013-06-07 19:07:50 +01004599 }
Phil Nashe5537842016-04-25 18:56:50 +01004600
4601 void parseIntoTokens( std::string const& arg, std::vector<Token>& tokens ) {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004602 for( std::size_t i = 0; i < arg.size(); ++i ) {
Phil Nashe5537842016-04-25 18:56:50 +01004603 char c = arg[i];
4604 if( c == '"' )
4605 inQuotes = !inQuotes;
4606 mode = handleMode( i, c, arg, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004607 }
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004608 mode = handleMode( arg.size(), '\0', arg, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004609 }
Phil Nashe5537842016-04-25 18:56:50 +01004610 Mode handleMode( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
4611 switch( mode ) {
4612 case None: return handleNone( i, c );
4613 case MaybeShortOpt: return handleMaybeShortOpt( i, c );
4614 case ShortOpt:
4615 case LongOpt:
4616 case SlashOpt: return handleOpt( i, c, arg, tokens );
4617 case Positional: return handlePositional( i, c, arg, tokens );
4618 default: throw std::logic_error( "Unknown mode" );
4619 }
4620 }
4621
4622 Mode handleNone( std::size_t i, char c ) {
4623 if( inQuotes ) {
4624 from = i;
4625 return Positional;
4626 }
4627 switch( c ) {
4628 case '-': return MaybeShortOpt;
4629#ifdef CLARA_PLATFORM_WINDOWS
4630 case '/': from = i+1; return SlashOpt;
4631#endif
4632 default: from = i; return Positional;
4633 }
4634 }
4635 Mode handleMaybeShortOpt( std::size_t i, char c ) {
4636 switch( c ) {
4637 case '-': from = i+1; return LongOpt;
4638 default: from = i; return ShortOpt;
4639 }
4640 }
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004641
Phil Nashe5537842016-04-25 18:56:50 +01004642 Mode handleOpt( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004643 if( std::string( ":=\0", 3 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004644 return mode;
4645
4646 std::string optName = arg.substr( from, i-from );
4647 if( mode == ShortOpt )
4648 for( std::size_t j = 0; j < optName.size(); ++j )
4649 tokens.push_back( Token( Token::ShortOpt, optName.substr( j, 1 ) ) );
4650 else if( mode == SlashOpt && optName.size() == 1 )
4651 tokens.push_back( Token( Token::ShortOpt, optName ) );
4652 else
4653 tokens.push_back( Token( Token::LongOpt, optName ) );
4654 return None;
4655 }
4656 Mode handlePositional( std::size_t i, char c, std::string const& arg, std::vector<Token>& tokens ) {
Phil Nash35f51052016-06-09 19:21:09 +01004657 if( inQuotes || std::string( "\0", 1 ).find( c ) == std::string::npos )
Phil Nashe5537842016-04-25 18:56:50 +01004658 return mode;
4659
4660 std::string data = arg.substr( from, i-from );
4661 tokens.push_back( Token( Token::Positional, data ) );
4662 return None;
4663 }
Phil Nasha695eb92012-08-13 07:46:10 +01004664 };
4665
Phil Nash786959d2013-06-07 19:07:50 +01004666 template<typename ConfigT>
Phil Nash472dc2a2014-03-17 18:40:58 +00004667 struct CommonArgProperties {
4668 CommonArgProperties() {}
4669 CommonArgProperties( Detail::BoundArgFunction<ConfigT> const& _boundField ) : boundField( _boundField ) {}
4670
4671 Detail::BoundArgFunction<ConfigT> boundField;
4672 std::string description;
Phil Nashaf8cd982014-03-24 18:15:04 +00004673 std::string detail;
Phil Nash472dc2a2014-03-17 18:40:58 +00004674 std::string placeholder; // Only value if boundField takes an arg
4675
4676 bool takesArg() const {
4677 return !placeholder.empty();
4678 }
Phil Nashaf8cd982014-03-24 18:15:04 +00004679 void validate() const {
4680 if( !boundField.isSet() )
4681 throw std::logic_error( "option not bound" );
4682 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004683 };
4684 struct OptionArgProperties {
4685 std::vector<std::string> shortNames;
4686 std::string longName;
4687
4688 bool hasShortName( std::string const& shortName ) const {
4689 return std::find( shortNames.begin(), shortNames.end(), shortName ) != shortNames.end();
4690 }
4691 bool hasLongName( std::string const& _longName ) const {
4692 return _longName == longName;
4693 }
Phil Nash472dc2a2014-03-17 18:40:58 +00004694 };
4695 struct PositionalArgProperties {
4696 PositionalArgProperties() : position( -1 ) {}
4697 int position; // -1 means non-positional (floating)
4698
4699 bool isFixedPositional() const {
4700 return position != -1;
4701 }
4702 };
4703
4704 template<typename ConfigT>
Phil Nash786959d2013-06-07 19:07:50 +01004705 class CommandLine {
4706
Phil Nash472dc2a2014-03-17 18:40:58 +00004707 struct Arg : CommonArgProperties<ConfigT>, OptionArgProperties, PositionalArgProperties {
4708 Arg() {}
4709 Arg( Detail::BoundArgFunction<ConfigT> const& _boundField ) : CommonArgProperties<ConfigT>( _boundField ) {}
Phil Nash786959d2013-06-07 19:07:50 +01004710
Phil Nash472dc2a2014-03-17 18:40:58 +00004711 using CommonArgProperties<ConfigT>::placeholder; // !TBD
4712
Phil Nash786959d2013-06-07 19:07:50 +01004713 std::string dbgName() const {
4714 if( !longName.empty() )
4715 return "--" + longName;
4716 if( !shortNames.empty() )
4717 return "-" + shortNames[0];
4718 return "positional args";
4719 }
Phil Nash786959d2013-06-07 19:07:50 +01004720 std::string commands() const {
4721 std::ostringstream oss;
4722 bool first = true;
4723 std::vector<std::string>::const_iterator it = shortNames.begin(), itEnd = shortNames.end();
4724 for(; it != itEnd; ++it ) {
4725 if( first )
4726 first = false;
4727 else
4728 oss << ", ";
4729 oss << "-" << *it;
4730 }
4731 if( !longName.empty() ) {
4732 if( !first )
4733 oss << ", ";
4734 oss << "--" << longName;
4735 }
Phil Nashb9fea752014-03-06 08:16:06 +00004736 if( !placeholder.empty() )
4737 oss << " <" << placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004738 return oss.str();
4739 }
Phil Nash786959d2013-06-07 19:07:50 +01004740 };
4741
Phil Nash3b4edd72016-02-10 19:24:48 +00004742 typedef CLARA_AUTO_PTR( Arg ) ArgAutoPtr;
Phil Nash5ecb72b2013-11-26 20:57:45 +00004743
Phil Nash472dc2a2014-03-17 18:40:58 +00004744 friend void addOptName( Arg& arg, std::string const& optName )
4745 {
4746 if( optName.empty() )
4747 return;
4748 if( Detail::startsWith( optName, "--" ) ) {
4749 if( !arg.longName.empty() )
4750 throw std::logic_error( "Only one long opt may be specified. '"
4751 + arg.longName
4752 + "' already specified, now attempting to add '"
4753 + optName + "'" );
4754 arg.longName = optName.substr( 2 );
4755 }
4756 else if( Detail::startsWith( optName, "-" ) )
4757 arg.shortNames.push_back( optName.substr( 1 ) );
4758 else
4759 throw std::logic_error( "option must begin with - or --. Option was: '" + optName + "'" );
4760 }
4761 friend void setPositionalArg( Arg& arg, int position )
4762 {
4763 arg.position = position;
4764 }
4765
Phil Nashb9fea752014-03-06 08:16:06 +00004766 class ArgBuilder {
Phil Nash786959d2013-06-07 19:07:50 +01004767 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004768 ArgBuilder( Arg* arg ) : m_arg( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004769
Phil Nash472dc2a2014-03-17 18:40:58 +00004770 // Bind a non-boolean data member (requires placeholder string)
4771 template<typename C, typename M>
4772 void bind( M C::* field, std::string const& placeholder ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004773 m_arg->boundField = new Detail::BoundDataMember<C,M>( field );
4774 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004775 }
4776 // Bind a boolean data member (no placeholder required)
4777 template<typename C>
4778 void bind( bool C::* field ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004779 m_arg->boundField = new Detail::BoundDataMember<C,bool>( field );
Phil Nash472dc2a2014-03-17 18:40:58 +00004780 }
4781
4782 // Bind a method taking a single, non-boolean argument (requires a placeholder string)
4783 template<typename C, typename M>
Phil Nashaf8cd982014-03-24 18:15:04 +00004784 void bind( void (C::* unaryMethod)( M ), std::string const& placeholder ) {
4785 m_arg->boundField = new Detail::BoundUnaryMethod<C,M>( unaryMethod );
4786 m_arg->placeholder = placeholder;
Phil Nash472dc2a2014-03-17 18:40:58 +00004787 }
4788
4789 // Bind a method taking a single, boolean argument (no placeholder string required)
4790 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004791 void bind( void (C::* unaryMethod)( bool ) ) {
4792 m_arg->boundField = new Detail::BoundUnaryMethod<C,bool>( unaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004793 }
4794
4795 // Bind a method that takes no arguments (will be called if opt is present)
4796 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004797 void bind( void (C::* nullaryMethod)() ) {
4798 m_arg->boundField = new Detail::BoundNullaryMethod<C>( nullaryMethod );
Phil Nash472dc2a2014-03-17 18:40:58 +00004799 }
4800
4801 // Bind a free function taking a single argument - the object to operate on (no placeholder string required)
4802 template<typename C>
Phil Nashaf8cd982014-03-24 18:15:04 +00004803 void bind( void (* unaryFunction)( C& ) ) {
4804 m_arg->boundField = new Detail::BoundUnaryFunction<C>( unaryFunction );
Phil Nash472dc2a2014-03-17 18:40:58 +00004805 }
4806
4807 // Bind a free function taking a single argument - the object to operate on (requires a placeholder string)
4808 template<typename C, typename T>
Phil Nashaf8cd982014-03-24 18:15:04 +00004809 void bind( void (* binaryFunction)( C&, T ), std::string const& placeholder ) {
4810 m_arg->boundField = new Detail::BoundBinaryFunction<C, T>( binaryFunction );
4811 m_arg->placeholder = placeholder;
Phil Nash786959d2013-06-07 19:07:50 +01004812 }
Phil Nashb9fea752014-03-06 08:16:06 +00004813
4814 ArgBuilder& describe( std::string const& description ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004815 m_arg->description = description;
Phil Nash786959d2013-06-07 19:07:50 +01004816 return *this;
4817 }
Phil Nash3b4edd72016-02-10 19:24:48 +00004818 ArgBuilder& detail( std::string const& detail ) {
4819 m_arg->detail = detail;
Phil Nash786959d2013-06-07 19:07:50 +01004820 return *this;
4821 }
Phil Nashb9fea752014-03-06 08:16:06 +00004822
Phil Nash472dc2a2014-03-17 18:40:58 +00004823 protected:
Phil Nashaf8cd982014-03-24 18:15:04 +00004824 Arg* m_arg;
Phil Nash786959d2013-06-07 19:07:50 +01004825 };
Phil Nash472dc2a2014-03-17 18:40:58 +00004826
Phil Nashb9fea752014-03-06 08:16:06 +00004827 class OptBuilder : public ArgBuilder {
4828 public:
Phil Nashaf8cd982014-03-24 18:15:04 +00004829 OptBuilder( Arg* arg ) : ArgBuilder( arg ) {}
Phil Nashb9fea752014-03-06 08:16:06 +00004830 OptBuilder( OptBuilder& other ) : ArgBuilder( other ) {}
4831
4832 OptBuilder& operator[]( std::string const& optName ) {
Phil Nashaf8cd982014-03-24 18:15:04 +00004833 addOptName( *ArgBuilder::m_arg, optName );
Phil Nashb9fea752014-03-06 08:16:06 +00004834 return *this;
4835 }
4836 };
Phil Nash786959d2013-06-07 19:07:50 +01004837
4838 public:
4839
4840 CommandLine()
4841 : m_boundProcessName( new Detail::NullBinder<ConfigT>() ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004842 m_highestSpecifiedArgPosition( 0 ),
4843 m_throwOnUnrecognisedTokens( false )
Phil Nash786959d2013-06-07 19:07:50 +01004844 {}
4845 CommandLine( CommandLine const& other )
4846 : m_boundProcessName( other.m_boundProcessName ),
4847 m_options ( other.m_options ),
4848 m_positionalArgs( other.m_positionalArgs ),
Phil Nash91ef5f72013-12-20 19:06:26 +00004849 m_highestSpecifiedArgPosition( other.m_highestSpecifiedArgPosition ),
4850 m_throwOnUnrecognisedTokens( other.m_throwOnUnrecognisedTokens )
Phil Nash786959d2013-06-07 19:07:50 +01004851 {
Phil Nash472dc2a2014-03-17 18:40:58 +00004852 if( other.m_floatingArg.get() )
Phil Nash85b4e942014-10-02 18:51:05 +01004853 m_floatingArg.reset( new Arg( *other.m_floatingArg ) );
Phil Nash786959d2013-06-07 19:07:50 +01004854 }
4855
Phil Nash91ef5f72013-12-20 19:06:26 +00004856 CommandLine& setThrowOnUnrecognisedTokens( bool shouldThrow = true ) {
4857 m_throwOnUnrecognisedTokens = shouldThrow;
4858 return *this;
4859 }
4860
Phil Nashb9fea752014-03-06 08:16:06 +00004861 OptBuilder operator[]( std::string const& optName ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004862 m_options.push_back( Arg() );
4863 addOptName( m_options.back(), optName );
Phil Nashaf8cd982014-03-24 18:15:04 +00004864 OptBuilder builder( &m_options.back() );
Phil Nashb9fea752014-03-06 08:16:06 +00004865 return builder;
Phil Nash786959d2013-06-07 19:07:50 +01004866 }
Phil Nashb9fea752014-03-06 08:16:06 +00004867
4868 ArgBuilder operator[]( int position ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004869 m_positionalArgs.insert( std::make_pair( position, Arg() ) );
4870 if( position > m_highestSpecifiedArgPosition )
4871 m_highestSpecifiedArgPosition = position;
4872 setPositionalArg( m_positionalArgs[position], position );
Phil Nashaf8cd982014-03-24 18:15:04 +00004873 ArgBuilder builder( &m_positionalArgs[position] );
Phil Nashb9fea752014-03-06 08:16:06 +00004874 return builder;
4875 }
4876
4877 // Invoke this with the _ instance
4878 ArgBuilder operator[]( UnpositionalTag ) {
Phil Nash472dc2a2014-03-17 18:40:58 +00004879 if( m_floatingArg.get() )
4880 throw std::logic_error( "Only one unpositional argument can be added" );
Phil Nash85b4e942014-10-02 18:51:05 +01004881 m_floatingArg.reset( new Arg() );
Phil Nashaf8cd982014-03-24 18:15:04 +00004882 ArgBuilder builder( m_floatingArg.get() );
Phil Nashb9fea752014-03-06 08:16:06 +00004883 return builder;
4884 }
4885
Phil Nash472dc2a2014-03-17 18:40:58 +00004886 template<typename C, typename M>
4887 void bindProcessName( M C::* field ) {
4888 m_boundProcessName = new Detail::BoundDataMember<C,M>( field );
4889 }
4890 template<typename C, typename M>
4891 void bindProcessName( void (C::*_unaryMethod)( M ) ) {
4892 m_boundProcessName = new Detail::BoundUnaryMethod<C,M>( _unaryMethod );
Phil Nash786959d2013-06-07 19:07:50 +01004893 }
4894
Phil Nash1c2fbe12014-02-11 18:12:41 +00004895 void optUsage( std::ostream& os, std::size_t indent = 0, std::size_t width = Detail::consoleWidth ) const {
Phil Nash786959d2013-06-07 19:07:50 +01004896 typename std::vector<Arg>::const_iterator itBegin = m_options.begin(), itEnd = m_options.end(), it;
4897 std::size_t maxWidth = 0;
4898 for( it = itBegin; it != itEnd; ++it )
4899 maxWidth = (std::max)( maxWidth, it->commands().size() );
4900
4901 for( it = itBegin; it != itEnd; ++it ) {
Phil Nash3b4edd72016-02-10 19:24:48 +00004902 Detail::Text usage( it->commands(), Detail::TextAttributes()
Phil Nash786959d2013-06-07 19:07:50 +01004903 .setWidth( maxWidth+indent )
4904 .setIndent( indent ) );
Phil Nash1c2fbe12014-02-11 18:12:41 +00004905 Detail::Text desc( it->description, Detail::TextAttributes()
Phil Nashaf8cd982014-03-24 18:15:04 +00004906 .setWidth( width - maxWidth - 3 ) );
Phil Nash786959d2013-06-07 19:07:50 +01004907
Phil Nash3b4edd72016-02-10 19:24:48 +00004908 for( std::size_t i = 0; i < (std::max)( usage.size(), desc.size() ); ++i ) {
4909 std::string usageCol = i < usage.size() ? usage[i] : "";
Phil Nash786959d2013-06-07 19:07:50 +01004910 os << usageCol;
4911
4912 if( i < desc.size() && !desc[i].empty() )
4913 os << std::string( indent + 2 + maxWidth - usageCol.size(), ' ' )
4914 << desc[i];
4915 os << "\n";
4916 }
4917 }
4918 }
4919 std::string optUsage() const {
4920 std::ostringstream oss;
4921 optUsage( oss );
4922 return oss.str();
4923 }
4924
4925 void argSynopsis( std::ostream& os ) const {
4926 for( int i = 1; i <= m_highestSpecifiedArgPosition; ++i ) {
4927 if( i > 1 )
4928 os << " ";
4929 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( i );
4930 if( it != m_positionalArgs.end() )
Phil Nashb9fea752014-03-06 08:16:06 +00004931 os << "<" << it->second.placeholder << ">";
Phil Nash472dc2a2014-03-17 18:40:58 +00004932 else if( m_floatingArg.get() )
4933 os << "<" << m_floatingArg->placeholder << ">";
Phil Nash786959d2013-06-07 19:07:50 +01004934 else
4935 throw std::logic_error( "non consecutive positional arguments with no floating args" );
4936 }
4937 // !TBD No indication of mandatory args
Phil Nash472dc2a2014-03-17 18:40:58 +00004938 if( m_floatingArg.get() ) {
Phil Nash786959d2013-06-07 19:07:50 +01004939 if( m_highestSpecifiedArgPosition > 1 )
4940 os << " ";
Phil Nash472dc2a2014-03-17 18:40:58 +00004941 os << "[<" << m_floatingArg->placeholder << "> ...]";
Phil Nash786959d2013-06-07 19:07:50 +01004942 }
4943 }
4944 std::string argSynopsis() const {
4945 std::ostringstream oss;
4946 argSynopsis( oss );
4947 return oss.str();
4948 }
4949
4950 void usage( std::ostream& os, std::string const& procName ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004951 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004952 os << "usage:\n " << procName << " ";
4953 argSynopsis( os );
4954 if( !m_options.empty() ) {
4955 os << " [options]\n\nwhere options are: \n";
4956 optUsage( os, 2 );
4957 }
4958 os << "\n";
4959 }
4960 std::string usage( std::string const& procName ) const {
4961 std::ostringstream oss;
4962 usage( oss, procName );
4963 return oss.str();
4964 }
4965
Phil Nashe5537842016-04-25 18:56:50 +01004966 ConfigT parse( std::vector<std::string> const& args ) const {
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004967 ConfigT config;
Phil Nashe5537842016-04-25 18:56:50 +01004968 parseInto( args, config );
Phil Nash1f1ee3c2014-03-01 10:38:14 +00004969 return config;
4970 }
4971
Phil Nashe5537842016-04-25 18:56:50 +01004972 std::vector<Parser::Token> parseInto( std::vector<std::string> const& args, ConfigT& config ) const {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01004973 std::string processName = args.empty() ? std::string() : args[0];
Phil Nash786959d2013-06-07 19:07:50 +01004974 std::size_t lastSlash = processName.find_last_of( "/\\" );
4975 if( lastSlash != std::string::npos )
4976 processName = processName.substr( lastSlash+1 );
4977 m_boundProcessName.set( config, processName );
4978 std::vector<Parser::Token> tokens;
4979 Parser parser;
Phil Nashe5537842016-04-25 18:56:50 +01004980 parser.parseIntoTokens( args, tokens );
Phil Nash786959d2013-06-07 19:07:50 +01004981 return populate( tokens, config );
4982 }
4983
4984 std::vector<Parser::Token> populate( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nashaf8cd982014-03-24 18:15:04 +00004985 validate();
Phil Nash786959d2013-06-07 19:07:50 +01004986 std::vector<Parser::Token> unusedTokens = populateOptions( tokens, config );
4987 unusedTokens = populateFixedArgs( unusedTokens, config );
4988 unusedTokens = populateFloatingArgs( unusedTokens, config );
4989 return unusedTokens;
4990 }
4991
4992 std::vector<Parser::Token> populateOptions( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
4993 std::vector<Parser::Token> unusedTokens;
Phil Nash91ef5f72013-12-20 19:06:26 +00004994 std::vector<std::string> errors;
Phil Nash786959d2013-06-07 19:07:50 +01004995 for( std::size_t i = 0; i < tokens.size(); ++i ) {
4996 Parser::Token const& token = tokens[i];
4997 typename std::vector<Arg>::const_iterator it = m_options.begin(), itEnd = m_options.end();
4998 for(; it != itEnd; ++it ) {
4999 Arg const& arg = *it;
5000
5001 try {
5002 if( ( token.type == Parser::Token::ShortOpt && arg.hasShortName( token.data ) ) ||
5003 ( token.type == Parser::Token::LongOpt && arg.hasLongName( token.data ) ) ) {
5004 if( arg.takesArg() ) {
5005 if( i == tokens.size()-1 || tokens[i+1].type != Parser::Token::Positional )
Phil Nash91ef5f72013-12-20 19:06:26 +00005006 errors.push_back( "Expected argument to option: " + token.data );
5007 else
5008 arg.boundField.set( config, tokens[++i].data );
Phil Nash786959d2013-06-07 19:07:50 +01005009 }
5010 else {
Phil Nashe5537842016-04-25 18:56:50 +01005011 arg.boundField.set( config, "true" );
Phil Nash786959d2013-06-07 19:07:50 +01005012 }
5013 break;
5014 }
5015 }
5016 catch( std::exception& ex ) {
Phil Nash91ef5f72013-12-20 19:06:26 +00005017 errors.push_back( std::string( ex.what() ) + "\n- while parsing: (" + arg.commands() + ")" );
Phil Nash786959d2013-06-07 19:07:50 +01005018 }
5019 }
Phil Nash91ef5f72013-12-20 19:06:26 +00005020 if( it == itEnd ) {
5021 if( token.type == Parser::Token::Positional || !m_throwOnUnrecognisedTokens )
5022 unusedTokens.push_back( token );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005023 else if( errors.empty() && m_throwOnUnrecognisedTokens )
Phil Nash91ef5f72013-12-20 19:06:26 +00005024 errors.push_back( "unrecognised option: " + token.data );
5025 }
5026 }
5027 if( !errors.empty() ) {
5028 std::ostringstream oss;
5029 for( std::vector<std::string>::const_iterator it = errors.begin(), itEnd = errors.end();
5030 it != itEnd;
5031 ++it ) {
5032 if( it != errors.begin() )
5033 oss << "\n";
5034 oss << *it;
5035 }
5036 throw std::runtime_error( oss.str() );
Phil Nash786959d2013-06-07 19:07:50 +01005037 }
5038 return unusedTokens;
5039 }
5040 std::vector<Parser::Token> populateFixedArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
5041 std::vector<Parser::Token> unusedTokens;
5042 int position = 1;
5043 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5044 Parser::Token const& token = tokens[i];
5045 typename std::map<int, Arg>::const_iterator it = m_positionalArgs.find( position );
5046 if( it != m_positionalArgs.end() )
5047 it->second.boundField.set( config, token.data );
5048 else
5049 unusedTokens.push_back( token );
5050 if( token.type == Parser::Token::Positional )
5051 position++;
5052 }
5053 return unusedTokens;
5054 }
5055 std::vector<Parser::Token> populateFloatingArgs( std::vector<Parser::Token> const& tokens, ConfigT& config ) const {
Phil Nash472dc2a2014-03-17 18:40:58 +00005056 if( !m_floatingArg.get() )
Phil Nash786959d2013-06-07 19:07:50 +01005057 return tokens;
5058 std::vector<Parser::Token> unusedTokens;
5059 for( std::size_t i = 0; i < tokens.size(); ++i ) {
5060 Parser::Token const& token = tokens[i];
5061 if( token.type == Parser::Token::Positional )
Phil Nash472dc2a2014-03-17 18:40:58 +00005062 m_floatingArg->boundField.set( config, token.data );
Phil Nash786959d2013-06-07 19:07:50 +01005063 else
5064 unusedTokens.push_back( token );
5065 }
5066 return unusedTokens;
5067 }
5068
Phil Nashaf8cd982014-03-24 18:15:04 +00005069 void validate() const
5070 {
5071 if( m_options.empty() && m_positionalArgs.empty() && !m_floatingArg.get() )
5072 throw std::logic_error( "No options or arguments specified" );
5073
5074 for( typename std::vector<Arg>::const_iterator it = m_options.begin(),
5075 itEnd = m_options.end();
5076 it != itEnd; ++it )
5077 it->validate();
5078 }
5079
Phil Nash786959d2013-06-07 19:07:50 +01005080 private:
5081 Detail::BoundArgFunction<ConfigT> m_boundProcessName;
5082 std::vector<Arg> m_options;
5083 std::map<int, Arg> m_positionalArgs;
Phil Nash472dc2a2014-03-17 18:40:58 +00005084 ArgAutoPtr m_floatingArg;
Phil Nash786959d2013-06-07 19:07:50 +01005085 int m_highestSpecifiedArgPosition;
Phil Nash91ef5f72013-12-20 19:06:26 +00005086 bool m_throwOnUnrecognisedTokens;
Phil Nash786959d2013-06-07 19:07:50 +01005087 };
5088
5089} // end namespace Clara
5090
Phil Nashb9fea752014-03-06 08:16:06 +00005091STITCH_CLARA_CLOSE_NAMESPACE
5092#undef STITCH_CLARA_OPEN_NAMESPACE
5093#undef STITCH_CLARA_CLOSE_NAMESPACE
Phil Nash1c2fbe12014-02-11 18:12:41 +00005094
Phil Nash1f1ee3c2014-03-01 10:38:14 +00005095#endif // TWOBLUECUBES_CLARA_H_INCLUDED
Phil Nashb9fea752014-03-06 08:16:06 +00005096#undef STITCH_CLARA_OPEN_NAMESPACE
5097
5098// Restore Clara's value for console width, if present
5099#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5100#define CLARA_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5101#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH
5102#endif
Phil Nash1c2fbe12014-02-11 18:12:41 +00005103
Phil Nash5ecb72b2013-11-26 20:57:45 +00005104#include <fstream>
Phil Nashd08cee22017-02-13 16:15:42 +00005105#include <ctime>
Phil Nash5ecb72b2013-11-26 20:57:45 +00005106
Phil Nash786959d2013-06-07 19:07:50 +01005107namespace Catch {
5108
5109 inline void abortAfterFirst( ConfigData& config ) { config.abortAfter = 1; }
5110 inline void abortAfterX( ConfigData& config, int x ) {
5111 if( x < 1 )
5112 throw std::runtime_error( "Value after -x or --abortAfter must be greater than zero" );
5113 config.abortAfter = x;
5114 }
5115 inline void addTestOrTags( ConfigData& config, std::string const& _testSpec ) { config.testsOrTags.push_back( _testSpec ); }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005116 inline void addSectionToRun( ConfigData& config, std::string const& sectionName ) { config.sectionsToRun.push_back( sectionName ); }
Phil Nashe73583d2015-08-07 17:30:34 +01005117 inline void addReporterName( ConfigData& config, std::string const& _reporterName ) { config.reporterNames.push_back( _reporterName ); }
Phil Nash786959d2013-06-07 19:07:50 +01005118
5119 inline void addWarning( ConfigData& config, std::string const& _warning ) {
5120 if( _warning == "NoAssertions" )
Phil Nashce562092014-07-09 07:40:37 +01005121 config.warnings = static_cast<WarnAbout::What>( config.warnings | WarnAbout::NoAssertions );
Phil Nash786959d2013-06-07 19:07:50 +01005122 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005123 throw std::runtime_error( "Unrecognised warning: '" + _warning + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005124 }
5125 inline void setOrder( ConfigData& config, std::string const& order ) {
5126 if( startsWith( "declared", order ) )
5127 config.runOrder = RunTests::InDeclarationOrder;
5128 else if( startsWith( "lexical", order ) )
5129 config.runOrder = RunTests::InLexicographicalOrder;
5130 else if( startsWith( "random", order ) )
5131 config.runOrder = RunTests::InRandomOrder;
5132 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005133 throw std::runtime_error( "Unrecognised ordering: '" + order + '\'' );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005134 }
5135 inline void setRngSeed( ConfigData& config, std::string const& seed ) {
5136 if( seed == "time" ) {
5137 config.rngSeed = static_cast<unsigned int>( std::time(0) );
5138 }
5139 else {
5140 std::stringstream ss;
5141 ss << seed;
5142 ss >> config.rngSeed;
5143 if( ss.fail() )
Phil Nashd08cee22017-02-13 16:15:42 +00005144 throw std::runtime_error( "Argument to --rng-seed should be the word 'time' or a number" );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005145 }
Phil Nash786959d2013-06-07 19:07:50 +01005146 }
5147 inline void setVerbosity( ConfigData& config, int level ) {
5148 // !TBD: accept strings?
Phil Nashce562092014-07-09 07:40:37 +01005149 config.verbosity = static_cast<Verbosity::Level>( level );
Phil Nashaa7123b2013-08-15 19:01:00 +01005150 }
5151 inline void setShowDurations( ConfigData& config, bool _showDurations ) {
5152 config.showDurations = _showDurations
5153 ? ShowDurations::Always
5154 : ShowDurations::Never;
Phil Nash786959d2013-06-07 19:07:50 +01005155 }
Phil Nashae5ee2c2016-02-29 08:17:18 +00005156 inline void setUseColour( ConfigData& config, std::string const& value ) {
5157 std::string mode = toLower( value );
5158
5159 if( mode == "yes" )
5160 config.useColour = UseColour::Yes;
5161 else if( mode == "no" )
5162 config.useColour = UseColour::No;
5163 else if( mode == "auto" )
5164 config.useColour = UseColour::Auto;
5165 else
5166 throw std::runtime_error( "colour mode must be one of: auto, yes or no" );
5167 }
5168 inline void forceColour( ConfigData& config ) {
5169 config.useColour = UseColour::Yes;
5170 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005171 inline void loadTestNamesFromFile( ConfigData& config, std::string const& _filename ) {
5172 std::ifstream f( _filename.c_str() );
5173 if( !f.is_open() )
5174 throw std::domain_error( "Unable to load input file: " + _filename );
5175
5176 std::string line;
5177 while( std::getline( f, line ) ) {
5178 line = trim(line);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005179 if( !line.empty() && !startsWith( line, '#' ) ) {
5180 if( !startsWith( line, '"' ) )
5181 line = '"' + line + '"';
5182 addTestOrTags( config, line + ',' );
Phil Nash40f60682016-09-27 10:46:22 +01005183 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005184 }
5185 }
Phil Nash786959d2013-06-07 19:07:50 +01005186
5187 inline Clara::CommandLine<ConfigData> makeCommandLineParser() {
5188
Phil Nashb9fea752014-03-06 08:16:06 +00005189 using namespace Clara;
5190 CommandLine<ConfigData> cli;
Phil Nash786959d2013-06-07 19:07:50 +01005191
5192 cli.bindProcessName( &ConfigData::processName );
5193
Phil Nashb9fea752014-03-06 08:16:06 +00005194 cli["-?"]["-h"]["--help"]
Phil Nash786959d2013-06-07 19:07:50 +01005195 .describe( "display usage information" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005196 .bind( &ConfigData::showHelp );
Phil Nash786959d2013-06-07 19:07:50 +01005197
Phil Nashb9fea752014-03-06 08:16:06 +00005198 cli["-l"]["--list-tests"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005199 .describe( "list all/matching test cases" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005200 .bind( &ConfigData::listTests );
Phil Nash786959d2013-06-07 19:07:50 +01005201
Phil Nashb9fea752014-03-06 08:16:06 +00005202 cli["-t"]["--list-tags"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005203 .describe( "list all/matching tags" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005204 .bind( &ConfigData::listTags );
Phil Nash786959d2013-06-07 19:07:50 +01005205
Phil Nashb9fea752014-03-06 08:16:06 +00005206 cli["-s"]["--success"]
Phil Nash786959d2013-06-07 19:07:50 +01005207 .describe( "include successful tests in output" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005208 .bind( &ConfigData::showSuccessfulTests );
Phil Nash786959d2013-06-07 19:07:50 +01005209
Phil Nashb9fea752014-03-06 08:16:06 +00005210 cli["-b"]["--break"]
Phil Nash786959d2013-06-07 19:07:50 +01005211 .describe( "break into debugger on failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005212 .bind( &ConfigData::shouldDebugBreak );
Phil Nash786959d2013-06-07 19:07:50 +01005213
Phil Nashb9fea752014-03-06 08:16:06 +00005214 cli["-e"]["--nothrow"]
Phil Nash7d5f2712013-06-07 21:15:25 +01005215 .describe( "skip exception tests" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005216 .bind( &ConfigData::noThrow );
Phil Nash786959d2013-06-07 19:07:50 +01005217
Phil Nashaef6cd52014-04-23 07:10:10 +01005218 cli["-i"]["--invisibles"]
5219 .describe( "show invisibles (tabs, newlines)" )
5220 .bind( &ConfigData::showInvisibles );
5221
Phil Nashb9fea752014-03-06 08:16:06 +00005222 cli["-o"]["--out"]
Phil Nash786959d2013-06-07 19:07:50 +01005223 .describe( "output filename" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005224 .bind( &ConfigData::outputFilename, "filename" );
Phil Nash786959d2013-06-07 19:07:50 +01005225
Phil Nashb9fea752014-03-06 08:16:06 +00005226 cli["-r"]["--reporter"]
5227// .placeholder( "name[:filename]" )
Phil Nash5ecb72b2013-11-26 20:57:45 +00005228 .describe( "reporter to use (defaults to console)" )
Phil Nashe73583d2015-08-07 17:30:34 +01005229 .bind( &addReporterName, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005230
Phil Nashb9fea752014-03-06 08:16:06 +00005231 cli["-n"]["--name"]
Phil Nash786959d2013-06-07 19:07:50 +01005232 .describe( "suite name" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005233 .bind( &ConfigData::name, "name" );
Phil Nash786959d2013-06-07 19:07:50 +01005234
Phil Nashb9fea752014-03-06 08:16:06 +00005235 cli["-a"]["--abort"]
Phil Nash786959d2013-06-07 19:07:50 +01005236 .describe( "abort at first failure" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005237 .bind( &abortAfterFirst );
Phil Nash786959d2013-06-07 19:07:50 +01005238
Phil Nashb9fea752014-03-06 08:16:06 +00005239 cli["-x"]["--abortx"]
Phil Nash786959d2013-06-07 19:07:50 +01005240 .describe( "abort after x failures" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005241 .bind( &abortAfterX, "no. failures" );
Phil Nash786959d2013-06-07 19:07:50 +01005242
Phil Nashb9fea752014-03-06 08:16:06 +00005243 cli["-w"]["--warn"]
Phil Nash786959d2013-06-07 19:07:50 +01005244 .describe( "enable warnings" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005245 .bind( &addWarning, "warning name" );
Phil Nash786959d2013-06-07 19:07:50 +01005246
Phil Nashb9fea752014-03-06 08:16:06 +00005247// - needs updating if reinstated
5248// cli.into( &setVerbosity )
Phil Nash786959d2013-06-07 19:07:50 +01005249// .describe( "level of verbosity (0=no output)" )
5250// .shortOpt( "v")
5251// .longOpt( "verbosity" )
Phil Nashb9fea752014-03-06 08:16:06 +00005252// .placeholder( "level" );
Phil Nash786959d2013-06-07 19:07:50 +01005253
Phil Nashb9fea752014-03-06 08:16:06 +00005254 cli[_]
Phil Nash786959d2013-06-07 19:07:50 +01005255 .describe( "which test or tests to use" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005256 .bind( &addTestOrTags, "test name, pattern or tags" );
Phil Nash786959d2013-06-07 19:07:50 +01005257
Phil Nashb9fea752014-03-06 08:16:06 +00005258 cli["-d"]["--durations"]
Phil Nashaa7123b2013-08-15 19:01:00 +01005259 .describe( "show test durations" )
Phil Nashae5ee2c2016-02-29 08:17:18 +00005260 .bind( &setShowDurations, "yes|no" );
Phil Nashaa7123b2013-08-15 19:01:00 +01005261
Phil Nashb9fea752014-03-06 08:16:06 +00005262 cli["-f"]["--input-file"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005263 .describe( "load test names to run from a file" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005264 .bind( &loadTestNamesFromFile, "filename" );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005265
Phil Nashe6b365d2015-07-07 08:25:15 +01005266 cli["-#"]["--filenames-as-tags"]
5267 .describe( "adds a tag for the filename" )
5268 .bind( &ConfigData::filenamesAsTags );
5269
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005270 cli["-c"]["--section"]
5271 .describe( "specify section to run" )
5272 .bind( &addSectionToRun, "section name" );
5273
Phil Nash5ecb72b2013-11-26 20:57:45 +00005274 // Less common commands which don't have a short form
Phil Nashb9fea752014-03-06 08:16:06 +00005275 cli["--list-test-names-only"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005276 .describe( "list all/matching test cases names only" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005277 .bind( &ConfigData::listTestNamesOnly );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005278
Phil Nashb9fea752014-03-06 08:16:06 +00005279 cli["--list-reporters"]
Phil Nash5ecb72b2013-11-26 20:57:45 +00005280 .describe( "list all reporters" )
Phil Nash472dc2a2014-03-17 18:40:58 +00005281 .bind( &ConfigData::listReporters );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005282
Phil Nash6a8e8ad2014-09-15 18:40:24 +01005283 cli["--order"]
5284 .describe( "test case order (defaults to decl)" )
5285 .bind( &setOrder, "decl|lex|rand" );
5286
5287 cli["--rng-seed"]
5288 .describe( "set a specific seed for random numbers" )
5289 .bind( &setRngSeed, "'time'|number" );
5290
Phil Nasha806c3e2015-03-04 08:23:40 +00005291 cli["--force-colour"]
Phil Nashae5ee2c2016-02-29 08:17:18 +00005292 .describe( "force colourised output (deprecated)" )
5293 .bind( &forceColour );
5294
5295 cli["--use-colour"]
5296 .describe( "should output be colourised" )
5297 .bind( &setUseColour, "yes|no" );
Phil Nasha806c3e2015-03-04 08:23:40 +00005298
Phil Nash786959d2013-06-07 19:07:50 +01005299 return cli;
5300 }
5301
Phil Nasha695eb92012-08-13 07:46:10 +01005302} // end namespace Catch
5303
5304// #included from: internal/catch_list.hpp
5305#define TWOBLUECUBES_CATCH_LIST_HPP_INCLUDED
5306
Phil Nash1c2fbe12014-02-11 18:12:41 +00005307// #included from: catch_text.h
5308#define TWOBLUECUBES_CATCH_TEXT_H_INCLUDED
5309
5310#define TBC_TEXT_FORMAT_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH
5311
5312#define CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE Catch
Phil Nash472dc2a2014-03-17 18:40:58 +00005313// #included from: ../external/tbc_text_format.h
Phil Nash1c2fbe12014-02-11 18:12:41 +00005314// Only use header guard if we are not using an outer namespace
5315#ifndef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5316# ifdef TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5317# ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5318# define TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5319# endif
5320# else
5321# define TWOBLUECUBES_TEXT_FORMAT_H_INCLUDED
5322# endif
5323#endif
5324#ifndef TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5325#include <string>
5326#include <vector>
5327#include <sstream>
5328
5329// Use optional outer namespace
5330#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5331namespace CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE {
5332#endif
5333
5334namespace Tbc {
5335
5336#ifdef TBC_TEXT_FORMAT_CONSOLE_WIDTH
5337 const unsigned int consoleWidth = TBC_TEXT_FORMAT_CONSOLE_WIDTH;
5338#else
5339 const unsigned int consoleWidth = 80;
5340#endif
5341
5342 struct TextAttributes {
5343 TextAttributes()
5344 : initialIndent( std::string::npos ),
5345 indent( 0 ),
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005346 width( consoleWidth-1 )
Phil Nash1c2fbe12014-02-11 18:12:41 +00005347 {}
5348
5349 TextAttributes& setInitialIndent( std::size_t _value ) { initialIndent = _value; return *this; }
5350 TextAttributes& setIndent( std::size_t _value ) { indent = _value; return *this; }
5351 TextAttributes& setWidth( std::size_t _value ) { width = _value; return *this; }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005352
5353 std::size_t initialIndent; // indent of first line, or npos
5354 std::size_t indent; // indent of subsequent lines, or all if initialIndent is npos
5355 std::size_t width; // maximum width of text, including indent. Longer text will wrap
Phil Nash1c2fbe12014-02-11 18:12:41 +00005356 };
5357
5358 class Text {
5359 public:
5360 Text( std::string const& _str, TextAttributes const& _attr = TextAttributes() )
5361 : attr( _attr )
5362 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005363 const std::string wrappableBeforeChars = "[({<\t";
5364 const std::string wrappableAfterChars = "])}>-,./|\\";
5365 const std::string wrappableInsteadOfChars = " \n\r";
5366 std::string indent = _attr.initialIndent != std::string::npos
5367 ? std::string( _attr.initialIndent, ' ' )
5368 : std::string( _attr.indent, ' ' );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005369
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005370 typedef std::string::const_iterator iterator;
5371 iterator it = _str.begin();
5372 const iterator strEnd = _str.end();
5373
5374 while( it != strEnd ) {
5375
Phil Nash1c2fbe12014-02-11 18:12:41 +00005376 if( lines.size() >= 1000 ) {
5377 lines.push_back( "... message truncated due to excessive size" );
5378 return;
5379 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005380
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005381 std::string suffix;
5382 std::size_t width = (std::min)( static_cast<size_t>( strEnd-it ), _attr.width-static_cast<size_t>( indent.size() ) );
5383 iterator itEnd = it+width;
5384 iterator itNext = _str.end();
5385
5386 iterator itNewLine = std::find( it, itEnd, '\n' );
5387 if( itNewLine != itEnd )
5388 itEnd = itNewLine;
5389
5390 if( itEnd != strEnd ) {
5391 bool foundWrapPoint = false;
5392 iterator findIt = itEnd;
5393 do {
5394 if( wrappableAfterChars.find( *findIt ) != std::string::npos && findIt != itEnd ) {
5395 itEnd = findIt+1;
5396 itNext = findIt+1;
5397 foundWrapPoint = true;
5398 }
5399 else if( findIt > it && wrappableBeforeChars.find( *findIt ) != std::string::npos ) {
5400 itEnd = findIt;
5401 itNext = findIt;
5402 foundWrapPoint = true;
5403 }
5404 else if( wrappableInsteadOfChars.find( *findIt ) != std::string::npos ) {
5405 itNext = findIt+1;
5406 itEnd = findIt;
5407 foundWrapPoint = true;
5408 }
5409 if( findIt == it )
5410 break;
5411 else
5412 --findIt;
5413 }
5414 while( !foundWrapPoint );
5415
5416 if( !foundWrapPoint ) {
5417 // No good wrap char, so we'll break mid word and add a hyphen
5418 --itEnd;
5419 itNext = itEnd;
5420 suffix = "-";
Phil Nash1c2fbe12014-02-11 18:12:41 +00005421 }
5422 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005423 while( itEnd > it && wrappableInsteadOfChars.find( *(itEnd-1) ) != std::string::npos )
5424 --itEnd;
Phil Nash1c2fbe12014-02-11 18:12:41 +00005425 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005426 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005427 lines.push_back( indent + std::string( it, itEnd ) + suffix );
Phil Nash1c2fbe12014-02-11 18:12:41 +00005428
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005429 if( indent.size() != _attr.indent )
5430 indent = std::string( _attr.indent, ' ' );
5431 it = itNext;
5432 }
Phil Nash1c2fbe12014-02-11 18:12:41 +00005433 }
5434
5435 typedef std::vector<std::string>::const_iterator const_iterator;
5436
5437 const_iterator begin() const { return lines.begin(); }
5438 const_iterator end() const { return lines.end(); }
5439 std::string const& last() const { return lines.back(); }
5440 std::size_t size() const { return lines.size(); }
5441 std::string const& operator[]( std::size_t _index ) const { return lines[_index]; }
5442 std::string toString() const {
5443 std::ostringstream oss;
5444 oss << *this;
5445 return oss.str();
5446 }
5447
5448 inline friend std::ostream& operator << ( std::ostream& _stream, Text const& _text ) {
5449 for( Text::const_iterator it = _text.begin(), itEnd = _text.end();
5450 it != itEnd; ++it ) {
5451 if( it != _text.begin() )
5452 _stream << "\n";
5453 _stream << *it;
5454 }
5455 return _stream;
5456 }
5457
5458 private:
5459 std::string str;
5460 TextAttributes attr;
5461 std::vector<std::string> lines;
5462 };
5463
5464} // end namespace Tbc
5465
5466#ifdef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5467} // end outer namespace
5468#endif
5469
5470#endif // TWOBLUECUBES_TEXT_FORMAT_H_ALREADY_INCLUDED
5471#undef CLICHE_TBC_TEXT_FORMAT_OUTER_NAMESPACE
5472
5473namespace Catch {
5474 using Tbc::Text;
5475 using Tbc::TextAttributes;
5476}
5477
Phil Nash5c7d3d72013-04-01 11:27:10 +01005478// #included from: catch_console_colour.hpp
5479#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005480
5481namespace Catch {
Phil Nash5c7d3d72013-04-01 11:27:10 +01005482
Phil Nash12c16ff2013-04-05 20:58:01 +01005483 struct Colour {
5484 enum Code {
5485 None = 0,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005486
Phil Nash12c16ff2013-04-05 20:58:01 +01005487 White,
5488 Red,
5489 Green,
5490 Blue,
5491 Cyan,
5492 Yellow,
5493 Grey,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005494
Phil Nash12c16ff2013-04-05 20:58:01 +01005495 Bright = 0x10,
Phil Nash5c7d3d72013-04-01 11:27:10 +01005496
Phil Nash12c16ff2013-04-05 20:58:01 +01005497 BrightRed = Bright | Red,
5498 BrightGreen = Bright | Green,
5499 LightGrey = Bright | Grey,
5500 BrightWhite = Bright | White,
5501
5502 // By intention
5503 FileName = LightGrey,
Phil Nash52e1e742014-07-03 08:11:38 +01005504 Warning = Yellow,
Phil Nash12c16ff2013-04-05 20:58:01 +01005505 ResultError = BrightRed,
5506 ResultSuccess = BrightGreen,
Phil Nash52e1e742014-07-03 08:11:38 +01005507 ResultExpectedFailure = Warning,
Phil Nash12c16ff2013-04-05 20:58:01 +01005508
5509 Error = BrightRed,
5510 Success = Green,
5511
5512 OriginalExpression = Cyan,
5513 ReconstructedExpression = Yellow,
5514
5515 SecondaryText = LightGrey,
5516 Headers = White
Phil Nash5c7d3d72013-04-01 11:27:10 +01005517 };
5518
Phil Nash12c16ff2013-04-05 20:58:01 +01005519 // Use constructed object for RAII guard
5520 Colour( Code _colourCode );
Phil Nashce562092014-07-09 07:40:37 +01005521 Colour( Colour const& other );
Phil Nash12c16ff2013-04-05 20:58:01 +01005522 ~Colour();
Phil Nash5c7d3d72013-04-01 11:27:10 +01005523
Phil Nash12c16ff2013-04-05 20:58:01 +01005524 // Use static method for one-shot changes
5525 static void use( Code _colourCode );
Phil Nash5c7d3d72013-04-01 11:27:10 +01005526
5527 private:
Phil Nashce562092014-07-09 07:40:37 +01005528 bool m_moved;
Phil Nash5c7d3d72013-04-01 11:27:10 +01005529 };
5530
Phil Nash52e1e742014-07-03 08:11:38 +01005531 inline std::ostream& operator << ( std::ostream& os, Colour const& ) { return os; }
5532
Phil Nash5c7d3d72013-04-01 11:27:10 +01005533} // end namespace Catch
5534
Phil Nash3649fdf2013-12-03 18:53:55 +00005535// #included from: catch_interfaces_reporter.h
5536#define TWOBLUECUBES_CATCH_INTERFACES_REPORTER_H_INCLUDED
5537
Phil Nash3649fdf2013-12-03 18:53:55 +00005538#include <string>
5539#include <ostream>
5540#include <map>
Phil Nash3649fdf2013-12-03 18:53:55 +00005541
5542namespace Catch
5543{
5544 struct ReporterConfig {
Phil Nash7e346192015-11-03 08:00:43 +00005545 explicit ReporterConfig( Ptr<IConfig const> const& _fullConfig )
Phil Nash3649fdf2013-12-03 18:53:55 +00005546 : m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}
5547
Phil Nash7e346192015-11-03 08:00:43 +00005548 ReporterConfig( Ptr<IConfig const> const& _fullConfig, std::ostream& _stream )
Phil Nash3649fdf2013-12-03 18:53:55 +00005549 : m_stream( &_stream ), m_fullConfig( _fullConfig ) {}
5550
5551 std::ostream& stream() const { return *m_stream; }
Phil Nash7e346192015-11-03 08:00:43 +00005552 Ptr<IConfig const> fullConfig() const { return m_fullConfig; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005553
5554 private:
5555 std::ostream* m_stream;
Phil Nash7e346192015-11-03 08:00:43 +00005556 Ptr<IConfig const> m_fullConfig;
Phil Nash3649fdf2013-12-03 18:53:55 +00005557 };
5558
5559 struct ReporterPreferences {
5560 ReporterPreferences()
5561 : shouldRedirectStdOut( false )
5562 {}
5563
5564 bool shouldRedirectStdOut;
5565 };
5566
5567 template<typename T>
5568 struct LazyStat : Option<T> {
5569 LazyStat() : used( false ) {}
5570 LazyStat& operator=( T const& _value ) {
5571 Option<T>::operator=( _value );
5572 used = false;
5573 return *this;
5574 }
5575 void reset() {
5576 Option<T>::reset();
5577 used = false;
5578 }
5579 bool used;
5580 };
5581
5582 struct TestRunInfo {
5583 TestRunInfo( std::string const& _name ) : name( _name ) {}
5584 std::string name;
5585 };
5586 struct GroupInfo {
5587 GroupInfo( std::string const& _name,
5588 std::size_t _groupIndex,
5589 std::size_t _groupsCount )
5590 : name( _name ),
5591 groupIndex( _groupIndex ),
5592 groupsCounts( _groupsCount )
5593 {}
5594
5595 std::string name;
5596 std::size_t groupIndex;
5597 std::size_t groupsCounts;
5598 };
5599
5600 struct AssertionStats {
5601 AssertionStats( AssertionResult const& _assertionResult,
5602 std::vector<MessageInfo> const& _infoMessages,
5603 Totals const& _totals )
5604 : assertionResult( _assertionResult ),
5605 infoMessages( _infoMessages ),
5606 totals( _totals )
5607 {
5608 if( assertionResult.hasMessage() ) {
5609 // Copy message into messages list.
5610 // !TBD This should have been done earlier, somewhere
5611 MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );
5612 builder << assertionResult.getMessage();
5613 builder.m_info.message = builder.m_stream.str();
5614
5615 infoMessages.push_back( builder.m_info );
5616 }
5617 }
5618 virtual ~AssertionStats();
5619
Phil Nash318c9362015-05-19 18:40:00 +01005620# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005621 AssertionStats( AssertionStats const& ) = default;
5622 AssertionStats( AssertionStats && ) = default;
5623 AssertionStats& operator = ( AssertionStats const& ) = default;
5624 AssertionStats& operator = ( AssertionStats && ) = default;
5625# endif
5626
Phil Nash3649fdf2013-12-03 18:53:55 +00005627 AssertionResult assertionResult;
5628 std::vector<MessageInfo> infoMessages;
5629 Totals totals;
5630 };
5631
5632 struct SectionStats {
5633 SectionStats( SectionInfo const& _sectionInfo,
5634 Counts const& _assertions,
5635 double _durationInSeconds,
5636 bool _missingAssertions )
5637 : sectionInfo( _sectionInfo ),
5638 assertions( _assertions ),
5639 durationInSeconds( _durationInSeconds ),
5640 missingAssertions( _missingAssertions )
5641 {}
5642 virtual ~SectionStats();
Phil Nash318c9362015-05-19 18:40:00 +01005643# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005644 SectionStats( SectionStats const& ) = default;
5645 SectionStats( SectionStats && ) = default;
5646 SectionStats& operator = ( SectionStats const& ) = default;
5647 SectionStats& operator = ( SectionStats && ) = default;
5648# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005649
5650 SectionInfo sectionInfo;
5651 Counts assertions;
5652 double durationInSeconds;
5653 bool missingAssertions;
5654 };
5655
5656 struct TestCaseStats {
5657 TestCaseStats( TestCaseInfo const& _testInfo,
5658 Totals const& _totals,
5659 std::string const& _stdOut,
5660 std::string const& _stdErr,
5661 bool _aborting )
5662 : testInfo( _testInfo ),
5663 totals( _totals ),
5664 stdOut( _stdOut ),
5665 stdErr( _stdErr ),
5666 aborting( _aborting )
5667 {}
5668 virtual ~TestCaseStats();
5669
Phil Nash318c9362015-05-19 18:40:00 +01005670# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005671 TestCaseStats( TestCaseStats const& ) = default;
5672 TestCaseStats( TestCaseStats && ) = default;
5673 TestCaseStats& operator = ( TestCaseStats const& ) = default;
5674 TestCaseStats& operator = ( TestCaseStats && ) = default;
5675# endif
5676
Phil Nash3649fdf2013-12-03 18:53:55 +00005677 TestCaseInfo testInfo;
5678 Totals totals;
5679 std::string stdOut;
5680 std::string stdErr;
5681 bool aborting;
5682 };
5683
5684 struct TestGroupStats {
5685 TestGroupStats( GroupInfo const& _groupInfo,
5686 Totals const& _totals,
5687 bool _aborting )
5688 : groupInfo( _groupInfo ),
5689 totals( _totals ),
5690 aborting( _aborting )
5691 {}
5692 TestGroupStats( GroupInfo const& _groupInfo )
5693 : groupInfo( _groupInfo ),
5694 aborting( false )
5695 {}
5696 virtual ~TestGroupStats();
5697
Phil Nash318c9362015-05-19 18:40:00 +01005698# ifdef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nashd7e17902014-04-18 08:49:35 +01005699 TestGroupStats( TestGroupStats const& ) = default;
5700 TestGroupStats( TestGroupStats && ) = default;
5701 TestGroupStats& operator = ( TestGroupStats const& ) = default;
5702 TestGroupStats& operator = ( TestGroupStats && ) = default;
5703# endif
5704
Phil Nash3649fdf2013-12-03 18:53:55 +00005705 GroupInfo groupInfo;
5706 Totals totals;
5707 bool aborting;
5708 };
5709
5710 struct TestRunStats {
5711 TestRunStats( TestRunInfo const& _runInfo,
5712 Totals const& _totals,
5713 bool _aborting )
5714 : runInfo( _runInfo ),
5715 totals( _totals ),
5716 aborting( _aborting )
5717 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005718 virtual ~TestRunStats();
5719
Phil Nash318c9362015-05-19 18:40:00 +01005720# ifndef CATCH_CONFIG_CPP11_GENERATED_METHODS
Phil Nash3649fdf2013-12-03 18:53:55 +00005721 TestRunStats( TestRunStats const& _other )
5722 : runInfo( _other.runInfo ),
5723 totals( _other.totals ),
5724 aborting( _other.aborting )
5725 {}
Phil Nashd7e17902014-04-18 08:49:35 +01005726# else
5727 TestRunStats( TestRunStats const& ) = default;
5728 TestRunStats( TestRunStats && ) = default;
5729 TestRunStats& operator = ( TestRunStats const& ) = default;
5730 TestRunStats& operator = ( TestRunStats && ) = default;
5731# endif
Phil Nash3649fdf2013-12-03 18:53:55 +00005732
5733 TestRunInfo runInfo;
5734 Totals totals;
5735 bool aborting;
5736 };
5737
Phil Nash92b141e2016-04-28 08:13:00 +01005738 class MultipleReporters;
5739
Phil Nash3649fdf2013-12-03 18:53:55 +00005740 struct IStreamingReporter : IShared {
5741 virtual ~IStreamingReporter();
5742
5743 // Implementing class must also provide the following static method:
5744 // static std::string getDescription();
5745
5746 virtual ReporterPreferences getPreferences() const = 0;
5747
5748 virtual void noMatchingTestCases( std::string const& spec ) = 0;
5749
5750 virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;
5751 virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;
5752
5753 virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;
5754 virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;
5755
5756 virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;
5757
Phil Nash576aff62014-12-21 00:21:23 +00005758 // The return value indicates if the messages buffer should be cleared:
Phil Nash3649fdf2013-12-03 18:53:55 +00005759 virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005760
Phil Nash3649fdf2013-12-03 18:53:55 +00005761 virtual void sectionEnded( SectionStats const& sectionStats ) = 0;
5762 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;
5763 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;
5764 virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;
Phil Nash92f08362014-12-22 20:18:05 +00005765
5766 virtual void skipTest( TestCaseInfo const& testInfo ) = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01005767
5768 virtual MultipleReporters* tryAsMulti() { return CATCH_NULL; }
Phil Nash3649fdf2013-12-03 18:53:55 +00005769 };
5770
Phil Nashe73583d2015-08-07 17:30:34 +01005771 struct IReporterFactory : IShared {
Phil Nash3649fdf2013-12-03 18:53:55 +00005772 virtual ~IReporterFactory();
5773 virtual IStreamingReporter* create( ReporterConfig const& config ) const = 0;
5774 virtual std::string getDescription() const = 0;
5775 };
5776
5777 struct IReporterRegistry {
Phil Nashe73583d2015-08-07 17:30:34 +01005778 typedef std::map<std::string, Ptr<IReporterFactory> > FactoryMap;
5779 typedef std::vector<Ptr<IReporterFactory> > Listeners;
Phil Nash3649fdf2013-12-03 18:53:55 +00005780
5781 virtual ~IReporterRegistry();
Phil Nash7e346192015-11-03 08:00:43 +00005782 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005783 virtual FactoryMap const& getFactories() const = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005784 virtual Listeners const& getListeners() const = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00005785 };
5786
Phil Nashe73583d2015-08-07 17:30:34 +01005787 Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter );
5788
Phil Nash3649fdf2013-12-03 18:53:55 +00005789}
5790
Phil Nasha695eb92012-08-13 07:46:10 +01005791#include <limits>
Phil Nash38f7eef2013-03-29 13:44:33 +00005792#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01005793
5794namespace Catch {
Phil Nasha695eb92012-08-13 07:46:10 +01005795
Phil Nash786959d2013-06-07 19:07:50 +01005796 inline std::size_t listTests( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005797
5798 TestSpec testSpec = config.testSpec();
5799 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005800 Catch::cout() << "Matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005801 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005802 Catch::cout() << "All available test cases:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005803 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005804 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005805
5806 std::size_t matchedTests = 0;
Phil Nash8d44f2d2013-11-13 08:10:45 +00005807 TextAttributes nameAttr, tagsAttr;
5808 nameAttr.setInitialIndent( 2 ).setIndent( 4 );
5809 tagsAttr.setIndent( 6 );
5810
Phil Nashe73583d2015-08-07 17:30:34 +01005811 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005812 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005813 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005814 ++it ) {
5815 matchedTests++;
5816 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Phil Nash52e1e742014-07-03 08:11:38 +01005817 Colour::Code colour = testCaseInfo.isHidden()
Phil Nash20cad7c2014-04-15 18:44:37 +01005818 ? Colour::SecondaryText
5819 : Colour::None;
5820 Colour colourGuard( colour );
Phil Nash38f7eef2013-03-29 13:44:33 +00005821
Phil Nash383d7c02014-10-02 19:08:19 +01005822 Catch::cout() << Text( testCaseInfo.name, nameAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005823 if( !testCaseInfo.tags.empty() )
Phil Nash383d7c02014-10-02 19:08:19 +01005824 Catch::cout() << Text( testCaseInfo.tagsAsString, tagsAttr ) << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005825 }
Phil Nash8d44f2d2013-11-13 08:10:45 +00005826
Phil Nash65cc14c2014-05-16 18:54:48 +01005827 if( !config.testSpec().hasFilters() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005828 Catch::cout() << pluralise( matchedTests, "test case" ) << '\n' << std::endl;
Phil Nash38f7eef2013-03-29 13:44:33 +00005829 else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005830 Catch::cout() << pluralise( matchedTests, "matching test case" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005831 return matchedTests;
Phil Nash38f7eef2013-03-29 13:44:33 +00005832 }
Phil Nasha695eb92012-08-13 07:46:10 +01005833
Phil Nash5ecb72b2013-11-26 20:57:45 +00005834 inline std::size_t listTestsNamesOnly( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005835 TestSpec testSpec = config.testSpec();
5836 if( !config.testSpec().hasFilters() )
Phil Nashacdd3b52014-06-30 07:35:36 +01005837 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005838 std::size_t matchedTests = 0;
Phil Nashe73583d2015-08-07 17:30:34 +01005839 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005840 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash5ecb72b2013-11-26 20:57:45 +00005841 it != itEnd;
Phil Nash20cad7c2014-04-15 18:44:37 +01005842 ++it ) {
5843 matchedTests++;
5844 TestCaseInfo const& testCaseInfo = it->getTestCaseInfo();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005845 if( startsWith( testCaseInfo.name, '#' ) )
5846 Catch::cout() << '"' << testCaseInfo.name << '"' << std::endl;
Phil Nash40f60682016-09-27 10:46:22 +01005847 else
5848 Catch::cout() << testCaseInfo.name << std::endl;
Phil Nash20cad7c2014-04-15 18:44:37 +01005849 }
Phil Nash5ecb72b2013-11-26 20:57:45 +00005850 return matchedTests;
5851 }
5852
Phil Nash48fac9c2014-05-20 19:02:37 +01005853 struct TagInfo {
5854 TagInfo() : count ( 0 ) {}
5855 void add( std::string const& spelling ) {
5856 ++count;
5857 spellings.insert( spelling );
5858 }
5859 std::string all() const {
5860 std::string out;
5861 for( std::set<std::string>::const_iterator it = spellings.begin(), itEnd = spellings.end();
5862 it != itEnd;
5863 ++it )
5864 out += "[" + *it + "]";
5865 return out;
5866 }
5867 std::set<std::string> spellings;
5868 std::size_t count;
5869 };
5870
Phil Nash786959d2013-06-07 19:07:50 +01005871 inline std::size_t listTags( Config const& config ) {
Phil Nash65cc14c2014-05-16 18:54:48 +01005872 TestSpec testSpec = config.testSpec();
5873 if( config.testSpec().hasFilters() )
Phil Nash383d7c02014-10-02 19:08:19 +01005874 Catch::cout() << "Tags for matching test cases:\n";
Phil Nash65cc14c2014-05-16 18:54:48 +01005875 else {
Phil Nash383d7c02014-10-02 19:08:19 +01005876 Catch::cout() << "All available tags:\n";
Phil Nashacdd3b52014-06-30 07:35:36 +01005877 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "*" ).testSpec();
Phil Nash65cc14c2014-05-16 18:54:48 +01005878 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005879
Phil Nash9241e432014-05-20 18:50:59 +01005880 std::map<std::string, TagInfo> tagCounts;
Phil Nash38f7eef2013-03-29 13:44:33 +00005881
Phil Nashe73583d2015-08-07 17:30:34 +01005882 std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );
Phil Nash20cad7c2014-04-15 18:44:37 +01005883 for( std::vector<TestCase>::const_iterator it = matchedTestCases.begin(), itEnd = matchedTestCases.end();
Phil Nash8d44f2d2013-11-13 08:10:45 +00005884 it != itEnd;
5885 ++it ) {
Phil Nash20cad7c2014-04-15 18:44:37 +01005886 for( std::set<std::string>::const_iterator tagIt = it->getTestCaseInfo().tags.begin(),
5887 tagItEnd = it->getTestCaseInfo().tags.end();
5888 tagIt != tagItEnd;
5889 ++tagIt ) {
5890 std::string tagName = *tagIt;
Phil Nash9241e432014-05-20 18:50:59 +01005891 std::string lcaseTagName = toLower( tagName );
5892 std::map<std::string, TagInfo>::iterator countIt = tagCounts.find( lcaseTagName );
Phil Nash20cad7c2014-04-15 18:44:37 +01005893 if( countIt == tagCounts.end() )
Phil Nash9241e432014-05-20 18:50:59 +01005894 countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;
5895 countIt->second.add( tagName );
Phil Nash38f7eef2013-03-29 13:44:33 +00005896 }
Phil Nasha695eb92012-08-13 07:46:10 +01005897 }
Phil Nash38f7eef2013-03-29 13:44:33 +00005898
Phil Nash9241e432014-05-20 18:50:59 +01005899 for( std::map<std::string, TagInfo>::const_iterator countIt = tagCounts.begin(),
5900 countItEnd = tagCounts.end();
Phil Nash38f7eef2013-03-29 13:44:33 +00005901 countIt != countItEnd;
5902 ++countIt ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +00005903 std::ostringstream oss;
Phil Nash9241e432014-05-20 18:50:59 +01005904 oss << " " << std::setw(2) << countIt->second.count << " ";
5905 Text wrapper( countIt->second.all(), TextAttributes()
5906 .setInitialIndent( 0 )
5907 .setIndent( oss.str().size() )
5908 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH-10 ) );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005909 Catch::cout() << oss.str() << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005910 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005911 Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005912 return tagCounts.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005913 }
5914
Phil Nash786959d2013-06-07 19:07:50 +01005915 inline std::size_t listReporters( Config const& /*config*/ ) {
Phil Nash576aff62014-12-21 00:21:23 +00005916 Catch::cout() << "Available reporters:\n";
Phil Nash38f7eef2013-03-29 13:44:33 +00005917 IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();
Phil Nash786959d2013-06-07 19:07:50 +01005918 IReporterRegistry::FactoryMap::const_iterator itBegin = factories.begin(), itEnd = factories.end(), it;
5919 std::size_t maxNameLen = 0;
5920 for(it = itBegin; it != itEnd; ++it )
5921 maxNameLen = (std::max)( maxNameLen, it->first.size() );
5922
5923 for(it = itBegin; it != itEnd; ++it ) {
5924 Text wrapper( it->second->getDescription(), TextAttributes()
5925 .setInitialIndent( 0 )
5926 .setIndent( 7+maxNameLen )
5927 .setWidth( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 ) );
Phil Nash383d7c02014-10-02 19:08:19 +01005928 Catch::cout() << " "
Phil Nash786959d2013-06-07 19:07:50 +01005929 << it->first
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005930 << ':'
Phil Nash786959d2013-06-07 19:07:50 +01005931 << std::string( maxNameLen - it->first.size() + 2, ' ' )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005932 << wrapper << '\n';
Phil Nash38f7eef2013-03-29 13:44:33 +00005933 }
Phil Nash383d7c02014-10-02 19:08:19 +01005934 Catch::cout() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01005935 return factories.size();
Phil Nash38f7eef2013-03-29 13:44:33 +00005936 }
5937
Phil Nash786959d2013-06-07 19:07:50 +01005938 inline Option<std::size_t> list( Config const& config ) {
5939 Option<std::size_t> listedCount;
5940 if( config.listTests() )
5941 listedCount = listedCount.valueOr(0) + listTests( config );
Phil Nash5ecb72b2013-11-26 20:57:45 +00005942 if( config.listTestNamesOnly() )
5943 listedCount = listedCount.valueOr(0) + listTestsNamesOnly( config );
Phil Nash786959d2013-06-07 19:07:50 +01005944 if( config.listTags() )
5945 listedCount = listedCount.valueOr(0) + listTags( config );
5946 if( config.listReporters() )
5947 listedCount = listedCount.valueOr(0) + listReporters( config );
5948 return listedCount;
Phil Nasha695eb92012-08-13 07:46:10 +01005949 }
5950
5951} // end namespace Catch
5952
Phil Nashe73583d2015-08-07 17:30:34 +01005953// #included from: internal/catch_run_context.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04005954#define TWOBLUECUBES_CATCH_RUNNER_IMPL_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005955
Phil Nash8a52a392013-07-25 08:12:03 +01005956// #included from: catch_test_case_tracker.hpp
5957#define TWOBLUECUBES_CATCH_TEST_CASE_TRACKER_HPP_INCLUDED
Phil Nasha695eb92012-08-13 07:46:10 +01005958
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02005959#include <algorithm>
Phil Nasha695eb92012-08-13 07:46:10 +01005960#include <string>
Phil Nash8a52a392013-07-25 08:12:03 +01005961#include <assert.h>
Phil Nash7e346192015-11-03 08:00:43 +00005962#include <vector>
Phil Nashd08cee22017-02-13 16:15:42 +00005963#include <stdexcept>
Phil Nasha695eb92012-08-13 07:46:10 +01005964
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02005965CATCH_INTERNAL_SUPPRESS_ETD_WARNINGS
5966
Phil Nasha695eb92012-08-13 07:46:10 +01005967namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +00005968namespace TestCaseTracking {
Phil Nasha695eb92012-08-13 07:46:10 +01005969
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005970 struct NameAndLocation {
5971 std::string name;
5972 SourceLineInfo location;
5973
5974 NameAndLocation( std::string const& _name, SourceLineInfo const& _location )
5975 : name( _name ),
5976 location( _location )
5977 {}
5978 };
5979
Phil Nash7e346192015-11-03 08:00:43 +00005980 struct ITracker : SharedImpl<> {
5981 virtual ~ITracker();
Phil Nash8a52a392013-07-25 08:12:03 +01005982
Phil Nash7e346192015-11-03 08:00:43 +00005983 // static queries
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01005984 virtual NameAndLocation const& nameAndLocation() const = 0;
Phil Nash8a52a392013-07-25 08:12:03 +01005985
Phil Nash7e346192015-11-03 08:00:43 +00005986 // dynamic queries
5987 virtual bool isComplete() const = 0; // Successfully completed or failed
5988 virtual bool isSuccessfullyCompleted() const = 0;
5989 virtual bool isOpen() const = 0; // Started but not complete
5990 virtual bool hasChildren() const = 0;
5991
5992 virtual ITracker& parent() = 0;
5993
5994 // actions
5995 virtual void close() = 0; // Successfully complete
5996 virtual void fail() = 0;
5997 virtual void markAsNeedingAnotherRun() = 0;
5998
5999 virtual void addChild( Ptr<ITracker> const& child ) = 0;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006000 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) = 0;
Phil Nash7e346192015-11-03 08:00:43 +00006001 virtual void openChild() = 0;
Phil Nash92b141e2016-04-28 08:13:00 +01006002
6003 // Debug/ checking
6004 virtual bool isSectionTracker() const = 0;
6005 virtual bool isIndexTracker() const = 0;
Phil Nash7e346192015-11-03 08:00:43 +00006006 };
6007
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006008 class TrackerContext {
Phil Nash7e346192015-11-03 08:00:43 +00006009
Phil Nash8a52a392013-07-25 08:12:03 +01006010 enum RunState {
6011 NotStarted,
6012 Executing,
Phil Nash7e346192015-11-03 08:00:43 +00006013 CompletedCycle
Phil Nasha695eb92012-08-13 07:46:10 +01006014 };
6015
Phil Nash7e346192015-11-03 08:00:43 +00006016 Ptr<ITracker> m_rootTracker;
6017 ITracker* m_currentTracker;
6018 RunState m_runState;
6019
6020 public:
6021
6022 static TrackerContext& instance() {
6023 static TrackerContext s_instance;
6024 return s_instance;
6025 }
6026
6027 TrackerContext()
6028 : m_currentTracker( CATCH_NULL ),
6029 m_runState( NotStarted )
Phil Nasha695eb92012-08-13 07:46:10 +01006030 {}
6031
Phil Nash7e346192015-11-03 08:00:43 +00006032 ITracker& startRun();
Phil Nasha695eb92012-08-13 07:46:10 +01006033
Phil Nash7e346192015-11-03 08:00:43 +00006034 void endRun() {
6035 m_rootTracker.reset();
6036 m_currentTracker = CATCH_NULL;
6037 m_runState = NotStarted;
Phil Nasha695eb92012-08-13 07:46:10 +01006038 }
Phil Nash3b18d9e2015-06-30 18:26:09 +01006039
Phil Nash7e346192015-11-03 08:00:43 +00006040 void startCycle() {
6041 m_currentTracker = m_rootTracker.get();
6042 m_runState = Executing;
Phil Nasha695eb92012-08-13 07:46:10 +01006043 }
Phil Nash7e346192015-11-03 08:00:43 +00006044 void completeCycle() {
6045 m_runState = CompletedCycle;
6046 }
6047
6048 bool completedCycle() const {
6049 return m_runState == CompletedCycle;
6050 }
6051 ITracker& currentTracker() {
6052 return *m_currentTracker;
6053 }
6054 void setCurrentTracker( ITracker* tracker ) {
6055 m_currentTracker = tracker;
6056 }
6057 };
6058
6059 class TrackerBase : public ITracker {
6060 protected:
6061 enum CycleState {
6062 NotStarted,
6063 Executing,
6064 ExecutingChildren,
6065 NeedsAnotherRun,
6066 CompletedSuccessfully,
6067 Failed
6068 };
6069 class TrackerHasName {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006070 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00006071 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006072 TrackerHasName( NameAndLocation const& nameAndLocation ) : m_nameAndLocation( nameAndLocation ) {}
Phil Nash7e346192015-11-03 08:00:43 +00006073 bool operator ()( Ptr<ITracker> const& tracker ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006074 return
6075 tracker->nameAndLocation().name == m_nameAndLocation.name &&
6076 tracker->nameAndLocation().location == m_nameAndLocation.location;
Phil Nash7e346192015-11-03 08:00:43 +00006077 }
6078 };
6079 typedef std::vector<Ptr<ITracker> > Children;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006080 NameAndLocation m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00006081 TrackerContext& m_ctx;
6082 ITracker* m_parent;
6083 Children m_children;
6084 CycleState m_runState;
6085 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006086 TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6087 : m_nameAndLocation( nameAndLocation ),
Phil Nash7e346192015-11-03 08:00:43 +00006088 m_ctx( ctx ),
6089 m_parent( parent ),
6090 m_runState( NotStarted )
6091 {}
6092 virtual ~TrackerBase();
6093
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006094 virtual NameAndLocation const& nameAndLocation() const CATCH_OVERRIDE {
6095 return m_nameAndLocation;
Phil Nash7e346192015-11-03 08:00:43 +00006096 }
6097 virtual bool isComplete() const CATCH_OVERRIDE {
6098 return m_runState == CompletedSuccessfully || m_runState == Failed;
6099 }
6100 virtual bool isSuccessfullyCompleted() const CATCH_OVERRIDE {
6101 return m_runState == CompletedSuccessfully;
6102 }
6103 virtual bool isOpen() const CATCH_OVERRIDE {
6104 return m_runState != NotStarted && !isComplete();
6105 }
6106 virtual bool hasChildren() const CATCH_OVERRIDE {
Phil Nash8a52a392013-07-25 08:12:03 +01006107 return !m_children.empty();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006108 }
6109
Phil Nash7e346192015-11-03 08:00:43 +00006110 virtual void addChild( Ptr<ITracker> const& child ) CATCH_OVERRIDE {
6111 m_children.push_back( child );
6112 }
Phil Nasha695eb92012-08-13 07:46:10 +01006113
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006114 virtual ITracker* findChild( NameAndLocation const& nameAndLocation ) CATCH_OVERRIDE {
6115 Children::const_iterator it = std::find_if( m_children.begin(), m_children.end(), TrackerHasName( nameAndLocation ) );
Phil Nash7e346192015-11-03 08:00:43 +00006116 return( it != m_children.end() )
6117 ? it->get()
6118 : CATCH_NULL;
6119 }
6120 virtual ITracker& parent() CATCH_OVERRIDE {
6121 assert( m_parent ); // Should always be non-null except for root
6122 return *m_parent;
6123 }
6124
6125 virtual void openChild() CATCH_OVERRIDE {
6126 if( m_runState != ExecutingChildren ) {
Phil Nash3b18d9e2015-06-30 18:26:09 +01006127 m_runState = ExecutingChildren;
Phil Nash7e346192015-11-03 08:00:43 +00006128 if( m_parent )
6129 m_parent->openChild();
Phil Nash3b18d9e2015-06-30 18:26:09 +01006130 }
Phil Nasha695eb92012-08-13 07:46:10 +01006131 }
Phil Nash92b141e2016-04-28 08:13:00 +01006132
6133 virtual bool isSectionTracker() const CATCH_OVERRIDE { return false; }
6134 virtual bool isIndexTracker() const CATCH_OVERRIDE { return false; }
6135
Phil Nash7e346192015-11-03 08:00:43 +00006136 void open() {
6137 m_runState = Executing;
6138 moveToThis();
6139 if( m_parent )
6140 m_parent->openChild();
Phil Nasha695eb92012-08-13 07:46:10 +01006141 }
6142
Phil Nash7e346192015-11-03 08:00:43 +00006143 virtual void close() CATCH_OVERRIDE {
Phil Nasha695eb92012-08-13 07:46:10 +01006144
Phil Nash7e346192015-11-03 08:00:43 +00006145 // Close any still open children (e.g. generators)
6146 while( &m_ctx.currentTracker() != this )
6147 m_ctx.currentTracker().close();
6148
6149 switch( m_runState ) {
6150 case NotStarted:
6151 case CompletedSuccessfully:
6152 case Failed:
6153 throw std::logic_error( "Illogical state" );
6154
6155 case NeedsAnotherRun:
6156 break;;
6157
6158 case Executing:
6159 m_runState = CompletedSuccessfully;
6160 break;
6161 case ExecutingChildren:
6162 if( m_children.empty() || m_children.back()->isComplete() )
6163 m_runState = CompletedSuccessfully;
6164 break;
6165
6166 default:
6167 throw std::logic_error( "Unexpected state" );
Phil Nash8a52a392013-07-25 08:12:03 +01006168 }
Phil Nash7e346192015-11-03 08:00:43 +00006169 moveToParent();
6170 m_ctx.completeCycle();
6171 }
6172 virtual void fail() CATCH_OVERRIDE {
6173 m_runState = Failed;
6174 if( m_parent )
6175 m_parent->markAsNeedingAnotherRun();
6176 moveToParent();
6177 m_ctx.completeCycle();
6178 }
6179 virtual void markAsNeedingAnotherRun() CATCH_OVERRIDE {
6180 m_runState = NeedsAnotherRun;
6181 }
Phil Nasha695eb92012-08-13 07:46:10 +01006182 private:
Phil Nash7e346192015-11-03 08:00:43 +00006183 void moveToParent() {
6184 assert( m_parent );
6185 m_ctx.setCurrentTracker( m_parent );
Phil Nash8a52a392013-07-25 08:12:03 +01006186 }
Phil Nash7e346192015-11-03 08:00:43 +00006187 void moveToThis() {
6188 m_ctx.setCurrentTracker( this );
Phil Nash8a52a392013-07-25 08:12:03 +01006189 }
Phil Nasha695eb92012-08-13 07:46:10 +01006190 };
Phil Nash8a52a392013-07-25 08:12:03 +01006191
Phil Nash7e346192015-11-03 08:00:43 +00006192 class SectionTracker : public TrackerBase {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006193 std::vector<std::string> m_filters;
Phil Nash7e346192015-11-03 08:00:43 +00006194 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006195 SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )
6196 : TrackerBase( nameAndLocation, ctx, parent )
6197 {
6198 if( parent ) {
6199 while( !parent->isSectionTracker() )
6200 parent = &parent->parent();
6201
6202 SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );
6203 addNextFilters( parentSection.m_filters );
6204 }
6205 }
Phil Nash7e346192015-11-03 08:00:43 +00006206 virtual ~SectionTracker();
Phil Nash8a52a392013-07-25 08:12:03 +01006207
Phil Nash92b141e2016-04-28 08:13:00 +01006208 virtual bool isSectionTracker() const CATCH_OVERRIDE { return true; }
6209
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006210 static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {
Phil Nash7e346192015-11-03 08:00:43 +00006211 SectionTracker* section = CATCH_NULL;
6212
6213 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006214 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006215 assert( childTracker );
6216 assert( childTracker->isSectionTracker() );
6217 section = static_cast<SectionTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006218 }
6219 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006220 section = new SectionTracker( nameAndLocation, ctx, &currentTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006221 currentTracker.addChild( section );
6222 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006223 if( !ctx.completedCycle() )
6224 section->tryOpen();
Phil Nash7e346192015-11-03 08:00:43 +00006225 return *section;
6226 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006227
6228 void tryOpen() {
6229 if( !isComplete() && (m_filters.empty() || m_filters[0].empty() || m_filters[0] == m_nameAndLocation.name ) )
6230 open();
6231 }
6232
6233 void addInitialFilters( std::vector<std::string> const& filters ) {
6234 if( !filters.empty() ) {
6235 m_filters.push_back(""); // Root - should never be consulted
6236 m_filters.push_back(""); // Test Case - not a section filter
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006237 m_filters.insert( m_filters.end(), filters.begin(), filters.end() );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006238 }
6239 }
6240 void addNextFilters( std::vector<std::string> const& filters ) {
6241 if( filters.size() > 1 )
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006242 m_filters.insert( m_filters.end(), ++filters.begin(), filters.end() );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006243 }
Phil Nash7e346192015-11-03 08:00:43 +00006244 };
6245
6246 class IndexTracker : public TrackerBase {
6247 int m_size;
6248 int m_index;
6249 public:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006250 IndexTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent, int size )
6251 : TrackerBase( nameAndLocation, ctx, parent ),
Phil Nash7e346192015-11-03 08:00:43 +00006252 m_size( size ),
6253 m_index( -1 )
6254 {}
6255 virtual ~IndexTracker();
6256
Phil Nash92b141e2016-04-28 08:13:00 +01006257 virtual bool isIndexTracker() const CATCH_OVERRIDE { return true; }
6258
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006259 static IndexTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation, int size ) {
Phil Nash7e346192015-11-03 08:00:43 +00006260 IndexTracker* tracker = CATCH_NULL;
6261
6262 ITracker& currentTracker = ctx.currentTracker();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006263 if( ITracker* childTracker = currentTracker.findChild( nameAndLocation ) ) {
Phil Nash92b141e2016-04-28 08:13:00 +01006264 assert( childTracker );
6265 assert( childTracker->isIndexTracker() );
6266 tracker = static_cast<IndexTracker*>( childTracker );
Phil Nash7e346192015-11-03 08:00:43 +00006267 }
6268 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006269 tracker = new IndexTracker( nameAndLocation, ctx, &currentTracker, size );
Phil Nash7e346192015-11-03 08:00:43 +00006270 currentTracker.addChild( tracker );
6271 }
6272
6273 if( !ctx.completedCycle() && !tracker->isComplete() ) {
6274 if( tracker->m_runState != ExecutingChildren && tracker->m_runState != NeedsAnotherRun )
6275 tracker->moveNext();
6276 tracker->open();
6277 }
6278
6279 return *tracker;
6280 }
6281
6282 int index() const { return m_index; }
6283
6284 void moveNext() {
6285 m_index++;
6286 m_children.clear();
6287 }
6288
6289 virtual void close() CATCH_OVERRIDE {
6290 TrackerBase::close();
6291 if( m_runState == CompletedSuccessfully && m_index < m_size-1 )
6292 m_runState = Executing;
6293 }
6294 };
6295
6296 inline ITracker& TrackerContext::startRun() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006297 m_rootTracker = new SectionTracker( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, CATCH_NULL );
Phil Nash7e346192015-11-03 08:00:43 +00006298 m_currentTracker = CATCH_NULL;
6299 m_runState = Executing;
6300 return *m_rootTracker;
6301 }
6302
6303} // namespace TestCaseTracking
6304
6305using TestCaseTracking::ITracker;
6306using TestCaseTracking::TrackerContext;
6307using TestCaseTracking::SectionTracker;
6308using TestCaseTracking::IndexTracker;
Phil Nash8a52a392013-07-25 08:12:03 +01006309
6310} // namespace Catch
Phil Nasha695eb92012-08-13 07:46:10 +01006311
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006312CATCH_INTERNAL_UNSUPPRESS_ETD_WARNINGS
6313
Phil Nash93b61e12014-08-22 19:35:41 +01006314// #included from: catch_fatal_condition.hpp
6315#define TWOBLUECUBES_CATCH_FATAL_CONDITION_H_INCLUDED
6316
6317namespace Catch {
6318
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006319 // Report the error condition
6320 inline void reportFatal( std::string const& message ) {
Phil Nash93b61e12014-08-22 19:35:41 +01006321 IContext& context = Catch::getCurrentContext();
6322 IResultCapture* resultCapture = context.getResultCapture();
6323 resultCapture->handleFatalErrorCondition( message );
Phil Nash93b61e12014-08-22 19:35:41 +01006324 }
6325
6326} // namespace Catch
6327
6328#if defined ( CATCH_PLATFORM_WINDOWS ) /////////////////////////////////////////
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006329// #included from: catch_windows_h_proxy.h
Phil Nash93b61e12014-08-22 19:35:41 +01006330
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006331#define TWOBLUECUBES_CATCH_WINDOWS_H_PROXY_H_INCLUDED
6332
6333#ifdef CATCH_DEFINES_NOMINMAX
6334# define NOMINMAX
6335#endif
6336#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6337# define WIN32_LEAN_AND_MEAN
6338#endif
6339
6340#ifdef __AFXDLL
6341#include <AfxWin.h>
6342#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006343#include <windows.h>
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006344#endif
6345
6346#ifdef CATCH_DEFINES_NOMINMAX
6347# undef NOMINMAX
6348#endif
6349#ifdef CATCH_DEFINES_WIN32_LEAN_AND_MEAN
6350# undef WIN32_LEAN_AND_MEAN
6351#endif
6352
6353
6354# if !defined ( CATCH_CONFIG_WINDOWS_SEH )
6355
6356namespace Catch {
6357 struct FatalConditionHandler {
6358 void reset() {}
6359 };
6360}
6361
6362# else // CATCH_CONFIG_WINDOWS_SEH is defined
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006363
Phil Nash93b61e12014-08-22 19:35:41 +01006364namespace Catch {
6365
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006366 struct SignalDefs { DWORD id; const char* name; };
6367 extern SignalDefs signalDefs[];
6368 // There is no 1-1 mapping between signals and windows exceptions.
6369 // Windows can easily distinguish between SO and SigSegV,
6370 // but SigInt, SigTerm, etc are handled differently.
6371 SignalDefs signalDefs[] = {
6372 { EXCEPTION_ILLEGAL_INSTRUCTION, "SIGILL - Illegal instruction signal" },
6373 { EXCEPTION_STACK_OVERFLOW, "SIGSEGV - Stack overflow" },
6374 { EXCEPTION_ACCESS_VIOLATION, "SIGSEGV - Segmentation violation signal" },
6375 { EXCEPTION_INT_DIVIDE_BY_ZERO, "Divide by zero error" },
6376 };
6377
Phil Nashe54ac702014-10-21 07:25:26 +01006378 struct FatalConditionHandler {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006379
6380 static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {
6381 for (int i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6382 if (ExceptionInfo->ExceptionRecord->ExceptionCode == signalDefs[i].id) {
6383 reportFatal(signalDefs[i].name);
6384 }
6385 }
6386 // If its not an exception we care about, pass it along.
6387 // This stops us from eating debugger breaks etc.
6388 return EXCEPTION_CONTINUE_SEARCH;
6389 }
6390
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006391 FatalConditionHandler() {
6392 isSet = true;
6393 // 32k seems enough for Catch to handle stack overflow,
6394 // but the value was found experimentally, so there is no strong guarantee
6395 guaranteeSize = 32 * 1024;
6396 exceptionHandlerHandle = CATCH_NULL;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006397 // Register as first handler in current chain
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006398 exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006399 // Pass in guarantee size to be filled
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006400 SetThreadStackGuarantee(&guaranteeSize);
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006401 }
6402
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006403 static void reset() {
6404 if (isSet) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006405 // Unregister handler and restore the old guarantee
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006406 RemoveVectoredExceptionHandler(exceptionHandlerHandle);
6407 SetThreadStackGuarantee(&guaranteeSize);
6408 exceptionHandlerHandle = CATCH_NULL;
6409 isSet = false;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006410 }
6411 }
6412
6413 ~FatalConditionHandler() {
6414 reset();
6415 }
6416 private:
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006417 static bool isSet;
6418 static ULONG guaranteeSize;
6419 static PVOID exceptionHandlerHandle;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006420 };
Phil Nash93b61e12014-08-22 19:35:41 +01006421
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006422 bool FatalConditionHandler::isSet = false;
6423 ULONG FatalConditionHandler::guaranteeSize = 0;
6424 PVOID FatalConditionHandler::exceptionHandlerHandle = CATCH_NULL;
6425
Phil Nash93b61e12014-08-22 19:35:41 +01006426} // namespace Catch
6427
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +01006428# endif // CATCH_CONFIG_WINDOWS_SEH
6429
Phil Nash93b61e12014-08-22 19:35:41 +01006430#else // Not Windows - assumed to be POSIX compatible //////////////////////////
6431
Phil Nash0952b762017-02-28 14:19:09 +00006432# if !defined(CATCH_CONFIG_POSIX_SIGNALS)
6433
6434namespace Catch {
6435 struct FatalConditionHandler {
6436 void reset() {}
6437 };
6438}
6439
6440# else // CATCH_CONFIG_POSIX_SIGNALS is defined
6441
Phil Nash93b61e12014-08-22 19:35:41 +01006442#include <signal.h>
6443
6444namespace Catch {
6445
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006446 struct SignalDefs {
6447 int id;
6448 const char* name;
6449 };
Phil Nash93b61e12014-08-22 19:35:41 +01006450 extern SignalDefs signalDefs[];
6451 SignalDefs signalDefs[] = {
6452 { SIGINT, "SIGINT - Terminal interrupt signal" },
6453 { SIGILL, "SIGILL - Illegal instruction signal" },
6454 { SIGFPE, "SIGFPE - Floating point error signal" },
6455 { SIGSEGV, "SIGSEGV - Segmentation violation signal" },
6456 { SIGTERM, "SIGTERM - Termination request signal" },
6457 { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006458 };
Phil Nash93b61e12014-08-22 19:35:41 +01006459
6460 struct FatalConditionHandler {
6461
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006462 static bool isSet;
6463 static struct sigaction oldSigActions [sizeof(signalDefs)/sizeof(SignalDefs)];
6464 static stack_t oldSigStack;
6465 static char altStackMem[SIGSTKSZ];
6466
Phil Nash93b61e12014-08-22 19:35:41 +01006467 static void handleSignal( int sig ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006468 std::string name = "<unknown signal>";
6469 for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {
6470 SignalDefs &def = signalDefs[i];
6471 if (sig == def.id) {
6472 name = def.name;
6473 break;
6474 }
6475 }
6476 reset();
6477 reportFatal(name);
6478 raise( sig );
Phil Nash93b61e12014-08-22 19:35:41 +01006479 }
6480
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006481 FatalConditionHandler() {
6482 isSet = true;
6483 stack_t sigStack;
6484 sigStack.ss_sp = altStackMem;
6485 sigStack.ss_size = SIGSTKSZ;
6486 sigStack.ss_flags = 0;
6487 sigaltstack(&sigStack, &oldSigStack);
6488 struct sigaction sa = { 0 };
6489
6490 sa.sa_handler = handleSignal;
6491 sa.sa_flags = SA_ONSTACK;
6492 for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {
6493 sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);
Phil Nash85b4e942014-10-02 18:51:05 +01006494 }
6495 }
6496
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006497 ~FatalConditionHandler() {
6498 reset();
6499 }
6500 static void reset() {
6501 if( isSet ) {
6502 // Set signals back to previous values -- hopefully nobody overwrote them in the meantime
6503 for( std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i ) {
6504 sigaction(signalDefs[i].id, &oldSigActions[i], CATCH_NULL);
6505 }
6506 // Return the old stack
6507 sigaltstack(&oldSigStack, CATCH_NULL);
6508 isSet = false;
6509 }
6510 }
Phil Nash93b61e12014-08-22 19:35:41 +01006511 };
6512
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006513 bool FatalConditionHandler::isSet = false;
6514 struct sigaction FatalConditionHandler::oldSigActions[sizeof(signalDefs)/sizeof(SignalDefs)] = {};
6515 stack_t FatalConditionHandler::oldSigStack = {};
6516 char FatalConditionHandler::altStackMem[SIGSTKSZ] = {};
6517
Phil Nash93b61e12014-08-22 19:35:41 +01006518} // namespace Catch
6519
Phil Nash0952b762017-02-28 14:19:09 +00006520# endif // CATCH_CONFIG_POSIX_SIGNALS
6521
Phil Nash93b61e12014-08-22 19:35:41 +01006522#endif // not Windows
6523
Phil Nasha695eb92012-08-13 07:46:10 +01006524#include <set>
6525#include <string>
6526
6527namespace Catch {
6528
6529 class StreamRedirect {
6530
6531 public:
6532 StreamRedirect( std::ostream& stream, std::string& targetString )
6533 : m_stream( stream ),
6534 m_prevBuf( stream.rdbuf() ),
6535 m_targetString( targetString )
6536 {
6537 stream.rdbuf( m_oss.rdbuf() );
6538 }
6539
6540 ~StreamRedirect() {
6541 m_targetString += m_oss.str();
6542 m_stream.rdbuf( m_prevBuf );
6543 }
6544
6545 private:
6546 std::ostream& m_stream;
6547 std::streambuf* m_prevBuf;
6548 std::ostringstream m_oss;
6549 std::string& m_targetString;
6550 };
6551
6552 ///////////////////////////////////////////////////////////////////////////
6553
Phil Nash786959d2013-06-07 19:07:50 +01006554 class RunContext : public IResultCapture, public IRunner {
Phil Nasha695eb92012-08-13 07:46:10 +01006555
Phil Nash786959d2013-06-07 19:07:50 +01006556 RunContext( RunContext const& );
6557 void operator =( RunContext const& );
Phil Nasha695eb92012-08-13 07:46:10 +01006558
6559 public:
6560
Phil Nashb971fe72015-07-02 08:21:38 +01006561 explicit RunContext( Ptr<IConfig const> const& _config, Ptr<IStreamingReporter> const& reporter )
6562 : m_runInfo( _config->name() ),
Phil Nasha1fbfea2012-12-01 23:57:18 +00006563 m_context( getCurrentMutableContext() ),
Phil Nashb971fe72015-07-02 08:21:38 +01006564 m_activeTestCase( CATCH_NULL ),
6565 m_config( _config ),
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006566 m_reporter( reporter ),
6567 m_shouldReportUnexpected ( true )
Phil Nasha695eb92012-08-13 07:46:10 +01006568 {
6569 m_context.setRunner( this );
Phil Nash786959d2013-06-07 19:07:50 +01006570 m_context.setConfig( m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006571 m_context.setResultCapture( this );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006572 m_reporter->testRunStarting( m_runInfo );
Phil Nasha695eb92012-08-13 07:46:10 +01006573 }
6574
Phil Nash786959d2013-06-07 19:07:50 +01006575 virtual ~RunContext() {
Phil Nash2e7d9662013-01-16 09:44:43 +00006576 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, aborting() ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006577 }
6578
Phil Nash2e7d9662013-01-16 09:44:43 +00006579 void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount ) {
6580 m_reporter->testGroupStarting( GroupInfo( testSpec, groupIndex, groupsCount ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006581 }
Phil Nash2e7d9662013-01-16 09:44:43 +00006582 void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount ) {
6583 m_reporter->testGroupEnded( TestGroupStats( GroupInfo( testSpec, groupIndex, groupsCount ), totals, aborting() ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006584 }
Phil Nasha695eb92012-08-13 07:46:10 +01006585
Phil Nash8defc712013-04-24 19:10:02 +01006586 Totals runTest( TestCase const& testCase ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006587 Totals prevTotals = m_totals;
6588
6589 std::string redirectedCout;
6590 std::string redirectedCerr;
6591
Phil Nasha1fbfea2012-12-01 23:57:18 +00006592 TestCaseInfo testInfo = testCase.getTestCaseInfo();
Phil Nasha695eb92012-08-13 07:46:10 +01006593
Phil Nasha1fbfea2012-12-01 23:57:18 +00006594 m_reporter->testCaseStarting( testInfo );
6595
Phil Nash8a52a392013-07-25 08:12:03 +01006596 m_activeTestCase = &testCase;
Phil Nasha695eb92012-08-13 07:46:10 +01006597
6598 do {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006599 ITracker& rootTracker = m_trackerContext.startRun();
Phil Nashd08cee22017-02-13 16:15:42 +00006600 assert( rootTracker.isSectionTracker() );
6601 static_cast<SectionTracker&>( rootTracker ).addInitialFilters( m_config->getSectionsToRun() );
Phil Nasha695eb92012-08-13 07:46:10 +01006602 do {
Phil Nash7e346192015-11-03 08:00:43 +00006603 m_trackerContext.startCycle();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006604 m_testCaseTracker = &SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( testInfo.name, testInfo.lineInfo ) );
Phil Nasha695eb92012-08-13 07:46:10 +01006605 runCurrentTest( redirectedCout, redirectedCerr );
Phil Nasha695eb92012-08-13 07:46:10 +01006606 }
Phil Nash7e346192015-11-03 08:00:43 +00006607 while( !m_testCaseTracker->isSuccessfullyCompleted() && !aborting() );
Phil Nasha695eb92012-08-13 07:46:10 +01006608 }
Phil Nash7e346192015-11-03 08:00:43 +00006609 // !TBD: deprecated - this will be replaced by indexed trackers
Phil Nasha695eb92012-08-13 07:46:10 +01006610 while( getCurrentContext().advanceGeneratorsForCurrentTest() && !aborting() );
6611
Phil Nash28463672012-11-21 18:06:13 +00006612 Totals deltaTotals = m_totals.delta( prevTotals );
Phil Nashc984fc32016-03-15 07:24:26 +00006613 if( testInfo.expectedToFail() && deltaTotals.testCases.passed > 0 ) {
6614 deltaTotals.assertions.failed++;
6615 deltaTotals.testCases.passed--;
6616 deltaTotals.testCases.failed++;
6617 }
Phil Nash28463672012-11-21 18:06:13 +00006618 m_totals.testCases += deltaTotals.testCases;
Phil Nash2e7d9662013-01-16 09:44:43 +00006619 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6620 deltaTotals,
6621 redirectedCout,
6622 redirectedCerr,
Phil Nash2e7d9662013-01-16 09:44:43 +00006623 aborting() ) );
Phil Nash28463672012-11-21 18:06:13 +00006624
Phil Nashb971fe72015-07-02 08:21:38 +01006625 m_activeTestCase = CATCH_NULL;
Phil Nash7e346192015-11-03 08:00:43 +00006626 m_testCaseTracker = CATCH_NULL;
Phil Nasha695eb92012-08-13 07:46:10 +01006627
Phil Nash5bc030d2012-08-16 18:48:50 +01006628 return deltaTotals;
Phil Nasha695eb92012-08-13 07:46:10 +01006629 }
6630
Phil Nash786959d2013-06-07 19:07:50 +01006631 Ptr<IConfig const> config() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006632 return m_config;
6633 }
6634
6635 private: // IResultCapture
6636
Phil Nash8defc712013-04-24 19:10:02 +01006637 virtual void assertionEnded( AssertionResult const& result ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006638 if( result.getResultType() == ResultWas::Ok ) {
6639 m_totals.assertions.passed++;
6640 }
Phil Nash90a35942012-11-13 22:04:29 +00006641 else if( !result.isOk() ) {
Phil Nasha695eb92012-08-13 07:46:10 +01006642 m_totals.assertions.failed++;
Phil Nasha695eb92012-08-13 07:46:10 +01006643 }
6644
Phil Nashb5fd5a62013-06-28 17:09:57 +01006645 if( m_reporter->assertionEnded( AssertionStats( result, m_messages, m_totals ) ) )
6646 m_messages.clear();
Phil Nasha90a88a2012-11-19 19:59:10 +00006647
Phil Nasha2773812013-02-02 20:37:58 +00006648 // Reset working state
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006649 m_lastAssertionInfo = AssertionInfo( std::string(), m_lastAssertionInfo.lineInfo, "{Unknown expression after the reported line}" , m_lastAssertionInfo.resultDisposition );
Phil Nashab036682014-06-02 07:48:03 +01006650 m_lastResult = result;
Phil Nasha695eb92012-08-13 07:46:10 +01006651 }
6652
6653 virtual bool sectionStarted (
Phil Nasha1fbfea2012-12-01 23:57:18 +00006654 SectionInfo const& sectionInfo,
Phil Nasha695eb92012-08-13 07:46:10 +01006655 Counts& assertions
6656 )
6657 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006658 ITracker& sectionTracker = SectionTracker::acquire( m_trackerContext, TestCaseTracking::NameAndLocation( sectionInfo.name, sectionInfo.lineInfo ) );
Phil Nash7e346192015-11-03 08:00:43 +00006659 if( !sectionTracker.isOpen() )
Phil Nasha695eb92012-08-13 07:46:10 +01006660 return false;
Phil Nash7e346192015-11-03 08:00:43 +00006661 m_activeSections.push_back( &sectionTracker );
Phil Nasha695eb92012-08-13 07:46:10 +01006662
Phil Nasha1fbfea2012-12-01 23:57:18 +00006663 m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;
Phil Nash90a35942012-11-13 22:04:29 +00006664
Phil Nasha1fbfea2012-12-01 23:57:18 +00006665 m_reporter->sectionStarting( sectionInfo );
6666
Phil Nasha695eb92012-08-13 07:46:10 +01006667 assertions = m_totals.assertions;
6668
6669 return true;
6670 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006671 bool testForMissingAssertions( Counts& assertions ) {
Phil Nash7e346192015-11-03 08:00:43 +00006672 if( assertions.total() != 0 )
6673 return false;
Phil Nash9e421532015-11-03 17:06:54 +00006674 if( !m_config->warnAboutMissingAssertions() )
Phil Nash7e346192015-11-03 08:00:43 +00006675 return false;
6676 if( m_trackerContext.currentTracker().hasChildren() )
Phil Nashaa7123b2013-08-15 19:01:00 +01006677 return false;
6678 m_totals.assertions.failed++;
6679 assertions.failed++;
6680 return true;
6681 }
Phil Nasha695eb92012-08-13 07:46:10 +01006682
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006683 virtual void sectionEnded( SectionEndInfo const& endInfo ) {
6684 Counts assertions = m_totals.assertions - endInfo.prevAssertions;
Phil Nashaa7123b2013-08-15 19:01:00 +01006685 bool missingAssertions = testForMissingAssertions( assertions );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006686
Phil Nash7e346192015-11-03 08:00:43 +00006687 if( !m_activeSections.empty() ) {
6688 m_activeSections.back()->close();
6689 m_activeSections.pop_back();
6690 }
Phil Nasha1fbfea2012-12-01 23:57:18 +00006691
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006692 m_reporter->sectionEnded( SectionStats( endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions ) );
Phil Nasha2773812013-02-02 20:37:58 +00006693 m_messages.clear();
Phil Nasha695eb92012-08-13 07:46:10 +01006694 }
6695
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006696 virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) {
Phil Nash7e346192015-11-03 08:00:43 +00006697 if( m_unfinishedSections.empty() )
6698 m_activeSections.back()->fail();
6699 else
6700 m_activeSections.back()->close();
6701 m_activeSections.pop_back();
6702
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006703 m_unfinishedSections.push_back( endInfo );
6704 }
6705
Phil Nashb5fd5a62013-06-28 17:09:57 +01006706 virtual void pushScopedMessage( MessageInfo const& message ) {
6707 m_messages.push_back( message );
Phil Nasha695eb92012-08-13 07:46:10 +01006708 }
6709
Phil Nashb5fd5a62013-06-28 17:09:57 +01006710 virtual void popScopedMessage( MessageInfo const& message ) {
6711 m_messages.erase( std::remove( m_messages.begin(), m_messages.end(), message ), m_messages.end() );
Phil Nasha695eb92012-08-13 07:46:10 +01006712 }
6713
Phil Nasha695eb92012-08-13 07:46:10 +01006714 virtual std::string getCurrentTestName() const {
Phil Nash8a52a392013-07-25 08:12:03 +01006715 return m_activeTestCase
6716 ? m_activeTestCase->getTestCaseInfo().name
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006717 : std::string();
Phil Nasha695eb92012-08-13 07:46:10 +01006718 }
6719
Phil Nashce612bf2012-11-01 08:27:09 +00006720 virtual const AssertionResult* getLastResult() const {
Phil Nasha695eb92012-08-13 07:46:10 +01006721 return &m_lastResult;
6722 }
6723
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006724 virtual void exceptionEarlyReported() {
6725 m_shouldReportUnexpected = false;
6726 }
6727
Phil Nash93b61e12014-08-22 19:35:41 +01006728 virtual void handleFatalErrorCondition( std::string const& message ) {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01006729 // Don't rebuild the result -- the stringification itself can cause more fatal errors
6730 // Instead, fake a result data.
6731 AssertionResultData tempResult;
6732 tempResult.resultType = ResultWas::FatalErrorCondition;
6733 tempResult.message = message;
6734 AssertionResult result(m_lastAssertionInfo, tempResult);
6735
6736 getResultCapture().assertionEnded(result);
Phil Nash93b61e12014-08-22 19:35:41 +01006737
6738 handleUnfinishedSections();
6739
6740 // Recreate section for test case (as we will lose the one that was in scope)
6741 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
6742 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
6743
6744 Counts assertions;
6745 assertions.failed = 1;
6746 SectionStats testCaseSectionStats( testCaseSection, assertions, 0, false );
6747 m_reporter->sectionEnded( testCaseSectionStats );
6748
6749 TestCaseInfo testInfo = m_activeTestCase->getTestCaseInfo();
6750
6751 Totals deltaTotals;
6752 deltaTotals.testCases.failed = 1;
6753 m_reporter->testCaseEnded( TestCaseStats( testInfo,
6754 deltaTotals,
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006755 std::string(),
6756 std::string(),
Phil Nash93b61e12014-08-22 19:35:41 +01006757 false ) );
6758 m_totals.testCases.failed++;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006759 testGroupEnded( std::string(), m_totals, 1, 1 );
Phil Nash93b61e12014-08-22 19:35:41 +01006760 m_reporter->testRunEnded( TestRunStats( m_runInfo, m_totals, false ) );
6761 }
6762
Phil Nash56d5c422012-08-23 20:08:50 +01006763 public:
6764 // !TBD We need to do this another way!
Phil Nasha695eb92012-08-13 07:46:10 +01006765 bool aborting() const {
Phil Nash786959d2013-06-07 19:07:50 +01006766 return m_totals.assertions.failed == static_cast<std::size_t>( m_config->abortAfter() );
Phil Nasha695eb92012-08-13 07:46:10 +01006767 }
6768
Phil Nash56d5c422012-08-23 20:08:50 +01006769 private:
6770
Phil Nasha695eb92012-08-13 07:46:10 +01006771 void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr ) {
Phil Nash8a52a392013-07-25 08:12:03 +01006772 TestCaseInfo const& testCaseInfo = m_activeTestCase->getTestCaseInfo();
Phil Nashce562092014-07-09 07:40:37 +01006773 SectionInfo testCaseSection( testCaseInfo.lineInfo, testCaseInfo.name, testCaseInfo.description );
Phil Nash8a52a392013-07-25 08:12:03 +01006774 m_reporter->sectionStarting( testCaseSection );
Phil Nashaa7123b2013-08-15 19:01:00 +01006775 Counts prevAssertions = m_totals.assertions;
6776 double duration = 0;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006777 m_shouldReportUnexpected = true;
Phil Nasha695eb92012-08-13 07:46:10 +01006778 try {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01006779 m_lastAssertionInfo = AssertionInfo( "TEST_CASE", testCaseInfo.lineInfo, std::string(), ResultDisposition::Normal );
Phil Nashd768b1b2013-02-04 00:05:16 +00006780
Phil Nash8f66e342015-07-02 23:03:13 +01006781 seedRng( *m_config );
Phil Nasha695eb92012-08-13 07:46:10 +01006782
Phil Nashaa7123b2013-08-15 19:01:00 +01006783 Timer timer;
6784 timer.start();
Phil Nasha1fbfea2012-12-01 23:57:18 +00006785 if( m_reporter->getPreferences().shouldRedirectStdOut ) {
Phil Nash383d7c02014-10-02 19:08:19 +01006786 StreamRedirect coutRedir( Catch::cout(), redirectedCout );
6787 StreamRedirect cerrRedir( Catch::cerr(), redirectedCerr );
Phil Nash93b61e12014-08-22 19:35:41 +01006788 invokeActiveTestCase();
Phil Nasha695eb92012-08-13 07:46:10 +01006789 }
6790 else {
Phil Nash93b61e12014-08-22 19:35:41 +01006791 invokeActiveTestCase();
Phil Nasha70fbe32012-08-31 08:10:36 +01006792 }
Phil Nashaa7123b2013-08-15 19:01:00 +01006793 duration = timer.getElapsedSeconds();
Phil Nasha695eb92012-08-13 07:46:10 +01006794 }
6795 catch( TestFailureException& ) {
6796 // This just means the test was aborted due to failure
6797 }
6798 catch(...) {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006799 // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions
6800 // are reported without translation at the point of origin.
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006801 if (m_shouldReportUnexpected) {
6802 makeUnexpectedResultBuilder().useActiveException();
6803 }
Phil Nasha695eb92012-08-13 07:46:10 +01006804 }
Phil Nash7e346192015-11-03 08:00:43 +00006805 m_testCaseTracker->close();
Phil Nash93b61e12014-08-22 19:35:41 +01006806 handleUnfinishedSections();
Phil Nashd768b1b2013-02-04 00:05:16 +00006807 m_messages.clear();
Phil Nashaa7123b2013-08-15 19:01:00 +01006808
6809 Counts assertions = m_totals.assertions - prevAssertions;
6810 bool missingAssertions = testForMissingAssertions( assertions );
6811
Phil Nash52e1e742014-07-03 08:11:38 +01006812 if( testCaseInfo.okToFail() ) {
6813 std::swap( assertions.failedButOk, assertions.failed );
6814 m_totals.assertions.failed -= assertions.failedButOk;
6815 m_totals.assertions.failedButOk += assertions.failedButOk;
6816 }
6817
Phil Nashaa7123b2013-08-15 19:01:00 +01006818 SectionStats testCaseSectionStats( testCaseSection, assertions, duration, missingAssertions );
Phil Nash8a52a392013-07-25 08:12:03 +01006819 m_reporter->sectionEnded( testCaseSectionStats );
Phil Nasha695eb92012-08-13 07:46:10 +01006820 }
6821
Phil Nash93b61e12014-08-22 19:35:41 +01006822 void invokeActiveTestCase() {
6823 FatalConditionHandler fatalConditionHandler; // Handle signals
6824 m_activeTestCase->invoke();
Phil Nash85b4e942014-10-02 18:51:05 +01006825 fatalConditionHandler.reset();
Phil Nash93b61e12014-08-22 19:35:41 +01006826 }
6827
Phil Nasha695eb92012-08-13 07:46:10 +01006828 private:
Phil Nash93b61e12014-08-22 19:35:41 +01006829
6830 ResultBuilder makeUnexpectedResultBuilder() const {
6831 return ResultBuilder( m_lastAssertionInfo.macroName.c_str(),
6832 m_lastAssertionInfo.lineInfo,
6833 m_lastAssertionInfo.capturedExpression.c_str(),
6834 m_lastAssertionInfo.resultDisposition );
6835 }
6836
6837 void handleUnfinishedSections() {
6838 // If sections ended prematurely due to an exception we stored their
6839 // infos here so we can tear them down outside the unwind process.
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006840 for( std::vector<SectionEndInfo>::const_reverse_iterator it = m_unfinishedSections.rbegin(),
Phil Nash93b61e12014-08-22 19:35:41 +01006841 itEnd = m_unfinishedSections.rend();
6842 it != itEnd;
6843 ++it )
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006844 sectionEnded( *it );
Phil Nash93b61e12014-08-22 19:35:41 +01006845 m_unfinishedSections.clear();
6846 }
6847
Phil Nasha1fbfea2012-12-01 23:57:18 +00006848 TestRunInfo m_runInfo;
Phil Nasha695eb92012-08-13 07:46:10 +01006849 IMutableContext& m_context;
Phil Nash8a52a392013-07-25 08:12:03 +01006850 TestCase const* m_activeTestCase;
Phil Nash7e346192015-11-03 08:00:43 +00006851 ITracker* m_testCaseTracker;
6852 ITracker* m_currentSectionTracker;
Phil Nashce612bf2012-11-01 08:27:09 +00006853 AssertionResult m_lastResult;
Phil Nasha695eb92012-08-13 07:46:10 +01006854
Phil Nash786959d2013-06-07 19:07:50 +01006855 Ptr<IConfig const> m_config;
Phil Nasha695eb92012-08-13 07:46:10 +01006856 Totals m_totals;
Phil Nasha1fbfea2012-12-01 23:57:18 +00006857 Ptr<IStreamingReporter> m_reporter;
Phil Nasha2773812013-02-02 20:37:58 +00006858 std::vector<MessageInfo> m_messages;
Phil Nash90a35942012-11-13 22:04:29 +00006859 AssertionInfo m_lastAssertionInfo;
Phil Nash0c1c9fa2015-09-27 03:28:14 -07006860 std::vector<SectionEndInfo> m_unfinishedSections;
Phil Nash7e346192015-11-03 08:00:43 +00006861 std::vector<ITracker*> m_activeSections;
6862 TrackerContext m_trackerContext;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006863 bool m_shouldReportUnexpected;
Phil Nasha695eb92012-08-13 07:46:10 +01006864 };
6865
Phil Nashab036682014-06-02 07:48:03 +01006866 IResultCapture& getResultCapture() {
6867 if( IResultCapture* capture = getCurrentContext().getResultCapture() )
6868 return *capture;
6869 else
6870 throw std::logic_error( "No result capture instance" );
6871 }
6872
Phil Nasha695eb92012-08-13 07:46:10 +01006873} // end namespace Catch
6874
Phil Nash7673a302012-11-15 22:15:41 +00006875// #included from: internal/catch_version.h
6876#define TWOBLUECUBES_CATCH_VERSION_H_INCLUDED
6877
6878namespace Catch {
6879
6880 // Versioning information
6881 struct Version {
Phil Nasha1fbfea2012-12-01 23:57:18 +00006882 Version( unsigned int _majorVersion,
6883 unsigned int _minorVersion,
Phil Nash21f7ef62015-06-29 18:05:23 +01006884 unsigned int _patchNumber,
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006885 char const * const _branchName,
Phil Nash21f7ef62015-06-29 18:05:23 +01006886 unsigned int _buildNumber );
Phil Nasha1fbfea2012-12-01 23:57:18 +00006887
Phil Nash9d469b62014-04-18 08:30:31 +01006888 unsigned int const majorVersion;
6889 unsigned int const minorVersion;
Phil Nash21f7ef62015-06-29 18:05:23 +01006890 unsigned int const patchNumber;
6891
6892 // buildNumber is only used if branchName is not null
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006893 char const * const branchName;
Phil Nash9d469b62014-04-18 08:30:31 +01006894 unsigned int const buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01006895
6896 friend std::ostream& operator << ( std::ostream& os, Version const& version );
Phil Nashdd26e882013-03-25 09:25:31 +00006897
Phil Nash503d5d02013-07-03 08:25:11 +01006898 private:
6899 void operator=( Version const& );
Phil Nash7673a302012-11-15 22:15:41 +00006900 };
6901
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02006902 inline Version libraryVersion();
Phil Nash7673a302012-11-15 22:15:41 +00006903}
6904
Phil Nash89d1e6c2011-05-24 08:23:02 +01006905#include <fstream>
6906#include <stdlib.h>
6907#include <limits>
6908
Phil Nash89d2a3f2012-05-16 15:09:17 +01006909namespace Catch {
6910
Phil Nashe73583d2015-08-07 17:30:34 +01006911 Ptr<IStreamingReporter> createReporter( std::string const& reporterName, Ptr<Config> const& config ) {
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006912 Ptr<IStreamingReporter> reporter = getRegistryHub().getReporterRegistry().create( reporterName, config.get() );
6913 if( !reporter ) {
6914 std::ostringstream oss;
6915 oss << "No reporter registered with name: '" << reporterName << "'";
6916 throw std::domain_error( oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01006917 }
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006918 return reporter;
6919 }
Phil Nash5bc030d2012-08-16 18:48:50 +01006920
Phil Nashe73583d2015-08-07 17:30:34 +01006921 Ptr<IStreamingReporter> makeReporter( Ptr<Config> const& config ) {
6922 std::vector<std::string> reporters = config->getReporterNames();
6923 if( reporters.empty() )
6924 reporters.push_back( "console" );
6925
6926 Ptr<IStreamingReporter> reporter;
6927 for( std::vector<std::string>::const_iterator it = reporters.begin(), itEnd = reporters.end();
6928 it != itEnd;
6929 ++it )
6930 reporter = addReporter( reporter, createReporter( *it, config ) );
6931 return reporter;
6932 }
Phil Nash7e346192015-11-03 08:00:43 +00006933 Ptr<IStreamingReporter> addListeners( Ptr<IConfig const> const& config, Ptr<IStreamingReporter> reporters ) {
Phil Nashe73583d2015-08-07 17:30:34 +01006934 IReporterRegistry::Listeners listeners = getRegistryHub().getReporterRegistry().getListeners();
6935 for( IReporterRegistry::Listeners::const_iterator it = listeners.begin(), itEnd = listeners.end();
6936 it != itEnd;
6937 ++it )
6938 reporters = addReporter(reporters, (*it)->create( ReporterConfig( config ) ) );
6939 return reporters;
6940 }
6941
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006942 Totals runTests( Ptr<Config> const& config ) {
6943
Phil Nash7e346192015-11-03 08:00:43 +00006944 Ptr<IConfig const> iconfig = config.get();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006945
Phil Nash7e346192015-11-03 08:00:43 +00006946 Ptr<IStreamingReporter> reporter = makeReporter( config );
6947 reporter = addListeners( iconfig, reporter );
6948
6949 RunContext context( iconfig, reporter );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006950
6951 Totals totals;
6952
6953 context.testGroupStarting( config->name(), 1, 1 );
6954
6955 TestSpec testSpec = config->testSpec();
6956 if( !testSpec.hasFilters() )
6957 testSpec = TestSpecParser( ITagAliasRegistry::get() ).parse( "~[.]" ).testSpec(); // All not hidden tests
6958
Phil Nash7e346192015-11-03 08:00:43 +00006959 std::vector<TestCase> const& allTestCases = getAllTestCasesSorted( *iconfig );
Phil Nashe73583d2015-08-07 17:30:34 +01006960 for( std::vector<TestCase>::const_iterator it = allTestCases.begin(), itEnd = allTestCases.end();
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006961 it != itEnd;
6962 ++it ) {
Phil Nash7e346192015-11-03 08:00:43 +00006963 if( !context.aborting() && matchTest( *it, testSpec, *iconfig ) )
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006964 totals += context.runTest( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01006965 else
6966 reporter->skipTest( *it );
Phil Nash5bc030d2012-08-16 18:48:50 +01006967 }
Phil Nash06e959b2012-05-25 08:52:05 +01006968
Phil Nash7e346192015-11-03 08:00:43 +00006969 context.testGroupEnded( iconfig->name(), totals, 1, 1 );
Phil Nash8b1b7cd2015-08-03 07:40:52 +01006970 return totals;
6971 }
Phil Nash56d5c422012-08-23 20:08:50 +01006972
Phil Nashe73583d2015-08-07 17:30:34 +01006973 void applyFilenamesAsTags( IConfig const& config ) {
6974 std::vector<TestCase> const& tests = getAllTestCasesSorted( config );
Phil Nashb971fe72015-07-02 08:21:38 +01006975 for(std::size_t i = 0; i < tests.size(); ++i ) {
6976 TestCase& test = const_cast<TestCase&>( tests[i] );
6977 std::set<std::string> tags = test.tags;
Phil Nash786959d2013-06-07 19:07:50 +01006978
Phil Nashb971fe72015-07-02 08:21:38 +01006979 std::string filename = test.lineInfo.file;
Phil Nashc1ca0fd2015-07-03 18:30:25 +01006980 std::string::size_type lastSlash = filename.find_last_of( "\\/" );
Phil Nashb971fe72015-07-02 08:21:38 +01006981 if( lastSlash != std::string::npos )
6982 filename = filename.substr( lastSlash+1 );
Phil Nash56d5c422012-08-23 20:08:50 +01006983
Phil Nashb971fe72015-07-02 08:21:38 +01006984 std::string::size_type lastDot = filename.find_last_of( "." );
6985 if( lastDot != std::string::npos )
6986 filename = filename.substr( 0, lastDot );
Phil Nash65cc14c2014-05-16 18:54:48 +01006987
Phil Nashe6b365d2015-07-07 08:25:15 +01006988 tags.insert( "#" + filename );
Phil Nashb971fe72015-07-02 08:21:38 +01006989 setTags( test, tags );
Phil Nash89d1e6c2011-05-24 08:23:02 +01006990 }
Phil Nashb971fe72015-07-02 08:21:38 +01006991 }
Phil Nash56d5c422012-08-23 20:08:50 +01006992
Phil Nashe54ac702014-10-21 07:25:26 +01006993 class Session : NonCopyable {
Phil Nash786959d2013-06-07 19:07:50 +01006994 static bool alreadyInstantiated;
Phil Nash56d5c422012-08-23 20:08:50 +01006995
Phil Nash786959d2013-06-07 19:07:50 +01006996 public:
Phil Nash56d5c422012-08-23 20:08:50 +01006997
Phil Nash786959d2013-06-07 19:07:50 +01006998 struct OnUnusedOptions { enum DoWhat { Ignore, Fail }; };
6999
7000 Session()
7001 : m_cli( makeCommandLineParser() ) {
7002 if( alreadyInstantiated ) {
7003 std::string msg = "Only one instance of Catch::Session can ever be used";
Phil Nash383d7c02014-10-02 19:08:19 +01007004 Catch::cerr() << msg << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01007005 throw std::logic_error( msg );
Phil Nash56d5c422012-08-23 20:08:50 +01007006 }
Phil Nash786959d2013-06-07 19:07:50 +01007007 alreadyInstantiated = true;
Phil Nash56d5c422012-08-23 20:08:50 +01007008 }
Phil Nash786959d2013-06-07 19:07:50 +01007009 ~Session() {
Phil Nash3b80af72012-08-09 07:47:30 +01007010 Catch::cleanUp();
Phil Nash89d1e6c2011-05-24 08:23:02 +01007011 }
7012
Phil Nash786959d2013-06-07 19:07:50 +01007013 void showHelp( std::string const& processName ) {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02007014 Catch::cout() << "\nCatch v" << libraryVersion() << "\n";
Phil Nash89d1e6c2011-05-24 08:23:02 +01007015
Phil Nash383d7c02014-10-02 19:08:19 +01007016 m_cli.usage( Catch::cout(), processName );
7017 Catch::cout() << "For more detail usage please see the project docs\n" << std::endl;
Phil Nash3b80af72012-08-09 07:47:30 +01007018 }
Phil Nash3b80af72012-08-09 07:47:30 +01007019
Phil Nashe5537842016-04-25 18:56:50 +01007020 int applyCommandLine( int argc, char const* const* const argv, OnUnusedOptions::DoWhat unusedOptionBehaviour = OnUnusedOptions::Fail ) {
Phil Nash786959d2013-06-07 19:07:50 +01007021 try {
Phil Nash91ef5f72013-12-20 19:06:26 +00007022 m_cli.setThrowOnUnrecognisedTokens( unusedOptionBehaviour == OnUnusedOptions::Fail );
Phil Nashe5537842016-04-25 18:56:50 +01007023 m_unusedTokens = m_cli.parseInto( Clara::argsToVector( argc, argv ), m_configData );
Phil Nash786959d2013-06-07 19:07:50 +01007024 if( m_configData.showHelp )
7025 showHelp( m_configData.processName );
7026 m_config.reset();
Phil Nash3b80af72012-08-09 07:47:30 +01007027 }
Phil Nash786959d2013-06-07 19:07:50 +01007028 catch( std::exception& ex ) {
Phil Nash46118712013-08-16 19:01:32 +01007029 {
7030 Colour colourGuard( Colour::Red );
Phil Nash21f7ef62015-06-29 18:05:23 +01007031 Catch::cerr()
7032 << "\nError(s) in input:\n"
7033 << Text( ex.what(), TextAttributes().setIndent(2) )
7034 << "\n\n";
Phil Nash46118712013-08-16 19:01:32 +01007035 }
Phil Nash383d7c02014-10-02 19:08:19 +01007036 m_cli.usage( Catch::cout(), m_configData.processName );
Phil Nash786959d2013-06-07 19:07:50 +01007037 return (std::numeric_limits<int>::max)();
7038 }
7039 return 0;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007040 }
Phil Nash89d2a3f2012-05-16 15:09:17 +01007041
Phil Nash786959d2013-06-07 19:07:50 +01007042 void useConfigData( ConfigData const& _configData ) {
7043 m_configData = _configData;
7044 m_config.reset();
7045 }
Phil Nash89d1e6c2011-05-24 08:23:02 +01007046
Phil Nashe5537842016-04-25 18:56:50 +01007047 int run( int argc, char const* const* const argv ) {
Phil Nash786959d2013-06-07 19:07:50 +01007048
7049 int returnCode = applyCommandLine( argc, argv );
7050 if( returnCode == 0 )
7051 returnCode = run();
7052 return returnCode;
7053 }
7054
7055 int run() {
7056 if( m_configData.showHelp )
7057 return 0;
7058
7059 try
7060 {
7061 config(); // Force config to be constructed
Phil Nash6a8e8ad2014-09-15 18:40:24 +01007062
Phil Nash8f66e342015-07-02 23:03:13 +01007063 seedRng( *m_config );
Phil Nash6a8e8ad2014-09-15 18:40:24 +01007064
Phil Nashe73583d2015-08-07 17:30:34 +01007065 if( m_configData.filenamesAsTags )
7066 applyFilenamesAsTags( *m_config );
Phil Nash786959d2013-06-07 19:07:50 +01007067
7068 // Handle list request
7069 if( Option<std::size_t> listed = list( config() ) )
7070 return static_cast<int>( *listed );
7071
Phil Nash8b1b7cd2015-08-03 07:40:52 +01007072 return static_cast<int>( runTests( m_config ).assertions.failed );
Phil Nash786959d2013-06-07 19:07:50 +01007073 }
7074 catch( std::exception& ex ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007075 Catch::cerr() << ex.what() << std::endl;
Phil Nash786959d2013-06-07 19:07:50 +01007076 return (std::numeric_limits<int>::max)();
7077 }
7078 }
7079
7080 Clara::CommandLine<ConfigData> const& cli() const {
7081 return m_cli;
7082 }
7083 std::vector<Clara::Parser::Token> const& unusedTokens() const {
7084 return m_unusedTokens;
7085 }
7086 ConfigData& configData() {
7087 return m_configData;
7088 }
7089 Config& config() {
7090 if( !m_config )
7091 m_config = new Config( m_configData );
7092 return *m_config;
7093 }
Phil Nash786959d2013-06-07 19:07:50 +01007094 private:
7095 Clara::CommandLine<ConfigData> m_cli;
7096 std::vector<Clara::Parser::Token> m_unusedTokens;
7097 ConfigData m_configData;
7098 Ptr<Config> m_config;
7099 };
7100
7101 bool Session::alreadyInstantiated = false;
Phil Nash89d1e6c2011-05-24 08:23:02 +01007102
7103} // end namespace Catch
7104
7105// #included from: catch_registry_hub.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007106#define TWOBLUECUBES_CATCH_REGISTRY_HUB_HPP_INCLUDED
Phil Nash371db8b2012-05-21 18:52:09 +01007107
Phil Nash89d1e6c2011-05-24 08:23:02 +01007108// #included from: catch_test_case_registry_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007109#define TWOBLUECUBES_CATCH_TEST_CASE_REGISTRY_IMPL_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +01007110
7111#include <vector>
7112#include <set>
Phil Nash3b80af72012-08-09 07:47:30 +01007113#include <sstream>
Phil Nash96304542014-09-15 23:32:13 +01007114#include <algorithm>
Phil Nash3b80af72012-08-09 07:47:30 +01007115
7116namespace Catch {
7117
Phil Nashe73583d2015-08-07 17:30:34 +01007118 struct RandomNumberGenerator {
Phil Nashe27c4ee2016-10-26 12:08:26 +01007119 typedef std::ptrdiff_t result_type;
Phil Nashac220282016-06-09 08:19:23 +01007120
7121 result_type operator()( result_type n ) const { return std::rand() % n; }
7122
Phil Nash3b2f2062017-01-11 16:43:56 +00007123#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nashac220282016-06-09 08:19:23 +01007124 static constexpr result_type min() { return 0; }
7125 static constexpr result_type max() { return 1000000; }
7126 result_type operator()() const { return std::rand() % max(); }
7127#endif
7128 template<typename V>
7129 static void shuffle( V& vector ) {
Phil Nash35f51052016-06-09 19:21:09 +01007130 RandomNumberGenerator rng;
Phil Nash3b2f2062017-01-11 16:43:56 +00007131#ifdef CATCH_CONFIG_CPP11_SHUFFLE
Phil Nash35f51052016-06-09 19:21:09 +01007132 std::shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01007133#else
Phil Nash35f51052016-06-09 19:21:09 +01007134 std::random_shuffle( vector.begin(), vector.end(), rng );
Phil Nashac220282016-06-09 08:19:23 +01007135#endif
7136 }
Phil Nashe73583d2015-08-07 17:30:34 +01007137 };
Phil Nashee3b2652014-09-18 18:25:10 +01007138
Phil Nashe73583d2015-08-07 17:30:34 +01007139 inline std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {
7140
7141 std::vector<TestCase> sorted = unsortedTestCases;
7142
7143 switch( config.runOrder() ) {
7144 case RunTests::InLexicographicalOrder:
Phil Nashac220282016-06-09 08:19:23 +01007145 std::sort( sorted.begin(), sorted.end() );
Phil Nashe73583d2015-08-07 17:30:34 +01007146 break;
7147 case RunTests::InRandomOrder:
7148 {
7149 seedRng( config );
Phil Nashac220282016-06-09 08:19:23 +01007150 RandomNumberGenerator::shuffle( sorted );
Phil Nashe73583d2015-08-07 17:30:34 +01007151 }
7152 break;
7153 case RunTests::InDeclarationOrder:
7154 // already in declaration order
7155 break;
7156 }
7157 return sorted;
7158 }
7159 bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {
7160 return testSpec.matches( testCase ) && ( config.allowThrows() || !testCase.throws() );
7161 }
Phil Nashe73583d2015-08-07 17:30:34 +01007162
7163 void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {
7164 std::set<TestCase> seenFunctions;
7165 for( std::vector<TestCase>::const_iterator it = functions.begin(), itEnd = functions.end();
7166 it != itEnd;
7167 ++it ) {
7168 std::pair<std::set<TestCase>::const_iterator, bool> prev = seenFunctions.insert( *it );
Phil Nashebf9f3b2016-05-10 19:09:59 +01007169 if( !prev.second ) {
7170 std::ostringstream ss;
7171
7172 ss << Colour( Colour::Red )
7173 << "error: TEST_CASE( \"" << it->name << "\" ) already defined.\n"
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007174 << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << '\n'
Phil Nashebf9f3b2016-05-10 19:09:59 +01007175 << "\tRedefined at " << it->getTestCaseInfo().lineInfo << std::endl;
7176
7177 throw std::runtime_error(ss.str());
Phil Nashe73583d2015-08-07 17:30:34 +01007178 }
7179 }
7180 }
7181
7182 std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {
7183 std::vector<TestCase> filtered;
Phil Nash8a05f462015-08-07 17:53:29 +01007184 filtered.reserve( testCases.size() );
7185 for( std::vector<TestCase>::const_iterator it = testCases.begin(), itEnd = testCases.end();
7186 it != itEnd;
7187 ++it )
7188 if( matchTest( *it, testSpec, config ) )
7189 filtered.push_back( *it );
Phil Nashe73583d2015-08-07 17:30:34 +01007190 return filtered;
7191 }
7192 std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {
7193 return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );
7194 }
7195
7196 class TestRegistry : public ITestCaseRegistry {
Phil Nash3b80af72012-08-09 07:47:30 +01007197 public:
Phil Nash981347b2015-12-09 18:11:48 +00007198 TestRegistry()
7199 : m_currentSortOrder( RunTests::InDeclarationOrder ),
7200 m_unnamedCount( 0 )
7201 {}
Phil Nash3b80af72012-08-09 07:47:30 +01007202 virtual ~TestRegistry();
7203
Phil Nash8defc712013-04-24 19:10:02 +01007204 virtual void registerTest( TestCase const& testCase ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00007205 std::string name = testCase.getTestCaseInfo().name;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007206 if( name.empty() ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007207 std::ostringstream oss;
Phil Nash93906752013-03-16 20:21:51 +00007208 oss << "Anonymous test case " << ++m_unnamedCount;
Phil Nasha1fbfea2012-12-01 23:57:18 +00007209 return registerTest( testCase.withName( oss.str() ) );
Phil Nash3b80af72012-08-09 07:47:30 +01007210 }
Phil Nashe73583d2015-08-07 17:30:34 +01007211 m_functions.push_back( testCase );
Phil Nash3b80af72012-08-09 07:47:30 +01007212 }
7213
Phil Nash8defc712013-04-24 19:10:02 +01007214 virtual std::vector<TestCase> const& getAllTests() const {
Phil Nashe73583d2015-08-07 17:30:34 +01007215 return m_functions;
Phil Nash3b80af72012-08-09 07:47:30 +01007216 }
Phil Nashe73583d2015-08-07 17:30:34 +01007217 virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const {
7218 if( m_sortedFunctions.empty() )
7219 enforceNoDuplicateTestCases( m_functions );
Phil Nash3b80af72012-08-09 07:47:30 +01007220
Phil Nashe73583d2015-08-07 17:30:34 +01007221 if( m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {
7222 m_sortedFunctions = sortTests( config, m_functions );
7223 m_currentSortOrder = config.runOrder();
Phil Nash3b80af72012-08-09 07:47:30 +01007224 }
Phil Nashe73583d2015-08-07 17:30:34 +01007225 return m_sortedFunctions;
Phil Nash92f08362014-12-22 20:18:05 +00007226 }
7227
7228 private:
Phil Nashe73583d2015-08-07 17:30:34 +01007229 std::vector<TestCase> m_functions;
7230 mutable RunTests::InWhatOrder m_currentSortOrder;
7231 mutable std::vector<TestCase> m_sortedFunctions;
Phil Nash3b80af72012-08-09 07:47:30 +01007232 size_t m_unnamedCount;
Phil Nash93a842e2015-07-13 06:36:07 +01007233 std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised
Phil Nash3b80af72012-08-09 07:47:30 +01007234 };
7235
7236 ///////////////////////////////////////////////////////////////////////////
7237
7238 class FreeFunctionTestCase : public SharedImpl<ITestCase> {
7239 public:
7240
7241 FreeFunctionTestCase( TestFunction fun ) : m_fun( fun ) {}
7242
7243 virtual void invoke() const {
7244 m_fun();
7245 }
7246
7247 private:
7248 virtual ~FreeFunctionTestCase();
7249
7250 TestFunction m_fun;
7251 };
7252
Phil Nash8defc712013-04-24 19:10:02 +01007253 inline std::string extractClassName( std::string const& classOrQualifiedMethodName ) {
Phil Nash90a35942012-11-13 22:04:29 +00007254 std::string className = classOrQualifiedMethodName;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007255 if( startsWith( className, '&' ) )
Phil Nash90a35942012-11-13 22:04:29 +00007256 {
7257 std::size_t lastColons = className.rfind( "::" );
7258 std::size_t penultimateColons = className.rfind( "::", lastColons-1 );
7259 if( penultimateColons == std::string::npos )
7260 penultimateColons = 1;
7261 className = className.substr( penultimateColons, lastColons-penultimateColons );
7262 }
7263 return className;
7264 }
7265
Phil Nash7e15d9b2015-11-20 16:59:14 +00007266 void registerTestCase
7267 ( ITestCase* testCase,
7268 char const* classOrQualifiedMethodName,
7269 NameAndDesc const& nameAndDesc,
7270 SourceLineInfo const& lineInfo ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007271
Phil Nash7e15d9b2015-11-20 16:59:14 +00007272 getMutableRegistryHub().registerTest
7273 ( makeTestCase
7274 ( testCase,
7275 extractClassName( classOrQualifiedMethodName ),
7276 nameAndDesc.name,
7277 nameAndDesc.description,
7278 lineInfo ) );
7279 }
7280 void registerTestCaseFunction
7281 ( TestFunction function,
7282 SourceLineInfo const& lineInfo,
7283 NameAndDesc const& nameAndDesc ) {
Phil Nashaa7123b2013-08-15 19:01:00 +01007284 registerTestCase( new FreeFunctionTestCase( function ), "", nameAndDesc, lineInfo );
Phil Nash3b80af72012-08-09 07:47:30 +01007285 }
7286
Phil Nash7e15d9b2015-11-20 16:59:14 +00007287 ///////////////////////////////////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007288
Phil Nash7e15d9b2015-11-20 16:59:14 +00007289 AutoReg::AutoReg
7290 ( TestFunction function,
7291 SourceLineInfo const& lineInfo,
7292 NameAndDesc const& nameAndDesc ) {
7293 registerTestCaseFunction( function, lineInfo, nameAndDesc );
Phil Nash3b80af72012-08-09 07:47:30 +01007294 }
7295
Phil Nash7e15d9b2015-11-20 16:59:14 +00007296 AutoReg::~AutoReg() {}
7297
Phil Nash3b80af72012-08-09 07:47:30 +01007298} // end namespace Catch
7299
7300// #included from: catch_reporter_registry.hpp
7301#define TWOBLUECUBES_CATCH_REPORTER_REGISTRY_HPP_INCLUDED
7302
7303#include <map>
7304
7305namespace Catch {
7306
7307 class ReporterRegistry : public IReporterRegistry {
7308
7309 public:
7310
Phil Nash19520152015-08-10 07:32:48 +01007311 virtual ~ReporterRegistry() CATCH_OVERRIDE {}
Phil Nash3b80af72012-08-09 07:47:30 +01007312
Phil Nash7e346192015-11-03 08:00:43 +00007313 virtual IStreamingReporter* create( std::string const& name, Ptr<IConfig const> const& config ) const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007314 FactoryMap::const_iterator it = m_factories.find( name );
7315 if( it == m_factories.end() )
Phil Nashb971fe72015-07-02 08:21:38 +01007316 return CATCH_NULL;
Phil Nash786959d2013-06-07 19:07:50 +01007317 return it->second->create( ReporterConfig( config ) );
Phil Nash3b80af72012-08-09 07:47:30 +01007318 }
7319
Phil Nashe73583d2015-08-07 17:30:34 +01007320 void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007321 m_factories.insert( std::make_pair( name, factory ) );
7322 }
Phil Nashe73583d2015-08-07 17:30:34 +01007323 void registerListener( Ptr<IReporterFactory> const& factory ) {
7324 m_listeners.push_back( factory );
7325 }
Phil Nash3b80af72012-08-09 07:47:30 +01007326
Phil Nash19520152015-08-10 07:32:48 +01007327 virtual FactoryMap const& getFactories() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007328 return m_factories;
7329 }
Phil Nash19520152015-08-10 07:32:48 +01007330 virtual Listeners const& getListeners() const CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007331 return m_listeners;
7332 }
Phil Nash3b80af72012-08-09 07:47:30 +01007333
7334 private:
7335 FactoryMap m_factories;
Phil Nashe73583d2015-08-07 17:30:34 +01007336 Listeners m_listeners;
Phil Nash3b80af72012-08-09 07:47:30 +01007337 };
7338}
7339
7340// #included from: catch_exception_translator_registry.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007341#define TWOBLUECUBES_CATCH_EXCEPTION_TRANSLATOR_REGISTRY_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007342
7343#ifdef __OBJC__
7344#import "Foundation/Foundation.h"
7345#endif
7346
7347namespace Catch {
7348
7349 class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {
7350 public:
7351 ~ExceptionTranslatorRegistry() {
7352 deleteAll( m_translators );
7353 }
7354
7355 virtual void registerTranslator( const IExceptionTranslator* translator ) {
7356 m_translators.push_back( translator );
7357 }
7358
7359 virtual std::string translateActiveException() const {
7360 try {
7361#ifdef __OBJC__
7362 // In Objective-C try objective-c exceptions first
7363 @try {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007364 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007365 }
7366 @catch (NSException *exception) {
Phil Nash13f98432014-12-12 08:11:18 +00007367 return Catch::toString( [exception description] );
Phil Nash3b80af72012-08-09 07:47:30 +01007368 }
7369#else
Phil Nashe4fa62a2015-11-18 08:39:54 +00007370 return tryTranslators();
Phil Nash3b80af72012-08-09 07:47:30 +01007371#endif
7372 }
Phil Nashab036682014-06-02 07:48:03 +01007373 catch( TestFailureException& ) {
7374 throw;
7375 }
Phil Nash3b80af72012-08-09 07:47:30 +01007376 catch( std::exception& ex ) {
7377 return ex.what();
7378 }
7379 catch( std::string& msg ) {
7380 return msg;
7381 }
7382 catch( const char* msg ) {
7383 return msg;
7384 }
7385 catch(...) {
Phil Nashe4fa62a2015-11-18 08:39:54 +00007386 return "Unknown exception";
Phil Nash3b80af72012-08-09 07:47:30 +01007387 }
7388 }
7389
Phil Nashe4fa62a2015-11-18 08:39:54 +00007390 std::string tryTranslators() const {
7391 if( m_translators.empty() )
7392 throw;
7393 else
7394 return m_translators[0]->translate( m_translators.begin()+1, m_translators.end() );
Phil Nash3b80af72012-08-09 07:47:30 +01007395 }
7396
7397 private:
7398 std::vector<const IExceptionTranslator*> m_translators;
7399 };
7400}
7401
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02007402// #included from: catch_tag_alias_registry.h
7403#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_H_INCLUDED
7404
7405#include <map>
7406
7407namespace Catch {
7408
7409 class TagAliasRegistry : public ITagAliasRegistry {
7410 public:
7411 virtual ~TagAliasRegistry();
7412 virtual Option<TagAlias> find( std::string const& alias ) const;
7413 virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const;
7414 void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );
7415
7416 private:
7417 std::map<std::string, TagAlias> m_registry;
7418 };
7419
7420} // end namespace Catch
7421
Phil Nash3b80af72012-08-09 07:47:30 +01007422namespace Catch {
7423
7424 namespace {
7425
7426 class RegistryHub : public IRegistryHub, public IMutableRegistryHub {
7427
Phil Nash8defc712013-04-24 19:10:02 +01007428 RegistryHub( RegistryHub const& );
7429 void operator=( RegistryHub const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007430
7431 public: // IRegistryHub
7432 RegistryHub() {
7433 }
Phil Nash19520152015-08-10 07:32:48 +01007434 virtual IReporterRegistry const& getReporterRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007435 return m_reporterRegistry;
7436 }
Phil Nash19520152015-08-10 07:32:48 +01007437 virtual ITestCaseRegistry const& getTestCaseRegistry() const CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007438 return m_testCaseRegistry;
7439 }
Phil Nash19520152015-08-10 07:32:48 +01007440 virtual IExceptionTranslatorRegistry& getExceptionTranslatorRegistry() CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007441 return m_exceptionTranslatorRegistry;
7442 }
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02007443 virtual ITagAliasRegistry const& getTagAliasRegistry() const CATCH_OVERRIDE {
7444 return m_tagAliasRegistry;
7445 }
Phil Nash3b80af72012-08-09 07:47:30 +01007446
7447 public: // IMutableRegistryHub
Phil Nash19520152015-08-10 07:32:48 +01007448 virtual void registerReporter( std::string const& name, Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007449 m_reporterRegistry.registerReporter( name, factory );
7450 }
Phil Nash19520152015-08-10 07:32:48 +01007451 virtual void registerListener( Ptr<IReporterFactory> const& factory ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01007452 m_reporterRegistry.registerListener( factory );
7453 }
Phil Nash19520152015-08-10 07:32:48 +01007454 virtual void registerTest( TestCase const& testInfo ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007455 m_testCaseRegistry.registerTest( testInfo );
7456 }
Phil Nash19520152015-08-10 07:32:48 +01007457 virtual void registerTranslator( const IExceptionTranslator* translator ) CATCH_OVERRIDE {
Phil Nash3b80af72012-08-09 07:47:30 +01007458 m_exceptionTranslatorRegistry.registerTranslator( translator );
7459 }
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02007460 virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) CATCH_OVERRIDE {
7461 m_tagAliasRegistry.add( alias, tag, lineInfo );
7462 }
Phil Nash3b80af72012-08-09 07:47:30 +01007463
7464 private:
7465 TestRegistry m_testCaseRegistry;
7466 ReporterRegistry m_reporterRegistry;
7467 ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02007468 TagAliasRegistry m_tagAliasRegistry;
Phil Nash3b80af72012-08-09 07:47:30 +01007469 };
7470
7471 // Single, global, instance
7472 inline RegistryHub*& getTheRegistryHub() {
Phil Nashb971fe72015-07-02 08:21:38 +01007473 static RegistryHub* theRegistryHub = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007474 if( !theRegistryHub )
7475 theRegistryHub = new RegistryHub();
7476 return theRegistryHub;
7477 }
7478 }
7479
7480 IRegistryHub& getRegistryHub() {
7481 return *getTheRegistryHub();
7482 }
7483 IMutableRegistryHub& getMutableRegistryHub() {
7484 return *getTheRegistryHub();
7485 }
7486 void cleanUp() {
7487 delete getTheRegistryHub();
Phil Nashb971fe72015-07-02 08:21:38 +01007488 getTheRegistryHub() = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007489 cleanUpContext();
7490 }
Phil Nashce612bf2012-11-01 08:27:09 +00007491 std::string translateActiveException() {
7492 return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();
7493 }
Phil Nash3b80af72012-08-09 07:47:30 +01007494
7495} // end namespace Catch
Matt Wozniskif29c8982012-09-17 01:42:29 -04007496
Phil Nash3b80af72012-08-09 07:47:30 +01007497// #included from: catch_notimplemented_exception.hpp
7498#define TWOBLUECUBES_CATCH_NOTIMPLEMENTED_EXCEPTION_HPP_INCLUDED
7499
Phil Nashd08cee22017-02-13 16:15:42 +00007500#include <sstream>
Phil Nash3b80af72012-08-09 07:47:30 +01007501
7502namespace Catch {
7503
Phil Nash8defc712013-04-24 19:10:02 +01007504 NotImplementedException::NotImplementedException( SourceLineInfo const& lineInfo )
Phil Nash3b80af72012-08-09 07:47:30 +01007505 : m_lineInfo( lineInfo ) {
7506 std::ostringstream oss;
Phil Nash2e7d9662013-01-16 09:44:43 +00007507 oss << lineInfo << ": function ";
Phil Nash3b80af72012-08-09 07:47:30 +01007508 oss << "not implemented";
7509 m_what = oss.str();
7510 }
7511
Phil Nashd7e17902014-04-18 08:49:35 +01007512 const char* NotImplementedException::what() const CATCH_NOEXCEPT {
Phil Nash3b80af72012-08-09 07:47:30 +01007513 return m_what.c_str();
7514 }
7515
7516} // end namespace Catch
7517
7518// #included from: catch_context_impl.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04007519#define TWOBLUECUBES_CATCH_CONTEXT_IMPL_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007520
Phil Nash3649fdf2013-12-03 18:53:55 +00007521// #included from: catch_stream.hpp
7522#define TWOBLUECUBES_CATCH_STREAM_HPP_INCLUDED
7523
Phil Nash3649fdf2013-12-03 18:53:55 +00007524#include <stdexcept>
7525#include <cstdio>
Phil Nash383d7c02014-10-02 19:08:19 +01007526#include <iostream>
Phil Nash3649fdf2013-12-03 18:53:55 +00007527
7528namespace Catch {
7529
7530 template<typename WriterF, size_t bufferSize=256>
7531 class StreamBufImpl : public StreamBufBase {
7532 char data[bufferSize];
7533 WriterF m_writer;
7534
7535 public:
7536 StreamBufImpl() {
7537 setp( data, data + sizeof(data) );
7538 }
7539
Phil Nashd7e17902014-04-18 08:49:35 +01007540 ~StreamBufImpl() CATCH_NOEXCEPT {
Phil Nash3649fdf2013-12-03 18:53:55 +00007541 sync();
7542 }
7543
7544 private:
7545 int overflow( int c ) {
7546 sync();
7547
7548 if( c != EOF ) {
7549 if( pbase() == epptr() )
7550 m_writer( std::string( 1, static_cast<char>( c ) ) );
7551 else
7552 sputc( static_cast<char>( c ) );
7553 }
7554 return 0;
7555 }
7556
7557 int sync() {
7558 if( pbase() != pptr() ) {
7559 m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );
7560 setp( pbase(), epptr() );
7561 }
7562 return 0;
7563 }
7564 };
7565
7566 ///////////////////////////////////////////////////////////////////////////
7567
Phil Nash7e346192015-11-03 08:00:43 +00007568 FileStream::FileStream( std::string const& filename ) {
7569 m_ofs.open( filename.c_str() );
7570 if( m_ofs.fail() ) {
7571 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01007572 oss << "Unable to open file: '" << filename << '\'';
Phil Nash7e346192015-11-03 08:00:43 +00007573 throw std::domain_error( oss.str() );
7574 }
7575 }
7576
7577 std::ostream& FileStream::stream() const {
7578 return m_ofs;
7579 }
7580
Phil Nash3649fdf2013-12-03 18:53:55 +00007581 struct OutputDebugWriter {
7582
7583 void operator()( std::string const&str ) {
7584 writeToDebugConsole( str );
7585 }
7586 };
7587
Phil Nash7e346192015-11-03 08:00:43 +00007588 DebugOutStream::DebugOutStream()
7589 : m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),
7590 m_os( m_streamBuf.get() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007591 {}
7592
Phil Nash7e346192015-11-03 08:00:43 +00007593 std::ostream& DebugOutStream::stream() const {
7594 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007595 }
Phil Nash383d7c02014-10-02 19:08:19 +01007596
Phil Nash7e346192015-11-03 08:00:43 +00007597 // Store the streambuf from cout up-front because
7598 // cout may get redirected when running tests
7599 CoutStream::CoutStream()
7600 : m_os( Catch::cout().rdbuf() )
Phil Nash3649fdf2013-12-03 18:53:55 +00007601 {}
7602
Phil Nash7e346192015-11-03 08:00:43 +00007603 std::ostream& CoutStream::stream() const {
7604 return m_os;
Phil Nash3649fdf2013-12-03 18:53:55 +00007605 }
Phil Nash383d7c02014-10-02 19:08:19 +01007606
Phil Nashfdc42d02015-12-04 10:19:08 +00007607#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions
Phil Nash383d7c02014-10-02 19:08:19 +01007608 std::ostream& cout() {
7609 return std::cout;
7610 }
7611 std::ostream& cerr() {
7612 return std::cerr;
7613 }
7614#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00007615}
7616
Phil Nash3b80af72012-08-09 07:47:30 +01007617namespace Catch {
7618
7619 class Context : public IMutableContext {
7620
Phil Nashb971fe72015-07-02 08:21:38 +01007621 Context() : m_config( CATCH_NULL ), m_runner( CATCH_NULL ), m_resultCapture( CATCH_NULL ) {}
Phil Nash8defc712013-04-24 19:10:02 +01007622 Context( Context const& );
7623 void operator=( Context const& );
Phil Nash3b80af72012-08-09 07:47:30 +01007624
Martin Hořeňovský9a566092017-01-20 12:49:59 +01007625 public:
7626 virtual ~Context() {
7627 deleteAllValues( m_generatorsByTestName );
7628 }
7629
Phil Nash3b80af72012-08-09 07:47:30 +01007630 public: // IContext
Phil Nash9241e432014-05-20 18:50:59 +01007631 virtual IResultCapture* getResultCapture() {
7632 return m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007633 }
Phil Nash9241e432014-05-20 18:50:59 +01007634 virtual IRunner* getRunner() {
7635 return m_runner;
Phil Nash3b80af72012-08-09 07:47:30 +01007636 }
Phil Nash8defc712013-04-24 19:10:02 +01007637 virtual size_t getGeneratorIndex( std::string const& fileInfo, size_t totalSize ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007638 return getGeneratorsForCurrentTest()
7639 .getGeneratorInfo( fileInfo, totalSize )
7640 .getCurrentIndex();
7641 }
7642 virtual bool advanceGeneratorsForCurrentTest() {
7643 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7644 return generators && generators->moveNext();
7645 }
7646
Phil Nash786959d2013-06-07 19:07:50 +01007647 virtual Ptr<IConfig const> getConfig() const {
Phil Nash3b80af72012-08-09 07:47:30 +01007648 return m_config;
7649 }
7650
7651 public: // IMutableContext
7652 virtual void setResultCapture( IResultCapture* resultCapture ) {
7653 m_resultCapture = resultCapture;
7654 }
7655 virtual void setRunner( IRunner* runner ) {
7656 m_runner = runner;
7657 }
Phil Nash786959d2013-06-07 19:07:50 +01007658 virtual void setConfig( Ptr<IConfig const> const& config ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007659 m_config = config;
7660 }
7661
7662 friend IMutableContext& getCurrentMutableContext();
7663
7664 private:
7665 IGeneratorsForTest* findGeneratorsForCurrentTest() {
Phil Nash9241e432014-05-20 18:50:59 +01007666 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007667
7668 std::map<std::string, IGeneratorsForTest*>::const_iterator it =
Phil Nasha806c3e2015-03-04 08:23:40 +00007669 m_generatorsByTestName.find( testName );
Phil Nash3b80af72012-08-09 07:47:30 +01007670 return it != m_generatorsByTestName.end()
Phil Nash8a52a392013-07-25 08:12:03 +01007671 ? it->second
Phil Nashb971fe72015-07-02 08:21:38 +01007672 : CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007673 }
7674
7675 IGeneratorsForTest& getGeneratorsForCurrentTest() {
7676 IGeneratorsForTest* generators = findGeneratorsForCurrentTest();
7677 if( !generators ) {
Phil Nash9241e432014-05-20 18:50:59 +01007678 std::string testName = getResultCapture()->getCurrentTestName();
Phil Nash3b80af72012-08-09 07:47:30 +01007679 generators = createGeneratorsForTest();
7680 m_generatorsByTestName.insert( std::make_pair( testName, generators ) );
7681 }
7682 return *generators;
7683 }
7684
7685 private:
Phil Nash93a945c2013-10-23 15:35:07 +01007686 Ptr<IConfig const> m_config;
Phil Nash3b80af72012-08-09 07:47:30 +01007687 IRunner* m_runner;
7688 IResultCapture* m_resultCapture;
Phil Nash3b80af72012-08-09 07:47:30 +01007689 std::map<std::string, IGeneratorsForTest*> m_generatorsByTestName;
7690 };
7691
7692 namespace {
Phil Nashb971fe72015-07-02 08:21:38 +01007693 Context* currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007694 }
7695 IMutableContext& getCurrentMutableContext() {
7696 if( !currentContext )
7697 currentContext = new Context();
7698 return *currentContext;
7699 }
7700 IContext& getCurrentContext() {
7701 return getCurrentMutableContext();
7702 }
7703
Phil Nash3b80af72012-08-09 07:47:30 +01007704 void cleanUpContext() {
7705 delete currentContext;
Phil Nashb971fe72015-07-02 08:21:38 +01007706 currentContext = CATCH_NULL;
Phil Nash3b80af72012-08-09 07:47:30 +01007707 }
7708}
Matt Wozniskif29c8982012-09-17 01:42:29 -04007709
Phil Nash3b80af72012-08-09 07:47:30 +01007710// #included from: catch_console_colour_impl.hpp
7711#define TWOBLUECUBES_CATCH_CONSOLE_COLOUR_IMPL_HPP_INCLUDED
7712
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01007713// #included from: catch_errno_guard.hpp
7714#define TWOBLUECUBES_CATCH_ERRNO_GUARD_HPP_INCLUDED
7715
7716#include <cerrno>
7717
7718namespace Catch {
7719
7720 class ErrnoGuard {
7721 public:
7722 ErrnoGuard():m_oldErrno(errno){}
7723 ~ErrnoGuard() { errno = m_oldErrno; }
7724 private:
7725 int m_oldErrno;
7726 };
7727
7728}
7729
Phil Nashe54ac702014-10-21 07:25:26 +01007730namespace Catch {
7731 namespace {
Phil Nash12c16ff2013-04-05 20:58:01 +01007732
Phil Nashe54ac702014-10-21 07:25:26 +01007733 struct IColourImpl {
7734 virtual ~IColourImpl() {}
7735 virtual void use( Colour::Code _colourCode ) = 0;
7736 };
7737
7738 struct NoColourImpl : IColourImpl {
7739 void use( Colour::Code ) {}
7740
7741 static IColourImpl* instance() {
7742 static NoColourImpl s_instance;
7743 return &s_instance;
7744 }
7745 };
7746
7747 } // anon namespace
7748} // namespace Catch
7749
7750#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )
7751# ifdef CATCH_PLATFORM_WINDOWS
7752# define CATCH_CONFIG_COLOUR_WINDOWS
7753# else
7754# define CATCH_CONFIG_COLOUR_ANSI
7755# endif
7756#endif
7757
7758#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007759
Phil Nash3b80af72012-08-09 07:47:30 +01007760namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007761namespace {
Phil Nash3b80af72012-08-09 07:47:30 +01007762
Phil Nashe54ac702014-10-21 07:25:26 +01007763 class Win32ColourImpl : public IColourImpl {
Phil Nash3b80af72012-08-09 07:47:30 +01007764 public:
Phil Nash12c16ff2013-04-05 20:58:01 +01007765 Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )
Phil Nash3b80af72012-08-09 07:47:30 +01007766 {
Phil Nash12c16ff2013-04-05 20:58:01 +01007767 CONSOLE_SCREEN_BUFFER_INFO csbiInfo;
7768 GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );
Phil Nash584032d2015-07-06 06:22:28 +01007769 originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );
7770 originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );
Phil Nash3b80af72012-08-09 07:47:30 +01007771 }
Phil Nash3b80af72012-08-09 07:47:30 +01007772
Phil Nash12c16ff2013-04-05 20:58:01 +01007773 virtual void use( Colour::Code _colourCode ) {
7774 switch( _colourCode ) {
Phil Nash584032d2015-07-06 06:22:28 +01007775 case Colour::None: return setTextAttribute( originalForegroundAttributes );
Phil Nash12c16ff2013-04-05 20:58:01 +01007776 case Colour::White: return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
7777 case Colour::Red: return setTextAttribute( FOREGROUND_RED );
7778 case Colour::Green: return setTextAttribute( FOREGROUND_GREEN );
7779 case Colour::Blue: return setTextAttribute( FOREGROUND_BLUE );
7780 case Colour::Cyan: return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );
7781 case Colour::Yellow: return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );
7782 case Colour::Grey: return setTextAttribute( 0 );
Phil Nash3b80af72012-08-09 07:47:30 +01007783
Phil Nash12c16ff2013-04-05 20:58:01 +01007784 case Colour::LightGrey: return setTextAttribute( FOREGROUND_INTENSITY );
7785 case Colour::BrightRed: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );
7786 case Colour::BrightGreen: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );
Phil Nash23520432013-06-28 14:11:28 +01007787 case Colour::BrightWhite: return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );
Phil Nash3b80af72012-08-09 07:47:30 +01007788
Phil Nash12c16ff2013-04-05 20:58:01 +01007789 case Colour::Bright: throw std::logic_error( "not a colour" );
7790 }
Phil Nash3b80af72012-08-09 07:47:30 +01007791 }
Phil Nash3b80af72012-08-09 07:47:30 +01007792
7793 private:
Phil Nash12c16ff2013-04-05 20:58:01 +01007794 void setTextAttribute( WORD _textAttribute ) {
Phil Nash584032d2015-07-06 06:22:28 +01007795 SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );
Phil Nash3b80af72012-08-09 07:47:30 +01007796 }
Phil Nash12c16ff2013-04-05 20:58:01 +01007797 HANDLE stdoutHandle;
Phil Nash584032d2015-07-06 06:22:28 +01007798 WORD originalForegroundAttributes;
7799 WORD originalBackgroundAttributes;
Phil Nash3b80af72012-08-09 07:47:30 +01007800 };
7801
Phil Nashe54ac702014-10-21 07:25:26 +01007802 IColourImpl* platformColourInstance() {
Phil Nash20cad7c2014-04-15 18:44:37 +01007803 static Win32ColourImpl s_instance;
Phil Nashae5ee2c2016-02-29 08:17:18 +00007804
7805 Ptr<IConfig const> config = getCurrentContext().getConfig();
7806 UseColour::YesOrNo colourMode = config
7807 ? config->useColour()
7808 : UseColour::Auto;
7809 if( colourMode == UseColour::Auto )
7810 colourMode = !isDebuggerActive()
7811 ? UseColour::Yes
7812 : UseColour::No;
7813 return colourMode == UseColour::Yes
7814 ? &s_instance
7815 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007816 }
Phil Nash3df6c0d2013-03-11 18:38:29 +00007817
7818} // end anon namespace
Phil Nash3b80af72012-08-09 07:47:30 +01007819} // end namespace Catch
7820
Phil Nashe54ac702014-10-21 07:25:26 +01007821#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////
Phil Nashce612bf2012-11-01 08:27:09 +00007822
7823#include <unistd.h>
7824
7825namespace Catch {
Phil Nash3df6c0d2013-03-11 18:38:29 +00007826namespace {
Phil Nashce612bf2012-11-01 08:27:09 +00007827
7828 // use POSIX/ ANSI console terminal codes
Phil Nash12c16ff2013-04-05 20:58:01 +01007829 // Thanks to Adam Strzelecki for original contribution
7830 // (http://github.com/nanoant)
Phil Nashce612bf2012-11-01 08:27:09 +00007831 // https://github.com/philsquared/Catch/pull/131
Phil Nashe54ac702014-10-21 07:25:26 +01007832 class PosixColourImpl : public IColourImpl {
Phil Nash12c16ff2013-04-05 20:58:01 +01007833 public:
7834 virtual void use( Colour::Code _colourCode ) {
7835 switch( _colourCode ) {
7836 case Colour::None:
7837 case Colour::White: return setColour( "[0m" );
7838 case Colour::Red: return setColour( "[0;31m" );
7839 case Colour::Green: return setColour( "[0;32m" );
Phil Nash3b2f2062017-01-11 16:43:56 +00007840 case Colour::Blue: return setColour( "[0;34m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007841 case Colour::Cyan: return setColour( "[0;36m" );
7842 case Colour::Yellow: return setColour( "[0;33m" );
7843 case Colour::Grey: return setColour( "[1;30m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007844
Phil Nash12c16ff2013-04-05 20:58:01 +01007845 case Colour::LightGrey: return setColour( "[0;37m" );
7846 case Colour::BrightRed: return setColour( "[1;31m" );
Phil Nash243f2d22013-04-12 10:43:06 +01007847 case Colour::BrightGreen: return setColour( "[1;32m" );
Phil Nash12c16ff2013-04-05 20:58:01 +01007848 case Colour::BrightWhite: return setColour( "[1;37m" );
Phil Nashce612bf2012-11-01 08:27:09 +00007849
Phil Nash12c16ff2013-04-05 20:58:01 +01007850 case Colour::Bright: throw std::logic_error( "not a colour" );
Phil Nashce612bf2012-11-01 08:27:09 +00007851 }
7852 }
Phil Nashe54ac702014-10-21 07:25:26 +01007853 static IColourImpl* instance() {
7854 static PosixColourImpl s_instance;
7855 return &s_instance;
7856 }
7857
Phil Nash12c16ff2013-04-05 20:58:01 +01007858 private:
7859 void setColour( const char* _escapeCode ) {
Phil Nash383d7c02014-10-02 19:08:19 +01007860 Catch::cout() << '\033' << _escapeCode;
Phil Nash3df6c0d2013-03-11 18:38:29 +00007861 }
7862 };
7863
Phil Nashe54ac702014-10-21 07:25:26 +01007864 IColourImpl* platformColourInstance() {
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01007865 ErrnoGuard guard;
Phil Nasha806c3e2015-03-04 08:23:40 +00007866 Ptr<IConfig const> config = getCurrentContext().getConfig();
Phil Nashae5ee2c2016-02-29 08:17:18 +00007867 UseColour::YesOrNo colourMode = config
7868 ? config->useColour()
7869 : UseColour::Auto;
7870 if( colourMode == UseColour::Auto )
7871 colourMode = (!isDebuggerActive() && isatty(STDOUT_FILENO) )
7872 ? UseColour::Yes
7873 : UseColour::No;
7874 return colourMode == UseColour::Yes
Phil Nashe54ac702014-10-21 07:25:26 +01007875 ? PosixColourImpl::instance()
7876 : NoColourImpl::instance();
Phil Nash20cad7c2014-04-15 18:44:37 +01007877 }
Phil Nashce612bf2012-11-01 08:27:09 +00007878
Phil Nash12c16ff2013-04-05 20:58:01 +01007879} // end anon namespace
7880} // end namespace Catch
Phil Nash3b80af72012-08-09 07:47:30 +01007881
Phil Nashe54ac702014-10-21 07:25:26 +01007882#else // not Windows or ANSI ///////////////////////////////////////////////
Phil Nash3b80af72012-08-09 07:47:30 +01007883
7884namespace Catch {
7885
Phil Nashe54ac702014-10-21 07:25:26 +01007886 static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }
Phil Nash20cad7c2014-04-15 18:44:37 +01007887
Phil Nashe54ac702014-10-21 07:25:26 +01007888} // end namespace Catch
7889
7890#endif // Windows/ ANSI/ None
7891
7892namespace Catch {
Phil Nash3b80af72012-08-09 07:47:30 +01007893
Phil Nashce562092014-07-09 07:40:37 +01007894 Colour::Colour( Code _colourCode ) : m_moved( false ) { use( _colourCode ); }
7895 Colour::Colour( Colour const& _other ) : m_moved( false ) { const_cast<Colour&>( _other ).m_moved = true; }
7896 Colour::~Colour(){ if( !m_moved ) use( None ); }
Phil Nash3b80af72012-08-09 07:47:30 +01007897
Phil Nashe54ac702014-10-21 07:25:26 +01007898 void Colour::use( Code _colourCode ) {
Phil Nashae5ee2c2016-02-29 08:17:18 +00007899 static IColourImpl* impl = platformColourInstance();
Phil Nashe54ac702014-10-21 07:25:26 +01007900 impl->use( _colourCode );
Phil Nash20cad7c2014-04-15 18:44:37 +01007901 }
Phil Nash3b80af72012-08-09 07:47:30 +01007902
7903} // end namespace Catch
7904
Phil Nash3b80af72012-08-09 07:47:30 +01007905// #included from: catch_generators_impl.hpp
7906#define TWOBLUECUBES_CATCH_GENERATORS_IMPL_HPP_INCLUDED
7907
7908#include <vector>
7909#include <string>
7910#include <map>
7911
7912namespace Catch {
7913
7914 struct GeneratorInfo : IGeneratorInfo {
7915
7916 GeneratorInfo( std::size_t size )
7917 : m_size( size ),
7918 m_currentIndex( 0 )
7919 {}
7920
7921 bool moveNext() {
7922 if( ++m_currentIndex == m_size ) {
7923 m_currentIndex = 0;
7924 return false;
7925 }
7926 return true;
7927 }
7928
7929 std::size_t getCurrentIndex() const {
7930 return m_currentIndex;
7931 }
7932
7933 std::size_t m_size;
7934 std::size_t m_currentIndex;
7935 };
7936
7937 ///////////////////////////////////////////////////////////////////////////
7938
7939 class GeneratorsForTest : public IGeneratorsForTest {
7940
7941 public:
7942 ~GeneratorsForTest() {
7943 deleteAll( m_generatorsInOrder );
7944 }
7945
Phil Nash8defc712013-04-24 19:10:02 +01007946 IGeneratorInfo& getGeneratorInfo( std::string const& fileInfo, std::size_t size ) {
Phil Nash3b80af72012-08-09 07:47:30 +01007947 std::map<std::string, IGeneratorInfo*>::const_iterator it = m_generatorsByName.find( fileInfo );
7948 if( it == m_generatorsByName.end() ) {
7949 IGeneratorInfo* info = new GeneratorInfo( size );
7950 m_generatorsByName.insert( std::make_pair( fileInfo, info ) );
7951 m_generatorsInOrder.push_back( info );
7952 return *info;
7953 }
7954 return *it->second;
7955 }
7956
7957 bool moveNext() {
7958 std::vector<IGeneratorInfo*>::const_iterator it = m_generatorsInOrder.begin();
7959 std::vector<IGeneratorInfo*>::const_iterator itEnd = m_generatorsInOrder.end();
7960 for(; it != itEnd; ++it ) {
7961 if( (*it)->moveNext() )
7962 return true;
7963 }
7964 return false;
7965 }
7966
7967 private:
7968 std::map<std::string, IGeneratorInfo*> m_generatorsByName;
7969 std::vector<IGeneratorInfo*> m_generatorsInOrder;
7970 };
7971
7972 IGeneratorsForTest* createGeneratorsForTest()
7973 {
7974 return new GeneratorsForTest();
7975 }
7976
7977} // end namespace Catch
7978
Phil Nashce612bf2012-11-01 08:27:09 +00007979// #included from: catch_assertionresult.hpp
7980#define TWOBLUECUBES_CATCH_ASSERTIONRESULT_HPP_INCLUDED
Phil Nash3b80af72012-08-09 07:47:30 +01007981
7982namespace Catch {
7983
Phil Nash8defc712013-04-24 19:10:02 +01007984 AssertionInfo::AssertionInfo( std::string const& _macroName,
7985 SourceLineInfo const& _lineInfo,
7986 std::string const& _capturedExpression,
Phil Nash90a35942012-11-13 22:04:29 +00007987 ResultDisposition::Flags _resultDisposition )
7988 : macroName( _macroName ),
7989 lineInfo( _lineInfo ),
7990 capturedExpression( _capturedExpression ),
7991 resultDisposition( _resultDisposition )
Phil Nash786959d2013-06-07 19:07:50 +01007992 {}
Phil Nash90a35942012-11-13 22:04:29 +00007993
Phil Nashce612bf2012-11-01 08:27:09 +00007994 AssertionResult::AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01007995
Phil Nash8defc712013-04-24 19:10:02 +01007996 AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )
Phil Nashce612bf2012-11-01 08:27:09 +00007997 : m_info( info ),
7998 m_resultData( data )
7999 {}
Phil Nash3b80af72012-08-09 07:47:30 +01008000
Phil Nashce612bf2012-11-01 08:27:09 +00008001 AssertionResult::~AssertionResult() {}
Phil Nash3b80af72012-08-09 07:47:30 +01008002
Phil Nash90a35942012-11-13 22:04:29 +00008003 // Result was a success
8004 bool AssertionResult::succeeded() const {
8005 return Catch::isOk( m_resultData.resultType );
8006 }
8007
8008 // Result was a success, or failure is suppressed
8009 bool AssertionResult::isOk() const {
8010 return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );
Phil Nash3b80af72012-08-09 07:47:30 +01008011 }
8012
Phil Nashce612bf2012-11-01 08:27:09 +00008013 ResultWas::OfType AssertionResult::getResultType() const {
8014 return m_resultData.resultType;
Phil Nash3b80af72012-08-09 07:47:30 +01008015 }
8016
Phil Nashce612bf2012-11-01 08:27:09 +00008017 bool AssertionResult::hasExpression() const {
8018 return !m_info.capturedExpression.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01008019 }
8020
Phil Nashce612bf2012-11-01 08:27:09 +00008021 bool AssertionResult::hasMessage() const {
8022 return !m_resultData.message.empty();
Phil Nash3b80af72012-08-09 07:47:30 +01008023 }
8024
Phil Nashce612bf2012-11-01 08:27:09 +00008025 std::string AssertionResult::getExpression() const {
Phil Nashab036682014-06-02 07:48:03 +01008026 if( isFalseTest( m_info.resultDisposition ) )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008027 return '!' + m_info.capturedExpression;
Phil Nash786959d2013-06-07 19:07:50 +01008028 else
8029 return m_info.capturedExpression;
8030 }
8031 std::string AssertionResult::getExpressionInMacro() const {
8032 if( m_info.macroName.empty() )
8033 return m_info.capturedExpression;
8034 else
8035 return m_info.macroName + "( " + m_info.capturedExpression + " )";
Phil Nash3b80af72012-08-09 07:47:30 +01008036 }
8037
Phil Nashce612bf2012-11-01 08:27:09 +00008038 bool AssertionResult::hasExpandedExpression() const {
Phil Nash67305122012-10-09 11:48:55 +01008039 return hasExpression() && getExpandedExpression() != getExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01008040 }
8041
Phil Nashce612bf2012-11-01 08:27:09 +00008042 std::string AssertionResult::getExpandedExpression() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008043 return m_resultData.reconstructExpression();
Phil Nash3b80af72012-08-09 07:47:30 +01008044 }
8045
Phil Nashce612bf2012-11-01 08:27:09 +00008046 std::string AssertionResult::getMessage() const {
8047 return m_resultData.message;
8048 }
8049 SourceLineInfo AssertionResult::getSourceInfo() const {
8050 return m_info.lineInfo;
Phil Nash3b80af72012-08-09 07:47:30 +01008051 }
8052
Phil Nashce612bf2012-11-01 08:27:09 +00008053 std::string AssertionResult::getTestMacroName() const {
8054 return m_info.macroName;
Phil Nash3b80af72012-08-09 07:47:30 +01008055 }
8056
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008057 void AssertionResult::discardDecomposedExpression() const {
8058 m_resultData.decomposedExpression = CATCH_NULL;
8059 }
8060
8061 void AssertionResult::expandDecomposedExpression() const {
8062 m_resultData.reconstructExpression();
8063 }
8064
Phil Nash3b80af72012-08-09 07:47:30 +01008065} // end namespace Catch
8066
Phil Nash5bc030d2012-08-16 18:48:50 +01008067// #included from: catch_test_case_info.hpp
Matt Wozniskif29c8982012-09-17 01:42:29 -04008068#define TWOBLUECUBES_CATCH_TEST_CASE_INFO_HPP_INCLUDED
Phil Nash5bc030d2012-08-16 18:48:50 +01008069
Phil Nashd08cee22017-02-13 16:15:42 +00008070#include <cctype>
8071
Phil Nash5bc030d2012-08-16 18:48:50 +01008072namespace Catch {
8073
Phil Nash52e1e742014-07-03 08:11:38 +01008074 inline TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008075 if( startsWith( tag, '.' ) ||
Phil Nash52e1e742014-07-03 08:11:38 +01008076 tag == "hide" ||
8077 tag == "!hide" )
8078 return TestCaseInfo::IsHidden;
8079 else if( tag == "!throws" )
8080 return TestCaseInfo::Throws;
8081 else if( tag == "!shouldfail" )
8082 return TestCaseInfo::ShouldFail;
8083 else if( tag == "!mayfail" )
8084 return TestCaseInfo::MayFail;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008085 else if( tag == "!nonportable" )
8086 return TestCaseInfo::NonPortable;
Phil Nash52e1e742014-07-03 08:11:38 +01008087 else
8088 return TestCaseInfo::None;
Phil Nash20cad7c2014-04-15 18:44:37 +01008089 }
8090 inline bool isReservedTag( std::string const& tag ) {
Phil Nashd08cee22017-02-13 16:15:42 +00008091 return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( tag[0] );
Phil Nash20cad7c2014-04-15 18:44:37 +01008092 }
Phil Nash65cc14c2014-05-16 18:54:48 +01008093 inline void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {
8094 if( isReservedTag( tag ) ) {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008095 std::ostringstream ss;
8096 ss << Colour(Colour::Red)
8097 << "Tag name [" << tag << "] not allowed.\n"
8098 << "Tag names starting with non alpha-numeric characters are reserved\n"
8099 << Colour(Colour::FileName)
8100 << _lineInfo << '\n';
8101 throw std::runtime_error(ss.str());
Phil Nash65cc14c2014-05-16 18:54:48 +01008102 }
8103 }
Phil Nash20cad7c2014-04-15 18:44:37 +01008104
Phil Nasha1fbfea2012-12-01 23:57:18 +00008105 TestCase makeTestCase( ITestCase* _testCase,
Phil Nash8defc712013-04-24 19:10:02 +01008106 std::string const& _className,
8107 std::string const& _name,
8108 std::string const& _descOrTags,
8109 SourceLineInfo const& _lineInfo )
Phil Nashfc1baac2012-09-15 17:53:27 +01008110 {
Phil Nash5ecb72b2013-11-26 20:57:45 +00008111 bool isHidden( startsWith( _name, "./" ) ); // Legacy support
Phil Nash65cc14c2014-05-16 18:54:48 +01008112
8113 // Parse out tags
Phil Nasha1fbfea2012-12-01 23:57:18 +00008114 std::set<std::string> tags;
Phil Nash65cc14c2014-05-16 18:54:48 +01008115 std::string desc, tag;
8116 bool inTag = false;
8117 for( std::size_t i = 0; i < _descOrTags.size(); ++i ) {
8118 char c = _descOrTags[i];
8119 if( !inTag ) {
8120 if( c == '[' )
8121 inTag = true;
8122 else
8123 desc += c;
Phil Nash20cad7c2014-04-15 18:44:37 +01008124 }
Phil Nash65cc14c2014-05-16 18:54:48 +01008125 else {
8126 if( c == ']' ) {
Phil Nash91c17f32014-12-15 07:26:31 +00008127 TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );
8128 if( prop == TestCaseInfo::IsHidden )
Phil Nashebd48882014-05-19 18:22:59 +01008129 isHidden = true;
Phil Nash91c17f32014-12-15 07:26:31 +00008130 else if( prop == TestCaseInfo::None )
8131 enforceNotReservedTag( tag, _lineInfo );
8132
8133 tags.insert( tag );
Phil Nash65cc14c2014-05-16 18:54:48 +01008134 tag.clear();
Phil Nash91c17f32014-12-15 07:26:31 +00008135 inTag = false;
Phil Nash65cc14c2014-05-16 18:54:48 +01008136 }
8137 else
8138 tag += c;
8139 }
Phil Nashde49ec42013-12-04 20:25:14 +00008140 }
Phil Nash9241e432014-05-20 18:50:59 +01008141 if( isHidden ) {
8142 tags.insert( "hide" );
8143 tags.insert( "." );
8144 }
8145
Phil Nash52e1e742014-07-03 08:11:38 +01008146 TestCaseInfo info( _name, _className, desc, tags, _lineInfo );
Phil Nasha1fbfea2012-12-01 23:57:18 +00008147 return TestCase( _testCase, info );
Phil Nashfc1baac2012-09-15 17:53:27 +01008148 }
Phil Nash5bc030d2012-08-16 18:48:50 +01008149
Phil Nashb971fe72015-07-02 08:21:38 +01008150 void setTags( TestCaseInfo& testCaseInfo, std::set<std::string> const& tags )
8151 {
8152 testCaseInfo.tags = tags;
8153 testCaseInfo.lcaseTags.clear();
8154
8155 std::ostringstream oss;
8156 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 +01008157 oss << '[' << *it << ']';
Phil Nashb971fe72015-07-02 08:21:38 +01008158 std::string lcaseTag = toLower( *it );
8159 testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );
8160 testCaseInfo.lcaseTags.insert( lcaseTag );
8161 }
8162 testCaseInfo.tagsAsString = oss.str();
8163 }
8164
Phil Nash8defc712013-04-24 19:10:02 +01008165 TestCaseInfo::TestCaseInfo( std::string const& _name,
8166 std::string const& _className,
8167 std::string const& _description,
8168 std::set<std::string> const& _tags,
Phil Nash8defc712013-04-24 19:10:02 +01008169 SourceLineInfo const& _lineInfo )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008170 : name( _name ),
8171 className( _className ),
8172 description( _description ),
Phil Nashff03cdf2012-12-06 08:44:51 +00008173 lineInfo( _lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01008174 properties( None )
Phil Nash38f7eef2013-03-29 13:44:33 +00008175 {
Phil Nashb971fe72015-07-02 08:21:38 +01008176 setTags( *this, _tags );
Phil Nash38f7eef2013-03-29 13:44:33 +00008177 }
Phil Nash5bc030d2012-08-16 18:48:50 +01008178
Phil Nash8defc712013-04-24 19:10:02 +01008179 TestCaseInfo::TestCaseInfo( TestCaseInfo const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008180 : name( other.name ),
8181 className( other.className ),
8182 description( other.description ),
8183 tags( other.tags ),
Phil Nash9241e432014-05-20 18:50:59 +01008184 lcaseTags( other.lcaseTags ),
Phil Nash38f7eef2013-03-29 13:44:33 +00008185 tagsAsString( other.tagsAsString ),
Phil Nashff03cdf2012-12-06 08:44:51 +00008186 lineInfo( other.lineInfo ),
Phil Nash52e1e742014-07-03 08:11:38 +01008187 properties( other.properties )
Phil Nash5bc030d2012-08-16 18:48:50 +01008188 {}
8189
Phil Nash52e1e742014-07-03 08:11:38 +01008190 bool TestCaseInfo::isHidden() const {
8191 return ( properties & IsHidden ) != 0;
8192 }
8193 bool TestCaseInfo::throws() const {
8194 return ( properties & Throws ) != 0;
8195 }
8196 bool TestCaseInfo::okToFail() const {
8197 return ( properties & (ShouldFail | MayFail ) ) != 0;
8198 }
8199 bool TestCaseInfo::expectedToFail() const {
8200 return ( properties & (ShouldFail ) ) != 0;
8201 }
8202
Phil Nash8defc712013-04-24 19:10:02 +01008203 TestCase::TestCase( ITestCase* testCase, TestCaseInfo const& info ) : TestCaseInfo( info ), test( testCase ) {}
Phil Nasha1fbfea2012-12-01 23:57:18 +00008204
Phil Nash8defc712013-04-24 19:10:02 +01008205 TestCase::TestCase( TestCase const& other )
Phil Nasha1fbfea2012-12-01 23:57:18 +00008206 : TestCaseInfo( other ),
8207 test( other.test )
Phil Nash5bc030d2012-08-16 18:48:50 +01008208 {}
8209
Phil Nash8defc712013-04-24 19:10:02 +01008210 TestCase TestCase::withName( std::string const& _newName ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008211 TestCase other( *this );
8212 other.name = _newName;
8213 return other;
Phil Nash5bc030d2012-08-16 18:48:50 +01008214 }
8215
Phil Nash9241e432014-05-20 18:50:59 +01008216 void TestCase::swap( TestCase& other ) {
8217 test.swap( other.test );
8218 name.swap( other.name );
8219 className.swap( other.className );
8220 description.swap( other.description );
8221 tags.swap( other.tags );
8222 lcaseTags.swap( other.lcaseTags );
8223 tagsAsString.swap( other.tagsAsString );
Phil Nash52e1e742014-07-03 08:11:38 +01008224 std::swap( TestCaseInfo::properties, static_cast<TestCaseInfo&>( other ).properties );
Phil Nash9241e432014-05-20 18:50:59 +01008225 std::swap( lineInfo, other.lineInfo );
8226 }
8227
Phil Nasha1fbfea2012-12-01 23:57:18 +00008228 void TestCase::invoke() const {
8229 test->invoke();
Phil Nash5bc030d2012-08-16 18:48:50 +01008230 }
8231
Phil Nash8defc712013-04-24 19:10:02 +01008232 bool TestCase::operator == ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008233 return test.get() == other.test.get() &&
8234 name == other.name &&
8235 className == other.className;
Phil Nash5bc030d2012-08-16 18:48:50 +01008236 }
8237
Phil Nash8defc712013-04-24 19:10:02 +01008238 bool TestCase::operator < ( TestCase const& other ) const {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008239 return name < other.name;
Phil Nash5bc030d2012-08-16 18:48:50 +01008240 }
Phil Nash8defc712013-04-24 19:10:02 +01008241 TestCase& TestCase::operator = ( TestCase const& other ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00008242 TestCase temp( other );
Phil Nashd2ec8492012-08-23 19:48:57 +01008243 swap( temp );
8244 return *this;
8245 }
Phil Nash799ecf92012-09-24 08:30:13 +01008246
Phil Nash8defc712013-04-24 19:10:02 +01008247 TestCaseInfo const& TestCase::getTestCaseInfo() const
Phil Nasha1fbfea2012-12-01 23:57:18 +00008248 {
8249 return *this;
8250 }
8251
Phil Nash799ecf92012-09-24 08:30:13 +01008252} // end namespace Catch
Phil Nash5bc030d2012-08-16 18:48:50 +01008253
Phil Nash7673a302012-11-15 22:15:41 +00008254// #included from: catch_version.hpp
8255#define TWOBLUECUBES_CATCH_VERSION_HPP_INCLUDED
8256
8257namespace Catch {
8258
Phil Nash21f7ef62015-06-29 18:05:23 +01008259 Version::Version
8260 ( unsigned int _majorVersion,
8261 unsigned int _minorVersion,
8262 unsigned int _patchNumber,
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008263 char const * const _branchName,
Phil Nash21f7ef62015-06-29 18:05:23 +01008264 unsigned int _buildNumber )
8265 : majorVersion( _majorVersion ),
8266 minorVersion( _minorVersion ),
8267 patchNumber( _patchNumber ),
8268 branchName( _branchName ),
8269 buildNumber( _buildNumber )
8270 {}
8271
8272 std::ostream& operator << ( std::ostream& os, Version const& version ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008273 os << version.majorVersion << '.'
8274 << version.minorVersion << '.'
Phil Nash21f7ef62015-06-29 18:05:23 +01008275 << version.patchNumber;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008276 // branchName is never null -> 0th char is \0 if it is empty
8277 if (version.branchName[0]) {
8278 os << '-' << version.branchName
8279 << '.' << version.buildNumber;
Phil Nash21f7ef62015-06-29 18:05:23 +01008280 }
8281 return os;
8282 }
8283
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008284 inline Version libraryVersion() {
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +02008285 static Version version( 1, 9, 2, "", 0 );
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008286 return version;
8287 }
Phil Nash21f7ef62015-06-29 18:05:23 +01008288
Phil Nash7673a302012-11-15 22:15:41 +00008289}
8290
Phil Nasha2773812013-02-02 20:37:58 +00008291// #included from: catch_message.hpp
8292#define TWOBLUECUBES_CATCH_MESSAGE_HPP_INCLUDED
8293
8294namespace Catch {
8295
8296 MessageInfo::MessageInfo( std::string const& _macroName,
8297 SourceLineInfo const& _lineInfo,
8298 ResultWas::OfType _type )
8299 : macroName( _macroName ),
8300 lineInfo( _lineInfo ),
8301 type( _type ),
8302 sequence( ++globalCount )
8303 {}
8304
8305 // This may need protecting if threading support is added
8306 unsigned int MessageInfo::globalCount = 0;
8307
8308 ////////////////////////////////////////////////////////////////////////////
8309
Phil Nashb5fd5a62013-06-28 17:09:57 +01008310 ScopedMessage::ScopedMessage( MessageBuilder const& builder )
8311 : m_info( builder.m_info )
8312 {
8313 m_info.message = builder.m_stream.str();
8314 getResultCapture().pushScopedMessage( m_info );
Phil Nasha2773812013-02-02 20:37:58 +00008315 }
Phil Nash9241e432014-05-20 18:50:59 +01008316 ScopedMessage::ScopedMessage( ScopedMessage const& other )
8317 : m_info( other.m_info )
8318 {}
8319
Phil Nashb5fd5a62013-06-28 17:09:57 +01008320 ScopedMessage::~ScopedMessage() {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008321 if ( !std::uncaught_exception() ){
8322 getResultCapture().popScopedMessage(m_info);
8323 }
Phil Nasha2773812013-02-02 20:37:58 +00008324 }
8325
8326} // end namespace Catch
8327
Phil Nash243f2d22013-04-12 10:43:06 +01008328// #included from: catch_legacy_reporter_adapter.hpp
Phil Nash87641772013-04-08 11:50:41 +01008329#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_HPP_INCLUDED
8330
8331// #included from: catch_legacy_reporter_adapter.h
8332#define TWOBLUECUBES_CATCH_LEGACY_REPORTER_ADAPTER_H_INCLUDED
8333
8334namespace Catch
8335{
Phil Nash3649fdf2013-12-03 18:53:55 +00008336 // Deprecated
8337 struct IReporter : IShared {
8338 virtual ~IReporter();
8339
8340 virtual bool shouldRedirectStdout() const = 0;
8341
8342 virtual void StartTesting() = 0;
8343 virtual void EndTesting( Totals const& totals ) = 0;
8344 virtual void StartGroup( std::string const& groupName ) = 0;
8345 virtual void EndGroup( std::string const& groupName, Totals const& totals ) = 0;
8346 virtual void StartTestCase( TestCaseInfo const& testInfo ) = 0;
8347 virtual void EndTestCase( TestCaseInfo const& testInfo, Totals const& totals, std::string const& stdOut, std::string const& stdErr ) = 0;
8348 virtual void StartSection( std::string const& sectionName, std::string const& description ) = 0;
8349 virtual void EndSection( std::string const& sectionName, Counts const& assertions ) = 0;
8350 virtual void NoAssertionsInSection( std::string const& sectionName ) = 0;
8351 virtual void NoAssertionsInTestCase( std::string const& testName ) = 0;
8352 virtual void Aborted() = 0;
8353 virtual void Result( AssertionResult const& result ) = 0;
8354 };
8355
Phil Nash87641772013-04-08 11:50:41 +01008356 class LegacyReporterAdapter : public SharedImpl<IStreamingReporter>
8357 {
8358 public:
Phil Nash786959d2013-06-07 19:07:50 +01008359 LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter );
Phil Nash87641772013-04-08 11:50:41 +01008360 virtual ~LegacyReporterAdapter();
8361
8362 virtual ReporterPreferences getPreferences() const;
8363 virtual void noMatchingTestCases( std::string const& );
8364 virtual void testRunStarting( TestRunInfo const& );
8365 virtual void testGroupStarting( GroupInfo const& groupInfo );
8366 virtual void testCaseStarting( TestCaseInfo const& testInfo );
8367 virtual void sectionStarting( SectionInfo const& sectionInfo );
8368 virtual void assertionStarting( AssertionInfo const& );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008369 virtual bool assertionEnded( AssertionStats const& assertionStats );
Phil Nash87641772013-04-08 11:50:41 +01008370 virtual void sectionEnded( SectionStats const& sectionStats );
8371 virtual void testCaseEnded( TestCaseStats const& testCaseStats );
8372 virtual void testGroupEnded( TestGroupStats const& testGroupStats );
8373 virtual void testRunEnded( TestRunStats const& testRunStats );
Phil Nash92f08362014-12-22 20:18:05 +00008374 virtual void skipTest( TestCaseInfo const& );
Phil Nash87641772013-04-08 11:50:41 +01008375
8376 private:
8377 Ptr<IReporter> m_legacyReporter;
Phil Nash87641772013-04-08 11:50:41 +01008378 };
8379}
8380
8381namespace Catch
8382{
Phil Nash786959d2013-06-07 19:07:50 +01008383 LegacyReporterAdapter::LegacyReporterAdapter( Ptr<IReporter> const& legacyReporter )
8384 : m_legacyReporter( legacyReporter )
Phil Nash87641772013-04-08 11:50:41 +01008385 {}
8386 LegacyReporterAdapter::~LegacyReporterAdapter() {}
8387
8388 ReporterPreferences LegacyReporterAdapter::getPreferences() const {
8389 ReporterPreferences prefs;
8390 prefs.shouldRedirectStdOut = m_legacyReporter->shouldRedirectStdout();
8391 return prefs;
8392 }
8393
8394 void LegacyReporterAdapter::noMatchingTestCases( std::string const& ) {}
8395 void LegacyReporterAdapter::testRunStarting( TestRunInfo const& ) {
8396 m_legacyReporter->StartTesting();
8397 }
8398 void LegacyReporterAdapter::testGroupStarting( GroupInfo const& groupInfo ) {
8399 m_legacyReporter->StartGroup( groupInfo.name );
8400 }
8401 void LegacyReporterAdapter::testCaseStarting( TestCaseInfo const& testInfo ) {
8402 m_legacyReporter->StartTestCase( testInfo );
8403 }
8404 void LegacyReporterAdapter::sectionStarting( SectionInfo const& sectionInfo ) {
8405 m_legacyReporter->StartSection( sectionInfo.name, sectionInfo.description );
8406 }
8407 void LegacyReporterAdapter::assertionStarting( AssertionInfo const& ) {
8408 // Not on legacy interface
8409 }
8410
Phil Nashb5fd5a62013-06-28 17:09:57 +01008411 bool LegacyReporterAdapter::assertionEnded( AssertionStats const& assertionStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008412 if( assertionStats.assertionResult.getResultType() != ResultWas::Ok ) {
8413 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
8414 it != itEnd;
8415 ++it ) {
8416 if( it->type == ResultWas::Info ) {
Phil Nashab036682014-06-02 07:48:03 +01008417 ResultBuilder rb( it->macroName.c_str(), it->lineInfo, "", ResultDisposition::Normal );
8418 rb << it->message;
8419 rb.setResultType( ResultWas::Info );
8420 AssertionResult result = rb.build();
Phil Nash87641772013-04-08 11:50:41 +01008421 m_legacyReporter->Result( result );
8422 }
8423 }
8424 }
8425 m_legacyReporter->Result( assertionStats.assertionResult );
Phil Nashb5fd5a62013-06-28 17:09:57 +01008426 return true;
Phil Nash87641772013-04-08 11:50:41 +01008427 }
8428 void LegacyReporterAdapter::sectionEnded( SectionStats const& sectionStats ) {
8429 if( sectionStats.missingAssertions )
8430 m_legacyReporter->NoAssertionsInSection( sectionStats.sectionInfo.name );
8431 m_legacyReporter->EndSection( sectionStats.sectionInfo.name, sectionStats.assertions );
8432 }
8433 void LegacyReporterAdapter::testCaseEnded( TestCaseStats const& testCaseStats ) {
Phil Nash87641772013-04-08 11:50:41 +01008434 m_legacyReporter->EndTestCase
8435 ( testCaseStats.testInfo,
8436 testCaseStats.totals,
8437 testCaseStats.stdOut,
8438 testCaseStats.stdErr );
8439 }
8440 void LegacyReporterAdapter::testGroupEnded( TestGroupStats const& testGroupStats ) {
8441 if( testGroupStats.aborting )
8442 m_legacyReporter->Aborted();
8443 m_legacyReporter->EndGroup( testGroupStats.groupInfo.name, testGroupStats.totals );
8444 }
8445 void LegacyReporterAdapter::testRunEnded( TestRunStats const& testRunStats ) {
8446 m_legacyReporter->EndTesting( testRunStats.totals );
8447 }
Phil Nash92f08362014-12-22 20:18:05 +00008448 void LegacyReporterAdapter::skipTest( TestCaseInfo const& ) {
8449 }
Phil Nash87641772013-04-08 11:50:41 +01008450}
8451
Phil Nashaa7123b2013-08-15 19:01:00 +01008452// #included from: catch_timer.hpp
8453
8454#ifdef __clang__
8455#pragma clang diagnostic push
8456#pragma clang diagnostic ignored "-Wc++11-long-long"
8457#endif
8458
Phil Nash04a33642013-08-16 19:09:09 +01008459#ifdef CATCH_PLATFORM_WINDOWS
Phil Nash0952b762017-02-28 14:19:09 +00008460
Phil Nashaa7123b2013-08-15 19:01:00 +01008461#else
Phil Nash0952b762017-02-28 14:19:09 +00008462
Phil Nashaa7123b2013-08-15 19:01:00 +01008463#include <sys/time.h>
Phil Nashc6535a02017-03-01 16:04:44 +00008464
Phil Nashaa7123b2013-08-15 19:01:00 +01008465#endif
8466
8467namespace Catch {
8468
8469 namespace {
Phil Nash04a33642013-08-16 19:09:09 +01008470#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashaa7123b2013-08-15 19:01:00 +01008471 uint64_t getCurrentTicks() {
8472 static uint64_t hz=0, hzo=0;
8473 if (!hz) {
Phil Nash37e55612015-03-27 18:02:28 +00008474 QueryPerformanceFrequency( reinterpret_cast<LARGE_INTEGER*>( &hz ) );
8475 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &hzo ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008476 }
8477 uint64_t t;
Phil Nash37e55612015-03-27 18:02:28 +00008478 QueryPerformanceCounter( reinterpret_cast<LARGE_INTEGER*>( &t ) );
Phil Nashaa7123b2013-08-15 19:01:00 +01008479 return ((t-hzo)*1000000)/hz;
8480 }
8481#else
8482 uint64_t getCurrentTicks() {
8483 timeval t;
Phil Nashb971fe72015-07-02 08:21:38 +01008484 gettimeofday(&t,CATCH_NULL);
Phil Nashce562092014-07-09 07:40:37 +01008485 return static_cast<uint64_t>( t.tv_sec ) * 1000000ull + static_cast<uint64_t>( t.tv_usec );
Phil Nashaa7123b2013-08-15 19:01:00 +01008486 }
8487#endif
8488 }
8489
8490 void Timer::start() {
8491 m_ticks = getCurrentTicks();
8492 }
Phil Nash4caabfa2014-09-03 19:23:22 +01008493 unsigned int Timer::getElapsedMicroseconds() const {
Phil Nashce562092014-07-09 07:40:37 +01008494 return static_cast<unsigned int>(getCurrentTicks() - m_ticks);
Phil Nashaa7123b2013-08-15 19:01:00 +01008495 }
8496 unsigned int Timer::getElapsedMilliseconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008497 return static_cast<unsigned int>(getElapsedMicroseconds()/1000);
Phil Nashaa7123b2013-08-15 19:01:00 +01008498 }
8499 double Timer::getElapsedSeconds() const {
Phil Nash4caabfa2014-09-03 19:23:22 +01008500 return getElapsedMicroseconds()/1000000.0;
Phil Nashaa7123b2013-08-15 19:01:00 +01008501 }
8502
8503} // namespace Catch
8504
8505#ifdef __clang__
8506#pragma clang diagnostic pop
8507#endif
Phil Nash3649fdf2013-12-03 18:53:55 +00008508// #included from: catch_common.hpp
8509#define TWOBLUECUBES_CATCH_COMMON_HPP_INCLUDED
8510
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008511#include <cstring>
Phil Nashd08cee22017-02-13 16:15:42 +00008512#include <cctype>
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008513
Phil Nash3649fdf2013-12-03 18:53:55 +00008514namespace Catch {
8515
8516 bool startsWith( std::string const& s, std::string const& prefix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008517 return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());
8518 }
8519 bool startsWith( std::string const& s, char prefix ) {
8520 return !s.empty() && s[0] == prefix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008521 }
8522 bool endsWith( std::string const& s, std::string const& suffix ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008523 return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());
8524 }
8525 bool endsWith( std::string const& s, char suffix ) {
8526 return !s.empty() && s[s.size()-1] == suffix;
Phil Nash3649fdf2013-12-03 18:53:55 +00008527 }
8528 bool contains( std::string const& s, std::string const& infix ) {
8529 return s.find( infix ) != std::string::npos;
8530 }
Phil Nashe27c4ee2016-10-26 12:08:26 +01008531 char toLowerCh(char c) {
Phil Nashd08cee22017-02-13 16:15:42 +00008532 return static_cast<char>( std::tolower( c ) );
Phil Nashe27c4ee2016-10-26 12:08:26 +01008533 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008534 void toLowerInPlace( std::string& s ) {
Phil Nashe27c4ee2016-10-26 12:08:26 +01008535 std::transform( s.begin(), s.end(), s.begin(), toLowerCh );
Phil Nash3649fdf2013-12-03 18:53:55 +00008536 }
8537 std::string toLower( std::string const& s ) {
8538 std::string lc = s;
8539 toLowerInPlace( lc );
8540 return lc;
8541 }
8542 std::string trim( std::string const& str ) {
8543 static char const* whitespaceChars = "\n\r\t ";
8544 std::string::size_type start = str.find_first_not_of( whitespaceChars );
8545 std::string::size_type end = str.find_last_not_of( whitespaceChars );
8546
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008547 return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();
Phil Nash3649fdf2013-12-03 18:53:55 +00008548 }
8549
Phil Nash576aff62014-12-21 00:21:23 +00008550 bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {
8551 bool replaced = false;
8552 std::size_t i = str.find( replaceThis );
8553 while( i != std::string::npos ) {
8554 replaced = true;
8555 str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );
8556 if( i < str.size()-withThis.size() )
8557 i = str.find( replaceThis, i+withThis.size() );
8558 else
8559 i = std::string::npos;
8560 }
8561 return replaced;
8562 }
8563
Phil Nash3649fdf2013-12-03 18:53:55 +00008564 pluralise::pluralise( std::size_t count, std::string const& label )
8565 : m_count( count ),
8566 m_label( label )
8567 {}
8568
8569 std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008570 os << pluraliser.m_count << ' ' << pluraliser.m_label;
Phil Nash3649fdf2013-12-03 18:53:55 +00008571 if( pluraliser.m_count != 1 )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008572 os << 's';
Phil Nash3649fdf2013-12-03 18:53:55 +00008573 return os;
8574 }
8575
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008576 SourceLineInfo::SourceLineInfo() : file(""), line( 0 ){}
Phil Nashde49ec42013-12-04 20:25:14 +00008577 SourceLineInfo::SourceLineInfo( char const* _file, std::size_t _line )
Phil Nash3649fdf2013-12-03 18:53:55 +00008578 : file( _file ),
8579 line( _line )
8580 {}
Phil Nash3649fdf2013-12-03 18:53:55 +00008581 bool SourceLineInfo::empty() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008582 return file[0] == '\0';
Phil Nash3649fdf2013-12-03 18:53:55 +00008583 }
8584 bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008585 return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);
Phil Nash3649fdf2013-12-03 18:53:55 +00008586 }
Phil Nasha806c3e2015-03-04 08:23:40 +00008587 bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008588 return line < other.line || ( line == other.line && (std::strcmp(file, other.file) < 0));
Phil Nasha806c3e2015-03-04 08:23:40 +00008589 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008590
Phil Nash8f66e342015-07-02 23:03:13 +01008591 void seedRng( IConfig const& config ) {
8592 if( config.rngSeed() != 0 )
8593 std::srand( config.rngSeed() );
8594 }
8595 unsigned int rngSeed() {
8596 return getCurrentContext().getConfig()->rngSeed();
8597 }
8598
Phil Nash3649fdf2013-12-03 18:53:55 +00008599 std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {
8600#ifndef __GNUG__
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008601 os << info.file << '(' << info.line << ')';
Phil Nash3649fdf2013-12-03 18:53:55 +00008602#else
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008603 os << info.file << ':' << info.line;
Phil Nash3649fdf2013-12-03 18:53:55 +00008604#endif
8605 return os;
8606 }
8607
8608 void throwLogicError( std::string const& message, SourceLineInfo const& locationInfo ) {
8609 std::ostringstream oss;
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008610 oss << locationInfo << ": Internal Catch error: '" << message << '\'';
Phil Nashab036682014-06-02 07:48:03 +01008611 if( alwaysTrue() )
Phil Nash3649fdf2013-12-03 18:53:55 +00008612 throw std::logic_error( oss.str() );
8613 }
8614}
8615
8616// #included from: catch_section.hpp
8617#define TWOBLUECUBES_CATCH_SECTION_HPP_INCLUDED
8618
8619namespace Catch {
8620
Phil Nashce562092014-07-09 07:40:37 +01008621 SectionInfo::SectionInfo
8622 ( SourceLineInfo const& _lineInfo,
8623 std::string const& _name,
8624 std::string const& _description )
8625 : name( _name ),
8626 description( _description ),
8627 lineInfo( _lineInfo )
8628 {}
8629
8630 Section::Section( SectionInfo const& info )
8631 : m_info( info ),
Phil Nash9241e432014-05-20 18:50:59 +01008632 m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )
Phil Nash3649fdf2013-12-03 18:53:55 +00008633 {
8634 m_timer.start();
8635 }
8636
8637 Section::~Section() {
Phil Nash0c1c9fa2015-09-27 03:28:14 -07008638 if( m_sectionIncluded ) {
8639 SectionEndInfo endInfo( m_info, m_assertions, m_timer.getElapsedSeconds() );
8640 if( std::uncaught_exception() )
8641 getResultCapture().sectionEndedEarly( endInfo );
8642 else
8643 getResultCapture().sectionEnded( endInfo );
8644 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008645 }
8646
8647 // This indicates whether the section should be executed or not
Phil Nashce562092014-07-09 07:40:37 +01008648 Section::operator bool() const {
Phil Nash3649fdf2013-12-03 18:53:55 +00008649 return m_sectionIncluded;
8650 }
8651
8652} // end namespace Catch
8653
8654// #included from: catch_debugger.hpp
8655#define TWOBLUECUBES_CATCH_DEBUGGER_HPP_INCLUDED
8656
Phil Nash3649fdf2013-12-03 18:53:55 +00008657#ifdef CATCH_PLATFORM_MAC
8658
8659 #include <assert.h>
8660 #include <stdbool.h>
8661 #include <sys/types.h>
8662 #include <unistd.h>
8663 #include <sys/sysctl.h>
8664
8665 namespace Catch{
8666
8667 // The following function is taken directly from the following technical note:
8668 // http://developer.apple.com/library/mac/#qa/qa2004/qa1361.html
8669
8670 // Returns true if the current process is being debugged (either
8671 // running under the debugger or has a debugger attached post facto).
8672 bool isDebuggerActive(){
8673
Phil Nash3649fdf2013-12-03 18:53:55 +00008674 int mib[4];
8675 struct kinfo_proc info;
8676 size_t size;
8677
8678 // Initialize the flags so that, if sysctl fails for some bizarre
8679 // reason, we get a predictable result.
8680
8681 info.kp_proc.p_flag = 0;
8682
8683 // Initialize mib, which tells sysctl the info we want, in this case
8684 // we're looking for information about a specific process ID.
8685
8686 mib[0] = CTL_KERN;
8687 mib[1] = KERN_PROC;
8688 mib[2] = KERN_PROC_PID;
8689 mib[3] = getpid();
8690
8691 // Call sysctl.
8692
8693 size = sizeof(info);
Phil Nashb971fe72015-07-02 08:21:38 +01008694 if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, CATCH_NULL, 0) != 0 ) {
Phil Nash383d7c02014-10-02 19:08:19 +01008695 Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;
Phil Nash7eb5acc2014-01-08 17:17:31 +00008696 return false;
8697 }
Phil Nash3649fdf2013-12-03 18:53:55 +00008698
8699 // We're being debugged if the P_TRACED flag is set.
8700
8701 return ( (info.kp_proc.p_flag & P_TRACED) != 0 );
8702 }
8703 } // namespace Catch
8704
Martin Hořeňovský9a566092017-01-20 12:49:59 +01008705#elif defined(CATCH_PLATFORM_LINUX)
8706 #include <fstream>
8707 #include <string>
8708
8709 namespace Catch{
8710 // The standard POSIX way of detecting a debugger is to attempt to
8711 // ptrace() the process, but this needs to be done from a child and not
8712 // this process itself to still allow attaching to this process later
8713 // if wanted, so is rather heavy. Under Linux we have the PID of the
8714 // "debugger" (which doesn't need to be gdb, of course, it could also
8715 // be strace, for example) in /proc/$PID/status, so just get it from
8716 // there instead.
8717 bool isDebuggerActive(){
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01008718 // Libstdc++ has a bug, where std::ifstream sets errno to 0
8719 // This way our users can properly assert over errno values
8720 ErrnoGuard guard;
Martin Hořeňovský9a566092017-01-20 12:49:59 +01008721 std::ifstream in("/proc/self/status");
8722 for( std::string line; std::getline(in, line); ) {
8723 static const int PREFIX_LEN = 11;
8724 if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {
8725 // We're traced if the PID is not 0 and no other PID starts
8726 // with 0 digit, so it's enough to check for just a single
8727 // character.
8728 return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';
8729 }
8730 }
8731
8732 return false;
8733 }
8734 } // namespace Catch
Phil Nash3649fdf2013-12-03 18:53:55 +00008735#elif defined(_MSC_VER)
8736 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8737 namespace Catch {
8738 bool isDebuggerActive() {
8739 return IsDebuggerPresent() != 0;
8740 }
8741 }
8742#elif defined(__MINGW32__)
8743 extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();
8744 namespace Catch {
8745 bool isDebuggerActive() {
8746 return IsDebuggerPresent() != 0;
8747 }
8748 }
8749#else
8750 namespace Catch {
8751 inline bool isDebuggerActive() { return false; }
8752 }
8753#endif // Platform
8754
8755#ifdef CATCH_PLATFORM_WINDOWS
Phil Nashd08cee22017-02-13 16:15:42 +00008756
Phil Nash3649fdf2013-12-03 18:53:55 +00008757 namespace Catch {
8758 void writeToDebugConsole( std::string const& text ) {
8759 ::OutputDebugStringA( text.c_str() );
8760 }
8761 }
8762#else
8763 namespace Catch {
8764 void writeToDebugConsole( std::string const& text ) {
8765 // !TBD: Need a version for Mac/ XCode and other IDEs
Phil Nash383d7c02014-10-02 19:08:19 +01008766 Catch::cout() << text;
Phil Nash3649fdf2013-12-03 18:53:55 +00008767 }
8768 }
8769#endif // Platform
8770
Phil Nashaef6cd52014-04-23 07:10:10 +01008771// #included from: catch_tostring.hpp
8772#define TWOBLUECUBES_CATCH_TOSTRING_HPP_INCLUDED
8773
8774namespace Catch {
8775
Phil Nashab036682014-06-02 07:48:03 +01008776namespace Detail {
8777
Phil Nash2f6371f2015-07-23 23:06:26 +01008778 const std::string unprintableString = "{?}";
Phil Nash6a8e8ad2014-09-15 18:40:24 +01008779
Phil Nashab036682014-06-02 07:48:03 +01008780 namespace {
Phil Nash2f6371f2015-07-23 23:06:26 +01008781 const int hexThreshold = 255;
8782
Phil Nashab036682014-06-02 07:48:03 +01008783 struct Endianness {
8784 enum Arch { Big, Little };
8785
8786 static Arch which() {
8787 union _{
8788 int asInt;
8789 char asChar[sizeof (int)];
8790 } u;
8791
8792 u.asInt = 1;
8793 return ( u.asChar[sizeof(int)-1] == 1 ) ? Big : Little;
8794 }
8795 };
8796 }
8797
8798 std::string rawMemoryToString( const void *object, std::size_t size )
8799 {
8800 // Reverse order for little endian architectures
8801 int i = 0, end = static_cast<int>( size ), inc = 1;
8802 if( Endianness::which() == Endianness::Little ) {
8803 i = end-1;
8804 end = inc = -1;
8805 }
8806
8807 unsigned char const *bytes = static_cast<unsigned char const *>(object);
8808 std::ostringstream os;
8809 os << "0x" << std::setfill('0') << std::hex;
8810 for( ; i != end; i += inc )
8811 os << std::setw(2) << static_cast<unsigned>(bytes[i]);
8812 return os.str();
8813 }
8814}
8815
Phil Nashaef6cd52014-04-23 07:10:10 +01008816std::string toString( std::string const& value ) {
8817 std::string s = value;
8818 if( getCurrentContext().getConfig()->showInvisibles() ) {
8819 for(size_t i = 0; i < s.size(); ++i ) {
8820 std::string subs;
8821 switch( s[i] ) {
8822 case '\n': subs = "\\n"; break;
8823 case '\t': subs = "\\t"; break;
8824 default: break;
8825 }
8826 if( !subs.empty() ) {
8827 s = s.substr( 0, i ) + subs + s.substr( i+1 );
8828 ++i;
8829 }
8830 }
8831 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008832 return '"' + s + '"';
Phil Nashaef6cd52014-04-23 07:10:10 +01008833}
8834std::string toString( std::wstring const& value ) {
8835
8836 std::string s;
8837 s.reserve( value.size() );
8838 for(size_t i = 0; i < value.size(); ++i )
8839 s += value[i] <= 0xff ? static_cast<char>( value[i] ) : '?';
Phil Nash13f98432014-12-12 08:11:18 +00008840 return Catch::toString( s );
Phil Nashaef6cd52014-04-23 07:10:10 +01008841}
8842
8843std::string toString( const char* const value ) {
8844 return value ? Catch::toString( std::string( value ) ) : std::string( "{null string}" );
8845}
8846
8847std::string toString( char* const value ) {
8848 return Catch::toString( static_cast<const char*>( value ) );
8849}
8850
Phil Nash544bf332014-08-20 08:09:32 +01008851std::string toString( const wchar_t* const value )
8852{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008853 return value ? Catch::toString( std::wstring(value) ) : std::string( "{null string}" );
Phil Nash544bf332014-08-20 08:09:32 +01008854}
8855
8856std::string toString( wchar_t* const value )
8857{
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008858 return Catch::toString( static_cast<const wchar_t*>( value ) );
Phil Nash544bf332014-08-20 08:09:32 +01008859}
8860
Phil Nashaef6cd52014-04-23 07:10:10 +01008861std::string toString( int value ) {
8862 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008863 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008864 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008865 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008866 return oss.str();
8867}
8868
8869std::string toString( unsigned long value ) {
8870 std::ostringstream oss;
Phil Nashc51e8682015-05-21 06:16:15 +01008871 oss << value;
Phil Nash2f6371f2015-07-23 23:06:26 +01008872 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008873 oss << " (0x" << std::hex << value << ')';
Phil Nashaef6cd52014-04-23 07:10:10 +01008874 return oss.str();
8875}
8876
8877std::string toString( unsigned int value ) {
Phil Nash13f98432014-12-12 08:11:18 +00008878 return Catch::toString( static_cast<unsigned long>( value ) );
Phil Nashaef6cd52014-04-23 07:10:10 +01008879}
8880
Phil Nash28c2e072014-07-09 19:22:49 +01008881template<typename T>
8882std::string fpToString( T value, int precision ) {
Phil Nashaef6cd52014-04-23 07:10:10 +01008883 std::ostringstream oss;
Phil Nash28c2e072014-07-09 19:22:49 +01008884 oss << std::setprecision( precision )
Phil Nashaef6cd52014-04-23 07:10:10 +01008885 << std::fixed
8886 << value;
8887 std::string d = oss.str();
8888 std::size_t i = d.find_last_not_of( '0' );
8889 if( i != std::string::npos && i != d.size()-1 ) {
8890 if( d[i] == '.' )
8891 i++;
8892 d = d.substr( 0, i+1 );
8893 }
8894 return d;
8895}
8896
Phil Nash28c2e072014-07-09 19:22:49 +01008897std::string toString( const double value ) {
8898 return fpToString( value, 10 );
8899}
8900std::string toString( const float value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008901 return fpToString( value, 5 ) + 'f';
Phil Nash28c2e072014-07-09 19:22:49 +01008902}
8903
Phil Nashaef6cd52014-04-23 07:10:10 +01008904std::string toString( bool value ) {
8905 return value ? "true" : "false";
8906}
8907
8908std::string toString( char value ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008909 if ( value == '\r' )
8910 return "'\\r'";
8911 if ( value == '\f' )
8912 return "'\\f'";
8913 if ( value == '\n' )
8914 return "'\\n'";
8915 if ( value == '\t' )
8916 return "'\\t'";
8917 if ( '\0' <= value && value < ' ' )
8918 return toString( static_cast<unsigned int>( value ) );
8919 char chstr[] = "' '";
8920 chstr[1] = value;
8921 return chstr;
Phil Nashaef6cd52014-04-23 07:10:10 +01008922}
8923
8924std::string toString( signed char value ) {
8925 return toString( static_cast<char>( value ) );
8926}
8927
8928std::string toString( unsigned char value ) {
8929 return toString( static_cast<char>( value ) );
8930}
8931
Phil Nash2f6371f2015-07-23 23:06:26 +01008932#ifdef CATCH_CONFIG_CPP11_LONG_LONG
8933std::string toString( long long value ) {
8934 std::ostringstream oss;
8935 oss << value;
8936 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008937 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008938 return oss.str();
8939}
8940std::string toString( unsigned long long value ) {
8941 std::ostringstream oss;
8942 oss << value;
8943 if( value > Detail::hexThreshold )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01008944 oss << " (0x" << std::hex << value << ')';
Phil Nash2f6371f2015-07-23 23:06:26 +01008945 return oss.str();
8946}
8947#endif
8948
Phil Nashaef6cd52014-04-23 07:10:10 +01008949#ifdef CATCH_CONFIG_CPP11_NULLPTR
8950std::string toString( std::nullptr_t ) {
8951 return "nullptr";
8952}
8953#endif
8954
8955#ifdef __OBJC__
8956 std::string toString( NSString const * const& nsstring ) {
8957 if( !nsstring )
8958 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008959 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008960 }
8961 std::string toString( NSString * CATCH_ARC_STRONG const& nsstring ) {
8962 if( !nsstring )
8963 return "nil";
Phil Nashacdd3b52014-06-30 07:35:36 +01008964 return "@" + toString([nsstring UTF8String]);
Phil Nashaef6cd52014-04-23 07:10:10 +01008965 }
8966 std::string toString( NSObject* const& nsObject ) {
8967 return toString( [nsObject description] );
8968 }
8969#endif
8970
8971} // end namespace Catch
8972
Phil Nashab036682014-06-02 07:48:03 +01008973// #included from: catch_result_builder.hpp
8974#define TWOBLUECUBES_CATCH_RESULT_BUILDER_HPP_INCLUDED
8975
8976namespace Catch {
8977
Phil Nash93a842e2015-07-13 06:36:07 +01008978 std::string capturedExpressionWithSecondArgument( std::string const& capturedExpression, std::string const& secondArg ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008979 return secondArg.empty() || secondArg == "\"\""
Phil Nash93a842e2015-07-13 06:36:07 +01008980 ? capturedExpression
Phil Nash5bbdc8f2015-07-15 23:03:11 +01008981 : capturedExpression + ", " + secondArg;
Phil Nash93a842e2015-07-13 06:36:07 +01008982 }
Phil Nashab036682014-06-02 07:48:03 +01008983 ResultBuilder::ResultBuilder( char const* macroName,
8984 SourceLineInfo const& lineInfo,
8985 char const* capturedExpression,
Phil Nash93a842e2015-07-13 06:36:07 +01008986 ResultDisposition::Flags resultDisposition,
8987 char const* secondArg )
8988 : m_assertionInfo( macroName, lineInfo, capturedExpressionWithSecondArgument( capturedExpression, secondArg ), resultDisposition ),
Phil Nashab036682014-06-02 07:48:03 +01008989 m_shouldDebugBreak( false ),
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008990 m_shouldThrow( false ),
8991 m_guardException( false )
Phil Nashab036682014-06-02 07:48:03 +01008992 {}
8993
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02008994 ResultBuilder::~ResultBuilder() {
8995#if defined(CATCH_CONFIG_FAST_COMPILE)
8996 if ( m_guardException ) {
8997 m_stream.oss << "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";
8998 captureResult( ResultWas::ThrewException );
8999 getCurrentContext().getResultCapture()->exceptionEarlyReported();
9000 }
9001#endif
9002 }
9003
Phil Nashab036682014-06-02 07:48:03 +01009004 ResultBuilder& ResultBuilder::setResultType( ResultWas::OfType result ) {
9005 m_data.resultType = result;
9006 return *this;
9007 }
9008 ResultBuilder& ResultBuilder::setResultType( bool result ) {
9009 m_data.resultType = result ? ResultWas::Ok : ResultWas::ExpressionFailed;
9010 return *this;
9011 }
Phil Nashab036682014-06-02 07:48:03 +01009012
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009013 void ResultBuilder::endExpression( DecomposedExpression const& expr ) {
9014 AssertionResult result = build( expr );
9015 handleResult( result );
Phil Nashab036682014-06-02 07:48:03 +01009016 }
9017
9018 void ResultBuilder::useActiveException( ResultDisposition::Flags resultDisposition ) {
9019 m_assertionInfo.resultDisposition = resultDisposition;
9020 m_stream.oss << Catch::translateActiveException();
9021 captureResult( ResultWas::ThrewException );
9022 }
9023
9024 void ResultBuilder::captureResult( ResultWas::OfType resultType ) {
9025 setResultType( resultType );
9026 captureExpression();
9027 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009028
Phil Nash93a842e2015-07-13 06:36:07 +01009029 void ResultBuilder::captureExpectedException( std::string const& expectedMessage ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01009030 if( expectedMessage.empty() )
Phil Nash0952b762017-02-28 14:19:09 +00009031 captureExpectedException( Matchers::Impl::MatchAllOf<std::string>() );
Phil Nash5bbdc8f2015-07-15 23:03:11 +01009032 else
9033 captureExpectedException( Matchers::Equals( expectedMessage ) );
9034 }
9035
Phil Nash0952b762017-02-28 14:19:09 +00009036 void ResultBuilder::captureExpectedException( Matchers::Impl::MatcherBase<std::string> const& matcher ) {
Phil Nash5bbdc8f2015-07-15 23:03:11 +01009037
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009038 assert( !isFalseTest( m_assertionInfo.resultDisposition ) );
Phil Nash93a842e2015-07-13 06:36:07 +01009039 AssertionResultData data = m_data;
9040 data.resultType = ResultWas::Ok;
9041 data.reconstructedExpression = m_assertionInfo.capturedExpression;
Phil Nash93a842e2015-07-13 06:36:07 +01009042
Phil Nash5bbdc8f2015-07-15 23:03:11 +01009043 std::string actualMessage = Catch::translateActiveException();
9044 if( !matcher.match( actualMessage ) ) {
9045 data.resultType = ResultWas::ExpressionFailed;
9046 data.reconstructedExpression = actualMessage;
Phil Nash93a842e2015-07-13 06:36:07 +01009047 }
9048 AssertionResult result( m_assertionInfo, data );
9049 handleResult( result );
9050 }
Phil Nashab036682014-06-02 07:48:03 +01009051
9052 void ResultBuilder::captureExpression() {
9053 AssertionResult result = build();
Phil Nash93a842e2015-07-13 06:36:07 +01009054 handleResult( result );
9055 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009056
Phil Nash93a842e2015-07-13 06:36:07 +01009057 void ResultBuilder::handleResult( AssertionResult const& result )
9058 {
Phil Nashab036682014-06-02 07:48:03 +01009059 getResultCapture().assertionEnded( result );
9060
9061 if( !result.isOk() ) {
9062 if( getCurrentContext().getConfig()->shouldDebugBreak() )
9063 m_shouldDebugBreak = true;
Phil Nash318c9362015-05-19 18:40:00 +01009064 if( getCurrentContext().getRunner()->aborting() || (m_assertionInfo.resultDisposition & ResultDisposition::Normal) )
Phil Nashab036682014-06-02 07:48:03 +01009065 m_shouldThrow = true;
9066 }
9067 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009068
Phil Nashab036682014-06-02 07:48:03 +01009069 void ResultBuilder::react() {
Phil Nash0952b762017-02-28 14:19:09 +00009070#if defined(CATCH_CONFIG_FAST_COMPILE)
9071 if (m_shouldDebugBreak) {
9072 ///////////////////////////////////////////////////////////////////
9073 // To inspect the state during test, you need to go one level up the callstack
9074 // To go back to the test and change execution, jump over the throw statement
9075 ///////////////////////////////////////////////////////////////////
9076 CATCH_BREAK_INTO_DEBUGGER();
9077 }
9078#endif
Phil Nashab036682014-06-02 07:48:03 +01009079 if( m_shouldThrow )
9080 throw Catch::TestFailureException();
9081 }
9082
9083 bool ResultBuilder::shouldDebugBreak() const { return m_shouldDebugBreak; }
9084 bool ResultBuilder::allowThrows() const { return getCurrentContext().getConfig()->allowThrows(); }
9085
9086 AssertionResult ResultBuilder::build() const
9087 {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009088 return build( *this );
9089 }
Phil Nashab036682014-06-02 07:48:03 +01009090
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009091 // CAVEAT: The returned AssertionResult stores a pointer to the argument expr,
9092 // a temporary DecomposedExpression, which in turn holds references to
9093 // operands, possibly temporary as well.
9094 // It should immediately be passed to handleResult; if the expression
9095 // needs to be reported, its string expansion must be composed before
9096 // the temporaries are destroyed.
9097 AssertionResult ResultBuilder::build( DecomposedExpression const& expr ) const
9098 {
9099 assert( m_data.resultType != ResultWas::Unknown );
Phil Nashab036682014-06-02 07:48:03 +01009100 AssertionResultData data = m_data;
9101
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009102 // Flip bool results if FalseTest flag is set
9103 if( isFalseTest( m_assertionInfo.resultDisposition ) ) {
9104 data.negate( expr.isBinaryExpression() );
Phil Nashab036682014-06-02 07:48:03 +01009105 }
9106
9107 data.message = m_stream.oss.str();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009108 data.decomposedExpression = &expr; // for lazy reconstruction
Phil Nashab036682014-06-02 07:48:03 +01009109 return AssertionResult( m_assertionInfo, data );
9110 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009111
9112 void ResultBuilder::reconstructExpression( std::string& dest ) const {
9113 dest = m_assertionInfo.capturedExpression;
Phil Nashab036682014-06-02 07:48:03 +01009114 }
9115
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009116 void ResultBuilder::setExceptionGuard() {
9117 m_guardException = true;
9118 }
9119 void ResultBuilder::unsetExceptionGuard() {
9120 m_guardException = false;
9121 }
9122
Phil Nashab036682014-06-02 07:48:03 +01009123} // end namespace Catch
9124
Phil Nashacdd3b52014-06-30 07:35:36 +01009125// #included from: catch_tag_alias_registry.hpp
9126#define TWOBLUECUBES_CATCH_TAG_ALIAS_REGISTRY_HPP_INCLUDED
9127
Phil Nashacdd3b52014-06-30 07:35:36 +01009128namespace Catch {
9129
9130 TagAliasRegistry::~TagAliasRegistry() {}
9131
9132 Option<TagAlias> TagAliasRegistry::find( std::string const& alias ) const {
9133 std::map<std::string, TagAlias>::const_iterator it = m_registry.find( alias );
9134 if( it != m_registry.end() )
9135 return it->second;
9136 else
9137 return Option<TagAlias>();
9138 }
9139
9140 std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {
9141 std::string expandedTestSpec = unexpandedTestSpec;
9142 for( std::map<std::string, TagAlias>::const_iterator it = m_registry.begin(), itEnd = m_registry.end();
9143 it != itEnd;
9144 ++it ) {
9145 std::size_t pos = expandedTestSpec.find( it->first );
9146 if( pos != std::string::npos ) {
9147 expandedTestSpec = expandedTestSpec.substr( 0, pos ) +
9148 it->second.tag +
9149 expandedTestSpec.substr( pos + it->first.size() );
9150 }
9151 }
9152 return expandedTestSpec;
9153 }
9154
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009155 void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01009156
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009157 if( !startsWith( alias, "[@" ) || !endsWith( alias, ']' ) ) {
Phil Nashacdd3b52014-06-30 07:35:36 +01009158 std::ostringstream oss;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009159 oss << Colour( Colour::Red )
9160 << "error: tag alias, \"" << alias << "\" is not of the form [@alias name].\n"
9161 << Colour( Colour::FileName )
9162 << lineInfo << '\n';
Phil Nashacdd3b52014-06-30 07:35:36 +01009163 throw std::domain_error( oss.str().c_str() );
9164 }
9165 if( !m_registry.insert( std::make_pair( alias, TagAlias( tag, lineInfo ) ) ).second ) {
9166 std::ostringstream oss;
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009167 oss << Colour( Colour::Red )
9168 << "error: tag alias, \"" << alias << "\" already registered.\n"
9169 << "\tFirst seen at "
9170 << Colour( Colour::Red ) << find(alias)->lineInfo << '\n'
9171 << Colour( Colour::Red ) << "\tRedefined at "
9172 << Colour( Colour::FileName) << lineInfo << '\n';
Phil Nashacdd3b52014-06-30 07:35:36 +01009173 throw std::domain_error( oss.str().c_str() );
9174 }
9175 }
9176
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009177 ITagAliasRegistry::~ITagAliasRegistry() {}
Phil Nashacdd3b52014-06-30 07:35:36 +01009178
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009179 ITagAliasRegistry const& ITagAliasRegistry::get() {
9180 return getRegistryHub().getTagAliasRegistry();
Phil Nashacdd3b52014-06-30 07:35:36 +01009181 }
9182
Phil Nashacdd3b52014-06-30 07:35:36 +01009183 RegistrarForTagAliases::RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo ) {
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +02009184 getMutableRegistryHub().registerTagAlias( alias, tag, lineInfo );
Phil Nashacdd3b52014-06-30 07:35:36 +01009185 }
9186
9187} // end namespace Catch
9188
Phil Nash0952b762017-02-28 14:19:09 +00009189// #included from: catch_matchers_string.hpp
9190
9191namespace Catch {
9192namespace Matchers {
9193
9194 namespace StdString {
9195
9196 CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )
9197 : m_caseSensitivity( caseSensitivity ),
9198 m_str( adjustString( str ) )
9199 {}
9200 std::string CasedString::adjustString( std::string const& str ) const {
9201 return m_caseSensitivity == CaseSensitive::No
9202 ? toLower( str )
9203 : str;
9204 }
9205 std::string CasedString::caseSensitivitySuffix() const {
9206 return m_caseSensitivity == CaseSensitive::No
9207 ? " (case insensitive)"
9208 : std::string();
9209 }
9210
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01009211 StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )
Phil Nash0952b762017-02-28 14:19:09 +00009212 : m_comparator( comparator ),
9213 m_operation( operation ) {
9214 }
9215
9216 std::string StringMatcherBase::describe() const {
9217 std::string description;
9218 description.reserve(5 + m_operation.size() + m_comparator.m_str.size() +
9219 m_comparator.caseSensitivitySuffix().size());
9220 description += m_operation;
9221 description += ": \"";
9222 description += m_comparator.m_str;
9223 description += "\"";
9224 description += m_comparator.caseSensitivitySuffix();
9225 return description;
9226 }
9227
9228 EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}
9229
9230 bool EqualsMatcher::match( std::string const& source ) const {
9231 return m_comparator.adjustString( source ) == m_comparator.m_str;
9232 }
9233
9234 ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}
9235
9236 bool ContainsMatcher::match( std::string const& source ) const {
9237 return contains( m_comparator.adjustString( source ), m_comparator.m_str );
9238 }
9239
9240 StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}
9241
9242 bool StartsWithMatcher::match( std::string const& source ) const {
9243 return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9244 }
9245
9246 EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}
9247
9248 bool EndsWithMatcher::match( std::string const& source ) const {
9249 return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );
9250 }
9251
9252 } // namespace StdString
9253
9254 StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9255 return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );
9256 }
9257 StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9258 return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );
9259 }
9260 StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9261 return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9262 }
9263 StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {
9264 return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );
9265 }
9266
9267} // namespace Matchers
9268} // namespace Catch
Phil Nashe73583d2015-08-07 17:30:34 +01009269// #included from: ../reporters/catch_reporter_multi.hpp
9270#define TWOBLUECUBES_CATCH_REPORTER_MULTI_HPP_INCLUDED
9271
9272namespace Catch {
9273
9274class MultipleReporters : public SharedImpl<IStreamingReporter> {
9275 typedef std::vector<Ptr<IStreamingReporter> > Reporters;
9276 Reporters m_reporters;
9277
9278public:
9279 void add( Ptr<IStreamingReporter> const& reporter ) {
9280 m_reporters.push_back( reporter );
9281 }
9282
9283public: // IStreamingReporter
9284
9285 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9286 return m_reporters[0]->getPreferences();
9287 }
9288
9289 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
9290 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9291 it != itEnd;
9292 ++it )
9293 (*it)->noMatchingTestCases( spec );
9294 }
9295
9296 virtual void testRunStarting( TestRunInfo const& testRunInfo ) CATCH_OVERRIDE {
9297 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9298 it != itEnd;
9299 ++it )
9300 (*it)->testRunStarting( testRunInfo );
9301 }
9302
9303 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
9304 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9305 it != itEnd;
9306 ++it )
9307 (*it)->testGroupStarting( groupInfo );
9308 }
9309
9310 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9311 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9312 it != itEnd;
9313 ++it )
9314 (*it)->testCaseStarting( testInfo );
9315 }
9316
9317 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
9318 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9319 it != itEnd;
9320 ++it )
9321 (*it)->sectionStarting( sectionInfo );
9322 }
9323
9324 virtual void assertionStarting( AssertionInfo const& assertionInfo ) CATCH_OVERRIDE {
9325 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9326 it != itEnd;
9327 ++it )
9328 (*it)->assertionStarting( assertionInfo );
9329 }
9330
9331 // The return value indicates if the messages buffer should be cleared:
9332 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
9333 bool clearBuffer = false;
9334 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9335 it != itEnd;
9336 ++it )
9337 clearBuffer |= (*it)->assertionEnded( assertionStats );
9338 return clearBuffer;
9339 }
9340
9341 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
9342 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9343 it != itEnd;
9344 ++it )
9345 (*it)->sectionEnded( sectionStats );
9346 }
9347
9348 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
9349 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9350 it != itEnd;
9351 ++it )
9352 (*it)->testCaseEnded( testCaseStats );
9353 }
9354
9355 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
9356 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9357 it != itEnd;
9358 ++it )
9359 (*it)->testGroupEnded( testGroupStats );
9360 }
9361
9362 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
9363 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9364 it != itEnd;
9365 ++it )
9366 (*it)->testRunEnded( testRunStats );
9367 }
9368
9369 virtual void skipTest( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
9370 for( Reporters::const_iterator it = m_reporters.begin(), itEnd = m_reporters.end();
9371 it != itEnd;
9372 ++it )
9373 (*it)->skipTest( testInfo );
9374 }
Phil Nash92b141e2016-04-28 08:13:00 +01009375
9376 virtual MultipleReporters* tryAsMulti() CATCH_OVERRIDE {
9377 return this;
9378 }
9379
Phil Nashe73583d2015-08-07 17:30:34 +01009380};
9381
9382Ptr<IStreamingReporter> addReporter( Ptr<IStreamingReporter> const& existingReporter, Ptr<IStreamingReporter> const& additionalReporter ) {
9383 Ptr<IStreamingReporter> resultingReporter;
9384
9385 if( existingReporter ) {
Phil Nash92b141e2016-04-28 08:13:00 +01009386 MultipleReporters* multi = existingReporter->tryAsMulti();
Phil Nashe73583d2015-08-07 17:30:34 +01009387 if( !multi ) {
9388 multi = new MultipleReporters;
9389 resultingReporter = Ptr<IStreamingReporter>( multi );
9390 if( existingReporter )
9391 multi->add( existingReporter );
9392 }
9393 else
9394 resultingReporter = existingReporter;
9395 multi->add( additionalReporter );
9396 }
9397 else
9398 resultingReporter = additionalReporter;
9399
9400 return resultingReporter;
9401}
9402
9403} // end namespace Catch
9404
Phil Nash3faa4122013-08-15 19:09:07 +01009405// #included from: ../reporters/catch_reporter_xml.hpp
9406#define TWOBLUECUBES_CATCH_REPORTER_XML_HPP_INCLUDED
Phil Nash56d5c422012-08-23 20:08:50 +01009407
Phil Nash3649fdf2013-12-03 18:53:55 +00009408// #included from: catch_reporter_bases.hpp
9409#define TWOBLUECUBES_CATCH_REPORTER_BASES_HPP_INCLUDED
9410
Phil Nashb7713942014-12-22 07:42:57 +00009411#include <cstring>
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01009412#include <cfloat>
9413#include <cstdio>
Phil Nash0952b762017-02-28 14:19:09 +00009414#include <assert.h>
Phil Nashb7713942014-12-22 07:42:57 +00009415
Phil Nash3649fdf2013-12-03 18:53:55 +00009416namespace Catch {
9417
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01009418 namespace {
9419 // Because formatting using c++ streams is stateful, drop down to C is required
9420 // Alternatively we could use stringstream, but its performance is... not good.
9421 std::string getFormattedDuration( double duration ) {
9422 // Max exponent + 1 is required to represent the whole part
9423 // + 1 for decimal point
9424 // + 3 for the 3 decimal places
9425 // + 1 for null terminator
9426 const size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;
9427 char buffer[maxDoubleSize];
9428
9429 // Save previous errno, to prevent sprintf from overwriting it
9430 ErrnoGuard guard;
9431#ifdef _MSC_VER
9432 sprintf_s(buffer, "%.3f", duration);
9433#else
9434 sprintf(buffer, "%.3f", duration);
9435#endif
9436 return std::string(buffer);
9437 }
9438 }
9439
Phil Nash3649fdf2013-12-03 18:53:55 +00009440 struct StreamingReporterBase : SharedImpl<IStreamingReporter> {
9441
9442 StreamingReporterBase( ReporterConfig const& _config )
9443 : m_config( _config.fullConfig() ),
9444 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009445 {
9446 m_reporterPrefs.shouldRedirectStdOut = false;
9447 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009448
Phil Nashe73583d2015-08-07 17:30:34 +01009449 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9450 return m_reporterPrefs;
9451 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009452
Phil Nashe73583d2015-08-07 17:30:34 +01009453 virtual ~StreamingReporterBase() CATCH_OVERRIDE;
Phil Nash3649fdf2013-12-03 18:53:55 +00009454
Phil Nashe73583d2015-08-07 17:30:34 +01009455 virtual void noMatchingTestCases( std::string const& ) CATCH_OVERRIDE {}
9456
9457 virtual void testRunStarting( TestRunInfo const& _testRunInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009458 currentTestRunInfo = _testRunInfo;
9459 }
Phil Nashe73583d2015-08-07 17:30:34 +01009460 virtual void testGroupStarting( GroupInfo const& _groupInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009461 currentGroupInfo = _groupInfo;
9462 }
9463
Phil Nashe73583d2015-08-07 17:30:34 +01009464 virtual void testCaseStarting( TestCaseInfo const& _testInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009465 currentTestCaseInfo = _testInfo;
9466 }
Phil Nashe73583d2015-08-07 17:30:34 +01009467 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009468 m_sectionStack.push_back( _sectionInfo );
9469 }
9470
Phil Nashe73583d2015-08-07 17:30:34 +01009471 virtual void sectionEnded( SectionStats const& /* _sectionStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009472 m_sectionStack.pop_back();
9473 }
Phil Nashe73583d2015-08-07 17:30:34 +01009474 virtual void testCaseEnded( TestCaseStats const& /* _testCaseStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009475 currentTestCaseInfo.reset();
Phil Nash3649fdf2013-12-03 18:53:55 +00009476 }
Phil Nashe73583d2015-08-07 17:30:34 +01009477 virtual void testGroupEnded( TestGroupStats const& /* _testGroupStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009478 currentGroupInfo.reset();
9479 }
Phil Nashe73583d2015-08-07 17:30:34 +01009480 virtual void testRunEnded( TestRunStats const& /* _testRunStats */ ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009481 currentTestCaseInfo.reset();
9482 currentGroupInfo.reset();
9483 currentTestRunInfo.reset();
9484 }
9485
Phil Nashe73583d2015-08-07 17:30:34 +01009486 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {
Phil Nash92f08362014-12-22 20:18:05 +00009487 // Don't do anything with this by default.
9488 // It can optionally be overridden in the derived class.
9489 }
9490
Phil Nash7e346192015-11-03 08:00:43 +00009491 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009492 std::ostream& stream;
9493
9494 LazyStat<TestRunInfo> currentTestRunInfo;
9495 LazyStat<GroupInfo> currentGroupInfo;
9496 LazyStat<TestCaseInfo> currentTestCaseInfo;
9497
9498 std::vector<SectionInfo> m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009499 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009500 };
9501
9502 struct CumulativeReporterBase : SharedImpl<IStreamingReporter> {
9503 template<typename T, typename ChildNodeT>
9504 struct Node : SharedImpl<> {
9505 explicit Node( T const& _value ) : value( _value ) {}
9506 virtual ~Node() {}
9507
9508 typedef std::vector<Ptr<ChildNodeT> > ChildNodes;
9509 T value;
9510 ChildNodes children;
9511 };
9512 struct SectionNode : SharedImpl<> {
9513 explicit SectionNode( SectionStats const& _stats ) : stats( _stats ) {}
9514 virtual ~SectionNode();
9515
9516 bool operator == ( SectionNode const& other ) const {
9517 return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;
9518 }
9519 bool operator == ( Ptr<SectionNode> const& other ) const {
9520 return operator==( *other );
9521 }
9522
9523 SectionStats stats;
9524 typedef std::vector<Ptr<SectionNode> > ChildSections;
9525 typedef std::vector<AssertionStats> Assertions;
9526 ChildSections childSections;
9527 Assertions assertions;
9528 std::string stdOut;
9529 std::string stdErr;
9530 };
Phil Nasheb760f62013-12-18 08:38:33 +00009531
9532 struct BySectionInfo {
9533 BySectionInfo( SectionInfo const& other ) : m_other( other ) {}
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009534 BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}
Phil Nasheb760f62013-12-18 08:38:33 +00009535 bool operator() ( Ptr<SectionNode> const& node ) const {
9536 return node->stats.sectionInfo.lineInfo == m_other.lineInfo;
9537 }
9538 private:
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009539 void operator=( BySectionInfo const& );
Phil Nasheb760f62013-12-18 08:38:33 +00009540 SectionInfo const& m_other;
9541 };
Phil Nash3649fdf2013-12-03 18:53:55 +00009542
9543 typedef Node<TestCaseStats, SectionNode> TestCaseNode;
9544 typedef Node<TestGroupStats, TestCaseNode> TestGroupNode;
9545 typedef Node<TestRunStats, TestGroupNode> TestRunNode;
9546
9547 CumulativeReporterBase( ReporterConfig const& _config )
9548 : m_config( _config.fullConfig() ),
9549 stream( _config.stream() )
Phil Nashe73583d2015-08-07 17:30:34 +01009550 {
9551 m_reporterPrefs.shouldRedirectStdOut = false;
9552 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009553 ~CumulativeReporterBase();
9554
Phil Nashe73583d2015-08-07 17:30:34 +01009555 virtual ReporterPreferences getPreferences() const CATCH_OVERRIDE {
9556 return m_reporterPrefs;
9557 }
Phil Nash3649fdf2013-12-03 18:53:55 +00009558
Phil Nashe73583d2015-08-07 17:30:34 +01009559 virtual void testRunStarting( TestRunInfo const& ) CATCH_OVERRIDE {}
9560 virtual void testGroupStarting( GroupInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009561
Phil Nashe73583d2015-08-07 17:30:34 +01009562 virtual void testCaseStarting( TestCaseInfo const& ) CATCH_OVERRIDE {}
9563
9564 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009565 SectionStats incompleteStats( sectionInfo, Counts(), 0, false );
9566 Ptr<SectionNode> node;
9567 if( m_sectionStack.empty() ) {
9568 if( !m_rootSection )
9569 m_rootSection = new SectionNode( incompleteStats );
9570 node = m_rootSection;
9571 }
9572 else {
9573 SectionNode& parentNode = *m_sectionStack.back();
9574 SectionNode::ChildSections::const_iterator it =
Phil Nasheb760f62013-12-18 08:38:33 +00009575 std::find_if( parentNode.childSections.begin(),
9576 parentNode.childSections.end(),
9577 BySectionInfo( sectionInfo ) );
Phil Nash3649fdf2013-12-03 18:53:55 +00009578 if( it == parentNode.childSections.end() ) {
9579 node = new SectionNode( incompleteStats );
9580 parentNode.childSections.push_back( node );
9581 }
9582 else
9583 node = *it;
9584 }
9585 m_sectionStack.push_back( node );
9586 m_deepestSection = node;
9587 }
9588
Phil Nashe73583d2015-08-07 17:30:34 +01009589 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash3649fdf2013-12-03 18:53:55 +00009590
Phil Nashe5537842016-04-25 18:56:50 +01009591 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009592 assert( !m_sectionStack.empty() );
9593 SectionNode& sectionNode = *m_sectionStack.back();
9594 sectionNode.assertions.push_back( assertionStats );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009595 // AssertionResult holds a pointer to a temporary DecomposedExpression,
9596 // which getExpandedExpression() calls to build the expression string.
9597 // Our section stack copy of the assertionResult will likely outlive the
9598 // temporary, so it must be expanded or discarded now to avoid calling
9599 // a destroyed object later.
9600 prepareExpandedExpression( sectionNode.assertions.back().assertionResult );
Phil Nash3649fdf2013-12-03 18:53:55 +00009601 return true;
9602 }
Phil Nashe73583d2015-08-07 17:30:34 +01009603 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009604 assert( !m_sectionStack.empty() );
9605 SectionNode& node = *m_sectionStack.back();
9606 node.stats = sectionStats;
9607 m_sectionStack.pop_back();
9608 }
Phil Nashe73583d2015-08-07 17:30:34 +01009609 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009610 Ptr<TestCaseNode> node = new TestCaseNode( testCaseStats );
9611 assert( m_sectionStack.size() == 0 );
9612 node->children.push_back( m_rootSection );
9613 m_testCases.push_back( node );
9614 m_rootSection.reset();
9615
9616 assert( m_deepestSection );
9617 m_deepestSection->stdOut = testCaseStats.stdOut;
9618 m_deepestSection->stdErr = testCaseStats.stdErr;
9619 }
Phil Nashe73583d2015-08-07 17:30:34 +01009620 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009621 Ptr<TestGroupNode> node = new TestGroupNode( testGroupStats );
9622 node->children.swap( m_testCases );
9623 m_testGroups.push_back( node );
9624 }
Phil Nashe73583d2015-08-07 17:30:34 +01009625 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nash3649fdf2013-12-03 18:53:55 +00009626 Ptr<TestRunNode> node = new TestRunNode( testRunStats );
9627 node->children.swap( m_testGroups );
9628 m_testRuns.push_back( node );
Phil Nasha6d74bd2013-12-11 08:28:15 +00009629 testRunEndedCumulative();
Phil Nash3649fdf2013-12-03 18:53:55 +00009630 }
Phil Nasha6d74bd2013-12-11 08:28:15 +00009631 virtual void testRunEndedCumulative() = 0;
Phil Nash3649fdf2013-12-03 18:53:55 +00009632
Phil Nashe73583d2015-08-07 17:30:34 +01009633 virtual void skipTest( TestCaseInfo const& ) CATCH_OVERRIDE {}
Phil Nash92f08362014-12-22 20:18:05 +00009634
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009635 virtual void prepareExpandedExpression( AssertionResult& result ) const {
9636 if( result.isOk() )
9637 result.discardDecomposedExpression();
9638 else
9639 result.expandDecomposedExpression();
9640 }
9641
Phil Nash7e346192015-11-03 08:00:43 +00009642 Ptr<IConfig const> m_config;
Phil Nash3649fdf2013-12-03 18:53:55 +00009643 std::ostream& stream;
9644 std::vector<AssertionStats> m_assertions;
9645 std::vector<std::vector<Ptr<SectionNode> > > m_sections;
9646 std::vector<Ptr<TestCaseNode> > m_testCases;
9647 std::vector<Ptr<TestGroupNode> > m_testGroups;
9648
9649 std::vector<Ptr<TestRunNode> > m_testRuns;
9650
9651 Ptr<SectionNode> m_rootSection;
9652 Ptr<SectionNode> m_deepestSection;
9653 std::vector<Ptr<SectionNode> > m_sectionStack;
Phil Nashe73583d2015-08-07 17:30:34 +01009654 ReporterPreferences m_reporterPrefs;
Phil Nash3649fdf2013-12-03 18:53:55 +00009655
9656 };
9657
Phil Nash576aff62014-12-21 00:21:23 +00009658 template<char C>
9659 char const* getLineOfChars() {
9660 static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};
9661 if( !*line ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009662 std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );
Phil Nash576aff62014-12-21 00:21:23 +00009663 line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;
9664 }
9665 return line;
9666 }
9667
Phil Nashe73583d2015-08-07 17:30:34 +01009668 struct TestEventListenerBase : StreamingReporterBase {
9669 TestEventListenerBase( ReporterConfig const& _config )
9670 : StreamingReporterBase( _config )
9671 {}
9672
9673 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {}
Phil Nash08844e72015-11-05 18:52:18 +00009674 virtual bool assertionEnded( AssertionStats const& ) CATCH_OVERRIDE {
Phil Nashe73583d2015-08-07 17:30:34 +01009675 return false;
9676 }
9677 };
9678
Phil Nash3649fdf2013-12-03 18:53:55 +00009679} // end namespace Catch
9680
Phil Nash56d5c422012-08-23 20:08:50 +01009681// #included from: ../internal/catch_reporter_registrars.hpp
9682#define TWOBLUECUBES_CATCH_REPORTER_REGISTRARS_HPP_INCLUDED
9683
9684namespace Catch {
9685
9686 template<typename T>
Phil Nasha1fbfea2012-12-01 23:57:18 +00009687 class LegacyReporterRegistrar {
9688
9689 class ReporterFactory : public IReporterFactory {
Phil Nash8defc712013-04-24 19:10:02 +01009690 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash786959d2013-06-07 19:07:50 +01009691 return new LegacyReporterAdapter( new T( config ) );
Phil Nasha1fbfea2012-12-01 23:57:18 +00009692 }
9693
9694 virtual std::string getDescription() const {
9695 return T::getDescription();
9696 }
9697 };
9698
9699 public:
9700
Phil Nash8defc712013-04-24 19:10:02 +01009701 LegacyReporterRegistrar( std::string const& name ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009702 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9703 }
9704 };
9705
9706 template<typename T>
Phil Nash56d5c422012-08-23 20:08:50 +01009707 class ReporterRegistrar {
9708
Phil Nashe73583d2015-08-07 17:30:34 +01009709 class ReporterFactory : public SharedImpl<IReporterFactory> {
Phil Nash56d5c422012-08-23 20:08:50 +01009710
Phil Nasha1fbfea2012-12-01 23:57:18 +00009711 // *** Please Note ***:
9712 // - If you end up here looking at a compiler error because it's trying to register
9713 // your custom reporter class be aware that the native reporter interface has changed
9714 // to IStreamingReporter. The "legacy" interface, IReporter, is still supported via
9715 // an adapter. Just use REGISTER_LEGACY_REPORTER to take advantage of the adapter.
9716 // However please consider updating to the new interface as the old one is now
9717 // deprecated and will probably be removed quite soon!
9718 // Please contact me via github if you have any questions at all about this.
9719 // In fact, ideally, please contact me anyway to let me know you've hit this - as I have
9720 // no idea who is actually using custom reporters at all (possibly no-one!).
9721 // The new interface is designed to minimise exposure to interface changes in the future.
Phil Nash8defc712013-04-24 19:10:02 +01009722 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
Phil Nash56d5c422012-08-23 20:08:50 +01009723 return new T( config );
9724 }
9725
9726 virtual std::string getDescription() const {
9727 return T::getDescription();
9728 }
9729 };
9730
9731 public:
9732
Phil Nash8defc712013-04-24 19:10:02 +01009733 ReporterRegistrar( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009734 getMutableRegistryHub().registerReporter( name, new ReporterFactory() );
9735 }
9736 };
Phil Nashe73583d2015-08-07 17:30:34 +01009737
9738 template<typename T>
9739 class ListenerRegistrar {
9740
9741 class ListenerFactory : public SharedImpl<IReporterFactory> {
9742
9743 virtual IStreamingReporter* create( ReporterConfig const& config ) const {
9744 return new T( config );
9745 }
9746 virtual std::string getDescription() const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +01009747 return std::string();
Phil Nashe73583d2015-08-07 17:30:34 +01009748 }
9749 };
9750
9751 public:
9752
9753 ListenerRegistrar() {
9754 getMutableRegistryHub().registerListener( new ListenerFactory() );
9755 }
9756 };
Phil Nash56d5c422012-08-23 20:08:50 +01009757}
9758
Phil Nasha1fbfea2012-12-01 23:57:18 +00009759#define INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009760 namespace{ Catch::LegacyReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nashe73583d2015-08-07 17:30:34 +01009761
Phil Nash56d5c422012-08-23 20:08:50 +01009762#define INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType ) \
Phil Nash380f98e2013-10-17 22:45:21 +01009763 namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); }
Phil Nash56d5c422012-08-23 20:08:50 +01009764
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01009765// Deprecated - use the form without INTERNAL_
Phil Nashe73583d2015-08-07 17:30:34 +01009766#define INTERNAL_CATCH_REGISTER_LISTENER( listenerType ) \
9767 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9768
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +01009769#define CATCH_REGISTER_LISTENER( listenerType ) \
9770 namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; }
9771
Phil Nash56d5c422012-08-23 20:08:50 +01009772// #included from: ../internal/catch_xmlwriter.hpp
9773#define TWOBLUECUBES_CATCH_XMLWRITER_HPP_INCLUDED
9774
9775#include <sstream>
9776#include <string>
9777#include <vector>
Phil Nash2f6371f2015-07-23 23:06:26 +01009778#include <iomanip>
Phil Nash56d5c422012-08-23 20:08:50 +01009779
9780namespace Catch {
9781
Phil Nash2f6371f2015-07-23 23:06:26 +01009782 class XmlEncode {
9783 public:
9784 enum ForWhat { ForTextNodes, ForAttributes };
9785
9786 XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes )
9787 : m_str( str ),
9788 m_forWhat( forWhat )
9789 {}
9790
9791 void encodeTo( std::ostream& os ) const {
9792
9793 // Apostrophe escaping not necessary if we always use " to write attributes
9794 // (see: http://www.w3.org/TR/xml/#syntax)
9795
9796 for( std::size_t i = 0; i < m_str.size(); ++ i ) {
9797 char c = m_str[i];
9798 switch( c ) {
9799 case '<': os << "&lt;"; break;
9800 case '&': os << "&amp;"; break;
9801
9802 case '>':
9803 // See: http://www.w3.org/TR/xml/#syntax
9804 if( i > 2 && m_str[i-1] == ']' && m_str[i-2] == ']' )
9805 os << "&gt;";
9806 else
9807 os << c;
9808 break;
9809
9810 case '\"':
9811 if( m_forWhat == ForAttributes )
9812 os << "&quot;";
9813 else
9814 os << c;
9815 break;
9816
9817 default:
Phil Nash40f60682016-09-27 10:46:22 +01009818 // Escape control chars - based on contribution by @espenalb in PR #465 and
9819 // by @mrpi PR #588
Phil Nashd08cee22017-02-13 16:15:42 +00009820 if ( ( c >= 0 && c < '\x09' ) || ( c > '\x0D' && c < '\x20') || c=='\x7F' ) {
9821 // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0
9822 os << "\\x" << std::uppercase << std::hex << std::setfill('0') << std::setw(2)
9823 << static_cast<int>( c );
9824 }
Phil Nash2f6371f2015-07-23 23:06:26 +01009825 else
9826 os << c;
9827 }
9828 }
9829 }
9830
9831 friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {
9832 xmlEncode.encodeTo( os );
9833 return os;
9834 }
9835
9836 private:
9837 std::string m_str;
9838 ForWhat m_forWhat;
9839 };
9840
Phil Nash56d5c422012-08-23 20:08:50 +01009841 class XmlWriter {
9842 public:
9843
9844 class ScopedElement {
9845 public:
9846 ScopedElement( XmlWriter* writer )
9847 : m_writer( writer )
9848 {}
9849
Phil Nash8defc712013-04-24 19:10:02 +01009850 ScopedElement( ScopedElement const& other )
Phil Nash56d5c422012-08-23 20:08:50 +01009851 : m_writer( other.m_writer ){
Phil Nashb971fe72015-07-02 08:21:38 +01009852 other.m_writer = CATCH_NULL;
Phil Nash56d5c422012-08-23 20:08:50 +01009853 }
9854
9855 ~ScopedElement() {
9856 if( m_writer )
9857 m_writer->endElement();
9858 }
9859
Phil Nash8defc712013-04-24 19:10:02 +01009860 ScopedElement& writeText( std::string const& text, bool indent = true ) {
Phil Nasha1fbfea2012-12-01 23:57:18 +00009861 m_writer->writeText( text, indent );
Phil Nash56d5c422012-08-23 20:08:50 +01009862 return *this;
9863 }
9864
9865 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009866 ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009867 m_writer->writeAttribute( name, attribute );
9868 return *this;
9869 }
9870
9871 private:
9872 mutable XmlWriter* m_writer;
9873 };
9874
9875 XmlWriter()
9876 : m_tagIsOpen( false ),
9877 m_needsNewline( false ),
Phil Nashd08cee22017-02-13 16:15:42 +00009878 m_os( Catch::cout() )
Phil Nash40f60682016-09-27 10:46:22 +01009879 {
Phil Nashd08cee22017-02-13 16:15:42 +00009880 writeDeclaration();
Phil Nash40f60682016-09-27 10:46:22 +01009881 }
Phil Nash56d5c422012-08-23 20:08:50 +01009882
9883 XmlWriter( std::ostream& os )
9884 : m_tagIsOpen( false ),
9885 m_needsNewline( false ),
Phil Nashd08cee22017-02-13 16:15:42 +00009886 m_os( os )
Phil Nash40f60682016-09-27 10:46:22 +01009887 {
Phil Nashd08cee22017-02-13 16:15:42 +00009888 writeDeclaration();
Phil Nash40f60682016-09-27 10:46:22 +01009889 }
Phil Nash56d5c422012-08-23 20:08:50 +01009890
9891 ~XmlWriter() {
9892 while( !m_tags.empty() )
9893 endElement();
9894 }
9895
Phil Nash8defc712013-04-24 19:10:02 +01009896 XmlWriter& startElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009897 ensureTagClosed();
9898 newlineIfNecessary();
Phil Nashd08cee22017-02-13 16:15:42 +00009899 m_os << m_indent << '<' << name;
Phil Nash56d5c422012-08-23 20:08:50 +01009900 m_tags.push_back( name );
9901 m_indent += " ";
9902 m_tagIsOpen = true;
9903 return *this;
9904 }
9905
Phil Nash8defc712013-04-24 19:10:02 +01009906 ScopedElement scopedElement( std::string const& name ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009907 ScopedElement scoped( this );
9908 startElement( name );
9909 return scoped;
9910 }
9911
9912 XmlWriter& endElement() {
9913 newlineIfNecessary();
9914 m_indent = m_indent.substr( 0, m_indent.size()-2 );
9915 if( m_tagIsOpen ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009916 m_os << "/>";
Phil Nash56d5c422012-08-23 20:08:50 +01009917 m_tagIsOpen = false;
9918 }
9919 else {
Phil Nashd08cee22017-02-13 16:15:42 +00009920 m_os << m_indent << "</" << m_tags.back() << ">";
Phil Nash56d5c422012-08-23 20:08:50 +01009921 }
Phil Nashd08cee22017-02-13 16:15:42 +00009922 m_os << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01009923 m_tags.pop_back();
9924 return *this;
9925 }
9926
Phil Nash8defc712013-04-24 19:10:02 +01009927 XmlWriter& writeAttribute( std::string const& name, std::string const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009928 if( !name.empty() && !attribute.empty() )
Phil Nashd08cee22017-02-13 16:15:42 +00009929 m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009930 return *this;
9931 }
9932
Phil Nash8defc712013-04-24 19:10:02 +01009933 XmlWriter& writeAttribute( std::string const& name, bool attribute ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009934 m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';
Phil Nash56d5c422012-08-23 20:08:50 +01009935 return *this;
9936 }
9937
9938 template<typename T>
Phil Nash8defc712013-04-24 19:10:02 +01009939 XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {
Phil Nash2f6371f2015-07-23 23:06:26 +01009940 std::ostringstream oss;
9941 oss << attribute;
9942 return writeAttribute( name, oss.str() );
Phil Nash56d5c422012-08-23 20:08:50 +01009943 }
9944
Phil Nash8defc712013-04-24 19:10:02 +01009945 XmlWriter& writeText( std::string const& text, bool indent = true ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009946 if( !text.empty() ){
9947 bool tagWasOpen = m_tagIsOpen;
9948 ensureTagClosed();
Phil Nasha1fbfea2012-12-01 23:57:18 +00009949 if( tagWasOpen && indent )
Phil Nashd08cee22017-02-13 16:15:42 +00009950 m_os << m_indent;
9951 m_os << XmlEncode( text );
Phil Nash56d5c422012-08-23 20:08:50 +01009952 m_needsNewline = true;
9953 }
9954 return *this;
9955 }
9956
Phil Nash8defc712013-04-24 19:10:02 +01009957 XmlWriter& writeComment( std::string const& text ) {
Phil Nash56d5c422012-08-23 20:08:50 +01009958 ensureTagClosed();
Phil Nashd08cee22017-02-13 16:15:42 +00009959 m_os << m_indent << "<!--" << text << "-->";
Phil Nash56d5c422012-08-23 20:08:50 +01009960 m_needsNewline = true;
9961 return *this;
9962 }
9963
Phil Nashd08cee22017-02-13 16:15:42 +00009964 void writeStylesheetRef( std::string const& url ) {
9965 m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";
9966 }
9967
Phil Nash56d5c422012-08-23 20:08:50 +01009968 XmlWriter& writeBlankLine() {
9969 ensureTagClosed();
Phil Nashd08cee22017-02-13 16:15:42 +00009970 m_os << '\n';
Phil Nash56d5c422012-08-23 20:08:50 +01009971 return *this;
9972 }
9973
Phil Nashd08cee22017-02-13 16:15:42 +00009974 void ensureTagClosed() {
9975 if( m_tagIsOpen ) {
9976 m_os << ">" << std::endl;
9977 m_tagIsOpen = false;
9978 }
Phil Nash9241e432014-05-20 18:50:59 +01009979 }
9980
Phil Nash56d5c422012-08-23 20:08:50 +01009981 private:
Phil Nash9241e432014-05-20 18:50:59 +01009982 XmlWriter( XmlWriter const& );
9983 void operator=( XmlWriter const& );
Phil Nash56d5c422012-08-23 20:08:50 +01009984
Phil Nashd08cee22017-02-13 16:15:42 +00009985 void writeDeclaration() {
9986 m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
Phil Nash56d5c422012-08-23 20:08:50 +01009987 }
9988
9989 void newlineIfNecessary() {
9990 if( m_needsNewline ) {
Phil Nashd08cee22017-02-13 16:15:42 +00009991 m_os << std::endl;
Phil Nash56d5c422012-08-23 20:08:50 +01009992 m_needsNewline = false;
9993 }
9994 }
9995
Phil Nash56d5c422012-08-23 20:08:50 +01009996 bool m_tagIsOpen;
9997 bool m_needsNewline;
9998 std::vector<std::string> m_tags;
9999 std::string m_indent;
Phil Nashd08cee22017-02-13 16:15:42 +000010000 std::ostream& m_os;
Phil Nash56d5c422012-08-23 20:08:50 +010010001 };
10002
10003}
Phil Nash2f6371f2015-07-23 23:06:26 +010010004// #included from: catch_reenable_warnings.h
10005
10006#define TWOBLUECUBES_CATCH_REENABLE_WARNINGS_H_INCLUDED
10007
10008#ifdef __clang__
10009# ifdef __ICC // icpc defines the __clang__ macro
10010# pragma warning(pop)
10011# else
10012# pragma clang diagnostic pop
10013# endif
10014#elif defined __GNUC__
10015# pragma GCC diagnostic pop
10016#endif
10017
10018
Phil Nash56d5c422012-08-23 20:08:50 +010010019namespace Catch {
Phil Nashd76e0812014-12-30 18:26:07 +000010020 class XmlReporter : public StreamingReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +010010021 public:
Phil Nashd76e0812014-12-30 18:26:07 +000010022 XmlReporter( ReporterConfig const& _config )
10023 : StreamingReporterBase( _config ),
Phil Nash2be37272016-11-29 12:15:50 +000010024 m_xml(_config.stream()),
Phil Nashd76e0812014-12-30 18:26:07 +000010025 m_sectionDepth( 0 )
Phil Nashe73583d2015-08-07 17:30:34 +010010026 {
10027 m_reporterPrefs.shouldRedirectStdOut = true;
10028 }
Phil Nashd76e0812014-12-30 18:26:07 +000010029
Phil Nashe73583d2015-08-07 17:30:34 +010010030 virtual ~XmlReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +010010031
10032 static std::string getDescription() {
10033 return "Reports test results as an XML document";
10034 }
Phil Nash56d5c422012-08-23 20:08:50 +010010035
Phil Nashd08cee22017-02-13 16:15:42 +000010036 virtual std::string getStylesheetRef() const {
10037 return std::string();
10038 }
10039
Phil Nash0952b762017-02-28 14:19:09 +000010040 void writeSourceInfo( SourceLineInfo const& sourceInfo ) {
10041 m_xml
10042 .writeAttribute( "filename", sourceInfo.file )
10043 .writeAttribute( "line", sourceInfo.line );
10044 }
10045
Phil Nashd76e0812014-12-30 18:26:07 +000010046 public: // StreamingReporterBase
Phil Nash56d5c422012-08-23 20:08:50 +010010047
Phil Nashe73583d2015-08-07 17:30:34 +010010048 virtual void noMatchingTestCases( std::string const& s ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010049 StreamingReporterBase::noMatchingTestCases( s );
10050 }
10051
Phil Nashe73583d2015-08-07 17:30:34 +010010052 virtual void testRunStarting( TestRunInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010053 StreamingReporterBase::testRunStarting( testInfo );
Phil Nashd08cee22017-02-13 16:15:42 +000010054 std::string stylesheetRef = getStylesheetRef();
10055 if( !stylesheetRef.empty() )
10056 m_xml.writeStylesheetRef( stylesheetRef );
Phil Nash56d5c422012-08-23 20:08:50 +010010057 m_xml.startElement( "Catch" );
Phil Nashd76e0812014-12-30 18:26:07 +000010058 if( !m_config->name().empty() )
10059 m_xml.writeAttribute( "name", m_config->name() );
Phil Nash56d5c422012-08-23 20:08:50 +010010060 }
10061
Phil Nashe73583d2015-08-07 17:30:34 +010010062 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010063 StreamingReporterBase::testGroupStarting( groupInfo );
Phil Nash56d5c422012-08-23 20:08:50 +010010064 m_xml.startElement( "Group" )
Phil Nashd76e0812014-12-30 18:26:07 +000010065 .writeAttribute( "name", groupInfo.name );
Phil Nash56d5c422012-08-23 20:08:50 +010010066 }
10067
Phil Nashe73583d2015-08-07 17:30:34 +010010068 virtual void testCaseStarting( TestCaseInfo const& testInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010069 StreamingReporterBase::testCaseStarting(testInfo);
Phil Nashd08cee22017-02-13 16:15:42 +000010070 m_xml.startElement( "TestCase" )
10071 .writeAttribute( "name", trim( testInfo.name ) )
10072 .writeAttribute( "description", testInfo.description )
10073 .writeAttribute( "tags", testInfo.tagsAsString );
Phil Nashd76e0812014-12-30 18:26:07 +000010074
Phil Nash0952b762017-02-28 14:19:09 +000010075 writeSourceInfo( testInfo.lineInfo );
10076
Phil Nashd76e0812014-12-30 18:26:07 +000010077 if ( m_config->showDurations() == ShowDurations::Always )
10078 m_testCaseTimer.start();
Phil Nashd08cee22017-02-13 16:15:42 +000010079 m_xml.ensureTagClosed();
Phil Nash56d5c422012-08-23 20:08:50 +010010080 }
10081
Phil Nashe73583d2015-08-07 17:30:34 +010010082 virtual void sectionStarting( SectionInfo const& sectionInfo ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010083 StreamingReporterBase::sectionStarting( sectionInfo );
Phil Nash8a52a392013-07-25 08:12:03 +010010084 if( m_sectionDepth++ > 0 ) {
10085 m_xml.startElement( "Section" )
Phil Nashd76e0812014-12-30 18:26:07 +000010086 .writeAttribute( "name", trim( sectionInfo.name ) )
10087 .writeAttribute( "description", sectionInfo.description );
Phil Nash0952b762017-02-28 14:19:09 +000010088 writeSourceInfo( sectionInfo.lineInfo );
Phil Nashd08cee22017-02-13 16:15:42 +000010089 m_xml.ensureTagClosed();
Phil Nash8a52a392013-07-25 08:12:03 +010010090 }
Phil Nash56d5c422012-08-23 20:08:50 +010010091 }
10092
Phil Nashe73583d2015-08-07 17:30:34 +010010093 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE { }
Phil Nash56d5c422012-08-23 20:08:50 +010010094
Phil Nashe73583d2015-08-07 17:30:34 +010010095 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Phil Nash56d5c422012-08-23 20:08:50 +010010096
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010097 AssertionResult const& result = assertionStats.assertionResult;
10098
10099 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
10100
10101 if( includeResults ) {
10102 // Print any info messages in <Info> tags.
Phil Nashd76e0812014-12-30 18:26:07 +000010103 for( std::vector<MessageInfo>::const_iterator it = assertionStats.infoMessages.begin(), itEnd = assertionStats.infoMessages.end();
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010104 it != itEnd;
10105 ++it ) {
Phil Nashd76e0812014-12-30 18:26:07 +000010106 if( it->type == ResultWas::Info ) {
10107 m_xml.scopedElement( "Info" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010108 .writeText( it->message );
Phil Nashd76e0812014-12-30 18:26:07 +000010109 } else if ( it->type == ResultWas::Warning ) {
10110 m_xml.scopedElement( "Warning" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010111 .writeText( it->message );
Phil Nashd76e0812014-12-30 18:26:07 +000010112 }
10113 }
10114 }
10115
10116 // Drop out if result was successful but we're not printing them.
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010117 if( !includeResults && result.getResultType() != ResultWas::Warning )
Phil Nashd76e0812014-12-30 18:26:07 +000010118 return true;
10119
10120 // Print the expression if there is one.
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010121 if( result.hasExpression() ) {
Phil Nash56d5c422012-08-23 20:08:50 +010010122 m_xml.startElement( "Expression" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010123 .writeAttribute( "success", result.succeeded() )
10124 .writeAttribute( "type", result.getTestMacroName() );
Phil Nash0952b762017-02-28 14:19:09 +000010125
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010126 writeSourceInfo( result.getSourceInfo() );
Phil Nash56d5c422012-08-23 20:08:50 +010010127
10128 m_xml.scopedElement( "Original" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010129 .writeText( result.getExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +010010130 m_xml.scopedElement( "Expanded" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010131 .writeText( result.getExpandedExpression() );
Phil Nash56d5c422012-08-23 20:08:50 +010010132 }
10133
Phil Nashd76e0812014-12-30 18:26:07 +000010134 // And... Print a result applicable to each result type.
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010135 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +010010136 case ResultWas::ThrewException:
Phil Nash0952b762017-02-28 14:19:09 +000010137 m_xml.startElement( "Exception" );
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010138 writeSourceInfo( result.getSourceInfo() );
10139 m_xml.writeText( result.getMessage() );
Phil Nash0952b762017-02-28 14:19:09 +000010140 m_xml.endElement();
Phil Nash56d5c422012-08-23 20:08:50 +010010141 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010142 case ResultWas::FatalErrorCondition:
Phil Nash0952b762017-02-28 14:19:09 +000010143 m_xml.startElement( "FatalErrorCondition" );
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010144 writeSourceInfo( result.getSourceInfo() );
10145 m_xml.writeText( result.getMessage() );
Phil Nash0952b762017-02-28 14:19:09 +000010146 m_xml.endElement();
Phil Nash93b61e12014-08-22 19:35:41 +010010147 break;
Phil Nash56d5c422012-08-23 20:08:50 +010010148 case ResultWas::Info:
10149 m_xml.scopedElement( "Info" )
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010150 .writeText( result.getMessage() );
Phil Nash56d5c422012-08-23 20:08:50 +010010151 break;
10152 case ResultWas::Warning:
Phil Nashd76e0812014-12-30 18:26:07 +000010153 // Warning will already have been written
Phil Nash56d5c422012-08-23 20:08:50 +010010154 break;
10155 case ResultWas::ExplicitFailure:
Phil Nash0952b762017-02-28 14:19:09 +000010156 m_xml.startElement( "Failure" );
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010157 writeSourceInfo( result.getSourceInfo() );
10158 m_xml.writeText( result.getMessage() );
Phil Nash0952b762017-02-28 14:19:09 +000010159 m_xml.endElement();
Phil Nash56d5c422012-08-23 20:08:50 +010010160 break;
Phil Nashd76e0812014-12-30 18:26:07 +000010161 default:
Phil Nash56d5c422012-08-23 20:08:50 +010010162 break;
10163 }
Phil Nashd76e0812014-12-30 18:26:07 +000010164
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010165 if( result.hasExpression() )
Phil Nash56d5c422012-08-23 20:08:50 +010010166 m_xml.endElement();
Phil Nashd76e0812014-12-30 18:26:07 +000010167
10168 return true;
Phil Nash56d5c422012-08-23 20:08:50 +010010169 }
10170
Phil Nashe73583d2015-08-07 17:30:34 +010010171 virtual void sectionEnded( SectionStats const& sectionStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010172 StreamingReporterBase::sectionEnded( sectionStats );
10173 if( --m_sectionDepth > 0 ) {
10174 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );
10175 e.writeAttribute( "successes", sectionStats.assertions.passed );
10176 e.writeAttribute( "failures", sectionStats.assertions.failed );
10177 e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );
10178
10179 if ( m_config->showDurations() == ShowDurations::Always )
10180 e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );
10181
10182 m_xml.endElement();
10183 }
Phil Nash56d5c422012-08-23 20:08:50 +010010184 }
10185
Phil Nashe73583d2015-08-07 17:30:34 +010010186 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010187 StreamingReporterBase::testCaseEnded( testCaseStats );
10188 XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );
10189 e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );
10190
10191 if ( m_config->showDurations() == ShowDurations::Always )
10192 e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );
10193
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010194 if( !testCaseStats.stdOut.empty() )
10195 m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), false );
10196 if( !testCaseStats.stdErr.empty() )
10197 m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), false );
10198
Phil Nashd76e0812014-12-30 18:26:07 +000010199 m_xml.endElement();
10200 }
10201
Phil Nashe73583d2015-08-07 17:30:34 +010010202 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010203 StreamingReporterBase::testGroupEnded( testGroupStats );
10204 // TODO: Check testGroupStats.aborting and act accordingly.
10205 m_xml.scopedElement( "OverallResults" )
10206 .writeAttribute( "successes", testGroupStats.totals.assertions.passed )
10207 .writeAttribute( "failures", testGroupStats.totals.assertions.failed )
10208 .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );
10209 m_xml.endElement();
10210 }
10211
Phil Nashe73583d2015-08-07 17:30:34 +010010212 virtual void testRunEnded( TestRunStats const& testRunStats ) CATCH_OVERRIDE {
Phil Nashd76e0812014-12-30 18:26:07 +000010213 StreamingReporterBase::testRunEnded( testRunStats );
10214 m_xml.scopedElement( "OverallResults" )
10215 .writeAttribute( "successes", testRunStats.totals.assertions.passed )
10216 .writeAttribute( "failures", testRunStats.totals.assertions.failed )
10217 .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );
Phil Nash56d5c422012-08-23 20:08:50 +010010218 m_xml.endElement();
10219 }
10220
10221 private:
Phil Nashd76e0812014-12-30 18:26:07 +000010222 Timer m_testCaseTimer;
Phil Nash56d5c422012-08-23 20:08:50 +010010223 XmlWriter m_xml;
Phil Nash8a52a392013-07-25 08:12:03 +010010224 int m_sectionDepth;
Phil Nash56d5c422012-08-23 20:08:50 +010010225 };
10226
Phil Nashd76e0812014-12-30 18:26:07 +000010227 INTERNAL_CATCH_REGISTER_REPORTER( "xml", XmlReporter )
10228
Phil Nash56d5c422012-08-23 20:08:50 +010010229} // end namespace Catch
10230
10231// #included from: ../reporters/catch_reporter_junit.hpp
10232#define TWOBLUECUBES_CATCH_REPORTER_JUNIT_HPP_INCLUDED
10233
Phil Nashf276a052012-12-02 00:05:51 +000010234#include <assert.h>
10235
Phil Nash56d5c422012-08-23 20:08:50 +010010236namespace Catch {
10237
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010238 namespace {
10239 std::string getCurrentTimestamp() {
10240 // Beware, this is not reentrant because of backward compatibility issues
10241 // Also, UTC only, again because of backward compatibility (%z is C++11)
10242 time_t rawtime;
10243 std::time(&rawtime);
10244 const size_t timeStampSize = sizeof("2017-01-16T17:06:45Z");
10245
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010246#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010247 std::tm timeInfo = {};
10248 gmtime_s(&timeInfo, &rawtime);
10249#else
10250 std::tm* timeInfo;
10251 timeInfo = std::gmtime(&rawtime);
10252#endif
10253
10254 char timeStamp[timeStampSize];
10255 const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";
10256
Martin Hořeňovský7b8a27e2017-02-07 10:06:52 +010010257#ifdef _MSC_VER
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010258 std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);
10259#else
10260 std::strftime(timeStamp, timeStampSize, fmt, timeInfo);
10261#endif
10262 return std::string(timeStamp);
10263 }
10264
10265 }
10266
Phil Nashaa7123b2013-08-15 19:01:00 +010010267 class JunitReporter : public CumulativeReporterBase {
Phil Nash56d5c422012-08-23 20:08:50 +010010268 public:
Phil Nashaa7123b2013-08-15 19:01:00 +010010269 JunitReporter( ReporterConfig const& _config )
10270 : CumulativeReporterBase( _config ),
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +020010271 xml( _config.stream() ),
10272 m_okToFail( false )
Phil Nashe73583d2015-08-07 17:30:34 +010010273 {
10274 m_reporterPrefs.shouldRedirectStdOut = true;
10275 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010276
Phil Nashe73583d2015-08-07 17:30:34 +010010277 virtual ~JunitReporter() CATCH_OVERRIDE;
Phil Nash56d5c422012-08-23 20:08:50 +010010278
10279 static std::string getDescription() {
10280 return "Reports test results in an XML format that looks like Ant's junitreport target";
10281 }
10282
Phil Nashe73583d2015-08-07 17:30:34 +010010283 virtual void noMatchingTestCases( std::string const& /*spec*/ ) CATCH_OVERRIDE {}
Phil Nash56d5c422012-08-23 20:08:50 +010010284
Phil Nashe73583d2015-08-07 17:30:34 +010010285 virtual void testRunStarting( TestRunInfo const& runInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010286 CumulativeReporterBase::testRunStarting( runInfo );
10287 xml.startElement( "testsuites" );
10288 }
Phil Nash56d5c422012-08-23 20:08:50 +010010289
Phil Nashe73583d2015-08-07 17:30:34 +010010290 virtual void testGroupStarting( GroupInfo const& groupInfo ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010291 suiteTimer.start();
10292 stdOutForSuite.str("");
10293 stdErrForSuite.str("");
10294 unexpectedExceptions = 0;
10295 CumulativeReporterBase::testGroupStarting( groupInfo );
10296 }
10297
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +020010298 virtual void testCaseStarting( TestCaseInfo const& testCaseInfo ) CATCH_OVERRIDE {
10299 m_okToFail = testCaseInfo.okToFail();
10300 }
Phil Nashe73583d2015-08-07 17:30:34 +010010301 virtual bool assertionEnded( AssertionStats const& assertionStats ) CATCH_OVERRIDE {
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +020010302 if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )
Phil Nashaa7123b2013-08-15 19:01:00 +010010303 unexpectedExceptions++;
10304 return CumulativeReporterBase::assertionEnded( assertionStats );
10305 }
10306
Phil Nashe73583d2015-08-07 17:30:34 +010010307 virtual void testCaseEnded( TestCaseStats const& testCaseStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010308 stdOutForSuite << testCaseStats.stdOut;
10309 stdErrForSuite << testCaseStats.stdErr;
10310 CumulativeReporterBase::testCaseEnded( testCaseStats );
10311 }
10312
Phil Nashe73583d2015-08-07 17:30:34 +010010313 virtual void testGroupEnded( TestGroupStats const& testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010314 double suiteTime = suiteTimer.getElapsedSeconds();
10315 CumulativeReporterBase::testGroupEnded( testGroupStats );
10316 writeGroup( *m_testGroups.back(), suiteTime );
10317 }
10318
Phil Nashe73583d2015-08-07 17:30:34 +010010319 virtual void testRunEndedCumulative() CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010320 xml.endElement();
10321 }
10322
10323 void writeGroup( TestGroupNode const& groupNode, double suiteTime ) {
10324 XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );
10325 TestGroupStats const& stats = groupNode.value;
10326 xml.writeAttribute( "name", stats.groupInfo.name );
10327 xml.writeAttribute( "errors", unexpectedExceptions );
10328 xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );
10329 xml.writeAttribute( "tests", stats.totals.assertions.total() );
10330 xml.writeAttribute( "hostname", "tbd" ); // !TBD
10331 if( m_config->showDurations() == ShowDurations::Never )
10332 xml.writeAttribute( "time", "" );
Phil Nashef60d542012-11-16 08:47:03 +000010333 else
Phil Nashaa7123b2013-08-15 19:01:00 +010010334 xml.writeAttribute( "time", suiteTime );
Martin Hořeňovský9a566092017-01-20 12:49:59 +010010335 xml.writeAttribute( "timestamp", getCurrentTimestamp() );
Phil Nashaa7123b2013-08-15 19:01:00 +010010336
10337 // Write test cases
10338 for( TestGroupNode::ChildNodes::const_iterator
10339 it = groupNode.children.begin(), itEnd = groupNode.children.end();
10340 it != itEnd;
10341 ++it )
10342 writeTestCase( **it );
10343
10344 xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite.str() ), false );
10345 xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite.str() ), false );
Phil Nash56d5c422012-08-23 20:08:50 +010010346 }
10347
Phil Nashaa7123b2013-08-15 19:01:00 +010010348 void writeTestCase( TestCaseNode const& testCaseNode ) {
10349 TestCaseStats const& stats = testCaseNode.value;
10350
10351 // All test cases have exactly one section - which represents the
10352 // test case itself. That section may have 0-n nested sections
10353 assert( testCaseNode.children.size() == 1 );
10354 SectionNode const& rootSection = *testCaseNode.children.front();
10355
10356 std::string className = stats.testInfo.className;
10357
10358 if( className.empty() ) {
10359 if( rootSection.childSections.empty() )
10360 className = "global";
10361 }
10362 writeSection( className, "", rootSection );
Phil Nash56d5c422012-08-23 20:08:50 +010010363 }
10364
Phil Nashaa7123b2013-08-15 19:01:00 +010010365 void writeSection( std::string const& className,
10366 std::string const& rootName,
10367 SectionNode const& sectionNode ) {
10368 std::string name = trim( sectionNode.stats.sectionInfo.name );
10369 if( !rootName.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010370 name = rootName + '/' + name;
Phil Nash56d5c422012-08-23 20:08:50 +010010371
Phil Nashaa7123b2013-08-15 19:01:00 +010010372 if( !sectionNode.assertions.empty() ||
10373 !sectionNode.stdOut.empty() ||
10374 !sectionNode.stdErr.empty() ) {
10375 XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );
10376 if( className.empty() ) {
10377 xml.writeAttribute( "classname", name );
10378 xml.writeAttribute( "name", "root" );
10379 }
10380 else {
10381 xml.writeAttribute( "classname", className );
10382 xml.writeAttribute( "name", name );
10383 }
Phil Nash13f98432014-12-12 08:11:18 +000010384 xml.writeAttribute( "time", Catch::toString( sectionNode.stats.durationInSeconds ) );
Phil Nasha70fbe32012-08-31 08:10:36 +010010385
Phil Nashaa7123b2013-08-15 19:01:00 +010010386 writeAssertions( sectionNode );
Phil Nash56d5c422012-08-23 20:08:50 +010010387
Phil Nashaa7123b2013-08-15 19:01:00 +010010388 if( !sectionNode.stdOut.empty() )
10389 xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), false );
10390 if( !sectionNode.stdErr.empty() )
10391 xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), false );
10392 }
10393 for( SectionNode::ChildSections::const_iterator
10394 it = sectionNode.childSections.begin(),
10395 itEnd = sectionNode.childSections.end();
10396 it != itEnd;
10397 ++it )
10398 if( className.empty() )
10399 writeSection( name, "", **it );
10400 else
10401 writeSection( className, name, **it );
Phil Nash56d5c422012-08-23 20:08:50 +010010402 }
10403
Phil Nashaa7123b2013-08-15 19:01:00 +010010404 void writeAssertions( SectionNode const& sectionNode ) {
10405 for( SectionNode::Assertions::const_iterator
10406 it = sectionNode.assertions.begin(), itEnd = sectionNode.assertions.end();
10407 it != itEnd;
10408 ++it )
10409 writeAssertion( *it );
10410 }
10411 void writeAssertion( AssertionStats const& stats ) {
10412 AssertionResult const& result = stats.assertionResult;
10413 if( !result.isOk() ) {
10414 std::string elementName;
10415 switch( result.getResultType() ) {
Phil Nash56d5c422012-08-23 20:08:50 +010010416 case ResultWas::ThrewException:
Phil Nash93b61e12014-08-22 19:35:41 +010010417 case ResultWas::FatalErrorCondition:
Phil Nashaa7123b2013-08-15 19:01:00 +010010418 elementName = "error";
Phil Nash56d5c422012-08-23 20:08:50 +010010419 break;
10420 case ResultWas::ExplicitFailure:
Phil Nashaa7123b2013-08-15 19:01:00 +010010421 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010422 break;
10423 case ResultWas::ExpressionFailed:
Phil Nashaa7123b2013-08-15 19:01:00 +010010424 elementName = "failure";
Phil Nash56d5c422012-08-23 20:08:50 +010010425 break;
Phil Nash243f2d22013-04-12 10:43:06 +010010426 case ResultWas::DidntThrowException:
Phil Nashaa7123b2013-08-15 19:01:00 +010010427 elementName = "failure";
Phil Nash243f2d22013-04-12 10:43:06 +010010428 break;
Phil Nashaa7123b2013-08-15 19:01:00 +010010429
10430 // We should never see these here:
10431 case ResultWas::Info:
10432 case ResultWas::Warning:
10433 case ResultWas::Ok:
Phil Nash56d5c422012-08-23 20:08:50 +010010434 case ResultWas::Unknown:
10435 case ResultWas::FailureBit:
10436 case ResultWas::Exception:
Phil Nashaa7123b2013-08-15 19:01:00 +010010437 elementName = "internalError";
Phil Nash56d5c422012-08-23 20:08:50 +010010438 break;
10439 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010440
10441 XmlWriter::ScopedElement e = xml.scopedElement( elementName );
10442
10443 xml.writeAttribute( "message", result.getExpandedExpression() );
10444 xml.writeAttribute( "type", result.getTestMacroName() );
10445
10446 std::ostringstream oss;
10447 if( !result.getMessage().empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010448 oss << result.getMessage() << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010449 for( std::vector<MessageInfo>::const_iterator
10450 it = stats.infoMessages.begin(),
10451 itEnd = stats.infoMessages.end();
10452 it != itEnd;
10453 ++it )
10454 if( it->type == ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010455 oss << it->message << '\n';
Phil Nashaa7123b2013-08-15 19:01:00 +010010456
10457 oss << "at " << result.getSourceInfo();
10458 xml.writeText( oss.str(), false );
Phil Nash56d5c422012-08-23 20:08:50 +010010459 }
10460 }
10461
Phil Nashaa7123b2013-08-15 19:01:00 +010010462 XmlWriter xml;
10463 Timer suiteTimer;
10464 std::ostringstream stdOutForSuite;
10465 std::ostringstream stdErrForSuite;
10466 unsigned int unexpectedExceptions;
Martin Hořeňovskýfc7f0a02017-04-25 11:08:02 +020010467 bool m_okToFail;
Phil Nash56d5c422012-08-23 20:08:50 +010010468 };
10469
Phil Nashaa7123b2013-08-15 19:01:00 +010010470 INTERNAL_CATCH_REGISTER_REPORTER( "junit", JunitReporter )
10471
Phil Nash56d5c422012-08-23 20:08:50 +010010472} // end namespace Catch
10473
Phil Nashff03cdf2012-12-06 08:44:51 +000010474// #included from: ../reporters/catch_reporter_console.hpp
10475#define TWOBLUECUBES_CATCH_REPORTER_CONSOLE_HPP_INCLUDED
10476
Phil Nash0952b762017-02-28 14:19:09 +000010477#include <cfloat>
10478#include <cstdio>
10479
Phil Nashff03cdf2012-12-06 08:44:51 +000010480namespace Catch {
10481
Phil Nash2e7d9662013-01-16 09:44:43 +000010482 struct ConsoleReporter : StreamingReporterBase {
Phil Nashff03cdf2012-12-06 08:44:51 +000010483 ConsoleReporter( ReporterConfig const& _config )
Phil Nash2e7d9662013-01-16 09:44:43 +000010484 : StreamingReporterBase( _config ),
Phil Nash08e52962014-07-03 19:08:44 +010010485 m_headerPrinted( false )
Phil Nashff03cdf2012-12-06 08:44:51 +000010486 {}
10487
Phil Nashe73583d2015-08-07 17:30:34 +010010488 virtual ~ConsoleReporter() CATCH_OVERRIDE;
Phil Nashff03cdf2012-12-06 08:44:51 +000010489 static std::string getDescription() {
10490 return "Reports test results as plain lines of text";
10491 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010492
Phil Nashe73583d2015-08-07 17:30:34 +010010493 virtual void noMatchingTestCases( std::string const& spec ) CATCH_OVERRIDE {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010494 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash37186a12013-03-13 12:19:30 +000010495 }
10496
Phil Nashe73583d2015-08-07 17:30:34 +010010497 virtual void assertionStarting( AssertionInfo const& ) CATCH_OVERRIDE {
Phil Nashff03cdf2012-12-06 08:44:51 +000010498 }
Phil Nashbcad0932012-12-10 08:54:57 +000010499
Phil Nashe73583d2015-08-07 17:30:34 +010010500 virtual bool assertionEnded( AssertionStats const& _assertionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010501 AssertionResult const& result = _assertionStats.assertionResult;
Phil Nashbcad0932012-12-10 08:54:57 +000010502
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010503 bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();
Phil Nash8d44f2d2013-11-13 08:10:45 +000010504
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010505 // Drop out if result was successful but we're not printing them.
10506 if( !includeResults && result.getResultType() != ResultWas::Warning )
10507 return false;
Phil Nashbcad0932012-12-10 08:54:57 +000010508
10509 lazyPrint();
10510
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010511 AssertionPrinter printer( stream, _assertionStats, includeResults );
Phil Nashe4756452013-01-26 20:18:30 +000010512 printer.print();
Phil Nash2e7d9662013-01-16 09:44:43 +000010513 stream << std::endl;
Phil Nashb5fd5a62013-06-28 17:09:57 +010010514 return true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010515 }
10516
Phil Nashe73583d2015-08-07 17:30:34 +010010517 virtual void sectionStarting( SectionInfo const& _sectionInfo ) CATCH_OVERRIDE {
Phil Nasha04981b2013-03-08 09:30:25 +000010518 m_headerPrinted = false;
Phil Nashe4756452013-01-26 20:18:30 +000010519 StreamingReporterBase::sectionStarting( _sectionInfo );
Phil Nash2e7d9662013-01-16 09:44:43 +000010520 }
Phil Nashe73583d2015-08-07 17:30:34 +010010521 virtual void sectionEnded( SectionStats const& _sectionStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010522 if( _sectionStats.missingAssertions ) {
10523 lazyPrint();
Phil Nash12c16ff2013-04-05 20:58:01 +010010524 Colour colour( Colour::ResultError );
Phil Nashaa7123b2013-08-15 19:01:00 +010010525 if( m_sectionStack.size() > 1 )
10526 stream << "\nNo assertions in section";
10527 else
10528 stream << "\nNo assertions in test case";
10529 stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010530 }
Phil Nash0952b762017-02-28 14:19:09 +000010531 if( m_config->showDurations() == ShowDurations::Always ) {
10532 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
Phil Nash46118712013-08-16 19:01:32 +010010533 }
Phil Nash0952b762017-02-28 14:19:09 +000010534 if( m_headerPrinted ) {
10535 m_headerPrinted = false;
Phil Nashf7378ee2013-09-07 12:07:38 +010010536 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010537 StreamingReporterBase::sectionEnded( _sectionStats );
10538 }
10539
Phil Nashe73583d2015-08-07 17:30:34 +010010540 virtual void testCaseEnded( TestCaseStats const& _testCaseStats ) CATCH_OVERRIDE {
Phil Nash2e7d9662013-01-16 09:44:43 +000010541 StreamingReporterBase::testCaseEnded( _testCaseStats );
Phil Nasha04981b2013-03-08 09:30:25 +000010542 m_headerPrinted = false;
Phil Nash2e7d9662013-01-16 09:44:43 +000010543 }
Phil Nashe73583d2015-08-07 17:30:34 +010010544 virtual void testGroupEnded( TestGroupStats const& _testGroupStats ) CATCH_OVERRIDE {
Phil Nashaa7123b2013-08-15 19:01:00 +010010545 if( currentGroupInfo.used ) {
Phil Nash2e7d9662013-01-16 09:44:43 +000010546 printSummaryDivider();
10547 stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";
10548 printTotals( _testGroupStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010549 stream << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010550 }
10551 StreamingReporterBase::testGroupEnded( _testGroupStats );
10552 }
Phil Nashe73583d2015-08-07 17:30:34 +010010553 virtual void testRunEnded( TestRunStats const& _testRunStats ) CATCH_OVERRIDE {
Phil Nash52e1e742014-07-03 08:11:38 +010010554 printTotalsDivider( _testRunStats.totals );
Phil Nash2e7d9662013-01-16 09:44:43 +000010555 printTotals( _testRunStats.totals );
Phil Nash52e1e742014-07-03 08:11:38 +010010556 stream << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010557 StreamingReporterBase::testRunEnded( _testRunStats );
10558 }
10559
10560 private:
Phil Nashe4756452013-01-26 20:18:30 +000010561
10562 class AssertionPrinter {
Phil Nash503d5d02013-07-03 08:25:11 +010010563 void operator= ( AssertionPrinter const& );
Phil Nashe4756452013-01-26 20:18:30 +000010564 public:
Phil Nash8d44f2d2013-11-13 08:10:45 +000010565 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010566 : stream( _stream ),
10567 stats( _stats ),
10568 result( _stats.assertionResult ),
Phil Nash12c16ff2013-04-05 20:58:01 +010010569 colour( Colour::None ),
Phil Nasha2773812013-02-02 20:37:58 +000010570 message( result.getMessage() ),
Phil Nash8d44f2d2013-11-13 08:10:45 +000010571 messages( _stats.infoMessages ),
10572 printInfoMessages( _printInfoMessages )
Phil Nashe4756452013-01-26 20:18:30 +000010573 {
10574 switch( result.getResultType() ) {
10575 case ResultWas::Ok:
Phil Nash12c16ff2013-04-05 20:58:01 +010010576 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010577 passOrFail = "PASSED";
Phil Nasha2773812013-02-02 20:37:58 +000010578 //if( result.hasMessage() )
10579 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010580 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010581 if( _stats.infoMessages.size() > 1 )
10582 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010583 break;
10584 case ResultWas::ExpressionFailed:
10585 if( result.isOk() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010586 colour = Colour::Success;
Phil Nashe4756452013-01-26 20:18:30 +000010587 passOrFail = "FAILED - but was ok";
10588 }
10589 else {
Phil Nash12c16ff2013-04-05 20:58:01 +010010590 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010591 passOrFail = "FAILED";
10592 }
Phil Nasha2773812013-02-02 20:37:58 +000010593 if( _stats.infoMessages.size() == 1 )
Phil Nashe4756452013-01-26 20:18:30 +000010594 messageLabel = "with message";
Phil Nasha2773812013-02-02 20:37:58 +000010595 if( _stats.infoMessages.size() > 1 )
10596 messageLabel = "with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010597 break;
10598 case ResultWas::ThrewException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010599 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010600 passOrFail = "FAILED";
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020010601 messageLabel = "due to unexpected exception with ";
10602 if (_stats.infoMessages.size() == 1)
10603 messageLabel += "message";
10604 if (_stats.infoMessages.size() > 1)
10605 messageLabel += "messages";
Phil Nashe4756452013-01-26 20:18:30 +000010606 break;
Phil Nash93b61e12014-08-22 19:35:41 +010010607 case ResultWas::FatalErrorCondition:
10608 colour = Colour::Error;
10609 passOrFail = "FAILED";
10610 messageLabel = "due to a fatal error condition";
10611 break;
Phil Nashe4756452013-01-26 20:18:30 +000010612 case ResultWas::DidntThrowException:
Phil Nash12c16ff2013-04-05 20:58:01 +010010613 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010614 passOrFail = "FAILED";
10615 messageLabel = "because no exception was thrown where one was expected";
10616 break;
10617 case ResultWas::Info:
10618 messageLabel = "info";
10619 break;
10620 case ResultWas::Warning:
10621 messageLabel = "warning";
10622 break;
10623 case ResultWas::ExplicitFailure:
10624 passOrFail = "FAILED";
Phil Nash12c16ff2013-04-05 20:58:01 +010010625 colour = Colour::Error;
Phil Nasha2773812013-02-02 20:37:58 +000010626 if( _stats.infoMessages.size() == 1 )
10627 messageLabel = "explicitly with message";
10628 if( _stats.infoMessages.size() > 1 )
10629 messageLabel = "explicitly with messages";
Phil Nashe4756452013-01-26 20:18:30 +000010630 break;
Phil Nashe4756452013-01-26 20:18:30 +000010631 // These cases are here to prevent compiler warnings
10632 case ResultWas::Unknown:
10633 case ResultWas::FailureBit:
Phil Nash243f2d22013-04-12 10:43:06 +010010634 case ResultWas::Exception:
Phil Nashe4756452013-01-26 20:18:30 +000010635 passOrFail = "** internal error **";
Phil Nash12c16ff2013-04-05 20:58:01 +010010636 colour = Colour::Error;
Phil Nashe4756452013-01-26 20:18:30 +000010637 break;
10638 }
10639 }
10640
10641 void print() const {
Phil Nash767f1582013-03-04 12:19:15 +010010642 printSourceInfo();
Phil Nashe4756452013-01-26 20:18:30 +000010643 if( stats.totals.assertions.total() > 0 ) {
Phil Nash767f1582013-03-04 12:19:15 +010010644 if( result.isOk() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010645 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010646 printResultType();
10647 printOriginalExpression();
10648 printReconstructedExpression();
10649 }
Phil Nash767f1582013-03-04 12:19:15 +010010650 else {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010651 stream << '\n';
Phil Nash767f1582013-03-04 12:19:15 +010010652 }
Phil Nashe4756452013-01-26 20:18:30 +000010653 printMessage();
Phil Nashe4756452013-01-26 20:18:30 +000010654 }
10655
10656 private:
10657 void printResultType() const {
10658 if( !passOrFail.empty() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010659 Colour colourGuard( colour );
Phil Nashe4756452013-01-26 20:18:30 +000010660 stream << passOrFail << ":\n";
10661 }
10662 }
10663 void printOriginalExpression() const {
10664 if( result.hasExpression() ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010665 Colour colourGuard( Colour::OriginalExpression );
Phil Nashe4756452013-01-26 20:18:30 +000010666 stream << " ";
Phil Nash786959d2013-06-07 19:07:50 +010010667 stream << result.getExpressionInMacro();
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010668 stream << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010669 }
10670 }
10671 void printReconstructedExpression() const {
10672 if( result.hasExpandedExpression() ) {
10673 stream << "with expansion:\n";
Phil Nash12c16ff2013-04-05 20:58:01 +010010674 Colour colourGuard( Colour::ReconstructedExpression );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010675 stream << Text( result.getExpandedExpression(), TextAttributes().setIndent(2) ) << '\n';
Phil Nashe4756452013-01-26 20:18:30 +000010676 }
10677 }
10678 void printMessage() const {
10679 if( !messageLabel.empty() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010680 stream << messageLabel << ':' << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010681 for( std::vector<MessageInfo>::const_iterator it = messages.begin(), itEnd = messages.end();
10682 it != itEnd;
10683 ++it ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010684 // If this assertion is a warning ignore any INFO messages
10685 if( printInfoMessages || it->type != ResultWas::Info )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010686 stream << Text( it->message, TextAttributes().setIndent(2) ) << '\n';
Phil Nasha2773812013-02-02 20:37:58 +000010687 }
Phil Nashe4756452013-01-26 20:18:30 +000010688 }
10689 void printSourceInfo() const {
Phil Nash12c16ff2013-04-05 20:58:01 +010010690 Colour colourGuard( Colour::FileName );
Phil Nash767f1582013-03-04 12:19:15 +010010691 stream << result.getSourceInfo() << ": ";
Phil Nashe4756452013-01-26 20:18:30 +000010692 }
10693
Phil Nashe4756452013-01-26 20:18:30 +000010694 std::ostream& stream;
10695 AssertionStats const& stats;
10696 AssertionResult const& result;
Phil Nash12c16ff2013-04-05 20:58:01 +010010697 Colour::Code colour;
Phil Nashe4756452013-01-26 20:18:30 +000010698 std::string passOrFail;
10699 std::string messageLabel;
10700 std::string message;
Phil Nasha2773812013-02-02 20:37:58 +000010701 std::vector<MessageInfo> messages;
Phil Nash8d44f2d2013-11-13 08:10:45 +000010702 bool printInfoMessages;
Phil Nashe4756452013-01-26 20:18:30 +000010703 };
Phil Nash2e7d9662013-01-16 09:44:43 +000010704
10705 void lazyPrint() {
10706
Phil Nashaa7123b2013-08-15 19:01:00 +010010707 if( !currentTestRunInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010708 lazyPrintRunInfo();
Phil Nashaa7123b2013-08-15 19:01:00 +010010709 if( !currentGroupInfo.used )
Phil Nash2e7d9662013-01-16 09:44:43 +000010710 lazyPrintGroupInfo();
Phil Nash2e7d9662013-01-16 09:44:43 +000010711
Phil Nasha04981b2013-03-08 09:30:25 +000010712 if( !m_headerPrinted ) {
10713 printTestCaseAndSectionHeader();
10714 m_headerPrinted = true;
10715 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010716 }
10717 void lazyPrintRunInfo() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010718 stream << '\n' << getLineOfChars<'~'>() << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010719 Colour colour( Colour::SecondaryText );
Phil Nashaa7123b2013-08-15 19:01:00 +010010720 stream << currentTestRunInfo->name
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020010721 << " is a Catch v" << libraryVersion() << " host application.\n"
Phil Nash2e7d9662013-01-16 09:44:43 +000010722 << "Run with -? for options\n\n";
10723
Phil Nash6a8e8ad2014-09-15 18:40:24 +010010724 if( m_config->rngSeed() != 0 )
10725 stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";
10726
Phil Nashaa7123b2013-08-15 19:01:00 +010010727 currentTestRunInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010728 }
10729 void lazyPrintGroupInfo() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010730 if( !currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1 ) {
10731 printClosedHeader( "Group: " + currentGroupInfo->name );
10732 currentGroupInfo.used = true;
Phil Nash2e7d9662013-01-16 09:44:43 +000010733 }
10734 }
Phil Nasha04981b2013-03-08 09:30:25 +000010735 void printTestCaseAndSectionHeader() {
Phil Nashaa7123b2013-08-15 19:01:00 +010010736 assert( !m_sectionStack.empty() );
10737 printOpenHeader( currentTestCaseInfo->name );
Phil Nash2e7d9662013-01-16 09:44:43 +000010738
Phil Nashaa7123b2013-08-15 19:01:00 +010010739 if( m_sectionStack.size() > 1 ) {
10740 Colour colourGuard( Colour::Headers );
10741
10742 std::vector<SectionInfo>::const_iterator
10743 it = m_sectionStack.begin()+1, // Skip first section (test case)
10744 itEnd = m_sectionStack.end();
10745 for( ; it != itEnd; ++it )
10746 printHeaderString( it->name, 2 );
Phil Nash2e7d9662013-01-16 09:44:43 +000010747 }
Phil Nashaa7123b2013-08-15 19:01:00 +010010748
Phil Nashd08cee22017-02-13 16:15:42 +000010749 SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;
Phil Nash19279252013-04-20 21:07:32 +010010750
10751 if( !lineInfo.empty() ){
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010752 stream << getLineOfChars<'-'>() << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010753 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010754 stream << lineInfo << '\n';
Phil Nash19279252013-04-20 21:07:32 +010010755 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010756 stream << getLineOfChars<'.'>() << '\n' << std::endl;
Phil Nash2e7d9662013-01-16 09:44:43 +000010757 }
10758
Phil Nasha04981b2013-03-08 09:30:25 +000010759 void printClosedHeader( std::string const& _name ) {
10760 printOpenHeader( _name );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010761 stream << getLineOfChars<'.'>() << '\n';
Phil Nasha04981b2013-03-08 09:30:25 +000010762 }
Phil Nash19279252013-04-20 21:07:32 +010010763 void printOpenHeader( std::string const& _name ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010764 stream << getLineOfChars<'-'>() << '\n';
Phil Nash5c7d3d72013-04-01 11:27:10 +010010765 {
Phil Nash12c16ff2013-04-05 20:58:01 +010010766 Colour colourGuard( Colour::Headers );
Phil Nash19279252013-04-20 21:07:32 +010010767 printHeaderString( _name );
Phil Nash5c7d3d72013-04-01 11:27:10 +010010768 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010769 }
10770
Phil Nash12c16ff2013-04-05 20:58:01 +010010771 // if string has a : in first line will set indent to follow it on
10772 // subsequent lines
Phil Nash19279252013-04-20 21:07:32 +010010773 void printHeaderString( std::string const& _string, std::size_t indent = 0 ) {
Phil Nash12c16ff2013-04-05 20:58:01 +010010774 std::size_t i = _string.find( ": " );
10775 if( i != std::string::npos )
10776 i+=2;
10777 else
10778 i = 0;
Phil Nash19279252013-04-20 21:07:32 +010010779 stream << Text( _string, TextAttributes()
10780 .setIndent( indent+i)
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010781 .setInitialIndent( indent ) ) << '\n';
Phil Nash12c16ff2013-04-05 20:58:01 +010010782 }
10783
Phil Nash28c2e072014-07-09 19:22:49 +010010784 struct SummaryColumn {
10785
10786 SummaryColumn( std::string const& _label, Colour::Code _colour )
10787 : label( _label ),
10788 colour( _colour )
10789 {}
10790 SummaryColumn addRow( std::size_t count ) {
10791 std::ostringstream oss;
10792 oss << count;
10793 std::string row = oss.str();
10794 for( std::vector<std::string>::iterator it = rows.begin(); it != rows.end(); ++it ) {
10795 while( it->size() < row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010796 *it = ' ' + *it;
Phil Nash28c2e072014-07-09 19:22:49 +010010797 while( it->size() > row.size() )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010798 row = ' ' + row;
Phil Nash28c2e072014-07-09 19:22:49 +010010799 }
10800 rows.push_back( row );
10801 return *this;
10802 }
10803
10804 std::string label;
10805 Colour::Code colour;
10806 std::vector<std::string> rows;
10807
10808 };
10809
Phil Nash52e1e742014-07-03 08:11:38 +010010810 void printTotals( Totals const& totals ) {
Phil Nash8d44f2d2013-11-13 08:10:45 +000010811 if( totals.testCases.total() == 0 ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010812 stream << Colour( Colour::Warning ) << "No tests ran\n";
Phil Nash2e7d9662013-01-16 09:44:43 +000010813 }
Phil Nashc984fc32016-03-15 07:24:26 +000010814 else if( totals.assertions.total() > 0 && totals.testCases.allPassed() ) {
Phil Nash52e1e742014-07-03 08:11:38 +010010815 stream << Colour( Colour::ResultSuccess ) << "All tests passed";
10816 stream << " ("
Phil Nash2e7d9662013-01-16 09:44:43 +000010817 << pluralise( totals.assertions.passed, "assertion" ) << " in "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010818 << pluralise( totals.testCases.passed, "test case" ) << ')'
10819 << '\n';
Phil Nashbcad0932012-12-10 08:54:57 +000010820 }
Phil Nash28c2e072014-07-09 19:22:49 +010010821 else {
Phil Nash52e1e742014-07-03 08:11:38 +010010822
Phil Nash28c2e072014-07-09 19:22:49 +010010823 std::vector<SummaryColumn> columns;
10824 columns.push_back( SummaryColumn( "", Colour::None )
10825 .addRow( totals.testCases.total() )
10826 .addRow( totals.assertions.total() ) );
10827 columns.push_back( SummaryColumn( "passed", Colour::Success )
10828 .addRow( totals.testCases.passed )
10829 .addRow( totals.assertions.passed ) );
10830 columns.push_back( SummaryColumn( "failed", Colour::ResultError )
10831 .addRow( totals.testCases.failed )
10832 .addRow( totals.assertions.failed ) );
10833 columns.push_back( SummaryColumn( "failed as expected", Colour::ResultExpectedFailure )
10834 .addRow( totals.testCases.failedButOk )
10835 .addRow( totals.assertions.failedButOk ) );
Phil Nash52e1e742014-07-03 08:11:38 +010010836
Phil Nash28c2e072014-07-09 19:22:49 +010010837 printSummaryRow( "test cases", columns, 0 );
10838 printSummaryRow( "assertions", columns, 1 );
Phil Nashf1178122012-12-11 09:03:14 +000010839 }
Phil Nash28c2e072014-07-09 19:22:49 +010010840 }
10841 void printSummaryRow( std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row ) {
10842 for( std::vector<SummaryColumn>::const_iterator it = cols.begin(); it != cols.end(); ++it ) {
10843 std::string value = it->rows[row];
10844 if( it->label.empty() ) {
10845 stream << label << ": ";
10846 if( value != "0" )
10847 stream << value;
10848 else
10849 stream << Colour( Colour::Warning ) << "- none -";
10850 }
10851 else if( value != "0" ) {
10852 stream << Colour( Colour::LightGrey ) << " | ";
10853 stream << Colour( it->colour )
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010854 << value << ' ' << it->label;
Phil Nash28c2e072014-07-09 19:22:49 +010010855 }
10856 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010857 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010858 }
10859
Phil Nash52e1e742014-07-03 08:11:38 +010010860 static std::size_t makeRatio( std::size_t number, std::size_t total ) {
10861 std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number/ total : 0;
10862 return ( ratio == 0 && number > 0 ) ? 1 : ratio;
10863 }
10864 static std::size_t& findMax( std::size_t& i, std::size_t& j, std::size_t& k ) {
10865 if( i > j && i > k )
10866 return i;
10867 else if( j > k )
10868 return j;
10869 else
10870 return k;
10871 }
10872
10873 void printTotalsDivider( Totals const& totals ) {
10874 if( totals.testCases.total() > 0 ) {
10875 std::size_t failedRatio = makeRatio( totals.testCases.failed, totals.testCases.total() );
10876 std::size_t failedButOkRatio = makeRatio( totals.testCases.failedButOk, totals.testCases.total() );
10877 std::size_t passedRatio = makeRatio( totals.testCases.passed, totals.testCases.total() );
10878 while( failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH-1 )
10879 findMax( failedRatio, failedButOkRatio, passedRatio )++;
10880 while( failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH-1 )
10881 findMax( failedRatio, failedButOkRatio, passedRatio )--;
10882
Phil Nash52e1e742014-07-03 08:11:38 +010010883 stream << Colour( Colour::Error ) << std::string( failedRatio, '=' );
10884 stream << Colour( Colour::ResultExpectedFailure ) << std::string( failedButOkRatio, '=' );
Phil Nash28c2e072014-07-09 19:22:49 +010010885 if( totals.testCases.allPassed() )
10886 stream << Colour( Colour::ResultSuccess ) << std::string( passedRatio, '=' );
10887 else
10888 stream << Colour( Colour::Success ) << std::string( passedRatio, '=' );
Phil Nash52e1e742014-07-03 08:11:38 +010010889 }
10890 else {
10891 stream << Colour( Colour::Warning ) << std::string( CATCH_CONFIG_CONSOLE_WIDTH-1, '=' );
10892 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010893 stream << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010894 }
Phil Nash2e7d9662013-01-16 09:44:43 +000010895 void printSummaryDivider() {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010896 stream << getLineOfChars<'-'>() << '\n';
Phil Nashff03cdf2012-12-06 08:44:51 +000010897 }
Phil Nashff03cdf2012-12-06 08:44:51 +000010898
Phil Nashcf5ced52012-12-14 07:50:08 +000010899 private:
Phil Nasha04981b2013-03-08 09:30:25 +000010900 bool m_headerPrinted;
Phil Nashff03cdf2012-12-06 08:44:51 +000010901 };
10902
10903 INTERNAL_CATCH_REGISTER_REPORTER( "console", ConsoleReporter )
10904
10905} // end namespace Catch
10906
Phil Nash5a2df712014-05-01 19:07:02 +010010907// #included from: ../reporters/catch_reporter_compact.hpp
10908#define TWOBLUECUBES_CATCH_REPORTER_COMPACT_HPP_INCLUDED
10909
10910namespace Catch {
10911
10912 struct CompactReporter : StreamingReporterBase {
10913
10914 CompactReporter( ReporterConfig const& _config )
10915 : StreamingReporterBase( _config )
10916 {}
10917
10918 virtual ~CompactReporter();
10919
10920 static std::string getDescription() {
10921 return "Reports test results on a single line, suitable for IDEs";
10922 }
10923
10924 virtual ReporterPreferences getPreferences() const {
10925 ReporterPreferences prefs;
10926 prefs.shouldRedirectStdOut = false;
10927 return prefs;
10928 }
10929
10930 virtual void noMatchingTestCases( std::string const& spec ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010931 stream << "No test cases matched '" << spec << '\'' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010932 }
10933
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010934 virtual void assertionStarting( AssertionInfo const& ) {}
Phil Nash5a2df712014-05-01 19:07:02 +010010935
10936 virtual bool assertionEnded( AssertionStats const& _assertionStats ) {
10937 AssertionResult const& result = _assertionStats.assertionResult;
10938
10939 bool printInfoMessages = true;
10940
10941 // Drop out if result was successful and we're not printing those
10942 if( !m_config->includeSuccessfulResults() && result.isOk() ) {
10943 if( result.getResultType() != ResultWas::Warning )
10944 return false;
10945 printInfoMessages = false;
10946 }
10947
10948 AssertionPrinter printer( stream, _assertionStats, printInfoMessages );
10949 printer.print();
10950
10951 stream << std::endl;
10952 return true;
10953 }
10954
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010010955 virtual void sectionEnded(SectionStats const& _sectionStats) CATCH_OVERRIDE {
10956 if (m_config->showDurations() == ShowDurations::Always) {
10957 stream << getFormattedDuration(_sectionStats.durationInSeconds) << " s: " << _sectionStats.sectionInfo.name << std::endl;
10958 }
10959 }
10960
Phil Nash5a2df712014-05-01 19:07:02 +010010961 virtual void testRunEnded( TestRunStats const& _testRunStats ) {
10962 printTotals( _testRunStats.totals );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010010963 stream << '\n' << std::endl;
Phil Nash5a2df712014-05-01 19:07:02 +010010964 StreamingReporterBase::testRunEnded( _testRunStats );
10965 }
10966
10967 private:
10968 class AssertionPrinter {
10969 void operator= ( AssertionPrinter const& );
10970 public:
10971 AssertionPrinter( std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages )
10972 : stream( _stream )
10973 , stats( _stats )
10974 , result( _stats.assertionResult )
10975 , messages( _stats.infoMessages )
10976 , itMessage( _stats.infoMessages.begin() )
10977 , printInfoMessages( _printInfoMessages )
10978 {}
10979
10980 void print() {
10981 printSourceInfo();
10982
10983 itMessage = messages.begin();
10984
10985 switch( result.getResultType() ) {
10986 case ResultWas::Ok:
10987 printResultType( Colour::ResultSuccess, passedString() );
10988 printOriginalExpression();
10989 printReconstructedExpression();
10990 if ( ! result.hasExpression() )
10991 printRemainingMessages( Colour::None );
10992 else
10993 printRemainingMessages();
10994 break;
10995 case ResultWas::ExpressionFailed:
10996 if( result.isOk() )
10997 printResultType( Colour::ResultSuccess, failedString() + std::string( " - but was ok" ) );
10998 else
10999 printResultType( Colour::Error, failedString() );
11000 printOriginalExpression();
11001 printReconstructedExpression();
11002 printRemainingMessages();
11003 break;
11004 case ResultWas::ThrewException:
11005 printResultType( Colour::Error, failedString() );
11006 printIssue( "unexpected exception with message:" );
11007 printMessage();
11008 printExpressionWas();
11009 printRemainingMessages();
11010 break;
Phil Nash93b61e12014-08-22 19:35:41 +010011011 case ResultWas::FatalErrorCondition:
11012 printResultType( Colour::Error, failedString() );
11013 printIssue( "fatal error condition with message:" );
11014 printMessage();
11015 printExpressionWas();
11016 printRemainingMessages();
11017 break;
Phil Nash5a2df712014-05-01 19:07:02 +010011018 case ResultWas::DidntThrowException:
11019 printResultType( Colour::Error, failedString() );
11020 printIssue( "expected exception, got none" );
11021 printExpressionWas();
11022 printRemainingMessages();
11023 break;
11024 case ResultWas::Info:
11025 printResultType( Colour::None, "info" );
11026 printMessage();
11027 printRemainingMessages();
11028 break;
11029 case ResultWas::Warning:
11030 printResultType( Colour::None, "warning" );
11031 printMessage();
11032 printRemainingMessages();
11033 break;
11034 case ResultWas::ExplicitFailure:
11035 printResultType( Colour::Error, failedString() );
11036 printIssue( "explicitly" );
11037 printRemainingMessages( Colour::None );
11038 break;
11039 // These cases are here to prevent compiler warnings
11040 case ResultWas::Unknown:
11041 case ResultWas::FailureBit:
11042 case ResultWas::Exception:
11043 printResultType( Colour::Error, "** internal error **" );
11044 break;
11045 }
11046 }
11047
11048 private:
11049 // Colour::LightGrey
11050
Phil Nash9241e432014-05-20 18:50:59 +010011051 static Colour::Code dimColour() { return Colour::FileName; }
Phil Nash5a2df712014-05-01 19:07:02 +010011052
11053#ifdef CATCH_PLATFORM_MAC
11054 static const char* failedString() { return "FAILED"; }
11055 static const char* passedString() { return "PASSED"; }
11056#else
11057 static const char* failedString() { return "failed"; }
11058 static const char* passedString() { return "passed"; }
11059#endif
11060
11061 void printSourceInfo() const {
11062 Colour colourGuard( Colour::FileName );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011063 stream << result.getSourceInfo() << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010011064 }
11065
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010011066 void printResultType( Colour::Code colour, std::string const& passOrFail ) const {
Phil Nash5a2df712014-05-01 19:07:02 +010011067 if( !passOrFail.empty() ) {
11068 {
11069 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011070 stream << ' ' << passOrFail;
Phil Nash5a2df712014-05-01 19:07:02 +010011071 }
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011072 stream << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010011073 }
11074 }
11075
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010011076 void printIssue( std::string const& issue ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011077 stream << ' ' << issue;
Phil Nash5a2df712014-05-01 19:07:02 +010011078 }
11079
11080 void printExpressionWas() {
11081 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011082 stream << ';';
Phil Nash5a2df712014-05-01 19:07:02 +010011083 {
11084 Colour colour( dimColour() );
11085 stream << " expression was:";
11086 }
11087 printOriginalExpression();
11088 }
11089 }
11090
11091 void printOriginalExpression() const {
11092 if( result.hasExpression() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011093 stream << ' ' << result.getExpression();
Phil Nash5a2df712014-05-01 19:07:02 +010011094 }
11095 }
11096
11097 void printReconstructedExpression() const {
11098 if( result.hasExpandedExpression() ) {
11099 {
11100 Colour colour( dimColour() );
11101 stream << " for: ";
11102 }
11103 stream << result.getExpandedExpression();
11104 }
11105 }
11106
11107 void printMessage() {
11108 if ( itMessage != messages.end() ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011109 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010011110 ++itMessage;
11111 }
11112 }
11113
Phil Nash9241e432014-05-20 18:50:59 +010011114 void printRemainingMessages( Colour::Code colour = dimColour() ) {
Phil Nash5a2df712014-05-01 19:07:02 +010011115 if ( itMessage == messages.end() )
11116 return;
11117
11118 // using messages.end() directly yields compilation error:
11119 std::vector<MessageInfo>::const_iterator itEnd = messages.end();
11120 const std::size_t N = static_cast<std::size_t>( std::distance( itMessage, itEnd ) );
11121
11122 {
11123 Colour colourGuard( colour );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011124 stream << " with " << pluralise( N, "message" ) << ':';
Phil Nash5a2df712014-05-01 19:07:02 +010011125 }
11126
11127 for(; itMessage != itEnd; ) {
11128 // If this assertion is a warning ignore any INFO messages
11129 if( printInfoMessages || itMessage->type != ResultWas::Info ) {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011130 stream << " '" << itMessage->message << '\'';
Phil Nash5a2df712014-05-01 19:07:02 +010011131 if ( ++itMessage != itEnd ) {
11132 Colour colourGuard( dimColour() );
11133 stream << " and";
11134 }
11135 }
11136 }
11137 }
11138
11139 private:
11140 std::ostream& stream;
11141 AssertionStats const& stats;
11142 AssertionResult const& result;
11143 std::vector<MessageInfo> messages;
11144 std::vector<MessageInfo>::const_iterator itMessage;
11145 bool printInfoMessages;
11146 };
11147
11148 // Colour, message variants:
11149 // - white: No tests ran.
11150 // - red: Failed [both/all] N test cases, failed [both/all] M assertions.
11151 // - white: Passed [both/all] N test cases (no assertions).
11152 // - red: Failed N tests cases, failed M assertions.
11153 // - green: Passed [both/all] N tests cases with M assertions.
11154
11155 std::string bothOrAll( std::size_t count ) const {
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011156 return count == 1 ? std::string() : count == 2 ? "both " : "all " ;
Phil Nash5a2df712014-05-01 19:07:02 +010011157 }
11158
11159 void printTotals( const Totals& totals ) const {
11160 if( totals.testCases.total() == 0 ) {
11161 stream << "No tests ran.";
11162 }
11163 else if( totals.testCases.failed == totals.testCases.total() ) {
11164 Colour colour( Colour::ResultError );
11165 const std::string qualify_assertions_failed =
11166 totals.assertions.failed == totals.assertions.total() ?
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011167 bothOrAll( totals.assertions.failed ) : std::string();
Phil Nash5a2df712014-05-01 19:07:02 +010011168 stream <<
11169 "Failed " << bothOrAll( totals.testCases.failed )
11170 << pluralise( totals.testCases.failed, "test case" ) << ", "
11171 "failed " << qualify_assertions_failed <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011172 pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011173 }
11174 else if( totals.assertions.total() == 0 ) {
11175 stream <<
11176 "Passed " << bothOrAll( totals.testCases.total() )
11177 << pluralise( totals.testCases.total(), "test case" )
11178 << " (no assertions).";
11179 }
11180 else if( totals.assertions.failed ) {
11181 Colour colour( Colour::ResultError );
11182 stream <<
11183 "Failed " << pluralise( totals.testCases.failed, "test case" ) << ", "
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011184 "failed " << pluralise( totals.assertions.failed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011185 }
11186 else {
11187 Colour colour( Colour::ResultSuccess );
11188 stream <<
11189 "Passed " << bothOrAll( totals.testCases.passed )
11190 << pluralise( totals.testCases.passed, "test case" ) <<
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011191 " with " << pluralise( totals.assertions.passed, "assertion" ) << '.';
Phil Nash5a2df712014-05-01 19:07:02 +010011192 }
11193 }
11194 };
11195
11196 INTERNAL_CATCH_REGISTER_REPORTER( "compact", CompactReporter )
11197
11198} // end namespace Catch
11199
Phil Nasha695eb92012-08-13 07:46:10 +010011200namespace Catch {
Phil Nash7e346192015-11-03 08:00:43 +000011201 // These are all here to avoid warnings about not having any out of line
11202 // virtual methods
Phil Nasha695eb92012-08-13 07:46:10 +010011203 NonCopyable::~NonCopyable() {}
11204 IShared::~IShared() {}
Phil Nash7e346192015-11-03 08:00:43 +000011205 IStream::~IStream() CATCH_NOEXCEPT {}
Phil Nashece529a2015-11-03 17:37:43 +000011206 FileStream::~FileStream() CATCH_NOEXCEPT {}
11207 CoutStream::~CoutStream() CATCH_NOEXCEPT {}
11208 DebugOutStream::~DebugOutStream() CATCH_NOEXCEPT {}
Phil Nashd7e17902014-04-18 08:49:35 +010011209 StreamBufBase::~StreamBufBase() CATCH_NOEXCEPT {}
Phil Nasha695eb92012-08-13 07:46:10 +010011210 IContext::~IContext() {}
11211 IResultCapture::~IResultCapture() {}
11212 ITestCase::~ITestCase() {}
11213 ITestCaseRegistry::~ITestCaseRegistry() {}
11214 IRegistryHub::~IRegistryHub() {}
11215 IMutableRegistryHub::~IMutableRegistryHub() {}
11216 IExceptionTranslator::~IExceptionTranslator() {}
11217 IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() {}
11218 IReporter::~IReporter() {}
11219 IReporterFactory::~IReporterFactory() {}
11220 IReporterRegistry::~IReporterRegistry() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011221 IStreamingReporter::~IStreamingReporter() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011222 AssertionStats::~AssertionStats() {}
11223 SectionStats::~SectionStats() {}
11224 TestCaseStats::~TestCaseStats() {}
11225 TestGroupStats::~TestGroupStats() {}
11226 TestRunStats::~TestRunStats() {}
Phil Nashaa7123b2013-08-15 19:01:00 +010011227 CumulativeReporterBase::SectionNode::~SectionNode() {}
11228 CumulativeReporterBase::~CumulativeReporterBase() {}
Phil Nasha1fbfea2012-12-01 23:57:18 +000011229
Phil Nash2e7d9662013-01-16 09:44:43 +000011230 StreamingReporterBase::~StreamingReporterBase() {}
Phil Nashff03cdf2012-12-06 08:44:51 +000011231 ConsoleReporter::~ConsoleReporter() {}
Phil Nash5a2df712014-05-01 19:07:02 +010011232 CompactReporter::~CompactReporter() {}
Phil Nasha695eb92012-08-13 07:46:10 +010011233 IRunner::~IRunner() {}
11234 IMutableContext::~IMutableContext() {}
11235 IConfig::~IConfig() {}
11236 XmlReporter::~XmlReporter() {}
11237 JunitReporter::~JunitReporter() {}
11238 TestRegistry::~TestRegistry() {}
11239 FreeFunctionTestCase::~FreeFunctionTestCase() {}
11240 IGeneratorInfo::~IGeneratorInfo() {}
11241 IGeneratorsForTest::~IGeneratorsForTest() {}
Phil Nash8342ae82015-07-13 15:03:26 +010011242 WildcardPattern::~WildcardPattern() {}
Phil Nash65cc14c2014-05-16 18:54:48 +010011243 TestSpec::Pattern::~Pattern() {}
11244 TestSpec::NamePattern::~NamePattern() {}
11245 TestSpec::TagPattern::~TagPattern() {}
11246 TestSpec::ExcludedPattern::~ExcludedPattern() {}
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010011247 Matchers::Impl::MatcherUntypedBase::~MatcherUntypedBase() {}
Phil Nasha695eb92012-08-13 07:46:10 +010011248
11249 void Config::dummy() {}
Phil Nash7e346192015-11-03 08:00:43 +000011250
11251 namespace TestCaseTracking {
11252 ITracker::~ITracker() {}
11253 TrackerBase::~TrackerBase() {}
11254 SectionTracker::~SectionTracker() {}
11255 IndexTracker::~IndexTracker() {}
11256 }
Phil Nasha695eb92012-08-13 07:46:10 +010011257}
11258
Phil Nash5bc030d2012-08-16 18:48:50 +010011259#ifdef __clang__
Phil Nasha695eb92012-08-13 07:46:10 +010011260#pragma clang diagnostic pop
Phil Nash89d1e6c2011-05-24 08:23:02 +010011261#endif
Matt Wozniskif29c8982012-09-17 01:42:29 -040011262
Phil Nash9abb2762014-03-06 21:53:34 +000011263#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011264
Phil Nashde49ec42013-12-04 20:25:14 +000011265#ifdef CATCH_CONFIG_MAIN
Phil Nash89d1e6c2011-05-24 08:23:02 +010011266// #included from: internal/catch_default_main.hpp
Phil Nash3b80af72012-08-09 07:47:30 +010011267#define TWOBLUECUBES_CATCH_DEFAULT_MAIN_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011268
Phil Nash176eb812012-05-11 08:17:16 +010011269#ifndef __OBJC__
Phil Nash89d1e6c2011-05-24 08:23:02 +010011270
Phil Nash176eb812012-05-11 08:17:16 +010011271// Standard C/C++ main entry point
Phil Nash981347b2015-12-09 18:11:48 +000011272int main (int argc, char * argv[]) {
Phil Nash0952b762017-02-28 14:19:09 +000011273 int result = Catch::Session().run( argc, argv );
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011274 return ( result < 0xff ? result : 0xff );
Phil Nash176eb812012-05-11 08:17:16 +010011275}
11276
11277#else // __OBJC__
11278
11279// Objective-C entry point
11280int main (int argc, char * const argv[]) {
Phil Nash53c990a2012-03-17 18:20:06 +000011281#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011282 NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
Phil Nash53c990a2012-03-17 18:20:06 +000011283#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011284
11285 Catch::registerTestMethods();
Phil Nash786959d2013-06-07 19:07:50 +010011286 int result = Catch::Session().run( argc, (char* const*)argv );
Phil Nash89d1e6c2011-05-24 08:23:02 +010011287
Phil Nash53c990a2012-03-17 18:20:06 +000011288#if !CATCH_ARC_ENABLED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011289 [pool drain];
Phil Nash53c990a2012-03-17 18:20:06 +000011290#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011291
Martin Hořeňovskýce37f482017-02-01 21:47:43 +010011292 return ( result < 0xff ? result : 0xff );
Phil Nash89d1e6c2011-05-24 08:23:02 +010011293}
11294
Phil Nash176eb812012-05-11 08:17:16 +010011295#endif // __OBJC__
11296
Phil Nash9abb2762014-03-06 21:53:34 +000011297#endif
11298
11299#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED
11300# undef CLARA_CONFIG_MAIN
11301#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011302
Phil Nash89d1e6c2011-05-24 08:23:02 +010011303//////
11304
Phil Nash46bcd4b2012-07-20 18:43:48 +010011305// If this config identifier is defined then all CATCH macros are prefixed with CATCH_
11306#ifdef CATCH_CONFIG_PREFIX_ALL
11307
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011308#if defined(CATCH_CONFIG_FAST_COMPILE)
11309#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11310#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11311#else
11312#define CATCH_REQUIRE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, expr )
11313#define CATCH_REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11314#endif
Phil Nash46bcd4b2012-07-20 18:43:48 +010011315
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011316#define CATCH_REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11317#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11318#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11319#define CATCH_REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011320
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011321#define CATCH_CHECK( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11322#define CATCH_CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11323#define CATCH_CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11324#define CATCH_CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11325#define CATCH_CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011326
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011327#define CATCH_CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11328#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11329#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11330#define CATCH_CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011331
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011332#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011333
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011334#if defined(CATCH_CONFIG_FAST_COMPILE)
11335#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11336#else
11337#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11338#endif
11339
11340#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11341#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11342#define CATCH_SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )
11343#define CATCH_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
11344#define CATCH_SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CATCH_CAPTURE", #msg " := " << Catch::toString(msg) )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011345
Phil Nash93906752013-03-16 20:21:51 +000011346#ifdef CATCH_CONFIG_VARIADIC_MACROS
11347 #define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
Phil Nash786959d2013-06-07 19:07:50 +010011348 #define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011349 #define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
Phil Nashc7243562016-01-22 07:52:07 +000011350 #define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011351 #define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Phil Nash859760a2013-12-14 14:34:05 +000011352 #define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, "CATCH_FAIL", __VA_ARGS__ )
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011353 #define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11354 #define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011355#else
11356 #define CATCH_TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010011357 #define CATCH_TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011358 #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 +000011359 #define CATCH_REGISTER_TEST_CASE( function, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( function, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011360 #define CATCH_SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011361 #define CATCH_FAIL( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11362 #define CATCH_FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11363 #define CATCH_SUCCEED( msg ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
Phil Nash93906752013-03-16 20:21:51 +000011364#endif
11365#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011366
11367#define CATCH_REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000011368#define CATCH_REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash46bcd4b2012-07-20 18:43:48 +010011369
11370#define CATCH_GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11371
Phil Nash37186a12013-03-13 12:19:30 +000011372// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000011373#ifdef CATCH_CONFIG_VARIADIC_MACROS
11374#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010011375#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000011376#else
Phil Nash37186a12013-03-13 12:19:30 +000011377#define CATCH_SCENARIO( name, tags ) CATCH_TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010011378#define CATCH_SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000011379#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010011380#define CATCH_GIVEN( desc ) CATCH_SECTION( std::string( "Given: ") + desc, "" )
11381#define CATCH_WHEN( desc ) CATCH_SECTION( std::string( " When: ") + desc, "" )
11382#define CATCH_AND_WHEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
11383#define CATCH_THEN( desc ) CATCH_SECTION( std::string( " Then: ") + desc, "" )
11384#define CATCH_AND_THEN( desc ) CATCH_SECTION( std::string( " And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000011385
Phil Nash46bcd4b2012-07-20 18:43:48 +010011386// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required
11387#else
11388
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011389#if defined(CATCH_CONFIG_FAST_COMPILE)
11390#define REQUIRE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11391#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST_NO_TRY( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011392
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011393#else
11394#define REQUIRE( expr ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, expr )
11395#define REQUIRE_FALSE( expr ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, expr )
11396#endif
Phil Nash89d1e6c2011-05-24 08:23:02 +010011397
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011398#define REQUIRE_THROWS( expr ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, "", expr )
11399#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )
11400#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )
11401#define REQUIRE_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, expr )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011402
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011403#define CHECK( expr ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, expr )
11404#define CHECK_FALSE( expr ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, expr )
11405#define CHECKED_IF( expr ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, expr )
11406#define CHECKED_ELSE( expr ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, expr )
11407#define CHECK_NOFAIL( expr ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, expr )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011408
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011409#define CHECK_THROWS( expr ) INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, "", expr )
11410#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )
11411#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )
11412#define CHECK_NOTHROW( expr ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, expr )
Phil Nash78d95a02012-03-04 21:22:36 +000011413
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011414#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )
11415
11416#if defined(CATCH_CONFIG_FAST_COMPILE)
11417#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT_NO_TRY( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11418#else
11419#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )
11420#endif
11421
11422#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11423#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )
11424#define SCOPED_INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )
11425#define CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
11426#define SCOPED_CAPTURE( msg ) INTERNAL_CATCH_INFO( "CAPTURE", #msg " := " << Catch::toString(msg) )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011427
Phil Nash93906752013-03-16 20:21:51 +000011428#ifdef CATCH_CONFIG_VARIADIC_MACROS
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010011429#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )
11430#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )
11431#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )
11432#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )
11433#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011434#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )
11435#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
11436#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )
Phil Nash93906752013-03-16 20:21:51 +000011437#else
Martin Hořeňovský0c015aa2017-03-13 21:29:30 +010011438#define TEST_CASE( name, description ) INTERNAL_CATCH_TESTCASE( name, description )
Phil Nash786959d2013-06-07 19:07:50 +010011439 #define TEST_CASE_METHOD( className, name, description ) INTERNAL_CATCH_TEST_CASE_METHOD( className, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011440 #define METHOD_AS_TEST_CASE( method, name, description ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, name, description )
Phil Nash7424b232015-12-28 15:07:32 +000011441 #define REGISTER_TEST_CASE( method, name, description ) INTERNAL_CATCH_REGISTER_TESTCASE( method, name, description )
Phil Nash93906752013-03-16 20:21:51 +000011442 #define SECTION( name, description ) INTERNAL_CATCH_SECTION( name, description )
Martin Hořeňovský1b03c5a2017-04-07 22:56:36 +020011443 #define FAIL( msg ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, msg )
11444 #define FAIL_CHECK( msg ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, msg )
11445 #define SUCCEED( msg ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, msg )
Phil Nash93906752013-03-16 20:21:51 +000011446#endif
11447#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE( "", "" )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011448
11449#define REGISTER_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_REPORTER( name, reporterType )
Phil Nasha1fbfea2012-12-01 23:57:18 +000011450#define REGISTER_LEGACY_REPORTER( name, reporterType ) INTERNAL_CATCH_REGISTER_LEGACY_REPORTER( name, reporterType )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011451
11452#define GENERATE( expr) INTERNAL_CATCH_GENERATE( expr )
11453
Phil Nash46bcd4b2012-07-20 18:43:48 +010011454#endif
11455
11456#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )
Phil Nash89d1e6c2011-05-24 08:23:02 +010011457
Phil Nash37186a12013-03-13 12:19:30 +000011458// "BDD-style" convenience wrappers
Phil Nashbd7f7972013-03-21 09:00:24 +000011459#ifdef CATCH_CONFIG_VARIADIC_MACROS
11460#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )
Phil Nash544bf332014-08-20 08:09:32 +010011461#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )
Phil Nashbd7f7972013-03-21 09:00:24 +000011462#else
Phil Nash37186a12013-03-13 12:19:30 +000011463#define SCENARIO( name, tags ) TEST_CASE( "Scenario: " name, tags )
Phil Nash544bf332014-08-20 08:09:32 +010011464#define SCENARIO_METHOD( className, name, tags ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " name, tags )
Phil Nashbd7f7972013-03-21 09:00:24 +000011465#endif
Phil Nash2f6371f2015-07-23 23:06:26 +010011466#define GIVEN( desc ) SECTION( std::string(" Given: ") + desc, "" )
11467#define WHEN( desc ) SECTION( std::string(" When: ") + desc, "" )
11468#define AND_WHEN( desc ) SECTION( std::string("And when: ") + desc, "" )
11469#define THEN( desc ) SECTION( std::string(" Then: ") + desc, "" )
11470#define AND_THEN( desc ) SECTION( std::string(" And: ") + desc, "" )
Phil Nash37186a12013-03-13 12:19:30 +000011471
Phil Nash89d1e6c2011-05-24 08:23:02 +010011472using Catch::Detail::Approx;
11473
Phil Nashaec1e5e2012-05-09 19:37:51 +010011474#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED
Phil Nash89d1e6c2011-05-24 08:23:02 +010011475